Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc478143 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

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
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -732,6 +732,7 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
	int pcm_dev = cpcm->device;
	unsigned int size;
	int s, err;
	int type = SNDRV_DMA_TYPE_DEV_SG;

	list_for_each_entry(apcm, &chip->pcm_list, list) {
		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;
	if (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,
					      size, MAX_PREALLOC_SIZE);
	return 0;
+0 −1
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ struct azx_dev {
	 *  when link position is not greater than FIFO size
	 */
	unsigned int insufficient:1;
	unsigned int wc_marked:1;
};

#define azx_stream(dev)		(&(dev)->core)
+4 −77
Original line number Diff line number Diff line
@@ -397,61 +397,6 @@ static char *driver_short_names[] = {
	[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);

/*
@@ -2054,22 +1999,14 @@ static int dma_alloc_pages(struct hdac_bus *bus,
			   struct snd_dma_buffer *buf)
{
	struct azx *chip = bus_to_azx(bus);
	int err;

	err = snd_dma_alloc_pages(type,
				  bus->dev,
				  size, buf);
	if (err < 0)
		return err;
	mark_pages_wc(chip, buf, true);
	return 0;
	if (!azx_snoop(chip) && type == SNDRV_DMA_TYPE_DEV)
		type = SNDRV_DMA_TYPE_DEV_UC;
	return snd_dma_alloc_pages(type, bus->dev, size, 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);
}

@@ -2077,22 +2014,12 @@ static int substream_alloc_pages(struct azx *chip,
				 struct snd_pcm_substream *substream,
				 size_t size)
{
	struct azx_dev *azx_dev = get_azx_dev(substream);
	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;
	return snd_pcm_lib_malloc_pages(substream, size);
}

static int substream_free_pages(struct azx *chip,
				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);
}