Repository navigation
Conversation
|
@Keyon the only issues with work queue solution I have is that:
|
|
@keyonjie a question for my understanding: When you say that executing the pcm_elapsed in the stream irq handler will cause the stop ipc to timeout because the IPC interrupts are disabled. Why is that the case? |
|
@keyonjie I guess the general implicit rule we have here is "it is never allowed to call ipc back to dsp from receive message irq handling (deferred or not)" as it will always lead to timeout. Now how to make sure that will not happen? This PR will block the position update path, but is there some other paths we might have? |
|
@ranj063 it is because in irq thread handling we have ipc busy bit enabled (so irq is disabled) and we are calling message send to dsp and waiting for ack (which will not arrive as we have disabled irq). |
|
@ranj063 so problem is that calling alsa core's period elapsed will call pcm_stop depending on stream state (for e.g. draining or xrun) -> this will lead to sending message to dsp in receive irq handler. |
@juimonen Thanks but I still dont get this. We do this for all IPC's isnt it. set busy bit, send message and wait for reply. Whats different here? |
|
@ranj063 So this problematic call is not coming from userspace or kernel, it is coming from our own receive irq handler. Receive irq handler has enabled busy bit and is calling send message and waiting for ack. so we are sleeping with busy bit on -> it means that "don't send us anything because we are busy". I'm not sure about the internal workings: so is the irq just not coming, is the dsp checking the busy bit and not sending. Anyway we should "release" the ipc before sending, otherwise it will result in timeout. |
@juimonen sorry but what is the receive irq_handler? could you tell me the name of the handler? |
|
so for e.g. in intel/byt.c: byt_irq_handler & byt_irq_thread. You can see that byt_host_done (which disables busy bit, says "we're done") is called after snd_sof_ipc_msgs_rx. |
|
@ranjani see above |
I believe the patch can benefit byt also, need a minor patch added(let me do it since I am already here). |
|
@Keyon probably most specific description is that it's from async to async :) We have the quite new threaded irq method, so we are already running in kernel thread context. However reading the linux irq manuals, we are doing it pretty much as supposed to. So clear the interrupt in first handler, then do message copying in deferred thread. This is all clean and fine. It also allowed to sleep in this deferred processing as it is kernel thread context. Problem is that we are clearing the interrupt in linux (so kernel can process) but we are telling dsp with busy bit that you can't send messages. This is also fine, because otherwise we could miss interrupt from dsp (as we are processing previous one). So as I see it the problem is "waiting for receive ack while inside previous receive processing". So far I see your (and mine) solution as the cleanest thing to solve this fast. work queue makes another async call from deferred processing, so we are able to "release" the receive ipc. |
11ecfb5 to
0513cdd
Compare
We do elapse in interrupt context at the moment, this will lead to ipc timeout at trigger stop with some possibility, where the pcm elapse will call trigger stop and the stop ipc will timeout as the ipc interrupt is disabled at this context. Here we introduce a work to do pcm period elapse, and the stress test shows that it fixes this kind of ipc timeout issue. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
Change to use work for pcm elapse, this will fix trigger stop ipc timeout issue on skl+ platforms. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
To fix the trigger stop ipc timeout issue on platforms where uses position update IPCs. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
…ssue We are using share irq for ipc and stream ioc interrupts, we should check and make sure the interrupt is for ipc before we should store it to sdev->irq_status, otherwise, the previous stored one may be changed(to 0 usually) when a consequent ioc interrupt arrives. Here add check to fix that. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
Add stream_total into sof_intel_hda_dev to store the total hda stream number that the platform can support, and initialize it at stream_init. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
… interrupts only There is risk that the stream interrupt handler will take ipc interrupt and return IRQ_HANDLED, this may lead to ipc interrupt missed issue, here refine stream interrupt hanler to handle only its interrupts, to fix this kind of issues. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
To make sure the same new message won't be handled >= 2 times. Todo: maybe this is not needed. Signed-off-by: Keyon Jie <yang.jie@linux.intel.com>
@juimonen I don't worry that as the position update IPC from FW can take even bigger delay, this work mode was what we did before @lyakh's IPC refinement on SKL- platforms, it was proved working fine. OTOH, adding status check and decide defer it or not based on that looks not decent/general. And, in the future, when our IPC 2.0 we change the usage of doorbells to split sending ipc and waiting acknowledge(FW changes might need together). |
|
@keyonjie wrote:
Ok, that's good to know, so maybe ok.
How about detecting that the IPC send is coming from IRQ thread itself and not waiting But how about we only detect the case where we are in the IRQ thread? in_interrupt() did not work, but we could see other means to detect this "loop back" in IPC TX. I did a quick survey and in these cases, the caller is not doing anything with the response anyways, so waiting for the TX response does not seem to be necessary. If this leads to a big rework as well, then I'd vote for deferring the elapsed calls. |
There was a problem hiding this comment.
This should be split in two series
- deal with the stream/ipc interrupt handling
- deal with period elapsed issues.
Also this does not really explain why we have issues with PulseAudio since PulseAudio does not use period interrupts... Something is very odd in your descriptions.
| return ret; | ||
| } | ||
|
|
||
| /* |
There was a problem hiding this comment.
please update your commit message, it doesn't describe the problem nor why this patch helps.
Some of the English is incorrect, I don't know what 'we do elapse' means, nor what the 'PCM elapse' is.
The explanations are so convoluted it's hard to figure things out.
The additional question is why this belongs in the SOF core?
There was a problem hiding this comment.
yes, let me refine the commit, as you know, I always need to improve my English. :)
This belongs to SOF PCM core, not only for DPIB mode, it is similar to sof/ipc.c, SKL- or any other platforms which using SOF IPC mechanism should use it, you can see it is used in the last commit "ASoC: SOF: ipc: change to use snd_sof_pcm_elapsed() for pcm elapse" for byt/bdw...
| /* new message from DSP */ | ||
| if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY) { | ||
| if (hipctdr & CNL_DSP_REG_HIPCTDR_BUSY && | ||
| hipcctl & CNL_DSP_REG_HIPCCTL_BUSY) { |
There was a problem hiding this comment.
no, we've been there before. The hipcctl register controls the generation of the interrupt, so it's useless to test in the interrupt if the interrupt is enabled. NAK on this one.
There was a problem hiding this comment.
let me remove this commit after some experiments here, as written in the commit message, this may be not needed.
| /* mask BUSY interrupt */ | ||
| snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, | ||
| HDA_DSP_REG_HIPCCTL, | ||
| HDA_DSP_REG_HIPCCTL_BUSY, 0); |
| @@ -433,15 +433,23 @@ int hda_dsp_stream_hw_params(struct snd_sof_dev *sdev, | |||
| irqreturn_t hda_dsp_stream_interrupt(int irq, void *context) | |||
There was a problem hiding this comment.
fix your commit message
ASoC: SOF: Intel: hda-stream: handle real stream interrupts only
The stream and IPC share the same interrupt. The stream interrupt handler mistakenly uses the ipc interrupt
and return IRQ_HANDLED, causing the ipc interrupt to be missed.
Make sure the stream interrupt handler only deals with stream-related interrupts.
| u32 status; | ||
|
|
||
| dev_vdbg(bus->dev, "stream irq, INTSTS status: 0x%x\n", | ||
| snd_hdac_chip_readl(bus, INTSTS)); |
There was a problem hiding this comment.
is this necessary? If you add a log, then better add a log of the wrong interrupt being discarded
There was a problem hiding this comment.
I hit and debug these issues several rounds, so I want to add a verbose log here for the developer, print out the whole register here is good enough for the developer, it has several bits, the developer need to refer to spec to understand it fully.
| /* Inform ALSA only in case not do that with IPC */ | ||
| if (sof_hda->no_ipc_position) | ||
| snd_pcm_period_elapsed(s->substream); | ||
| snd_sof_pcm_elapsed(s->substream); |
There was a problem hiding this comment.
I really don't like all this nonsense of no_ipc_position. We are circling on the same problems on how to report the position...
There was a problem hiding this comment.
I can imagine, :) but that has no relationship with this PR, right?
| } | ||
|
|
||
| /* store the total playback + capture stream number */ | ||
| sof_hda->stream_total = num_total; |
There was a problem hiding this comment.
why is this needed? You don't use this information for anything in this patch set?
There was a problem hiding this comment.
it is used in the consequent stream interrupt refining one, to configure the correct bit mask for interrupt.
There was a problem hiding this comment.
somehow your commits are not in the right order in GitHub? It makes the reviews really hard...
| @@ -500,6 +500,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev) | |||
| struct hdac_ext_stream *stream; | |||
There was a problem hiding this comment.
add and strore hda stream number
s/strore/store
@kv2019i I am not quite high on this idea. I believe it is doable in that way, for example, add a new flag like no_wait to sof_ipc_tx_message(), and pass with no_wait=1 for all PCM trigger IPCs(or only for trigger stop). But what I concern with that is it might lead to kinds of issues with consequent IPCs, e.g. the next IPC TX might fail if it comes fast enough right after this as we are still in holding to the doorbells, it is also a challenge for FW, it is still in handling of trigger stop to the current PCM, but ALSA think it is already stopped, the response to that ALSA sending other IPCs to it(e.g. a new trigger start, or free) might be unpredictable.
|
Sure, it is easy to do that as they are already split into different commits.
wrt Pulseaudio IPC timeout issues, I haven't debugged or checked if this series can fix that, the stream/ipc interrupt handling part might improve it, though the period elapsed part not. |
|
@keyonjie @plbossart Today's test on customer CML laptop and WHL (HD-A) RVP showed that thesofproject/sof#1254 cannot be reproduced with this PR, and we can do simultaneous playback of 3 streams and capture of 3 streams, no sound distortion. |
it's good news but comments need to be addressed and we need two approvers, so mechanically this PR is delayed until next Tuesday with the long week-end. Please be mindful of time zones, vacations and reviewer availability when you want a PR merged... |
sure, let me do that ASAP. BTW, @plbossart do you prefer splitting this to 2 PRs or 1 PR with split commits is fine? |
juimonen
left a comment
There was a problem hiding this comment.
@keyonjie address @plbossart comments and LGTM. My approval is mostly on the work queue issue, and to me (thinking/debugging this for 2 days), this solution seems to be the best/easiest/cleanest thing to do (before bigger ipc refactoring).
2 PRs please. Also make sure you follow the convention ASoC: SOF: Intel:... for Intel stuff and ASoC: SOF for the rest. ASoC: SOF: hda-ipc is not quite correct. |
|
OK, then let me close this then. |
|
the PR is split into #849 and #850, @plbossart @juimonen @kv2019i please help review. Thanks. |
Several fixes here: