Bus error reporting has already been implemented for a long time, but before it was always active! Now it's user controllable by means off the "berr-reporting" parameter given to "ip link set ... ", which sets CAN_CTRLMODE_BERR_REPORTING within priv->can.ctrlmode. In case of an ESD_EV_CAN_ERROR_EXT now unconditionally supply priv->bec.rxerr and priv->bec.txerr with REC and TEC. Signed-off-by: Frank Jungclaus <frank.jungclaus@xxxxxx> --- drivers/net/can/usb/esd_usb.c | 47 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c index 588caba1453b..09649a45d6ff 100644 --- a/drivers/net/can/usb/esd_usb.c +++ b/drivers/net/can/usb/esd_usb.c @@ -230,12 +230,23 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, if (id == ESD_EV_CAN_ERROR_EXT) { u8 state = msg->msg.rx.data[0]; u8 ecc = msg->msg.rx.data[1]; - u8 rxerr = msg->msg.rx.data[2]; - u8 txerr = msg->msg.rx.data[3]; + + priv->bec.rxerr = msg->msg.rx.data[2]; + priv->bec.txerr = msg->msg.rx.data[3]; netdev_dbg(priv->netdev, "CAN_ERR_EV_EXT: dlc=%#02x state=%02x ecc=%02x rec=%02x tec=%02x\n", - msg->msg.rx.dlc, state, ecc, rxerr, txerr); + msg->msg.rx.dlc, state, ecc, priv->bec.rxerr, priv->bec.txerr); + + if (ecc) { + priv->can.can_stats.bus_error++; + stats->rx_errors++; + } + + if (state == priv->old_state && + !(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) + /* Neither a state change nor active bus error reporting */ + return; skb = alloc_can_err_skb(priv->netdev, &cf); if (skb == NULL) { @@ -270,16 +281,14 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, * berr-counters might stay on values like * 95 forever ... */ - txerr = 0; - rxerr = 0; + priv->bec.txerr = 0; + priv->bec.rxerr = 0; break; } } - if (ecc) { - priv->can.can_stats.bus_error++; - stats->rx_errors++; - + if (ecc && (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) { + /* Only if bus error reporting is active ... */ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; /* Store error in CAN protocol (type) in data[2] */ @@ -301,29 +310,26 @@ static void esd_usb_rx_event(struct esd_usb_net_priv *priv, if (!(ecc & SJA1000_ECC_DIR)) cf->data[2] |= CAN_ERR_PROT_TX; - /* Store error in CAN protocol (location) in data[3] */ + /* Store error position in the bit stream of the CAN frame in data[3] */ cf->data[3] = ecc & SJA1000_ECC_SEG; /* Store error status of CAN-controller in data[1] */ if (priv->can.state == CAN_STATE_ERROR_WARNING) { - if (txerr >= 96) + if (priv->bec.txerr >= 96) cf->data[1] |= CAN_ERR_CRTL_TX_WARNING; - if (rxerr >= 96) + if (priv->bec.rxerr >= 96) cf->data[1] |= CAN_ERR_CRTL_RX_WARNING; } else if (priv->can.state == CAN_STATE_ERROR_PASSIVE) { - if (txerr >= 128) + if (priv->bec.txerr >= 128) cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE; - if (rxerr >= 128) + if (priv->bec.rxerr >= 128) cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE; } - cf->data[6] = txerr; - cf->data[7] = rxerr; + cf->data[6] = priv->bec.txerr; + cf->data[7] = priv->bec.rxerr; } - priv->bec.txerr = txerr; - priv->bec.rxerr = rxerr; - netif_rx(skb); } } @@ -1021,7 +1027,8 @@ static int esd_usb_probe_one_net(struct usb_interface *intf, int index) priv->can.state = CAN_STATE_STOPPED; priv->can.ctrlmode_supported = CAN_CTRLMODE_LISTENONLY | - CAN_CTRLMODE_CC_LEN8_DLC; + CAN_CTRLMODE_CC_LEN8_DLC | + CAN_CTRLMODE_BERR_REPORTING; if (le16_to_cpu(dev->udev->descriptor.idProduct) == USB_CANUSBM_PRODUCT_ID) -- 2.25.1