]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
can: mcp251xfd: fix ring configuration when switching from CAN-CC to CAN-FD mode
authorMarc Kleine-Budde <mkl@pengutronix.de>
Fri, 5 Jul 2024 15:28:27 +0000 (17:28 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Tue, 6 Aug 2024 07:52:00 +0000 (09:52 +0200)
If the ring (rx, tx) and/or coalescing parameters (rx-frames-irq,
tx-frames-irq) have been configured while the interface was in CAN-CC
mode, but the interface is brought up in CAN-FD mode, the ring
parameters might be too big.

Use the default CAN-FD values in this case.

Fixes: 9263c2e92be9 ("can: mcp251xfd: ring: add support for runtime configurable RX/TX ring parameters")
Link: https://lore.kernel.org/all/20240805-mcp251xfd-fix-ringconfig-v1-1-72086f0ca5ee@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c

index 9e8e82cdba461242856293ffb936a0987e481e60..61b0d6fa52dd8054d8d73920335da06dbee346a3 100644 (file)
@@ -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.
index 7bd2bcb5cf876e6907d2b70d05be355ea5f55dfd..f72582d4d3e8e249a41633b2a93f8a9bc2d90f88 100644 (file)
@@ -469,11 +469,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) {