Commit 51ee075d authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge tag 'linux-can-fixes-for-6.13-20241202' of...

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: default avatarJakub Kicinski <kuba@kernel.org>
parents c889aa2e a8c69500
Loading
Loading
Loading
Loading
+17 −9
Original line number Diff line number Diff line
@@ -1014,42 +1014,47 @@ 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
	 */
	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");
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_STUFF;
		stats->rx_errors++;
		break;
	case LEC_FORM_ERROR:
		netdev_dbg(dev, "form error\n");
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_FORM;
		stats->rx_errors++;
		break;
	case LEC_ACK_ERROR:
		netdev_dbg(dev, "ack error\n");
		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");
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_BIT1;
		stats->tx_errors++;
		break;
	case LEC_BIT0_ERROR:
		netdev_dbg(dev, "bit0 error\n");
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_BIT0;
		stats->tx_errors++;
		break;
	case LEC_CRC_ERROR:
		netdev_dbg(dev, "CRC error\n");
		if (likely(skb))
			cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
		stats->rx_errors++;
		break;
@@ -1057,6 +1062,9 @@ static int c_can_handle_bus_err(struct net_device *dev,
		break;
	}

	if (unlikely(!skb))
		return 0;

	netif_receive_skb(skb);
	return 1;
}
+1 −1
Original line number Diff line number Diff line
@@ -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;
}
+40 −18
Original line number Diff line number Diff line
@@ -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. */
	if (likely(skb))
		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;

	if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
	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)
	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)
	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)
	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)
	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)
	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)
	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;
+23 −10
Original line number Diff line number Diff line
@@ -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
	 */
	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");
		stats->rx_errors++;
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_STUFF;
		break;
	case LEC_FORM_ERROR:
		netdev_dbg(dev, "form error\n");
		stats->rx_errors++;
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_FORM;
		break;
	case LEC_ACK_ERROR:
		netdev_dbg(dev, "ack error\n");
		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");
		stats->tx_errors++;
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_BIT1;
		break;
	case LEC_BIT0_ERROR:
		netdev_dbg(dev, "bit0 error\n");
		stats->tx_errors++;
		if (likely(skb))
			cf->data[2] |= CAN_ERR_PROT_BIT0;
		break;
	case LEC_CRC_ERROR:
		netdev_dbg(dev, "CRC error\n");
		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);

+39 −28
Original line number Diff line number Diff line
@@ -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");
		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,10 +461,9 @@ 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;

			/* set error type */
@@ -483,10 +483,16 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)

			/* set error location */
			cf->data[3] = ecc & ECC_SEG;
		}

		/* Error occurred during transmission? */
		if ((ecc & ECC_DIR) == 0)
		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,9 +508,11 @@ 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++;
		if (skb) {
			cf->can_id |= CAN_ERR_LOSTARB;
			cf->data[0] = alc & 0x1f;
		}
	}

	if (state != priv->can.state) {
		tx_state = txerr >= rxerr ? state : 0;
@@ -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;
Loading