Merge patch series "Fix {rx,tx}_errors CAN statistics"
Dario Binacchi <dario.binacchi@amarulasolutions.com> says:
This series extends the patch 4d6d265379 ("can: c_can: fix {rx,tx}_errors statistics"),
already merged into the mainline, to other CAN devices that similarly do
not correctly increment the error counters for reception/transmission.
Changes in v2:
- Fix patches 7 through 12 to ensure that statistics are updated even
if the allocation of skb fails.
- Add five new patches (i. e. 1-5), created during the further analysis
of the code while correcting patches from the v1 series (i. e. 7-12).
Link: https://patch.msgid.link/20241122221650.633981-1-dario.binacchi@amarulasolutions.com
[mkl: omitted patch 3]
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
@@ -1014,49 +1014,57 @@ static int c_can_handle_bus_err(struct net_device *dev,
|
||||
|
||||
/* propagate the error condition to the CAN stack */
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
/* check for 'last error code' which tells us the
|
||||
* type of the last error to occur on the CAN bus
|
||||
*/
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (likely(skb))
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (lec_type) {
|
||||
case LEC_STUFF_ERROR:
|
||||
netdev_dbg(dev, "stuff error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
stats->rx_errors++;
|
||||
break;
|
||||
case LEC_FORM_ERROR:
|
||||
netdev_dbg(dev, "form error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
stats->rx_errors++;
|
||||
break;
|
||||
case LEC_ACK_ERROR:
|
||||
netdev_dbg(dev, "ack error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
stats->tx_errors++;
|
||||
break;
|
||||
case LEC_BIT1_ERROR:
|
||||
netdev_dbg(dev, "bit1 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
stats->tx_errors++;
|
||||
break;
|
||||
case LEC_BIT0_ERROR:
|
||||
netdev_dbg(dev, "bit0 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
stats->tx_errors++;
|
||||
break;
|
||||
case LEC_CRC_ERROR:
|
||||
netdev_dbg(dev, "CRC error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
stats->rx_errors++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
netif_receive_skb(skb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -390,36 +390,55 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
|
||||
return 0;
|
||||
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
/* Propagate the error condition to the CAN stack. */
|
||||
skb = alloc_can_err_skb(ndev, &cf);
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
/* Read the error counter register and check for new errors. */
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (likely(skb))
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST)
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST) {
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST) {
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST) {
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST)
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
}
|
||||
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST)
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST) {
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
}
|
||||
|
||||
/* Reset the error counter, ack the IRQ and re-enable the counter. */
|
||||
writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
|
||||
@@ -427,6 +446,9 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
|
||||
priv->base + IFI_CANFD_INTERRUPT);
|
||||
writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
netif_receive_skb(skb);
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -695,47 +695,60 @@ static int m_can_handle_lec_err(struct net_device *dev,
|
||||
u32 timestamp = 0;
|
||||
|
||||
cdev->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
/* propagate the error condition to the CAN stack */
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
/* check for 'last error code' which tells us the
|
||||
* type of the last error to occur on the CAN bus
|
||||
*/
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (likely(skb))
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (lec_type) {
|
||||
case LEC_STUFF_ERROR:
|
||||
netdev_dbg(dev, "stuff error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
case LEC_FORM_ERROR:
|
||||
netdev_dbg(dev, "form error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case LEC_ACK_ERROR:
|
||||
netdev_dbg(dev, "ack error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_ACK;
|
||||
break;
|
||||
case LEC_BIT1_ERROR:
|
||||
netdev_dbg(dev, "bit1 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT1;
|
||||
break;
|
||||
case LEC_BIT0_ERROR:
|
||||
netdev_dbg(dev, "bit0 error\n");
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
stats->tx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT0;
|
||||
break;
|
||||
case LEC_CRC_ERROR:
|
||||
netdev_dbg(dev, "CRC error\n");
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
stats->rx_errors++;
|
||||
if (likely(skb))
|
||||
cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (unlikely(!skb))
|
||||
return 0;
|
||||
|
||||
if (cdev->is_peripheral)
|
||||
timestamp = m_can_get_timestamp(cdev);
|
||||
|
||||
|
||||
@@ -416,8 +416,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
int ret = 0;
|
||||
|
||||
skb = alloc_can_err_skb(dev, &cf);
|
||||
if (skb == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
txerr = priv->read_reg(priv, SJA1000_TXERR);
|
||||
rxerr = priv->read_reg(priv, SJA1000_RXERR);
|
||||
@@ -425,8 +423,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
if (isrc & IRQ_DOI) {
|
||||
/* data overrun interrupt */
|
||||
netdev_dbg(dev, "data overrun interrupt\n");
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
}
|
||||
|
||||
stats->rx_over_errors++;
|
||||
stats->rx_errors++;
|
||||
sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
|
||||
@@ -452,7 +453,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
else
|
||||
state = CAN_STATE_ERROR_ACTIVE;
|
||||
}
|
||||
if (state != CAN_STATE_BUS_OFF) {
|
||||
if (state != CAN_STATE_BUS_OFF && skb) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = txerr;
|
||||
cf->data[7] = rxerr;
|
||||
@@ -460,33 +461,38 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
if (isrc & IRQ_BEI) {
|
||||
/* bus error interrupt */
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
ecc = priv->read_reg(priv, SJA1000_ECC);
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
/* set error type */
|
||||
switch (ecc & ECC_MASK) {
|
||||
case ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* set error type */
|
||||
switch (ecc & ECC_MASK) {
|
||||
case ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
/* set error location */
|
||||
cf->data[3] = ecc & ECC_SEG;
|
||||
}
|
||||
|
||||
/* set error location */
|
||||
cf->data[3] = ecc & ECC_SEG;
|
||||
|
||||
/* Error occurred during transmission? */
|
||||
if ((ecc & ECC_DIR) == 0)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
if ((ecc & ECC_DIR) == 0) {
|
||||
stats->tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
}
|
||||
if (isrc & IRQ_EPI) {
|
||||
/* error passive interrupt */
|
||||
@@ -502,8 +508,10 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
netdev_dbg(dev, "arbitration lost interrupt\n");
|
||||
alc = priv->read_reg(priv, SJA1000_ALC);
|
||||
priv->can.can_stats.arbitration_lost++;
|
||||
cf->can_id |= CAN_ERR_LOSTARB;
|
||||
cf->data[0] = alc & 0x1f;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_LOSTARB;
|
||||
cf->data[0] = alc & 0x1f;
|
||||
}
|
||||
}
|
||||
|
||||
if (state != priv->can.state) {
|
||||
@@ -516,6 +524,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
|
||||
can_bus_off(dev);
|
||||
}
|
||||
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
netif_rx(skb);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -663,27 +663,27 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
|
||||
u8 rxerr, txerr;
|
||||
|
||||
skb = alloc_can_err_skb(net, &cf);
|
||||
if (!skb)
|
||||
break;
|
||||
|
||||
txerr = hi3110_read(spi, HI3110_READ_TEC);
|
||||
rxerr = hi3110_read(spi, HI3110_READ_REC);
|
||||
tx_state = txerr >= rxerr ? new_state : 0;
|
||||
rx_state = txerr <= rxerr ? new_state : 0;
|
||||
can_change_state(net, cf, tx_state, rx_state);
|
||||
netif_rx(skb);
|
||||
|
||||
if (new_state == CAN_STATE_BUS_OFF) {
|
||||
if (skb)
|
||||
netif_rx(skb);
|
||||
can_bus_off(net);
|
||||
if (priv->can.restart_ms == 0) {
|
||||
priv->force_quit = 1;
|
||||
hi3110_hw_sleep(spi);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
} else if (skb) {
|
||||
cf->can_id |= CAN_ERR_CNT;
|
||||
cf->data[6] = txerr;
|
||||
cf->data[7] = rxerr;
|
||||
netif_rx(skb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -696,27 +696,38 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
|
||||
/* Check for protocol errors */
|
||||
if (eflag & HI3110_ERR_PROTOCOL_MASK) {
|
||||
skb = alloc_can_err_skb(net, &cf);
|
||||
if (!skb)
|
||||
break;
|
||||
if (skb)
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
priv->can.can_stats.bus_error++;
|
||||
priv->net->stats.rx_errors++;
|
||||
if (eflag & HI3110_ERR_BITERR)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
else if (eflag & HI3110_ERR_FRMERR)
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
else if (eflag & HI3110_ERR_STUFERR)
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
else if (eflag & HI3110_ERR_CRCERR)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
else if (eflag & HI3110_ERR_ACKERR)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
|
||||
if (eflag & HI3110_ERR_BITERR) {
|
||||
priv->net->stats.tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
} else if (eflag & HI3110_ERR_FRMERR) {
|
||||
priv->net->stats.rx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
} else if (eflag & HI3110_ERR_STUFERR) {
|
||||
priv->net->stats.rx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
} else if (eflag & HI3110_ERR_CRCERR) {
|
||||
priv->net->stats.rx_errors++;
|
||||
if (skb)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
|
||||
} else if (eflag & HI3110_ERR_ACKERR) {
|
||||
priv->net->stats.tx_errors++;
|
||||
if (skb)
|
||||
cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
|
||||
}
|
||||
|
||||
cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
|
||||
cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
|
||||
netdev_dbg(priv->net, "Bus Error\n");
|
||||
netif_rx(skb);
|
||||
if (skb) {
|
||||
cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
|
||||
cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
|
||||
netif_rx(skb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -579,11 +579,9 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
/* bus error interrupt */
|
||||
netdev_dbg(dev, "bus error interrupt\n");
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
|
||||
|
||||
if (likely(skb)) {
|
||||
ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (ecc & SUN4I_STA_MASK_ERR) {
|
||||
@@ -601,9 +599,15 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
>> 16;
|
||||
break;
|
||||
}
|
||||
/* error occurred during transmission? */
|
||||
if ((ecc & SUN4I_STA_ERR_DIR) == 0)
|
||||
}
|
||||
|
||||
/* error occurred during transmission? */
|
||||
if ((ecc & SUN4I_STA_ERR_DIR) == 0) {
|
||||
if (likely(skb))
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
stats->tx_errors++;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
}
|
||||
if (isrc & SUN4I_INT_ERR_PASSIVE) {
|
||||
@@ -629,10 +633,10 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
|
||||
tx_state = txerr >= rxerr ? state : 0;
|
||||
rx_state = txerr <= rxerr ? state : 0;
|
||||
|
||||
if (likely(skb))
|
||||
can_change_state(dev, cf, tx_state, rx_state);
|
||||
else
|
||||
priv->can.state = state;
|
||||
/* The skb allocation might fail, but can_change_state()
|
||||
* handles cf == NULL.
|
||||
*/
|
||||
can_change_state(dev, cf, tx_state, rx_state);
|
||||
if (state == CAN_STATE_BUS_OFF)
|
||||
can_bus_off(dev);
|
||||
}
|
||||
|
||||
@@ -335,15 +335,14 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
|
||||
struct net_device_stats *stats = &dev->netdev->stats;
|
||||
|
||||
skb = alloc_can_err_skb(dev->netdev, &cf);
|
||||
if (skb == NULL)
|
||||
return;
|
||||
|
||||
if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
|
||||
u8 state = msg->msg.can_state;
|
||||
|
||||
if (state & SJA1000_SR_BS) {
|
||||
dev->can.state = CAN_STATE_BUS_OFF;
|
||||
cf->can_id |= CAN_ERR_BUSOFF;
|
||||
if (skb)
|
||||
cf->can_id |= CAN_ERR_BUSOFF;
|
||||
|
||||
dev->can.can_stats.bus_off++;
|
||||
can_bus_off(dev->netdev);
|
||||
@@ -361,44 +360,53 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
|
||||
|
||||
/* bus error interrupt */
|
||||
dev->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
|
||||
switch (ecc & SJA1000_ECC_MASK) {
|
||||
case SJA1000_ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case SJA1000_ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case SJA1000_ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
cf->data[3] = ecc & SJA1000_ECC_SEG;
|
||||
break;
|
||||
switch (ecc & SJA1000_ECC_MASK) {
|
||||
case SJA1000_ECC_BIT:
|
||||
cf->data[2] |= CAN_ERR_PROT_BIT;
|
||||
break;
|
||||
case SJA1000_ECC_FORM:
|
||||
cf->data[2] |= CAN_ERR_PROT_FORM;
|
||||
break;
|
||||
case SJA1000_ECC_STUFF:
|
||||
cf->data[2] |= CAN_ERR_PROT_STUFF;
|
||||
break;
|
||||
default:
|
||||
cf->data[3] = ecc & SJA1000_ECC_SEG;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Error occurred during transmission? */
|
||||
if ((ecc & SJA1000_ECC_DIR) == 0)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
if ((ecc & SJA1000_ECC_DIR) == 0) {
|
||||
stats->tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
if (dev->can.state == CAN_STATE_ERROR_WARNING ||
|
||||
dev->can.state == CAN_STATE_ERROR_PASSIVE) {
|
||||
if (skb && (dev->can.state == CAN_STATE_ERROR_WARNING ||
|
||||
dev->can.state == CAN_STATE_ERROR_PASSIVE)) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = (txerr > rxerr) ?
|
||||
CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
|
||||
}
|
||||
} else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_CRTL;
|
||||
cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
|
||||
}
|
||||
|
||||
stats->rx_over_errors++;
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
netif_rx(skb);
|
||||
if (skb)
|
||||
netif_rx(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -526,7 +526,6 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
|
||||
netdev_dbg(netdev, "bus error interrupt\n");
|
||||
|
||||
priv->can.can_stats.bus_error++;
|
||||
stats->rx_errors++;
|
||||
|
||||
if (skb) {
|
||||
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
|
||||
@@ -548,10 +547,15 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
|
||||
|
||||
/* set error location */
|
||||
cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
|
||||
}
|
||||
|
||||
/* Error occurred during transmission? */
|
||||
if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0)
|
||||
/* Error occurred during transmission? */
|
||||
if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) {
|
||||
stats->tx_errors++;
|
||||
if (skb)
|
||||
cf->data[2] |= CAN_ERR_PROT_TX;
|
||||
} else {
|
||||
stats->rx_errors++;
|
||||
}
|
||||
|
||||
set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
|
||||
|
||||
Reference in New Issue
Block a user