Always stop device when CAN_STATE_BUS_OFF is entered because the restart is issued automatically through can.do_set_mode depending on restart-ms. Otherwise the device re-enters CAN_STATE_ERROR_ACTIVE automatically after "128 occurences of 11 consecutive recessive bits". Also fixes potential race condition by resetting force_quit before enabling interrupts. Signed-off-by: Timo Schlüßler <schluessler@xxxxxxxxx> --- drivers/net/can/spi/mcp251x.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index f569fd4..6f359df 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -485,10 +485,10 @@ static int mcp251x_do_set_mode(struct net_device *net, enum can_mode mode) case CAN_MODE_START: mcp251x_clean(net); /* We have to delay work since SPI I/O may sleep */ + if (priv->can.state == CAN_STATE_BUS_OFF) + priv->after_suspend = AFTER_SUSPEND_RESTART; priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->restart_tx = 1; - if (priv->can.restart_ms == 0) - priv->after_suspend = AFTER_SUSPEND_RESTART; queue_work(priv->wq, &priv->restart_work); break; default: @@ -716,6 +716,7 @@ static void mcp251x_restart_work_handler(struct work_struct *ws) if (priv->after_suspend) { mcp251x_hw_reset(spi); mcp251x_setup(net, spi); + priv->force_quit = 0; if (priv->after_suspend & AFTER_SUSPEND_RESTART) { mcp251x_set_normal_mode(spi); } else if (priv->after_suspend & AFTER_SUSPEND_UP) { @@ -727,7 +728,6 @@ static void mcp251x_restart_work_handler(struct work_struct *ws) mcp251x_hw_sleep(spi); } priv->after_suspend = 0; - priv->force_quit = 0; } if (priv->restart_tx) { @@ -845,13 +845,11 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) } if (priv->can.state == CAN_STATE_BUS_OFF) { - if (priv->can.restart_ms == 0) { - priv->force_quit = 1; - priv->can.can_stats.bus_off++; - can_bus_off(net); - mcp251x_hw_sleep(spi); - break; - } + priv->force_quit = 1; + priv->can.can_stats.bus_off++; + can_bus_off(net); + mcp251x_hw_sleep(spi); + break; } if (intf == 0) -- 2.7.2