Skip to content

Commit

Permalink
can: mcp251x: fix deadlock if an interrupt occurs during mcp251x_open
Browse files Browse the repository at this point in the history
The mcp251x_hw_wake() function is called with the mpc_lock mutex held and
disables the interrupt handler so that no interrupts can be processed while
waking the device. If an interrupt has already occurred then waiting for
the interrupt handler to complete will deadlock because it will be trying
to acquire the same mutex.

CPU0                           CPU1
----                           ----
mcp251x_open()
 mutex_lock(&priv->mcp_lock)
  request_threaded_irq()
                               <interrupt>
                               mcp251x_can_ist()
                                mutex_lock(&priv->mcp_lock)
  mcp251x_hw_wake()
   disable_irq() <-- deadlock

Use disable_irq_nosync() instead because the interrupt handler does
everything while holding the mutex so it doesn't matter if it's still
running.

Fixes: 8ce8c0a ("can: mcp251x: only reset hardware as required")
Signed-off-by: Simon Arlott <[email protected]>
Reviewed-by: Przemek Kitszel <[email protected]>
Cc: [email protected]
Link: https://lore.kernel.org/all/4fc08687-1d80-43fe-9f0d-8ef8475e75f6@0882a8b5-c6c3-11e9-b005-00805fc181fe.uuid.home.arpa
Signed-off-by: Marc Kleine-Budde <[email protected]>
  • Loading branch information
nomis authored and Joshua-Riek committed Oct 7, 2024
1 parent dac0115 commit 41960e0
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion drivers/net/can/spi/mcp251x.c
Original file line number Diff line number Diff line change
Expand Up @@ -752,7 +752,7 @@ static int mcp251x_hw_wake(struct spi_device *spi)
int ret;

/* Force wakeup interrupt to wake device, but don't execute IST */
disable_irq(spi->irq);
disable_irq_nosync(spi->irq);
mcp251x_write_2regs(spi, CANINTE, CANINTE_WAKIE, CANINTF_WAKIF);

/* Wait for oscillator startup timer after wake up */
Expand Down

0 comments on commit 41960e0

Please sign in to comment.