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.zh...@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 -- _______________________________________________ linux-yocto mailing list linux-yocto@yoctoproject.org https://lists.yoctoproject.org/listinfo/linux-yocto