[linux-yocto] [PATCH 2/3] Handle IRQ storm issue in BXT-M
Guoqing Zhang
guoqing.zhang at intel.com
Thu Dec 8 00:50:12 PST 2016
The IRQ is level triggered in BXT-M which causes a IRQ storm. Disable
IRQ when handling it and re-enable it when done.
Signed-off-by: Guoqing Zhang <guoqing.zhang at intel.com>
---
sound/soc/intel/skylake/skl.c | 32 ++++++++++++++++++++++++++------
1 file changed, 26 insertions(+), 6 deletions(-)
diff --git a/sound/soc/intel/skylake/skl.c b/sound/soc/intel/skylake/skl.c
index cafcec3..55278b5 100644
--- a/sound/soc/intel/skylake/skl.c
+++ b/sound/soc/intel/skylake/skl.c
@@ -117,7 +117,9 @@ static irqreturn_t skl_interrupt(int irq, void *dev_id)
{
struct hdac_ext_bus *ebus = dev_id;
struct hdac_bus *bus = ebus_to_hbus(ebus);
+ u32 mask, int_enable;
u32 status;
+ int ret;
if (!pm_runtime_active(bus->dev))
return IRQ_NONE;
@@ -138,21 +140,40 @@ static irqreturn_t skl_interrupt(int irq, void *dev_id)
snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
}
- spin_unlock(&bus->reg_lock);
- return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED;
+ mask = (0x1 << ebus->num_streams) - 1;
+
+ status = snd_hdac_chip_readl(bus, INTSTS);
+ status &= mask;
+ if (status) {
+ /* Disable stream interrupts; Re-enable in bottom half */
+ int_enable = snd_hdac_chip_readl(bus, INTCTL);
+ snd_hdac_chip_writel(bus, INTCTL, (int_enable & (~mask)));
+ ret = IRQ_WAKE_THREAD;
+ } else
+ ret = IRQ_HANDLED;
+
+ spin_unlock(&bus->reg_lock);
+ return ret;
}
static irqreturn_t skl_threaded_handler(int irq, void *dev_id)
{
struct hdac_ext_bus *ebus = dev_id;
struct hdac_bus *bus = ebus_to_hbus(ebus);
+ u32 mask, int_enable;
u32 status;
-
+ unsigned long flags;
status = snd_hdac_chip_readl(bus, INTSTS);
snd_hdac_bus_handle_stream_irq(bus, status, skl_stream_update);
+ /* Re-enable stream interrupts */
+ mask = (0x1 << ebus->num_streams) - 1;
+ spin_lock_irqsave(&bus->reg_lock, flags);
+ int_enable = snd_hdac_chip_readl(bus, INTCTL);
+ snd_hdac_chip_writel(bus, INTCTL, (int_enable | mask));
+ spin_unlock_irqrestore(&bus->reg_lock, flags);
return IRQ_HANDLED;
}
@@ -160,7 +181,7 @@ static int skl_acquire_irq(struct hdac_ext_bus *ebus, int do_disconnect)
{
struct skl *skl = ebus_to_skl(ebus);
struct hdac_bus *bus = ebus_to_hbus(ebus);
- int ret;
+ int ret =0;
ret = request_threaded_irq(skl->pci->irq, skl_interrupt,
skl_threaded_handler,
@@ -563,7 +584,6 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
int err;
unsigned short gcap;
int cp_streams, pb_streams, start_idx;
-
err = pci_request_regions(pci, "Skylake HD audio");
if (err < 0)
return err;
@@ -619,6 +639,7 @@ static int skl_first_init(struct hdac_ext_bus *ebus)
if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
err = skl_i915_init(bus);
+
if (err < 0)
return err;
}
@@ -694,7 +715,6 @@ static int skl_probe(struct pci_dev *pci,
err = skl_platform_register(bus->dev);
if (err < 0)
goto out_dmic_free;
-
/* create codec instances */
err = skl_codec_create(ebus);
if (err < 0)
--
2.5.0
More information about the linux-yocto
mailing list