Messages in this thread |  | | Date | Sat, 28 May 2022 09:35:50 +0200 | From | Jimmy Assarsson <> | Subject | Re: [PATCH 06/12] can: kvaser_usb_leaf: Fix TX queue out of sync after restart |
| |
On 5/16/22 15:47, Anssi Hannula wrote: > The TX queue seems to be implicitly flushed by the hardware during > bus-off or bus-off recovery, but the driver does not reset the TX > bookkeeping. > > Despite not resetting TX bookkeeping the driver still re-enables TX > queue unconditionally, leading to "cannot find free context" / > NETDEV_TX_BUSY errors if the TX queue was full at bus-off time. > > Fix that by resetting TX bookkeeping on CAN restart. > > Also, add an explicit queue flush in case some hardware versions do not > do that implicitly.
See comment below regarding this.
> Tested with 0bfd:0124 Kvaser Mini PCI Express 2xHS FW 4.18.778. > > Fixes: 080f40a6fa28 ("can: kvaser_usb: Add support for Kvaser CAN/USB devices") > Signed-off-by: Anssi Hannula <anssi.hannula@bitwise.fi> > --- > drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 2 ++ > drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 2 +- > drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 6 ++++++ > 3 files changed, 9 insertions(+), 1 deletion(-) > > diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h > index 3a49257f9fa6..f1bea13a3829 100644 > --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h > +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h > @@ -175,6 +175,8 @@ struct kvaser_usb_dev_cfg { > extern const struct kvaser_usb_dev_ops kvaser_usb_hydra_dev_ops; > extern const struct kvaser_usb_dev_ops kvaser_usb_leaf_dev_ops; > > +void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv); > + > int kvaser_usb_recv_cmd(const struct kvaser_usb *dev, void *cmd, int len, > int *actual_len); > > diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c > index 7388fdca9079..a8d72fb8291a 100644 > --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c > +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c > @@ -440,7 +440,7 @@ static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv) > /* This method might sleep. Do not call it in the atomic context > * of URB completions. > */ > -static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv) > +void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv) > { > usb_kill_anchored_urbs(&priv->tx_submitted); > kvaser_usb_reset_tx_urb_contexts(priv); > diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c > index d7f2d64a8083..2d30a662edb5 100644 > --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c > +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c > @@ -1402,6 +1402,12 @@ static int kvaser_usb_leaf_set_mode(struct net_device *netdev, > > switch (mode) { > case CAN_MODE_START: > + err = kvaser_usb_leaf_flush_queue(priv);
All affected devices, leaf and usbcanII, will flush the Tx queue when receiving CMD_START_CHIP. So this is superfluous, and can be removed.
> + if (err) > + return err; > + > + kvaser_usb_unlink_tx_urbs(priv); > + > err = kvaser_usb_leaf_simple_cmd_async(priv, CMD_START_CHIP); > if (err) > return err;
|  |