Skip to content

Commit 8de78e0

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: Marc Kleine-Budde <mkl@pengutronix.de>
2 parents 053ae05 + ac2b81e commit 8de78e0

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,16 @@ void can_ram_get_layout(struct can_ram_layout *layout,
9797
if (ring) {
9898
u8 num_rx_coalesce = 0, num_tx_coalesce = 0;
9999

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

102111
/* The ethtool doc says:
103112
* To disable coalescing, set usecs = 0 and max_frames = 1.

drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
290290
const struct mcp251xfd_rx_ring *rx_ring;
291291
u16 base = 0, ram_used;
292292
u8 fifo_nr = 1;
293-
int i;
293+
int err = 0, i;
294294

295295
netdev_reset_queue(priv->ndev);
296296

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

392-
return 0;
392+
if (priv->tx_obj_num_coalesce_irq &&
393+
priv->tx_obj_num_coalesce_irq * 2 != priv->tx->obj_num) {
394+
netdev_err(priv->ndev,
395+
"Error during ring configuration, number of TEF coalescing buffers (%u) must be half of TEF buffers (%u).\n",
396+
priv->tx_obj_num_coalesce_irq, priv->tx->obj_num);
397+
err = -EINVAL;
398+
}
399+
400+
return err;
393401
}
394402

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

470478
/* switching from CAN-2.0 to CAN-FD mode or vice versa */
471479
if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
480+
const struct ethtool_ringparam ring = {
481+
.rx_pending = priv->rx_obj_num,
482+
.tx_pending = priv->tx->obj_num,
483+
};
484+
const struct ethtool_coalesce ec = {
485+
.rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq,
486+
.rx_max_coalesced_frames_irq = priv->rx_obj_num_coalesce_irq,
487+
.tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq,
488+
.tx_max_coalesced_frames_irq = priv->tx_obj_num_coalesce_irq,
489+
};
472490
struct can_ram_layout layout;
473491

474-
can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);
475-
priv->rx_obj_num = layout.default_rx;
476-
tx_ring->obj_num = layout.default_tx;
492+
can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, &ec, fd_mode);
493+
494+
priv->rx_obj_num = layout.cur_rx;
495+
priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
496+
497+
tx_ring->obj_num = layout.cur_tx;
498+
priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
477499
}
478500

479501
if (fd_mode) {

0 commit comments

Comments
 (0)