-
Notifications
You must be signed in to change notification settings - Fork 140
[TEST][ [RFC] ASoC: SOF: Intel: hda: use global interrupt enable/disable #1547
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -406,9 +406,20 @@ static irqreturn_t hda_dsp_interrupt_handler(int irq, void *context) | |
| { | ||
| struct snd_sof_dev *sdev = context; | ||
|
|
||
| if (hda_dsp_check_ipc_irq(sdev) || | ||
| hda_dsp_check_stream_irq(sdev)) | ||
| /* clear flags for interrupt sources */ | ||
| sdev->irq_event = 0; | ||
|
|
||
| if (hda_dsp_check_stream_irq(sdev) || | ||
| hda_dsp_check_ipc_irq(sdev)) { | ||
|
|
||
| /* disable GIE interrupt */ | ||
| snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, | ||
| SOF_HDA_INTCTL, | ||
| SOF_HDA_INT_GLOBAL_EN, | ||
| 0); | ||
|
|
||
| return IRQ_WAKE_THREAD; | ||
| } | ||
|
|
||
| return IRQ_NONE; | ||
| } | ||
|
|
@@ -417,11 +428,21 @@ static irqreturn_t hda_dsp_interrupt_thread(int irq, void *context) | |
| { | ||
| struct snd_sof_dev *sdev = context; | ||
|
|
||
| if (hda_dsp_check_ipc_irq(sdev)) | ||
| sof_ops(sdev)->irq_thread(irq, sdev); | ||
| if (hda_dsp_check_stream_irq(sdev)) | ||
| /* deal with streams and controller first */ | ||
| if (sdev->irq_event & SOF_HDA_IRQ_STREAM || | ||
| hda_dsp_check_stream_irq(sdev)) | ||
|
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. @plbossart @bardliao I was late to review as this is already merged, but isn't the "irq_event" flag superfluous here when we anyways call the check_foobar_irq() function in the thread?
Member
Author
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. it's a minor optimization, if we know the source needs to be dealt with we don't recheck in the thread. we can remove this if no one thinks it's useful, I didn't share the code upstream yet to allow for additional fixes/improvements. The other point I am not sure about is if we need to use snd_sof_dsp_update_bits() or snd_sof_dsp_update_bits_unlocked() for the GIE changes. it does look like I am using the same hw_lock twice.
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. @kv2019i @plbossart Can we check Global Interrupt Status (GIS) in the handler if we don't use irq_event? Also, we may not need to lock sdev->hw_lock in hda_dsp_check_ipc_irq() any more. I will test it today.
Member
Author
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.
sorry, can you elaborate, I didn't get your question @bardliao
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.
@plbossart Please check #1554 |
||
| hda_dsp_stream_threaded_handler(irq, sdev); | ||
|
|
||
| if (sdev->irq_event & SOF_HDA_IRQ_IPC || | ||
| hda_dsp_check_ipc_irq(sdev)) | ||
| sof_ops(sdev)->irq_thread(irq, sdev); | ||
|
|
||
|
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. @plbossart Sorry for missing this PR originally. Don't we have a race here? I was reviewing #1491 so I went to refresh my memory and re-read #1042 and there are explanations there, why in the IRQ thread the hard interrupt has to be enabled before processing it. If an edge-triggered interrupt hits after the thread has read the status for the last time and before the interrupt is re-enabled, we lose it.
Member
Author
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. the interrupts are disabled before the thread reads the status, and re-enabled after the threads deal with all status, so not sure what race conditions you are seeing. |
||
| /* enable GIE interrupt */ | ||
| snd_sof_dsp_update_bits(sdev, HDA_DSP_HDA_BAR, | ||
| SOF_HDA_INTCTL, | ||
| SOF_HDA_INT_GLOBAL_EN, | ||
| SOF_HDA_INT_GLOBAL_EN); | ||
|
|
||
| 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.
Just note that
hda_dsp_check_ipc_irq()will not be called ifhda_dsp_check_stream_irq()return true. Howeverhda_dsp_check_ipc_irq()will be called inhda_dsp_interrupt_thread()in that case. So, indeed, we don't need to check remaining event in the handler when there is already one event is confirmed.