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
has returned below bus-off (passive, warning or 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 an
Intel 82527 on a TQM855L board:
(000.201120) can0 88 [8] 31 33 FE 45 58 C2 08 FE
(000.200637) can0 2000020C [8] 00 0C 08 00 00 00 00 00 ERRORFRAME
controller-problem{rx-error-warning,tx-error-warning}
protocol-violation{{tx-dominant-bit-error}{}}
state-change{rx-error-warning,tx-error-warning}
(000.001016) can0 20000248 [8] 00 00 08 00 00 00 00 00 ERRORFRAME
protocol-violation{{tx-dominant-bit-error}{}}
bus-off
state-change{}
(005.007273) can0 20000100 [8] 00 00 00 00 00 00 00 00 ERRORFRAME
restarted-after-bus-off
(000.003323) can0 20000208 [8] 00 40 08 00 00 00 00 00 ERRORFRAME
protocol-violation{{tx-dominant-bit-error}{}}
state-change{back-to-error-active}
(000.005255) can0 A2 [3] 50 22 B6
Signed-off-by: Wolfgang Grandegger <[email protected]>
---
drivers/net/can/cc770/cc770.c | 24 ++++++++++++++++++++----
1 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index 905a3ca..6d77bbc 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -337,7 +337,16 @@ static void cc770_start(struct net_device *dev)
{
struct cc770_priv *priv = netdev_priv(dev);
- /* leave reset mode */
+ if (priv->can.state == CAN_STATE_BUS_OFF) {
+ /*
+ * Start bus-off recovery cycle by clearing the init
+ * bit and re-enabling the interrupts
+ */
+ cc770_write_reg(priv, control, priv->control_normal_mode);
+ return;
+ }
+
+ /* enter reset mode ? */
if (priv->can.state != CAN_STATE_STOPPED)
set_reset_mode(dev);
@@ -347,10 +356,13 @@ static void cc770_start(struct net_device *dev)
static int cc770_set_mode(struct net_device *dev, enum can_mode mode)
{
+ struct cc770_priv *priv = netdev_priv(dev);
+
switch (mode) {
case CAN_MODE_START:
- netif_wake_queue(dev);
cc770_start(dev);
+ if (priv->can.state != CAN_STATE_BUS_OFF)
+ netif_wake_queue(dev);
break;
default:
@@ -529,6 +541,7 @@ static int cc770_err(struct net_device *dev, u8 status)
/* Disable interrupts */
cc770_write_reg(priv, control, CTRL_INI);
new_state = CAN_STATE_BUS_OFF;
+ netif_stop_queue(dev);
can_bus_off(dev);
} else if (status & STAT_WARN) {
/* Only the CC770 does show error passive */
@@ -541,8 +554,12 @@ static int cc770_err(struct net_device *dev, u8 status)
/* Back to error avtive */
new_state = CAN_STATE_ERROR_ACTIVE;
}
- if (new_state != priv->can.state)
+ if (new_state != priv->can.state) {
+ /* Have we recovered from bus-off? */
+ if (priv->can.state == CAN_STATE_BUS_OFF)
+ netif_wake_queue(dev);
can_change_state(dev, cf, new_state, CAN_ERR_DIR_UNKNOWN);
+ }
lec = status & STAT_LEC_MASK;
if (lec < 7 && lec > 0) {
@@ -757,7 +774,6 @@ static int cc770_open(struct net_device *dev)
/* init and start chip */
cc770_start(dev);
- netif_start_queue(dev);
return 0;
}
--
1.7.4.1
_______________________________________________
Socketcan-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-users