[alsa-devel] `hda-intel: spurious response` several times in output of `dmesg`

Takashi Iwai tiwai at suse.de
Tue Sep 27 14:52:30 CEST 2011


At Mon, 19 Sep 2011 20:39:58 +0200,
Paul Menzel wrote:
> 
> Am Montag, den 19.09.2011, 15:19 +0200 schrieb Takashi Iwai:
> > At Mon, 19 Sep 2011 14:50:35 +0200, Paul Menzel wrote:
> > > 
> > > Am Montag, den 19.09.2011, 11:27 +0200 schrieb Takashi Iwai:
> > > > At Sun, 18 Sep 2011 20:28:03 +0200, Paul Menzel wrote:
> > > > > 
> > > > > Am Mittwoch, den 14.09.2011, 00:11 +0200 schrieb Paul Menzel:
> > > > > > Am Montag, den 12.09.2011, 11:28 +0200 schrieb Takashi Iwai:
> > > > > > > At Wed, 31 Aug 2011 12:37:28 +0200, Daniel Mack wrote:
> > > > > > > > 
> > > > > > > > On Wed, Aug 31, 2011 at 12:19 PM, Paul Menzel wrote:
> > > > > > 
> > > > > > > > > Am Donnerstag, den 25.08.2011, 17:01 +0200 schrieb Paul Menzel:
> > > > > > > > >
> > > > > > > > > […]
> > > > > > > > >
> > > > > > > > >> I just want to add that I also see these messages with Linux kernel
> > > > > > > > >> 3.0.2 and say seem to be related to suspend and resume.
> > > > > > > > >>
> > > > > > > > >> The values seem to differ though every time.
> > > > > > > > >>
> > > > > > > > >>         [ 1130.984969] hda-intel: spurious response 0x0:0x0, last cmd=0x620000
> > > > > > > > >>         [ 1130.984990] hda-intel: spurious response 0x1003c:0x0, last cmd=0x620000
> > > > > > > > >>         [ 1130.985011] hda-intel: spurious response 0x0:0x0, last cmd=0x620000
> > > > > > > > >>         [ 1130.985032] hda-intel: spurious response 0x10034:0x0, last cmd=0x620000
> > > > > > > > >>         [ 1130.985053] hda-intel: spurious response 0x0:0x0, last cmd=0x620000
> > > > > > > > >>
> > > > > > > > >>         [ … another suspend/resume … ]
> > > > > > > > >>
> > > > > > > > >>         [ 2726.277102] hda-intel: spurious response 0x0:0x0, last cmd=0x1e70700
> > > > > > > > >>         [ 2726.277123] hda-intel: spurious response 0x0:0x0, last cmd=0x1e70700
> > > > > > > > >>         [ 2726.277144] hda-intel: spurious response 0x0:0x0, last cmd=0x1e70700
> > > > > > > > >>         [ 2726.277165] hda-intel: spurious response 0xb:0x0, last cmd=0x1e70700
> > > > > > > > >>
> > > > > > > > >> Please find the output of `alsa-info.sh` [1] with this Linux version at
> > > > > > > > >> the end.
> > > > > 
> > > > > […]
> > > > > 
> > > > > > > The verb 0x620000 is to set a stream format to NID 0x06.
> > > > > > > For further debugging, more detailed information is needed.
> > > > > > > 
> > > > > > > I seem to have lost the original post, so could you attach
> > > > > > > alsa-info.sh output again, Paul?
> > > > > > 
> > > > > > Unfortunately I have to compress them due to the size limit. (Could you
> > > > > > increase that to for example 150 kB?)
> > > > > 
> > > > > The output of `alsa-info.sh` with Linux 3.1-rc6 (3ab0fcd6c)
> > > > > 
> > > > >         commit 3ab0fcd6cd45d0d0cac114e498848f37e7a463b2
> > > > >         Merge: 9183834 14515a0
> > > > >         Author: Takashi Iwai <tiwai at suse.de>
> > > > >         Date:   Fri Sep 16 08:34:05 2011 +0200
> > > > >         
> > > > >             Merge branch 'topic/misc'
> > > > > 
> > > > > is as follows.
> > > > 
> > > > Thanks.  Judging from the alsa-info.sh output, the relevant widgets
> > > > are for the SPDIF output, and I guess the messages are harmless.
> > > > 
> > > > Anyway, could you try the patch below?
> > > 
> > > > ---
> > > > diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> > > > index 2a8bed9..ef7e8de 100644
> > > > --- a/sound/pci/hda/hda_intel.c
> > > > +++ b/sound/pci/hda/hda_intel.c
> > > > @@ -2925,7 +2925,7 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
> > > >  	  .driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
> > > >  	/* VIA VT8251/VT8237A */
> > > >  	{ PCI_DEVICE(0x1106, 0x3288),
> > > > -	  .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
> > > > +	  .driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA | AZX_DCAPS_SYNC_WRITE },
> > > >  	/* SIS966 */
> > > >  	{ PCI_DEVICE(0x1039, 0x7502), .driver_data = AZX_DRIVER_SIS },
> > > >  	/* ULI M5461 */
> > > 
> > > I applied your patch, did `make oldconfig`, `make -j2 deb-pkg`,
> > > installed the packages and rebooted. But the message are still there as
> > > far as I can see.
> > 
> > OK, then it's really spurious interrupts.
> > This should be harmless, so you can ignore these messages.
> > 
> > Or, the patch below might work (just hide the messages).
> >
> > ---
> > diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> > index 2a8bed9..3449024 100644
> > --- a/sound/pci/hda/hda_intel.c
> > +++ b/sound/pci/hda/hda_intel.c
> > @@ -443,6 +443,7 @@ struct azx {
> >  	unsigned int msi :1;
> >  	unsigned int irq_pending_warned :1;
> >  	unsigned int probing :1; /* codec probing phase */
> > +	unsigned int in_suspend:1;
> >  
> >  	/* for debugging */
> >  	unsigned int last_cmd[AZX_MAX_CODECS];
> > @@ -696,11 +697,15 @@ static void azx_update_rirb(struct azx *chip)
> >  			chip->rirb.res[addr] = res;
> >  			smp_wmb();
> >  			chip->rirb.cmds[addr]--;
> > -		} else
> > +		} else if (!chip->in_suspend) {
> > +			/* we ignore spurious response messages during susepnd,
> 
> sus*pe*nd
> 
> > +			 * as some chips actually send bogus messages
> > +			 */
> >  			snd_printk(KERN_ERR SFX "spurious response %#x:%#x, "
> >  				   "last cmd=%#08x\n",
> >  				   res, res_ex,
> >  				   chip->last_cmd[addr]);
> > +		}
> >  	}
> >  }
> >  
> > @@ -2267,6 +2272,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
> >  	struct azx *chip = card->private_data;
> >  	int i;
> >  
> > +	chip->in_suspend = 1;
> >  	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
> >  	azx_clear_irq_pending(chip);
> >  	for (i = 0; i < HDA_MAX_PCMS; i++)
> > @@ -2283,6 +2289,7 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
> >  	pci_disable_device(pci);
> >  	pci_save_state(pci);
> >  	pci_set_power_state(pci, pci_choose_state(pci, state));
> > +	chip->in_suspend = 0;
> >  	return 0;
> >  }
> 
> Takashi, thank you very much for help and bearing with me. I applied
> your patch on top of the other one. The messages after resuming are gone
> but I still get these messages on start up (I think logging into GNOME).

