Commit fc478143 authored by Takashi Iwai's avatar Takashi Iwai

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: default avatarHans Hu <HansHu@zhaoxin.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 78c9be61
...@@ -732,6 +732,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec, ...@@ -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, ...@@ -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 { ...@@ -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[] = { ...@@ -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, ...@@ -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, ...@@ -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);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment