Skip to content

Commit

Permalink
ALSA: hda - Fix non-snoop page handling
Browse files Browse the repository at this point in the history
For non-snoop mode, we fiddle with the page attributes of CORB/RIRB
and the position buffer, but also the ring buffers.  The problem is
that the current code blindly assumes that the buffer is contiguous.
However, the ring buffers may be SG-buffers, thus a wrong vmapped
address is passed there, leading to Oops.

This patch fixes the handling for SG-buffers.

Bugzilla: https://bugzilla.novell.com/show_bug.cgi?id=800701

Cc: <stable@vger.kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
  • Loading branch information
Takashi Iwai committed Jan 29, 2013
1 parent f748abc commit 9ddf1ae
Showing 1 changed file with 26 additions and 14 deletions.
40 changes: 26 additions & 14 deletions sound/pci/hda/hda_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -656,29 +656,43 @@ static char *driver_short_names[] = {
#define get_azx_dev(substream) (substream->runtime->private_data)

#ifdef CONFIG_X86
static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on)
static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
{
int pages;

if (azx_snoop(chip))
return;
if (addr && size) {
int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
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 (on)
set_memory_wc((unsigned long)addr, pages);
set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
else
set_memory_wb((unsigned long)addr, pages);
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->area, buf->bytes, on);
__mark_pages_wc(chip, buf, on);
}
static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
struct snd_pcm_runtime *runtime, bool on)
struct snd_pcm_substream *substream, bool on)
{
if (azx_dev->wc_marked != on) {
__mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on);
__mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on);
azx_dev->wc_marked = on;
}
}
Expand All @@ -689,7 +703,7 @@ static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
{
}
static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
struct snd_pcm_runtime *runtime, bool on)
struct snd_pcm_substream *substream, bool on)
{
}
#endif
Expand Down Expand Up @@ -1968,19 +1982,18 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx *chip = apcm->chip;
struct snd_pcm_runtime *runtime = substream->runtime;
struct azx_dev *azx_dev = get_azx_dev(substream);
int ret;

mark_runtime_wc(chip, azx_dev, runtime, false);
mark_runtime_wc(chip, azx_dev, substream, false);
azx_dev->bufsize = 0;
azx_dev->period_bytes = 0;
azx_dev->format_val = 0;
ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (ret < 0)
return ret;
mark_runtime_wc(chip, azx_dev, runtime, true);
mark_runtime_wc(chip, azx_dev, substream, true);
return ret;
}

Expand All @@ -1989,7 +2002,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx_dev *azx_dev = get_azx_dev(substream);
struct azx *chip = apcm->chip;
struct snd_pcm_runtime *runtime = substream->runtime;
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];

/* reset BDL address */
Expand All @@ -2002,7 +2014,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)

snd_hda_codec_cleanup(apcm->codec, hinfo, substream);

mark_runtime_wc(chip, azx_dev, runtime, false);
mark_runtime_wc(chip, azx_dev, substream, false);
return snd_pcm_lib_free_pages(substream);
}

Expand Down

0 comments on commit 9ddf1ae

Please sign in to comment.