mirror of
https://github.com/torvalds/linux.git
synced 2026-05-30 10:04:04 +02:00
linux-can-fixes-for-6.13-20241202
-----BEGIN PGP SIGNATURE-----
iQFHBAABCgAxFiEEUEC6huC2BN0pvD5fKDiiPnotvG8FAmdNdZ0THG1rbEBwZW5n
dXRyb25peC5kZQAKCRAoOKI+ei28b76fB/9mW1n8e9GEUallIie+f+uGBRi4nMCI
GeyuVZyVMUH1pJBXHMQ4B17ZRJ8ynF0gFZ7evMbwsJ9aJ2ZOQVQWPO6FaAge2jrJ
9HD/LQsj55+YXaCyPnFlpCmH8HvA2ojVvIbpGyz+u9zAwJXI/2hwMVSNBt5HaAg7
iJ2Rij/PECWDD2cR/OU2cDNjZPMyn3HEyZGAEDKlsQZQbZNFfqFdr8MXP76ppjjx
f9PKW9LeaA6L2wyXjx2tTFIABsnJRJSQJenVVH/lQLC6Kqkq3j7Z0umAxQ6fQ9qT
5LvJt6rP+5ZsUEOxkG5mMhsweAaynzFvur+ZVCZpRg2HHL35PQ0UX67/
=ZT7R
-----END PGP SIGNATURE-----
Merge tag 'linux-can-fixes-for-6.13-20241202' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can
Marc Kleine-Budde says:
====================
pull-request: can 2024-12-02
The first patch is by me and allows the use of sleeping GPIOs to set
termination GPIOs.
Alexander Kozhinov fixes the gs_usb driver to use the endpoints
provided by the usb endpoint descriptions instead of hard coded ones.
Dario Binacchi contributes 11 statistics related patches for various
CAN driver. A potential use after free in the hi311x is fixed. The
statistics for the c_can, sun4i_can, hi311x, m_can, ifi_canfd,
sja1000, sun4i_can, ems_usb, f81604 are fixed: update statistics even
if the allocation of the error skb fails and fix the incrementing of
the rx,tx error counters.
A patch by me fixes the workaround for DS80000789E 6 erratum in the
mcp251xfd driver.
The last patch is by Dmitry Antipov, targets the j1939 CAN protocol
and fixes a skb reference counting issue.
* tag 'linux-can-fixes-for-6.13-20241202' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
can: j1939: j1939_session_new(): fix skb reference counting
can: mcp251xfd: mcp251xfd_get_tef_len(): work around erratum DS80000789E 6.
can: f81604: f81604_handle_can_bus_errors(): fix {rx,tx}_errors statistics
can: ems_usb: ems_usb_rx_err(): fix {rx,tx}_errors statistics
can: sun4i_can: sun4i_can_err(): fix {rx,tx}_errors statistics
can: sja1000: sja1000_err(): fix {rx,tx}_errors statistics
can: hi311x: hi3110_can_ist(): fix {rx,tx}_errors statistics
can: ifi_canfd: ifi_canfd_handle_lec_err(): fix {rx,tx}_errors statistics
can: m_can: m_can_handle_lec_err(): fix {rx,tx}_errors statistics
can: hi311x: hi3110_can_ist(): update state error statistics if skb allocation fails
can: hi311x: hi3110_can_ist(): fix potential use-after-free
can: sun4i_can: sun4i_can_err(): call can_change_state() even if cf is NULL
can: c_can: c_can_handle_bus_err(): update statistics if skb allocation fails
can: gs_usb: add usb endpoint address detection at driver probe step
can: dev: can_set_termination(): allow sleeping GPIOs
====================
Link: https://patch.msgid.link/20241202090040.1110280-1-mkl@pengutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
51ee075d69
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -468,7 +468,7 @@ static int can_set_termination(struct net_device *ndev, u16 term)
|
|||
else
|
||||
set = 0;
|
||||
|
||||
gpiod_set_value(priv->termination_gpio, set);
|
||||
gpiod_set_value_cansleep(priv->termination_gpio, set);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ static inline bool mcp251xfd_tx_fifo_sta_empty(u32 fifo_sta)
|
|||
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFERFFIF;
|
||||
}
|
||||
|
||||
static inline bool mcp251xfd_tx_fifo_sta_less_than_half_full(u32 fifo_sta)
|
||||
{
|
||||
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFHRFHIF;
|
||||
}
|
||||
|
||||
static inline int
|
||||
mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
|
||||
u8 *tef_tail)
|
||||
|
|
@ -147,7 +152,29 @@ mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
|
|||
BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
|
||||
|
||||
len = (chip_tx_tail << shift) - (tail << shift);
|
||||
*len_p = len >> shift;
|
||||
len >>= shift;
|
||||
|
||||
/* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
|
||||
* bits of a FIFOSTA register, here the TX-FIFO tail index
|
||||
* might be corrupted.
|
||||
*
|
||||
* However here it seems the bit indicating that the TX-FIFO
|
||||
* is empty (MCP251XFD_REG_FIFOSTA_TFERFFIF) is not correct
|
||||
* while the TX-FIFO tail index is.
|
||||
*
|
||||
* We assume the TX-FIFO is empty, i.e. all pending CAN frames
|
||||
* haven been send, if:
|
||||
* - Chip's head and tail index are equal (len == 0).
|
||||
* - The TX-FIFO is less than half full.
|
||||
* (The TX-FIFO empty case has already been checked at the
|
||||
* beginning of this function.)
|
||||
* - No free buffers in the TX ring.
|
||||
*/
|
||||
if (len == 0 && mcp251xfd_tx_fifo_sta_less_than_half_full(fifo_sta) &&
|
||||
mcp251xfd_get_tx_free(tx_ring) == 0)
|
||||
len = tx_ring->obj_num;
|
||||
|
||||
*len_p = len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,6 @@
|
|||
#define USB_XYLANTA_SAINT3_VENDOR_ID 0x16d0
|
||||
#define USB_XYLANTA_SAINT3_PRODUCT_ID 0x0f30
|
||||
|
||||
#define GS_USB_ENDPOINT_IN 1
|
||||
#define GS_USB_ENDPOINT_OUT 2
|
||||
|
||||
/* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts
|
||||
* for timer overflow (will be after ~71 minutes)
|
||||
*/
|
||||
|
|
@ -336,6 +333,9 @@ struct gs_usb {
|
|||
|
||||
unsigned int hf_size_rx;
|
||||
u8 active_channels;
|
||||
|
||||
unsigned int pipe_in;
|
||||
unsigned int pipe_out;
|
||||
};
|
||||
|
||||
/* 'allocate' a tx context.
|
||||
|
|
@ -687,7 +687,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
|
|||
|
||||
resubmit_urb:
|
||||
usb_fill_bulk_urb(urb, parent->udev,
|
||||
usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
|
||||
parent->pipe_in,
|
||||
hf, dev->parent->hf_size_rx,
|
||||
gs_usb_receive_bulk_callback, parent);
|
||||
|
||||
|
|
@ -819,7 +819,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
|
|||
}
|
||||
|
||||
usb_fill_bulk_urb(urb, dev->udev,
|
||||
usb_sndbulkpipe(dev->udev, GS_USB_ENDPOINT_OUT),
|
||||
dev->parent->pipe_out,
|
||||
hf, dev->hf_size_tx,
|
||||
gs_usb_xmit_callback, txc);
|
||||
|
||||
|
|
@ -925,8 +925,7 @@ static int gs_can_open(struct net_device *netdev)
|
|||
/* fill, anchor, and submit rx urb */
|
||||
usb_fill_bulk_urb(urb,
|
||||
dev->udev,
|
||||
usb_rcvbulkpipe(dev->udev,
|
||||
GS_USB_ENDPOINT_IN),
|
||||
dev->parent->pipe_in,
|
||||
buf,
|
||||
dev->parent->hf_size_rx,
|
||||
gs_usb_receive_bulk_callback, parent);
|
||||
|
|
@ -1413,6 +1412,7 @@ static int gs_usb_probe(struct usb_interface *intf,
|
|||
const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
struct usb_endpoint_descriptor *ep_in, *ep_out;
|
||||
struct gs_host_frame *hf;
|
||||
struct gs_usb *parent;
|
||||
struct gs_host_config hconf = {
|
||||
|
|
@ -1422,6 +1422,13 @@ static int gs_usb_probe(struct usb_interface *intf,
|
|||
unsigned int icount, i;
|
||||
int rc;
|
||||
|
||||
rc = usb_find_common_endpoints(intf->cur_altsetting,
|
||||
&ep_in, &ep_out, NULL, NULL);
|
||||
if (rc) {
|
||||
dev_err(&intf->dev, "Required endpoints not found\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* send host config */
|
||||
rc = usb_control_msg_send(udev, 0,
|
||||
GS_USB_BREQ_HOST_FORMAT,
|
||||
|
|
@ -1466,6 +1473,10 @@ static int gs_usb_probe(struct usb_interface *intf,
|
|||
usb_set_intfdata(intf, parent);
|
||||
parent->udev = udev;
|
||||
|
||||
/* store the detected endpoints */
|
||||
parent->pipe_in = usb_rcvbulkpipe(parent->udev, ep_in->bEndpointAddress);
|
||||
parent->pipe_out = usb_sndbulkpipe(parent->udev, ep_out->bEndpointAddress);
|
||||
|
||||
for (i = 0; i < icount; i++) {
|
||||
unsigned int hf_size_rx = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -1505,7 +1505,7 @@ static struct j1939_session *j1939_session_new(struct j1939_priv *priv,
|
|||
session->state = J1939_SESSION_NEW;
|
||||
|
||||
skb_queue_head_init(&session->skb_queue);
|
||||
skb_queue_tail(&session->skb_queue, skb);
|
||||
skb_queue_tail(&session->skb_queue, skb_get(skb));
|
||||
|
||||
skcb = j1939_skb_to_cb(skb);
|
||||
memcpy(&session->skcb, skcb, sizeof(session->skcb));
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user