| From foo@baz Sat Nov 10 11:24:34 PST 2018 |
| From: Takashi Iwai <tiwai@suse.de> |
| Date: Sat, 11 Aug 2018 23:33:34 +0200 |
| Subject: ALSA: hda: Check the non-cached stream buffers more explicitly |
| |
| From: Takashi Iwai <tiwai@suse.de> |
| |
| [ Upstream commit 78c9be61c3a5cd9e2439fd27a5ffad73a81958c7 ] |
| |
| Introduce a new flag, uc_buffer, to indicate that the controller |
| requires the non-cached pages for stream buffers, either as a |
| chip-specific requirement or specified via snoop=0 option. |
| This improves the code-readability. |
| |
| Also, this patch fixes the incorrect behavior for C-Media chip where |
| the stream buffers were never handled as non-cached due to the check |
| of driver_type even if you pass snoop=0 option. |
| |
| Signed-off-by: Takashi Iwai <tiwai@suse.de> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| sound/pci/hda/hda_controller.h | 1 + |
| sound/pci/hda/hda_intel.c | 11 ++++++++--- |
| 2 files changed, 9 insertions(+), 3 deletions(-) |
| |
| --- a/sound/pci/hda/hda_controller.h |
| +++ b/sound/pci/hda/hda_controller.h |
| @@ -155,6 +155,7 @@ struct azx { |
| unsigned int msi:1; |
| unsigned int probing:1; /* codec probing phase */ |
| unsigned int snoop:1; |
| + unsigned int uc_buffer:1; /* non-cached pages for stream buffers */ |
| unsigned int align_buffer_size:1; |
| unsigned int region_requested:1; |
| unsigned int disabled:1; /* disabled by vga_switcheroo */ |
| --- a/sound/pci/hda/hda_intel.c |
| +++ b/sound/pci/hda/hda_intel.c |
| @@ -410,7 +410,7 @@ static void __mark_pages_wc(struct azx * |
| #ifdef CONFIG_SND_DMA_SGBUF |
| if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) { |
| struct snd_sg_buf *sgbuf = dmab->private_data; |
| - if (chip->driver_type == AZX_DRIVER_CMEDIA) |
| + if (!chip->uc_buffer) |
| return; /* deal with only CORB/RIRB buffers */ |
| if (on) |
| set_pages_array_wc(sgbuf->page_table, sgbuf->pages); |
| @@ -1503,6 +1503,7 @@ static void azx_check_snoop_available(st |
| dev_info(chip->card->dev, "Force to %s mode by module option\n", |
| snoop ? "snoop" : "non-snoop"); |
| chip->snoop = snoop; |
| + chip->uc_buffer = !snoop; |
| return; |
| } |
| |
| @@ -1523,8 +1524,12 @@ static void azx_check_snoop_available(st |
| snoop = false; |
| |
| chip->snoop = snoop; |
| - if (!snoop) |
| + if (!snoop) { |
| dev_info(chip->card->dev, "Force to non-snoop mode\n"); |
| + /* C-Media requires non-cached pages only for CORB/RIRB */ |
| + if (chip->driver_type != AZX_DRIVER_CMEDIA) |
| + chip->uc_buffer = true; |
| + } |
| } |
| |
| static void azx_probe_work(struct work_struct *work) |
| @@ -1947,7 +1952,7 @@ static void pcm_mmap_prepare(struct snd_ |
| #ifdef CONFIG_X86 |
| struct azx_pcm *apcm = snd_pcm_substream_chip(substream); |
| struct azx *chip = apcm->chip; |
| - if (!azx_snoop(chip) && chip->driver_type != AZX_DRIVER_CMEDIA) |
| + if (chip->uc_buffer) |
| area->vm_page_prot = pgprot_writecombine(area->vm_page_prot); |
| #endif |
| } |