Skip to content

[RFC] ASoC: SOF: merge ipc and stream irq - #1483

Merged
plbossart merged 1 commit into
thesofproject:topic/sof-devfrom
bardliao:merge-ipc-stream-irq
Nov 21, 2019
Merged

plbossart merged 1 commit into
thesofproject:topic/sof-devfrom
bardliao:merge-ipc-stream-irq

Conversation

@bardliao

Copy link
Copy Markdown
Collaborator

We may lost interrupt on MSI mode if two interrupts are triggered at
the same time. Use single handler and check both interrupts can avoid
that.

Signed-off-by: Bard Liao yung-chuan.liao@linux.intel.com

Comment thread sound/soc/sof/intel/hda.c Outdated
irqreturn_t hda_dsp_interrupt_handler(int irq, void *context)
{
if ((hda_dsp_ipc_irq_handler(irq, context) == IRQ_WAKE_THREAD) ||
(hda_dsp_stream_interrupt(irq, context) == IRQ_WAKE_THREAD))

@RanderWang RanderWang Nov 14, 2019 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about to change hda_dsp_stream_interrupt to hda_dsp_stream_irq_handler like hda_dsp_ipc_irq_handler

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @RanderWang . I renamed them to is_stream_irq() and is_ipc_irq()

@plbossart plbossart left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @bardliao, looks mostly good, I suggested some improvements to make the code more readable.

Comment thread sound/soc/sof/intel/hda.c Outdated
irqreturn_t hda_dsp_interrupt_handler(int irq, void *context)
{
if ((hda_dsp_ipc_irq_handler(irq, context) == IRQ_WAKE_THREAD) ||
(hda_dsp_stream_interrupt(irq, context) == IRQ_WAKE_THREAD))

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change the return type of those functions to a boolean, e.g.

if (hda_dsp_check_ipc_irq(irq, context) || 
    hda_dsp_check_stream_irq(irq, context))
        return IRQ_WAKE_THREAD;

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plbossart Done. But I add a new function instead of changing hda_dsp_ipc_irq_handler() since it is used in somewhere else.


spin_lock(&sdev->hw_lock);
/* The function can be called at irq thread, so use spin_lock_irq */
spin_lock_irq(&sdev->hw_lock);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question:
I can never remember the rules for spin_locks.

Do we need to protect with the _irq suffix only here, or also in the thread?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it has to be protected with _irq in the thread and not necessarily in the IRQ handler (you'd use _irq if you're not 100% certain the code runs only in IRQ handlers). IIRC, that is.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @paulstelian97 for the explanation . @plbossart hda_dsp_ipc_irq_handler() will be called in the irq thread that's why I add the _irq suffix here. But actually I don't know if we do need the spin_lock or not. @RanderWang discussed it with me about it, but we didn't have a conclusion.

Comment thread sound/soc/sof/intel/hda-ipc.c Resolved
@bardliao

ghost commented Nov 15, 2019

Copy link
Copy Markdown
Collaborator Author

I use work in hda_dsp_interrupt_threaded() since we want to handle different interrupt in parallel. And it can prevent one is blocked by the other.

Comment thread sound/soc/sof/intel/hda-stream.c Outdated
struct hdac_bus *bus = context;
int ret = IRQ_WAKE_THREAD;
struct hdac_bus *bus = sof_to_bus(sdev);
int ret = true;

ghost Nov 18, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bool

Comment thread sound/soc/sof/intel/hda-ipc.c Outdated

bool is_ipc_irq(struct snd_sof_dev *sdev)
{
if (hda_dsp_ipc_irq_handler(0, sdev) == IRQ_WAKE_THREAD)

ghost Nov 18, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't you remove this function and do all the work here?
Why is a wrapper needed with a first parameter 0 that seems useless?

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I just want to reuse the code. Yes, I can remove that function.

Comment thread sound/soc/sof/intel/hda.c Outdated
struct snd_sof_dev *sdev =
container_of(work, struct snd_sof_dev, stream_work);

hda_dsp_stream_threaded_handler(0, sdev);

ghost Nov 18, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is really odd, you are not using the first argument 0?

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the first argument is never used.

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao a general comment about the naming of the functions. We should only call the hard interrupt handler as somthing_thread_handler(), the thread itself should just be called irq_thread or the stream_thread

Comment thread sound/soc/sof/intel/hda.c Outdated
struct snd_sof_dev *sdev =
container_of(work, struct snd_sof_dev, ipc_work);

sof_ops(sdev)->irq_thread(0, sdev);

ghost Nov 18, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this meant to handle the APL/CNL difference only?

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, currently, hda_dsp_probe() is for APL/CNL only and they have different .irq_thread.

@bardliao
bardliao force-pushed the merge-ipc-stream-irq branch from 6c13c11 to 905d11a Compare November 19, 2019 05:42
Comment thread sound/soc/sof/intel/hda.c Outdated
if (is_ipc_irq(sdev))
schedule_work(&sdev->ipc_work);
if (is_stream_irq(sdev))
schedule_work(&sdev->stream_work);

ghost Nov 19, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao why we need to process interrupt in second level scheduled work ? hda_dsp_interrupt_threaded is in a work scheduled by interrupt framework.

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RanderWang hda_dsp_stream_threaded_handler() could take a long time, and we don't wan't one threaded handler to wait for the other. Besides, we may want to use loop on each threaded handler in the future.

ghost Nov 19, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RanderWang has a point though.what would happen if we didn't not use a threaded handler, and called schedule_work directly from the handler?

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao I'm a bit concerned about this as well. We are essentially adding two mandatory context switches for every interrupt. First from hard-irq to irq thread, and then from irq thread to work-queue. Do you have concrete logs showing that the threaded handler is taking a lot of time?

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also agree that this seems a bit of an overkill. Instead we should just wake the appropriate thread in the handler based on is_ipc_irq() or is_stream_irq() is true.

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you all. Yes, it would be better to wake the appropriate thread in the handler.

ghost Nov 20, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RanderWang hda_dsp_stream_threaded_handler() could take a long time, and we don't wan't one threaded handler to wait for the other. Besides, we may want to use loop on each threaded handler in the future.

Actually, the two works are still scheduled on the same CPU because scheduler is designed to utilize cache data (please check scheduler documents), so this can't save time and spend extra time to schedule work.

ghost Nov 20, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@RanderWang has a point though.what would happen if we didn't not use a threaded handler, and called schedule_work directly from the handler?

We should follow the requirement of request_threaded_irq
please check the comments for request_threaded_irq in kernel.

 *	If you want to set up a threaded irq handler for your device
 *	then you need to supply @handler and @thread_fn. @handler is
 *	still called in hard interrupt context and has to check
 *	whether the interrupt originates from the device. If yes it
 *	needs to disable the interrupt on the device and return
 *	IRQ_WAKE_THREAD which will wake up the handler thread and run
 *	@thread_fn. This split handler design is necessary to support
 *	shared interrupts.

ghost Nov 20, 2019 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this was a completely dumb comment from me. Oops :-)
I think what I was trying to say if whether the same handler can trigger multiple threads, but that seems like asking for trouble.

ghost left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As overall design, I think this is the way to go. I have some concerns on the specific implementation, see comments inline.

ret = false;

spin_unlock(&bus->reg_lock);
spin_unlock_irq(&bus->reg_lock);

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit asymmetric in that is_ipc() function disabled IPC interrupts in this check, while this function does not disable the interrupt source? Why is this?

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question. I think we should disable it as well, but we can do it in another PR.

ghost Nov 20, 2019

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, please check the comments for request_threaded_irq

If yes it needs to disable the interrupt on the device and return IRQ_WAKE_THREAD which will wake up the handler thread and run @thread_fn. This split handler design is necessary to support shared interrupts.

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack @bardliao and @RanderWang This is matching existing code, so I'm ok to change in another PR. I do have a comment on naming the is_ipc_irq() functions (see my other comment).

Comment thread sound/soc/sof/intel/hda.c
"AudioDSP", sdev);
ret = request_threaded_irq(sdev->ipc_irq, hda_dsp_interrupt_handler,
hda_dsp_interrupt_threaded,
IRQF_SHARED, "AudioDSP", sdev);

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao Shouldn't this patch remove hda_dsp_ipc_irq_handler as well?

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hda_dsp_ipc_irq_handler is assigned to cnl and apl's irq_handler ops. But no one uses it. So, yes, we can remove hda_dsp_ipc_irq_handler as well.

Comment thread sound/soc/sof/intel/hda.c Outdated
if (is_ipc_irq(sdev))
schedule_work(&sdev->ipc_work);
if (is_stream_irq(sdev))
schedule_work(&sdev->stream_work);

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao I'm a bit concerned about this as well. We are essentially adding two mandatory context switches for every interrupt. First from hard-irq to irq thread, and then from irq thread to work-queue. Do you have concrete logs showing that the threaded handler is taking a lot of time?

u32 irq_status;

/* The function can be called at irq thread, so use spin_lock_irq */
spin_lock_irq(&sdev->hw_lock);

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao I'm not sure about this. I dont think we need to use spin_lock_irq(). Back when we're still upstreaming the SOF driver, IIRC the comment upstream was that spin_lock_irq() should only be in the hard interrupt handler.

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. I will double check it.

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ranj063 I can see spin_lock() is called twice without spin_unlock() if I test it with spin_lock() instead of spin_lock_irq(). I think the reason is that the irq did not be disabled when we use spin_lock() and the irq handler could be triggered when the irq thread is still running. Also, spin_lock_irq() is using in hda_dsp_stream_threaded_handler() which is a irq thread actually. So I believe that we should use spin_lock_irq()

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao @ranj063 You definitely need to use the "_irq()" variant here. These is_xxx_irq() functions are called both from hard-irq and softirq context, so plain spin_lock() will not work.

Comment thread sound/soc/sof/intel/hda.c
hdev->irq = pci_irq_vector(pci, 0);
/* ipc irq number is the same of hda irq */
sdev->ipc_irq = hdev->irq;
sdev->ipc_irq = pci_irq_vector(pci, 0);

ghost Nov 19, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao if this is a common irq, we should consider renaming it to maybe just irq?

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I also think about it. However, for those platforms without HDA, the irq is still for ipc only. That's why I leave it as it is for now.

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao even in that case it makes sense to rename it to something else. Maybe in another PR

@ranj063

ghost commented Nov 19, 2019

Copy link
Copy Markdown
Collaborator

@bardliao there was specific change we made in the stream interrupt handler to handled unsolicited responses from the HDA codecs (ie looping 10 times) and checking INTSTS. This is was fixed the IPC timeouts for us. Now, in this PR, you are suggesting moving it to the IRQ thread. I'm a bit concerned this could cause regressions though.

@plbossart

ghost commented Nov 20, 2019 •

Copy link
Copy Markdown
Member

@bardliao there was specific change we made in the stream interrupt handler to handled unsolicited responses from the HDA codecs (ie looping 10 times) and checking INTSTS. This is was fixed the IPC timeouts for us. Now, in this PR, you are suggesting moving it to the IRQ thread. I'm a bit concerned this could cause regressions though.

that was already done in the interrupt thread, but now it'd be moved to a workqueue and indeed this could impact the results

Since we are moving to a single thread, I wonder if the simple thing to do is to sequentially deal with IPC, then stream, then SoundWire (without using schedule_work as suggested so far). In the latter case, we actually use a work-queue already so there wouldn't be any change performance-wise. Also the peak times for interrupts don't overlap. For the firmware setup, we have a slew of IPC, but they happen before SoundWire kicks in. then we have stream interrupts while the flows are setup. It's not completely random, the control parts peak before the streaming.

The only change would come from the serialization of IPC and stream interrupts, but that doesn't look so bad to me.

@ranj063

ghost commented Nov 20, 2019

Copy link
Copy Markdown
Collaborator

that was already done in the interrupt thread, but now it'd be moved to a workqueue and indeed this could impact the results

@plbossart I am talking about this part:

for (i = 0, active = true; i < 10 && active; i++) {

This is still done in the handler and not in the thread. But with @bardliao 's changes this would be moved to the workqueue or if he changes it to the interrupt thread, either way I feel like this could cause a regression

@plbossart

ghost commented Nov 20, 2019

Copy link
Copy Markdown
Member

that was already done in the interrupt thread, but now it'd be moved to a workqueue and indeed this could impact the results

@plbossart I am talking about this part:

for (i = 0, active = true; i < 10 && active; i++) {

This is still done in the handler and not in the thread. But with @bardliao 's changes this would be moved to the workqueue or if he changes it to the interrupt thread, either way I feel like this could cause a regression

nope, the handler is here:

irqreturn_t hda_dsp_stream_interrupt(int irq, void *context)

@ranj063

ghost commented Nov 20, 2019

Copy link
Copy Markdown
Collaborator

that was already done in the interrupt thread, but now it'd be moved to a workqueue and indeed this could impact the results

@plbossart I am talking about this part:

for (i = 0, active = true; i < 10 && active; i++) {

This is still done in the handler and not in the thread. But with @bardliao 's changes this would be moved to the workqueue or if he changes it to the interrupt thread, either way I feel like this could cause a regression

nope, the handler is here:

irqreturn_t hda_dsp_stream_interrupt(int irq, void *context)

duh! yes you are correct @plbossart. the name threw me off a bit. In this case, if we dont use the workqueue, we should be fine I think

@RanderWang

ghost commented Nov 20, 2019

Copy link
Copy Markdown

duh! yes you are correct @plbossart. the name threw me off a bit. In this case, if we dont use the workqueue, we should be fine I think

yes, I was also confused. handler and thread are official name for request_threaded_irq, no thread- handler

@bardliao

ghost commented Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

duh! yes you are correct @plbossart. the name threw me off a bit. In this case, if we dont use the workqueue, we should be fine I think

yes, I was also confused. handler and thread are official name for request_threaded_irq, no thread- handler

@RanderWang @ranj063 We can rename it in another patch :)

@bardliao

ghost commented Nov 20, 2019

Copy link
Copy Markdown
Collaborator Author

@bardliao there was specific change we made in the stream interrupt handler to handled unsolicited responses from the HDA codecs (ie looping 10 times) and checking INTSTS. This is was fixed the IPC timeouts for us. Now, in this PR, you are suggesting moving it to the IRQ thread. I'm a bit concerned this could cause regressions though.

that was already done in the interrupt thread, but now it'd be moved to a workqueue and indeed this could impact the results

Since we are moving to a single thread, I wonder if the simple thing to do is to sequentially deal with IPC, then stream, then SoundWire (without using schedule_work as suggested so far). In the latter case, we actually use a work-queue already so there wouldn't be any change performance-wise. Also the peak times for interrupts don't overlap. For the firmware setup, we have a slew of IPC, but they happen before SoundWire kicks in. then we have stream interrupts while the flows are setup. It's not completely random, the control parts peak before the streaming.

The only change would come from the serialization of IPC and stream interrupts, but that doesn't look so bad to me.

ok. Let's go with sequentially dealing with IPC, stream, and SoundWire first and see if everything works fine. :)

@RanderWang

ghost commented Nov 20, 2019

Copy link
Copy Markdown

There is a potential risk to schedule work in thread function. For kernel, if thread function returns, interrupt frame work assumes all job has been done so another thread maybe invoked. But are the scheduled work done ? Do we need to sync all the scheduled works ? can anyone answer this question?

ghost left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starts to look good. I don't have any major concerns open. I'd like to hear your comments on the function naming, but otherwise I'm ready to press approve on this.

u32 irq_status;

/* The function can be called at irq thread, so use spin_lock_irq */
spin_lock_irq(&sdev->hw_lock);

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao @ranj063 You definitely need to use the "_irq()" variant here. These is_xxx_irq() functions are called both from hard-irq and softirq context, so plain spin_lock() will not work.

Comment thread sound/soc/sof/intel/hda.c Outdated
{
struct snd_sof_dev *sdev = context;

if (is_ipc_irq(sdev))

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao is_ipc_irq() is called in both hardirq and softirq. This is otherwise ok, but it's a bit odd that is_ipc_irq() also has side-effects in that it clears HDA_DSP_ADSPIC_IPC. I'd prefer to call the function something else than "is_foo_irq()" as to me (maybe just ipc_irq()). To me, a function with is_something(), indicates the function does not have side-effects. The functions here do more.

I guess this still works as the ADSPIS status bit remains high despite ADSPIC set low. And this matches with the current logic we have.

ghost Nov 20, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i I had the same feeling but it's hard to move the mask outside of the spinlock, and taking the spinlock twice, once to read ADSPIC2 and once to clear ADSPIS2 is not that great either.

maybe adding a comment would help explain the hidden side effect.
or rename from is_ipc to check_ipc, which is let of a status return

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @kv2019i @plbossart I will rename it and add a comment.

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kv2019i @plbossart done. BTW, do you know how to disable stream irq? Or we can leave it as it is for now?

ret = false;

spin_unlock(&bus->reg_lock);
spin_unlock_irq(&bus->reg_lock);

ghost Nov 20, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack @bardliao and @RanderWang This is matching existing code, so I'm ok to change in another PR. I do have a comment on naming the is_ipc_irq() functions (see my other comment).

…andlers

The existing code uses two handlers for a shared edge-based MSI interrupts.
In corner cases, interrupts are lost, leading to IPC timeouts. Those
timeouts do not appear in legacy mode.

This patch merges the two handlers into a single one. Follow-up patches
will extend this work to SoundWire interrupts which are also shared with
IPC and stream interrupts.

Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
@bardliao
bardliao force-pushed the merge-ipc-stream-irq branch from 74e85a9 to 93d20ac Compare November 21, 2019 02:05
Comment thread sound/soc/sof/intel/hda.c
hda_dsp_stream_threaded_handler(irq, sdev);

return IRQ_HANDLED;
}

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao this looks bad. You call check_ipc() in the handler, and then wake up the thread and then check_ipc() again and do the same thing over?

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ranj063 Yes, that's odd, but there are more than one interrupt could be trigger and one may be triggered after the handler is checked. So we need to recheck it on the thread. Actually, I think we can have a flag that store the interrupt status which is checked on the handler. So we won't need to double check it on the thread again. Please see hda_dsp_irq_thread

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just return IRQ_WAKE_THREAD in hda_dsp_interrupt_handler() and then handle all the checks in the thread?

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just return IRQ_WAKE_THREAD in hda_dsp_interrupt_handler() and then handle all the checks in the thread?

@ranj063 We can only do it when there is not a shared irq. i.e. No one else could trigger the irq. Probably, we can do that after ipc/stream/sdw irq are merged. And we don't need the handler if it return IRQ_WAKE_THREAD always.

@ClarexZhou

ghost commented Nov 21, 2019

Copy link
Copy Markdown

Run both function and stress tests on below devices. No side effect found.

BYT MinnowBoard BYT MinnowBoard APL UP2 APL UP2 GLK CML Chrome CML_Mantis ICL_RVP
nocodec I2S RT5682 nocodec I2S PCM512x I2S-DA7219 I2S RT5682 HDA ALC3204 HDA ALC700

ghost left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor note on the naming. Can be changed in a follow-up patch is other issues are cleared.

Comment thread sound/soc/sof/intel/hda.h
struct snd_dma_buffer *dmab,
struct hdac_stream *stream);
bool check_ipc(struct snd_sof_dev *sdev);
bool is_stream_irq(struct snd_sof_dev *sdev);

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao I'd have uniform names to this (even if stream irq function is changed in a later patch). E.g. something like:
check_ipc_irq()
check_stream_irq()

ghost Nov 21, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, I'll add an update to fix the naming but we should merge this today since it'll give us one working day to fix things before the week-end.

@plbossart

ghost commented Nov 21, 2019

Copy link
Copy Markdown
Member

SOFCI TEST

@plbossart

ghost commented Nov 21, 2019

Copy link
Copy Markdown
Member

@fredoh9 can you help here, CI seems to be stuck?

struct hdac_bus *bus = context;
int ret = IRQ_WAKE_THREAD;
struct hdac_bus *bus = sof_to_bus(sdev);
bool ret = true;

ghost Nov 21, 2019

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bardliao @plbossart I find this odd the default return value is true. The logic is correct but typically we always assume its false and return true when conditions are favorable.

ghost Nov 21, 2019

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the initial code assumed an IRQ_WAKE_THREAD as default, so it's acceptable to me.

@ranj063

ghost commented Nov 21, 2019

Copy link
Copy Markdown
Collaborator

@plbossart @bardliao this patch looks OK to merge given that its critical for testing but a follow up with minor changes will be needed.

@plbossart

ghost commented Nov 21, 2019

Copy link
Copy Markdown
Member

ok, so no CI today, so will assume things work and move on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants