The netdev queue is restarted not before the CAN error state has
returned to error active.

Here is an example output of "candump -candump -td -e any,0:0,#FFFFFFFF"
for a bus-off recovery due to a short circiut (restart after 5s) for a
Flexcan controller on the i.MX28 SOC:

 (000.200433)  can0    D  [4] B5 97 EB 52
 (000.200401)  can0  2000028C  [8] 00 20 08 00 00 00 91 00   ERRORFRAME
        controller-problem{tx-error-passive}
        protocol-violation{{tx-dominant-bit-error}{}}
        bus-error
        state-change{tx-error-passive}
        error-counter-tx-rx{{145}{0}}
 (000.001000)  can0  200002C8  [8] 00 00 08 00 00 00 0E 00   ERRORFRAME
        protocol-violation{{tx-dominant-bit-error}{}}
        bus-off
        bus-error
        state-change{}
        error-counter-tx-rx{{14}{0}}
 (005.006823)  can0  20000100  [8] 00 00 00 00 00 00 00 00   ERRORFRAME
        restarted-after-bus-off
 (000.001063)  can0  20000200  [8] 00 40 00 00 00 00 00 00   ERRORFRAME
        state-change{back-to-error-active}
 (000.006218)  can0   27  [2] 72 F3

Signed-off-by: Wolfgang Grandegger <[email protected]>
---
 drivers/net/can/flexcan.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 73e0597..86b697c 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -376,6 +376,7 @@ static int flexcan_poll_error_state(struct net_device *dev, 
u32 reg_esr)
                new_state = CAN_STATE_ERROR_PASSIVE;
        } else {
                new_state = CAN_STATE_BUS_OFF;
+               netif_stop_queue(dev);
                can_bus_off(dev);
        }
 
@@ -675,7 +676,9 @@ static int flexcan_chip_start(struct net_device *dev)
        reg_mcr &= ~FLEXCAN_MCR_HALT;
        flexcan_write(reg_mcr, &regs->mcr);
 
-       priv->can.state = CAN_STATE_ERROR_ACTIVE;
+       /* If from bus-off, wait for state change to error active */
+       if (priv->can.state != CAN_STATE_BUS_OFF)
+               priv->can.state = CAN_STATE_ERROR_ACTIVE;
 
        /* enable FIFO interrupts */
        flexcan_write(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
@@ -767,6 +770,7 @@ static int flexcan_close(struct net_device *dev)
 
 static int flexcan_set_mode(struct net_device *dev, enum can_mode mode)
 {
+       struct flexcan_priv *priv = netdev_priv(dev);
        int err;
 
        switch (mode) {
@@ -775,7 +779,9 @@ static int flexcan_set_mode(struct net_device *dev, enum 
can_mode mode)
                if (err)
                        return err;
 
-               netif_wake_queue(dev);
+               /* If from bus-off, wait for state change to error active */
+               if (priv->can.state != CAN_STATE_BUS_OFF)
+                       netif_wake_queue(dev);
 
                break;
 
-- 
1.7.4.1

_______________________________________________
Socketcan-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-users

Reply via email to