Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 150
ASoC: SOF: intel: fix issues in hda irq handling#1011
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -462,36 +462,32 @@ irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) | ||
| { | ||
| struct hdac_bus *bus = context; | ||
| struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); | ||
| u32 stream_mask; | ||
| int ret = IRQ_NONE; | ||
| u32 status; | ||
| if (!pm_runtime_active(bus->dev)) | ||
| return IRQ_NONE; | ||
| spin_lock(&bus->reg_lock); | ||
| status = snd_hdac_chip_readl(bus, INTSTS); | ||
| stream_mask = GENMASK(sof_hda->stream_max - 1, 0) | AZX_INT_CTRL_EN; | ||
| /* Not stream interrupt or register inaccessible, ignore it.*/ | ||
| if (!(status & stream_mask) || status == 0xffffffff) { | ||
| /* Register inaccessible, ignore it.*/ | ||
| if (status == 0xffffffff) { | ||
| spin_unlock(&bus->reg_lock); | ||
| return IRQ_NONE; | ||
| return ret; | ||
Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto | ||
| } | ||
| #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) | ||
| /* clear rirb int */ | ||
| status = snd_hdac_chip_readb(bus, RIRBSTS); | ||
| if (status & RIRB_INT_MASK) { | ||
| if (status & RIRB_INT_RESPONSE) | ||
| snd_hdac_bus_update_rirb(bus); | ||
| snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); | ||
| if (status & AZX_INT_CTRL_EN) { | ||
kv2019i marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. kv2019i marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_CTRL_EN, 0); | ||
| ret = IRQ_WAKE_THREAD; | ||
| } | ||
| #endif | ||
| if (status & GENMASK(sof_hda->stream_max - 1, 0)) | ||
| ret = IRQ_WAKE_THREAD; | ||
| spin_unlock(&bus->reg_lock); | ||
| return snd_hdac_chip_readl(bus, INTSTS) ? IRQ_WAKE_THREAD : IRQ_HANDLED; | ||
| return ret; | ||
| } | ||
| irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) | ||
| @@ -500,6 +496,7 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) | ||
| struct sof_intel_hda_dev *sof_hda = bus_to_sof_hda(bus); | ||
| u32 status = snd_hdac_chip_readl(bus, INTSTS); | ||
| struct hdac_stream *s; | ||
| u32 rirb_status; | ||
| u32 sd_status; | ||
| /* check streams */ | ||
| @@ -524,6 +521,17 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context) | ||
| } | ||
| } | ||
| /* unmask 2nd level CTRL_EN (CIS) before clearing 1st level RIRBSTS */ | ||
| snd_hdac_chip_updatel(bus, INTCTL, AZX_INT_CTRL_EN, 1); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. does this make sense to unmask before clearing the interrupts? CollaboratorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @plbossart This is on purpose. Clearing RIRBSTS bits will cause hardware to create a new interrupt and we want to allow this to happen by unmasking the CTRL_EN first. Collaborator There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. | ||
| /* clear rirb int */ | ||
| rirb_status = snd_hdac_chip_readb(bus, RIRBSTS); | ||
| if (rirb_status & RIRB_INT_MASK) { | ||
| if (rirb_status & RIRB_INT_RESPONSE) | ||
| snd_hdac_bus_update_rirb(bus); | ||
| snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK); | ||
| } | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All of this should be protected by an #ifdef SOF_HDA CollaboratorAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @plbossart Ack. | ||
| return IRQ_HANDLED; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep for RIRB but for stream events its' not really possible to get stream interrupts without being in pm_runtime_active, is it? Do we want to remove this completely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
agree that we should just move it to after the RIRB status check. And also just fyi that this doesnt fix our IPC timeout issues still.