OK, so something must be done not only suppressing the PM warnings.

BTW, I'm checking the non-snooping mode, and it might help in some
corner cases like yours, too.  Could you test the patch below?
It might be fuzzy to apply to 3.0, but should be trivial to edit by
hand.


thanks,

Takashi

---
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index dc36f75..3e7fda6 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1037,6 +1037,8 @@ static inline void snd_pcm_mmap_data_close(struct vm_area_struct *area)
 	atomic_dec(&substream->mmap_count);
 }
 
+int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
+			     struct vm_area_struct *area);
 /* mmap for io-memory area */
 #if defined(CONFIG_X86) || defined(CONFIG_PPC) || defined(CONFIG_ALPHA)
 #define SNDRV_PCM_INFO_MMAP_IOMEM	SNDRV_PCM_INFO_MMAP
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 1c6be91..b4bf4a4 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3156,8 +3156,8 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
 /*
  * mmap the DMA buffer on RAM
  */
-static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
-				struct vm_area_struct *area)
+int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
+			     struct vm_area_struct *area)
 {
 	area->vm_flags |= VM_RESERVED;
 #ifdef ARCH_HAS_DMA_MMAP_COHERENT
@@ -3177,6 +3177,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
 	area->vm_ops = &snd_pcm_vm_ops_data_fault;
 	return 0;
 }
+EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
 
 /*
  * mmap the DMA buffer on I/O memory area
@@ -3242,7 +3243,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
 	if (substream->ops->mmap)
 		err = substream->ops->mmap(substream, area);
 	else
-		err = snd_pcm_default_mmap(substream, area);
+		err = snd_pcm_lib_default_mmap(substream, area);
 	if (!err)
 		atomic_inc(&substream->mmap_count);
 	return err;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 2a8bed9..bfec401 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -34,7 +34,6 @@
  * 
  */
 
-#include <asm/io.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
@@ -46,6 +45,12 @@
 #include <linux/pci.h>
 #include <linux/mutex.h>
 #include <linux/reboot.h>
+#include <linux/io.h>
+#ifdef CONFIG_X86
+/* for snoop control */
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#endif
 #include <sound/core.h>
 #include <sound/initval.h>
 #include "hda_codec.h"
@@ -121,6 +126,15 @@ module_param(align_buffer_size, bool, 0644);
 MODULE_PARM_DESC(align_buffer_size,
 		"Force buffer and period sizes to be multiple of 128 bytes.");
 
+#ifdef CONFIG_X86
+static bool hda_snoop;
+module_param_named(snoop, hda_snoop, bool, 0444);
+MODULE_PARM_DESC(snoop, "Enable/disable snooping");
+#else
+#define hda_snoop	true
+#endif
+
+
 MODULE_LICENSE("GPL");
 MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
 			 "{Intel, ICH6M},"
@@ -376,6 +390,7 @@ struct azx_dev {
 	 *  when link position is not greater than FIFO size
 	 */
 	unsigned int insufficient :1;
+	unsigned int wc_marked:1;
 };
 
 /* CORB/RIRB */
@@ -548,6 +563,45 @@ static char *driver_short_names[] __devinitdata = {
 /* for pcm support */
 #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)
+{
+	if (hda_snoop)
+		return;
+	if (addr && size) {
+		int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+		if (on)
+			set_memory_wc((unsigned long)addr, pages);
+		else
+			set_memory_wb((unsigned long)addr, 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);
+}
+static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
+				   struct snd_pcm_runtime *runtime, bool on)
+{
+	if (azx_dev->wc_marked != on) {
+		__mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, 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_runtime *runtime, bool on)
+{
+}
+#endif
+
 static int azx_acquire_irq(struct azx *chip, int do_disconnect);
 static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
 /*
@@ -569,6 +623,7 @@ static int azx_alloc_cmd_io(struct azx *chip)
 		snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
 		return err;
 	}
+	mark_pages_wc(chip, &chip->rb, true);
 	return 0;
 }
 
@@ -1104,8 +1159,8 @@ static void azx_init_pci(struct azx *chip)
 	if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) {
 		snd_printdd(SFX "Enabling ATI snoop\n");
 		update_pci_byte(chip->pci,
-				ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 
-				0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+				ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07,
+				hda_snoop ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0);
 	}
 
 	/* For NVIDIA HDA, enable snoop */
@@ -1125,15 +1180,18 @@ static void azx_init_pci(struct azx *chip)
 	/* Enable SCH/PCH snoop if needed */
 	if (chip->driver_caps & AZX_DCAPS_SCH_SNOOP) {
 		pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
-		if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
-			pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
-				snoop & (~INTEL_SCH_HDA_DEVC_NOSNOOP));
+		if ((!hda_snoop && !(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)) ||
+		    (hda_snoop && (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP))) {
+			snoop &= ~INTEL_SCH_HDA_DEVC_NOSNOOP;
+			if (!hda_snoop)
+				snoop |= INTEL_SCH_HDA_DEVC_NOSNOOP;
+			pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, snoop);
 			pci_read_config_word(chip->pci,
 				INTEL_SCH_HDA_DEVC, &snoop);
-			snd_printdd(SFX "HDA snoop disabled, enabling ... %s\n",
-				(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
-				? "Failed" : "OK");
 		}
+		snd_printdd(SFX "HDA snoop %s\n",
+				(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
+				? "Disabled" : "Enabled");
         }
 }
 
@@ -1340,12 +1398,16 @@ static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
  */
 static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
 {
+	unsigned int val;
 	/* make sure the run bit is zero for SD */
 	azx_stream_clear(chip, azx_dev);
 	/* program the stream_tag */
-	azx_sd_writel(azx_dev, SD_CTL,
-		      (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
-		      (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT));
+	val = azx_sd_readl(azx_dev, SD_CTL);
+	val = (val & ~SD_CTL_STREAM_TAG_MASK) |
+		(azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT);
+	if (!hda_snoop)
+		val |= SD_CTL_TRAFFIC_PRIO;
+	azx_sd_writel(azx_dev, SD_CTL, val);
 
 	/* program the length of samples in cyclic buffer */
 	azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize);
@@ -1693,19 +1755,30 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
 static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
 			     struct snd_pcm_hw_params *hw_params)
 {
+	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);
 	azx_dev->bufsize = 0;
 	azx_dev->period_bytes = 0;
 	azx_dev->format_val = 0;
-	return snd_pcm_lib_malloc_pages(substream,
+	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);
+	return ret;
 }
 
 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 */
