ALSA: hda: Check the non-cached stream buffers more explicitly
authorTakashi Iwai <tiwai@suse.de>
Sat, 11 Aug 2018 21:33:34 +0000 (23:33 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Nov 2018 19:15:01 +0000 (11:15 -0800)
[ 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
sound/pci/hda/hda_intel.c

index a68e75b..53c3cd2 100644 (file)
@@ -160,6 +160,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 */
index 873d982..4e38905 100644 (file)
@@ -410,7 +410,7 @@ static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool
 #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);
@@ -1634,6 +1634,7 @@ static void azx_check_snoop_available(struct azx *chip)
                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;
        }
 
@@ -1654,8 +1655,12 @@ static void azx_check_snoop_available(struct azx *chip)
                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)
@@ -2094,7 +2099,7 @@ static void pcm_mmap_prepare(struct snd_pcm_substream *substream,
 #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
 }