The netif queue is restarted not before the CAN error state
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 recovery from error passive state due to no ack/cable (reconnect
after 5s) for a MSCAN on a MPC5200 SOC:
(000.203990) can2 31 [1] 5D
(000.204007) can2 20000204 [8] 00 08 00 00 00 00 00 00 ERRORFRAME
controller-problem{tx-error-warning}
state-change{tx-error-warning}
(000.000842) can2 20000240 [8] 00 00 00 00 00 00 00 00 ERRORFRAME
bus-off
state-change{}
(005.010926) can2 20000100 [8] 00 00 00 00 00 00 00 00 ERRORFRAME
restarted-after-bus-off
(000.002880) can2 20000200 [8] 00 40 00 00 00 00 00 00 ERRORFRAME
state-change{back-to-error-active}
(000.085464) can2 4B [8] 14 EF 5E D3 43 84 7C 87
And for a MSCAN on a MPC5121 SOC:
(000.204131) can0 36 [8] 3B ED 98 76 48 33 1A 13
(000.203927) can0 20000204 [8] 00 20 00 00 00 00 94 00 ERRORFRAME
controller-problem{tx-error-passive}
state-change{tx-error-passive}
error-counter-tx-rx{{148}{0}}
(000.000828) can0 20000240 [8] 00 00 00 00 00 00 7F 00 ERRORFRAME
bus-off
state-change{}
error-counter-tx-rx{{127}{0}}
(005.006905) can0 20000100 [8] 00 00 00 00 00 00 7F 00 ERRORFRAME
restarted-after-bus-off
error-counter-tx-rx{{127}{0}}
(000.003043) can0 20000200 [8] 00 40 00 00 00 00 00 00 ERRORFRAME
state-change{back-to-error-active}
(000.089262) can0 50 [6] 12 3E 5B 23 15 68
Signed-off-by: Wolfgang Grandegger <[email protected]>
---
drivers/net/can/mscan/mscan.c | 7 +++++--
drivers/net/can/sja1000/sja1000.c | 7 +++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index e9e6b14..0762093 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -180,7 +180,6 @@ static int mscan_restart(struct net_device *dev)
if (priv->type == MSCAN_TYPE_MPC5121) {
struct mscan_regs __iomem *regs = priv->reg_base;
- priv->can.state = CAN_STATE_ERROR_ACTIVE;
WARN(!(in_8(®s->canmisc) & MSCAN_BOHOLD),
"bus-off state expected\n");
out_8(®s->canmisc, MSCAN_BOHOLD);
@@ -374,8 +373,12 @@ static void mscan_get_err_frame(struct net_device *dev,
struct can_frame *frame,
setbits8(®s->canctl0,
MSCAN_SLPRQ | MSCAN_INITRQ);
}
+ netif_stop_queue(dev);
can_bus_off(dev);
}
+ /* Restart TX queue after recovered from bus-off */
+ if (priv->can.state == CAN_STATE_BUS_OFF)
+ netif_wake_queue(dev);
can_change_state(dev, frame, state, err_dir);
}
priv->shadow_statflg = canrflg & MSCAN_STAT_MSK;
@@ -507,7 +510,7 @@ static int mscan_do_set_mode(struct net_device *dev, enum
can_mode mode)
ret = mscan_restart(dev);
if (ret)
break;
- if (netif_queue_stopped(dev))
+ if (priv->can.state != CAN_STATE_BUS_OFF)
netif_wake_queue(dev);
break;
diff --git a/drivers/net/can/sja1000/sja1000.c
b/drivers/net/can/sja1000/sja1000.c
index 29af651..e70a966 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -166,7 +166,6 @@ static void sja1000_start(struct net_device *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;
}
@@ -458,8 +457,12 @@ static int sja1000_err(struct net_device *dev, uint8_t
isrc, uint8_t status)
cf->data[0] = alc & 0x1f;
}
- if (state != priv->can.state)
+ if (state != priv->can.state) {
+ /* Restart TX queue after recovered from bus-off */
+ if (priv->can.state == CAN_STATE_BUS_OFF)
+ netif_wake_queue(dev);
can_change_state(dev, cf, state, CAN_ERR_DIR_UNKNOWN);
+ }
netif_rx(skb);
--
1.7.4.1
_______________________________________________
Socketcan-users mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/socketcan-users