All of lore.kernel.org
 help / color / mirror / Atom feed
From: libin.yang@linux.intel.com
To: alsa-devel@alsa-project.org, tiwai@suse.de
Cc: libin.yang@intel.com, mengdong.lin@intel.com,
	Libin Yang <libin.yang@linux.intel.com>
Subject: [RFC: PATCH] ALSA: hda - clear IRQ statu twice on some Intel platforms
Date: Mon, 22 Feb 2016 15:39:50 +0800	[thread overview]
Message-ID: <1456126790-13480-1-git-send-email-libin.yang@linux.intel.com> (raw)

From: Libin Yang <libin.yang@linux.intel.com>

On some Intel platforms, we found the interrupt issue in
the below scenario:
1. driver is in irq handler
2. there is another interrupt from HW after interrupt status
   is cleared and before exiting from interrupt handler
3. exit from the current irq handling

After exiting the irq handler, it should raise another
interrupt for driver to handle the new interrupt. But actually,
it failed to raise the interrupt and driver will never have
chance to clear the interrupt status.

The patch clears the interrupt status again just before exiting
for interrupt handler. This can reduce the contest dramatically.

Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
---
 sound/pci/hda/hda_controller.c |  3 +++
 sound/pci/hda/hda_controller.h |  3 +++
 sound/pci/hda/hda_intel.c      | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 37cf9ce..2ca95c7 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -963,6 +963,9 @@ irqreturn_t azx_interrupt(int irq, void *dev_id)
 		azx_writeb(chip, RIRBSTS, RIRB_INT_MASK);
 	}
 
+	if (chip->post_irq)
+		chip->post_irq(chip);
+
 	spin_unlock(&bus->reg_lock);
 
 	return IRQ_HANDLED;
diff --git a/sound/pci/hda/hda_controller.h b/sound/pci/hda/hda_controller.h
index ec63bbf..ce59997 100644
--- a/sound/pci/hda/hda_controller.h
+++ b/sound/pci/hda/hda_controller.h
@@ -146,6 +146,9 @@ struct azx {
 	const struct firmware *fw;
 #endif
 
+	/* callback at the end of interrupt handler  */
+	void (*post_irq)(struct azx *);
+
 	/* flags */
 	int bdl_pos_adj;
 	int poll_count;
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 4045dca..6a47d88 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1663,6 +1663,43 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 	return 0;
 }
 
+/* HSW, BDW, SKL and BXT need do post_irq() */
+#define INTEL_IRQ_POST(chip) \
+	(((chip)->pci->vendor == PCI_VENDOR_ID_INTEL) && \
+	 (((chip)->pci->device == 0x0a0c) || \
+	 ((chip)->pci->device == 0x0c0c) || \
+	 ((chip)->pci->device == 0x0d0c) || \
+	 ((chip)->pci->device == 0x160c) || \
+	 ((chip)->pci->device == 0xa170) || \
+	 ((chip)->pci->device == 0x9d70) || \
+	 ((chip)->pci->device == 0x5a98)))
+
+
+/* on some intel platforms, if there occurs an interrupt
+ * when irq is being handled, interrupt signal will not be raised
+ * after the irq handler returns. And the interrupt status may never
+ * be cleared.
+ * So let's clear all the interrupt status before return from irq handler.
+ * This can help to reduce the contest between the irq handler and the signal.
+ */
+static void intel_post_irq(struct azx *chip)
+{
+	struct hdac_bus *bus = azx_bus(chip);
+	struct hdac_stream *azx_dev;
+
+	list_for_each_entry(azx_dev, &bus->stream_list, list)
+		snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK);
+
+	/* clear STATESTS */
+	snd_hdac_chip_writew(bus, STATESTS, STATESTS_INT_MASK);
+
+	/* clear rirb status */
+	snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
+
+	/* clear int status */
+	snd_hdac_chip_writel(bus, INTSTS, AZX_INT_CTRL_EN | AZX_INT_ALL_STREAM);
+}
+
 static int azx_first_init(struct azx *chip)
 {
 	int dev = chip->dev_index;
@@ -1717,6 +1754,9 @@ static int azx_first_init(struct azx *chip)
 	if (chip->pci->vendor == PCI_VENDOR_ID_AMD)
 		dma_bits = 40;
 
+	if (INTEL_IRQ_POST(chip))
+		chip->post_irq = intel_post_irq;
+
 	/* disable SB600 64bit support for safety */
 	if (chip->pci->vendor == PCI_VENDOR_ID_ATI) {
 		struct pci_dev *p_smbus;
-- 
1.9.1

             reply	other threads:[~2016-02-22  7:44 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-22  7:39 libin.yang [this message]
2016-02-22  8:43 ` [RFC: PATCH] ALSA: hda - clear IRQ statu twice on some Intel platforms Takashi Iwai
2016-02-23  8:57   ` Yang, Libin
2016-02-23  9:28     ` Takashi Iwai
2016-02-23 14:27       ` Yang, Libin
2016-02-23 15:04         ` Takashi Iwai
2016-02-26  5:22           ` Yang, Libin
2016-02-26  7:51             ` Takashi Iwai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1456126790-13480-1-git-send-email-libin.yang@linux.intel.com \
    --to=libin.yang@linux.intel.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=libin.yang@intel.com \
    --cc=mengdong.lin@intel.com \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.