mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
soundwire: cadence: Clear message complete before signaling waiting thread
Clear the CDNS_MCP_INT_RX_WL interrupt before signaling completion.
This is to prevent the potential race where:
- The main thread is scheduled immediately the completion is signaled,
and starts a new message
- The RX_WL IRQ for this new message happens before sdw_cdns_irq() has
been re-scheduled.
- When sdw_cdns_irq() is re-scheduled it clears the new RX_WL interrupt.
MAIN THREAD | IRQ THREAD
|
_cdns_xfer_msg() |
{ |
write data to FIFO |
wait_for_completion_timeout() |
<BLOCKED> | <---- RX_WL IRQ
| sdw_cdns_irq()
| {
| signal completion
<== RESCHEDULE <==
Handle message completion |
} |
|
Start new message |
_cdns_xfer_msg() |
{ |
write data to FIFO |
wait_for_completion_timeout() |
<BLOCKED> | <---- RX_WL IRQ
==> RESCHEDULE ==>
| // New RX_WL IRQ is cleared before
| // it has been handled.
| clear CDNS_MCP_INTSTAT
| return IRQ_HANDLED;
| }
Before this change, this error message was sometimes seen on kernels
that have large amounts of debugging enabled:
SCP Msg trf timed out
This error indicates that the completion has not been signalled after
500ms.
Signed-off-by: Richard Fitzgerald <rf@opensource.cirrus.com>
Fixes: 956baa1992 ("soundwire: cdns: Add sdw_master_ops and IO transfer support")
Reported-by: Norman Bintang <normanbt@google.com>
Closes: https://issuetracker.google.com/issues/477099834
Reviewed-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.dev>
Link: https://patch.msgid.link/20260310113133.1707288-1-rf@opensource.cirrus.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
b2c9f1d5a7
commit
cbfea84f82
|
|
@ -933,6 +933,14 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
|
|||
|
||||
cdns_read_response(cdns);
|
||||
|
||||
/*
|
||||
* Clear interrupt before signalling the completion to avoid
|
||||
* a race between this thread and the main thread starting
|
||||
* another TX.
|
||||
*/
|
||||
cdns_writel(cdns, CDNS_MCP_INTSTAT, CDNS_MCP_INT_RX_WL);
|
||||
int_status &= ~CDNS_MCP_INT_RX_WL;
|
||||
|
||||
if (defer && defer->msg) {
|
||||
cdns_fill_msg_resp(cdns, defer->msg,
|
||||
defer->length, 0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user