@@ -1718,6 +1791,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);
 	return snd_pcm_lib_free_pages(substream);
 }
 
@@ -2076,6 +2150,18 @@ static void azx_clear_irq_pending(struct azx *chip)
 	spin_unlock_irq(&chip->reg_lock);
 }
 
+#ifdef CONFIG_X86
+static int azx_pcm_mmap(struct snd_pcm_substream *substream,
+			struct vm_area_struct *area)
+{
+	if (!hda_snoop)
+		area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+	return snd_pcm_lib_default_mmap(substream, area);
+}
+#else
+#define azx_pcm_mmap	NULL
+#endif
+
 static struct snd_pcm_ops azx_pcm_ops = {
 	.open = azx_pcm_open,
 	.close = azx_pcm_close,
@@ -2085,6 +2171,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
 	.prepare = azx_pcm_prepare,
 	.trigger = azx_pcm_trigger,
 	.pointer = azx_pcm_pointer,
+	.mmap = azx_pcm_mmap,
 	.page = snd_pcm_sgbuf_ops_page,
 };
 
@@ -2365,13 +2452,19 @@ static int azx_free(struct azx *chip)
 
 	if (chip->azx_dev) {
 		for (i = 0; i < chip->num_streams; i++)
-			if (chip->azx_dev[i].bdl.area)
+			if (chip->azx_dev[i].bdl.area) {
+				mark_pages_wc(chip, &chip->azx_dev[i].bdl, false);
 				snd_dma_free_pages(&chip->azx_dev[i].bdl);
+			}
 	}
-	if (chip->rb.area)
+	if (chip->rb.area) {
+		mark_pages_wc(chip, &chip->rb, false);
 		snd_dma_free_pages(&chip->rb);
-	if (chip->posbuf.area)
+	}
+	if (chip->posbuf.area) {
+		mark_pages_wc(chip, &chip->posbuf, false);
 		snd_dma_free_pages(&chip->posbuf);
+	}
 	pci_release_regions(chip->pci);
 	pci_disable_device(chip->pci);
 	kfree(chip->azx_dev);
@@ -2693,6 +2786,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 			snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
 			goto errout;
 		}
+		mark_pages_wc(chip, &chip->azx_dev[i].bdl, true);
 	}
 	/* allocate memory for the position buffer */
 	err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
@@ -2702,6 +2796,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
 		snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
 		goto errout;
 	}
+	mark_pages_wc(chip, &chip->posbuf, true);
 	/* allocate CORB/RIRB */
 	err = azx_alloc_cmd_io(chip);
 	if (err < 0)


More information about the Alsa-devel mailing list