CAN error skb is an interface specific to socket CAN. The CAN error skb does not correspond to any actual CAN frame sent on the wire. Only an error flag and a delimiter are transmitted when an error occurs (c.f. ISO 11898-1 section 10.4.4.2 "Error flag"). For this reason, it makes no sense to increment the tx_packets and tx_bytes fields of struct net_device_stats when sending an error frame because no actual payload will be transmitted on the wire. N.B. Sending error frames is a very specific feature which, at the moment, is only supported by the Kvaser Hydra hardware. Please refer to [1] for more details on the topic. [1] https://lore.kernel.org/linux-can/CAMZ6RqK0rTNg3u3mBpZOoY51jLZ-et-J01tY6-+mWsM4meVw-A@xxxxxxxxxxxxxx/t/#u CC: Jimmy Assarsson <extja@xxxxxxxxxx> Signed-off-by: Vincent Mailhol <mailhol.vincent@xxxxxxxxxx> --- Hi Jimmy, The statistics problem also applies to the tx path. However, in contrary to the rx path, this is specific to the Kvaser driver because it is the only one to support sending error flags. I am not fully confident with my patch, so I am sending this as RFC. Your comments will be warmly welcomed! Yours sincerely, Vincent Mailhol --- drivers/net/can/usb/kvaser_usb/kvaser_usb.h | 3 +++ drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h index 390b6bde883c..9993d16dfe54 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb.h +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb.h @@ -73,6 +73,9 @@ struct kvaser_usb_dev_card_data { }; }; +/* Keep track of error frames in kvaser_usb_tx_urb_context:dlc */ +#define KVASER_USB_DLC_ERROR_FRAME (-1) + /* Context for an outstanding, not yet ACKed, transmission */ struct kvaser_usb_tx_urb_context { struct kvaser_usb_net_priv *priv; diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index adab5c2a8b99..571b1baf9d23 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1134,7 +1134,7 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev, } context = &priv->tx_contexts[transid % dev->max_tx_urbs]; - if (!one_shot_fail) { + if (!one_shot_fail && context->dlc != KVASER_USB_DLC_ERROR_FRAME) { struct net_device_stats *stats = &priv->netdev->stats; stats->tx_packets++; @@ -1483,8 +1483,10 @@ kvaser_usb_hydra_frame_to_cmd_std(const struct kvaser_usb_net_priv *priv, if (cf->can_id & CAN_RTR_FLAG) flags |= KVASER_USB_HYDRA_CF_FLAG_REMOTE_FRAME; - flags |= (cf->can_id & CAN_ERR_FLAG ? - KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME : 0); + if (cf->can_id & CAN_ERR_FLAG) + flags |= KVASER_USB_HYDRA_CF_FLAG_ERROR_FRAME; + else + *frame_len = KVASER_USB_DLC_ERROR_FRAME; cmd->tx_can.id = cpu_to_le32(id); cmd->tx_can.flags = flags; -- 2.32.0