A real bus off recovery cycle is triggered by re-setting the init
bit and the netif 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
SJA1000 on an EMS PCI card:

 (000.202225)  can0   5F  [8] 07 B4 4F 67 3A 90 D9 E4
 (000.201285)  can0  20000204  [8] 00 08 00 00 00 00 78 00   ERRORFRAME
        controller-problem{tx-error-warning}
        state-change{tx-error-warning}
        error-counter-tx-rx{{120}{0}}
 (000.003249)  can0  20000240  [8] 00 00 00 00 00 00 00 00   ERRORFRAME
        bus-off
        state-change{}
 (005.015531)  can0  20000100  [8] 00 00 00 00 00 00 7F 00   ERRORFRAME
        restarted-after-bus-off
        error-counter-tx-rx{{127}{0}}
 (000.000133)  can0  20000200  [8] 00 40 00 00 00 00 00 00   ERRORFRAME
        state-change{back-to-error-active}
 (000.031612)  can0   79  [5] 79 85 71 34 7A

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

diff --git a/drivers/net/can/sja1000/sja1000.c 
b/drivers/net/can/sja1000/sja1000.c
index f6a1c74..29af651 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -163,6 +163,13 @@ static void sja1000_start(struct net_device *dev)
 {
        struct sja1000_priv *priv = netdev_priv(dev);
 
+       if (priv->can.state == CAN_STATE_BUS_OFF) {
+               /* trigger bus-off recovery and restart queue */
+               priv->write_reg(priv, REG_MOD, 0x00);
+               netif_wake_queue(dev);
+               return;
+       }
+
        /* leave reset mode */
        if (priv->can.state != CAN_STATE_STOPPED)
                set_reset_mode(dev);
@@ -393,6 +400,7 @@ static int sja1000_err(struct net_device *dev, uint8_t 
isrc, uint8_t status)
 
                if (status & SR_BS) {
                        state = CAN_STATE_BUS_OFF;
+                       netif_stop_queue(dev);
                        can_bus_off(dev);
                } else if (status & SR_ES) {
                        state = CAN_STATE_ERROR_WARNING;
-- 
1.7.4.1

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

Reply via email to