Commit 9263c2e9 authored by Marc Kleine-Budde's avatar Marc Kleine-Budde

can: mcp251xfd: ring: add support for runtime configurable RX/TX ring parameters

This patch adds runtime configurable RX and TX ring parameters via
ethtool to the driver.

Link: https://lore.kernel.org/20220313083640.501791-8-mkl@pengutronix.deSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent c9e6b80d
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/ethtool.h> #include <linux/ethtool.h>
#include "mcp251xfd.h" #include "mcp251xfd.h"
#include "mcp251xfd-ram.h"
static void static void
mcp251xfd_ring_get_ringparam(struct net_device *ndev, mcp251xfd_ring_get_ringparam(struct net_device *ndev,
...@@ -17,19 +18,51 @@ mcp251xfd_ring_get_ringparam(struct net_device *ndev, ...@@ -17,19 +18,51 @@ mcp251xfd_ring_get_ringparam(struct net_device *ndev,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
const struct mcp251xfd_priv *priv = netdev_priv(ndev); const struct mcp251xfd_priv *priv = netdev_priv(ndev);
const bool fd_mode = mcp251xfd_is_fd_mode(priv);
struct can_ram_layout layout;
ring->rx_max_pending = MCP251XFD_RX_OBJ_NUM_MAX; can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);
ring->tx_max_pending = MCP251XFD_TX_OBJ_NUM_MAX; ring->rx_max_pending = layout.max_rx;
ring->tx_max_pending = layout.max_tx;
ring->rx_pending = priv->rx_obj_num; ring->rx_pending = priv->rx_obj_num;
ring->tx_pending = priv->tx->obj_num; ring->tx_pending = priv->tx->obj_num;
} }
static int
mcp251xfd_ring_set_ringparam(struct net_device *ndev,
struct ethtool_ringparam *ring,
struct kernel_ethtool_ringparam *kernel_ring,
struct netlink_ext_ack *extack)
{
struct mcp251xfd_priv *priv = netdev_priv(ndev);
const bool fd_mode = mcp251xfd_is_fd_mode(priv);
struct can_ram_layout layout;
can_ram_get_layout(&layout, &mcp251xfd_ram_config, ring, NULL, fd_mode);
if ((layout.cur_rx != priv->rx_obj_num ||
layout.cur_tx != priv->tx->obj_num) &&
netif_running(ndev))
return -EBUSY;
priv->rx_obj_num = layout.cur_rx;
priv->tx->obj_num = layout.cur_tx;
return 0;
}
static const struct ethtool_ops mcp251xfd_ethtool_ops = { static const struct ethtool_ops mcp251xfd_ethtool_ops = {
.get_ringparam = mcp251xfd_ring_get_ringparam, .get_ringparam = mcp251xfd_ring_get_ringparam,
.set_ringparam = mcp251xfd_ring_set_ringparam,
}; };
void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv) void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)
{ {
struct can_ram_layout layout;
priv->ndev->ethtool_ops = &mcp251xfd_ethtool_ops; priv->ndev->ethtool_ops = &mcp251xfd_ethtool_ops;
can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, false);
priv->rx_obj_num = layout.default_rx;
priv->tx->obj_num = layout.default_tx;
} }
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "mcp251xfd.h" #include "mcp251xfd.h"
#include "mcp251xfd-ram.h"
static inline u8 static inline u8
mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv, mcp251xfd_cmd_prepare_write_reg(const struct mcp251xfd_priv *priv,
...@@ -285,33 +286,63 @@ void mcp251xfd_ring_free(struct mcp251xfd_priv *priv) ...@@ -285,33 +286,63 @@ void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
} }
} }
const struct can_ram_config mcp251xfd_ram_config = {
.rx = {
.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
.size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_rx_obj_canfd),
.min = MCP251XFD_RX_OBJ_NUM_MIN,
.max = MCP251XFD_RX_OBJ_NUM_MAX,
.def[CAN_RAM_MODE_CAN] = CAN_RAM_NUM_MAX,
.def[CAN_RAM_MODE_CANFD] = CAN_RAM_NUM_MAX,
.fifo_num = MCP251XFD_FIFO_RX_NUM,
.fifo_depth_min = MCP251XFD_RX_FIFO_DEPTH_MIN,
},
.tx = {
.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_tef_obj) +
sizeof(struct mcp251xfd_hw_tx_obj_can),
.size[CAN_RAM_MODE_CANFD] = sizeof(struct mcp251xfd_hw_tef_obj) +
sizeof(struct mcp251xfd_hw_tx_obj_canfd),
.min = MCP251XFD_TX_OBJ_NUM_MIN,
.max = MCP251XFD_TX_OBJ_NUM_MAX,
.def[CAN_RAM_MODE_CAN] = MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT,
.def[CAN_RAM_MODE_CANFD] = MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT,
.fifo_num = MCP251XFD_FIFO_TX_NUM,
.fifo_depth_min = MCP251XFD_TX_FIFO_DEPTH_MIN,
},
.size = MCP251XFD_RAM_SIZE,
.fifo_depth = MCP251XFD_FIFO_DEPTH,
};
int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
{ {
struct mcp251xfd_tx_ring *tx_ring; const bool fd_mode = mcp251xfd_is_fd_mode(priv);
struct mcp251xfd_tx_ring *tx_ring = priv->tx;
struct mcp251xfd_rx_ring *rx_ring; struct mcp251xfd_rx_ring *rx_ring;
u8 tef_obj_size, tx_obj_size, rx_obj_size; u8 tx_obj_size, rx_obj_size;
u8 tx_obj_num;
u8 rem, i; u8 rem, i;
tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj); /* switching from CAN-2.0 to CAN-FD mode or vice versa */
if (mcp251xfd_is_fd_mode(priv)) { if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT; 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;
}
if (fd_mode) {
tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd); tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd); rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
set_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
} else { } else {
tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT;
tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can); tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can); rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
} }
priv->rx_obj_num = 0;
tx_ring = priv->tx;
tx_ring->obj_num = tx_obj_num;
tx_ring->obj_size = tx_obj_size; tx_ring->obj_size = tx_obj_size;
rem = (MCP251XFD_RAM_SIZE - tx_obj_num * rem = priv->rx_obj_num;
(tef_obj_size + tx_obj_size)) / rx_obj_size;
for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) { for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) {
u8 rx_obj_num; u8 rx_obj_num;
...@@ -319,8 +350,6 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv) ...@@ -319,8 +350,6 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
MCP251XFD_FIFO_DEPTH); MCP251XFD_FIFO_DEPTH);
rem -= rx_obj_num; rem -= rx_obj_num;
priv->rx_obj_num += rx_obj_num;
rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num, rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
GFP_KERNEL); GFP_KERNEL);
if (!rx_ring) { if (!rx_ring) {
......
...@@ -582,6 +582,12 @@ struct mcp251xfd_devtype_data { ...@@ -582,6 +582,12 @@ struct mcp251xfd_devtype_data {
u32 quirks; u32 quirks;
}; };
enum mcp251xfd_flags {
MCP251XFD_FLAGS_FD_MODE,
__MCP251XFD_FLAGS_SIZE__
};
struct mcp251xfd_priv { struct mcp251xfd_priv {
struct can_priv can; struct can_priv can;
struct can_rx_offload offload; struct can_rx_offload offload;
...@@ -607,6 +613,8 @@ struct mcp251xfd_priv { ...@@ -607,6 +613,8 @@ struct mcp251xfd_priv {
struct mcp251xfd_rx_ring *rx[MCP251XFD_FIFO_RX_NUM]; struct mcp251xfd_rx_ring *rx[MCP251XFD_FIFO_RX_NUM];
struct mcp251xfd_tx_ring tx[MCP251XFD_FIFO_TX_NUM]; struct mcp251xfd_tx_ring tx[MCP251XFD_FIFO_TX_NUM];
DECLARE_BITMAP(flags, __MCP251XFD_FLAGS_SIZE__);
u8 rx_ring_num; u8 rx_ring_num;
u8 rx_obj_num; u8 rx_obj_num;
...@@ -892,6 +900,7 @@ u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size, ...@@ -892,6 +900,7 @@ u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size,
u16 mcp251xfd_crc16_compute(const void *data, size_t data_size); u16 mcp251xfd_crc16_compute(const void *data, size_t data_size);
void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv); void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv);
int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv); int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv);
extern const struct can_ram_config mcp251xfd_ram_config;
int mcp251xfd_ring_init(struct mcp251xfd_priv *priv); int mcp251xfd_ring_init(struct mcp251xfd_priv *priv);
void mcp251xfd_ring_free(struct mcp251xfd_priv *priv); void mcp251xfd_ring_free(struct mcp251xfd_priv *priv);
int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv); int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment