mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 18:09:57 +00:00
ALSA: hda: Use new non-cached allocation for non-snoop mode
Now the ALSA memory allocator helper supports the new non-cached pages, let's use the new type, SNDRV_DMA_TYPE_DEV_UC_SG, for HD-audio driver. This allows us to reduce lots of codes. As another positive side-effect by this patch, the long-standing issue with non-snoop mode playing in the non-mmap mode is fixed. The core memalloc helper does the proper pgprot setup for non-cached pages for vmap(), which was missing in the past. Reported-and-tested-by: Hans Hu <HansHu@zhaoxin.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
78c9be61c3
commit
fc47814369
3 changed files with 8 additions and 79 deletions
|
@ -732,6 +732,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
|
||||||
int pcm_dev = cpcm->device;
|
int pcm_dev = cpcm->device;
|
||||||
unsigned int size;
|
unsigned int size;
|
||||||
int s, err;
|
int s, err;
|
||||||
|
int type = SNDRV_DMA_TYPE_DEV_SG;
|
||||||
|
|
||||||
list_for_each_entry(apcm, &chip->pcm_list, list) {
|
list_for_each_entry(apcm, &chip->pcm_list, list) {
|
||||||
if (apcm->pcm->device == pcm_dev) {
|
if (apcm->pcm->device == pcm_dev) {
|
||||||
|
@ -770,7 +771,9 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
|
||||||
size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
|
size = CONFIG_SND_HDA_PREALLOC_SIZE * 1024;
|
||||||
if (size > MAX_PREALLOC_SIZE)
|
if (size > MAX_PREALLOC_SIZE)
|
||||||
size = MAX_PREALLOC_SIZE;
|
size = MAX_PREALLOC_SIZE;
|
||||||
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
|
if (chip->uc_buffer)
|
||||||
|
type = SNDRV_DMA_TYPE_DEV_UC_SG;
|
||||||
|
snd_pcm_lib_preallocate_pages_for_all(pcm, type,
|
||||||
chip->card->dev,
|
chip->card->dev,
|
||||||
size, MAX_PREALLOC_SIZE);
|
size, MAX_PREALLOC_SIZE);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -76,7 +76,6 @@ struct azx_dev {
|
||||||
* when link position is not greater than FIFO size
|
* when link position is not greater than FIFO size
|
||||||
*/
|
*/
|
||||||
unsigned int insufficient:1;
|
unsigned int insufficient:1;
|
||||||
unsigned int wc_marked:1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define azx_stream(dev) (&(dev)->core)
|
#define azx_stream(dev) (&(dev)->core)
|
||||||
|
|
|
@ -397,61 +397,6 @@ static char *driver_short_names[] = {
|
||||||
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
|
[AZX_DRIVER_GENERIC] = "HD-Audio Generic",
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_X86
|
|
||||||
static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
|
|
||||||
{
|
|
||||||
int pages;
|
|
||||||
|
|
||||||
if (azx_snoop(chip))
|
|
||||||
return;
|
|
||||||
if (!dmab || !dmab->area || !dmab->bytes)
|
|
||||||
return;
|
|
||||||
|
|
||||||
#ifdef CONFIG_SND_DMA_SGBUF
|
|
||||||
if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
|
|
||||||
struct snd_sg_buf *sgbuf = dmab->private_data;
|
|
||||||
if (!chip->uc_buffer)
|
|
||||||
return; /* deal with only CORB/RIRB buffers */
|
|
||||||
if (on)
|
|
||||||
set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
|
|
||||||
else
|
|
||||||
set_pages_array_wb(sgbuf->page_table, sgbuf->pages);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
|
|
||||||
if (on)
|
|
||||||
set_memory_wc((unsigned long)dmab->area, pages);
|
|
||||||
else
|
|
||||||
set_memory_wb((unsigned long)dmab->area, pages);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
|
|
||||||
bool on)
|
|
||||||
{
|
|
||||||
__mark_pages_wc(chip, buf, on);
|
|
||||||
}
|
|
||||||
static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
|
|
||||||
struct snd_pcm_substream *substream, bool on)
|
|
||||||
{
|
|
||||||
if (azx_dev->wc_marked != on) {
|
|
||||||
__mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on);
|
|
||||||
azx_dev->wc_marked = on;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
/* NOP for other archs */
|
|
||||||
static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
|
|
||||||
bool on)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
|
|
||||||
struct snd_pcm_substream *substream, bool on)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int azx_acquire_irq(struct azx *chip, int do_disconnect);
|
static int azx_acquire_irq(struct azx *chip, int do_disconnect);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2054,22 +1999,14 @@ static int dma_alloc_pages(struct hdac_bus *bus,
|
||||||
struct snd_dma_buffer *buf)
|
struct snd_dma_buffer *buf)
|
||||||
{
|
{
|
||||||
struct azx *chip = bus_to_azx(bus);
|
struct azx *chip = bus_to_azx(bus);
|
||||||
int err;
|
|
||||||
|
|
||||||
err = snd_dma_alloc_pages(type,
|
if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV)
|
||||||
bus->dev,
|
type = SNDRV_DMA_TYPE_DEV_UC;
|
||||||
size, buf);
|
return snd_dma_alloc_pages(type, bus->dev, size, buf);
|
||||||
if (err < 0)
|
|
||||||
return err;
|
|
||||||
mark_pages_wc(chip, buf, true);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
|
static void dma_free_pages(struct hdac_bus *bus, struct snd_dma_buffer *buf)
|
||||||
{
|
{
|
||||||
struct azx *chip = bus_to_azx(bus);
|
|
||||||
|
|
||||||
mark_pages_wc(chip, buf, false);
|
|
||||||
snd_dma_free_pages(buf);
|
snd_dma_free_pages(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2077,22 +2014,12 @@ static int substream_alloc_pages(struct azx *chip,
|
||||||
struct snd_pcm_substream *substream,
|
struct snd_pcm_substream *substream,
|
||||||
size_t size)
|
size_t size)
|
||||||
{
|
{
|
||||||
struct azx_dev *azx_dev = get_azx_dev(substream);
|
return snd_pcm_lib_malloc_pages(substream, size);
|
||||||
int ret;
|
|
||||||
|
|
||||||
mark_runtime_wc(chip, azx_dev, substream, false);
|
|
||||||
ret = snd_pcm_lib_malloc_pages(substream, size);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
mark_runtime_wc(chip, azx_dev, substream, true);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int substream_free_pages(struct azx *chip,
|
static int substream_free_pages(struct azx *chip,
|
||||||
struct snd_pcm_substream *substream)
|
struct snd_pcm_substream *substream)
|
||||||
{
|
{
|
||||||
struct azx_dev *azx_dev = get_azx_dev(substream);
|
|
||||||
mark_runtime_wc(chip, azx_dev, substream, false);
|
|
||||||
return snd_pcm_lib_free_pages(substream);
|
return snd_pcm_lib_free_pages(substream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue