Commit 8de78e00 authored by Marc Kleine-Budde's avatar Marc Kleine-Budde
Browse files

Merge patch series "can: mcp251xfd: fix ring/coalescing configuration"

Marc Kleine-Budde <mkl@pengutronix.de> says:

When changing from CAN-CC to CAN-FD mode the ring and/or coalescing
parameters might be too big.

This series fixes the problem and adds a safeguard to detect broken
coalescing configuration.

Link: https://lore.kernel.org/all/20240805-mcp251xfd-fix-ringconfig-v1-0-72086f0ca5ee@pengutronix.de


Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parents 053ae05f ac2b81eb
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -97,7 +97,16 @@ void can_ram_get_layout(struct can_ram_layout *layout,
	if (ring) {
		u8 num_rx_coalesce = 0, num_tx_coalesce = 0;

		num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, ring->rx_pending);
		/* If the ring parameters have been configured in
		 * CAN-CC mode, but and we are in CAN-FD mode now,
		 * they might be to big. Use the default CAN-FD values
		 * in this case.
		 */
		num_rx = ring->rx_pending;
		if (num_rx > layout->max_rx)
			num_rx = layout->default_rx;

		num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);

		/* The ethtool doc says:
		 * To disable coalescing, set usecs = 0 and max_frames = 1.
+28 −6
Original line number Diff line number Diff line
@@ -290,7 +290,7 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
	const struct mcp251xfd_rx_ring *rx_ring;
	u16 base = 0, ram_used;
	u8 fifo_nr = 1;
	int i;
	int err = 0, i;

	netdev_reset_queue(priv->ndev);

@@ -386,10 +386,18 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
		netdev_err(priv->ndev,
			   "Error during ring configuration, using more RAM (%u bytes) than available (%u bytes).\n",
			   ram_used, MCP251XFD_RAM_SIZE);
		return -ENOMEM;
		err = -ENOMEM;
	}

	return 0;
	if (priv->tx_obj_num_coalesce_irq &&
	    priv->tx_obj_num_coalesce_irq * 2 != priv->tx->obj_num) {
		netdev_err(priv->ndev,
			   "Error during ring configuration, number of TEF coalescing buffers (%u) must be half of TEF buffers (%u).\n",
			   priv->tx_obj_num_coalesce_irq, priv->tx->obj_num);
		err = -EINVAL;
	}

	return err;
}

void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
@@ -469,11 +477,25 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)

	/* switching from CAN-2.0 to CAN-FD mode or vice versa */
	if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
		const struct ethtool_ringparam ring = {
			.rx_pending = priv->rx_obj_num,
			.tx_pending = priv->tx->obj_num,
		};
		const struct ethtool_coalesce ec = {
			.rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq,
			.rx_max_coalesced_frames_irq = priv->rx_obj_num_coalesce_irq,
			.tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq,
			.tx_max_coalesced_frames_irq = priv->tx_obj_num_coalesce_irq,
		};
		struct can_ram_layout layout;

		can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);
		priv->rx_obj_num = layout.default_rx;
		tx_ring->obj_num = layout.default_tx;
		can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, &ec, fd_mode);

		priv->rx_obj_num = layout.cur_rx;
		priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;

		tx_ring->obj_num = layout.cur_tx;
		priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
	}

	if (fd_mode) {