mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
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.de Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
This commit is contained in:
parent
c9e6b80dfd
commit
9263c2e92b
@ -9,6 +9,7 @@
|
||||
#include <linux/ethtool.h>
|
||||
|
||||
#include "mcp251xfd.h"
|
||||
#include "mcp251xfd-ram.h"
|
||||
|
||||
static void
|
||||
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)
|
||||
{
|
||||
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;
|
||||
ring->tx_max_pending = MCP251XFD_TX_OBJ_NUM_MAX;
|
||||
can_ram_get_layout(&layout, &mcp251xfd_ram_config, NULL, NULL, fd_mode);
|
||||
ring->rx_max_pending = layout.max_rx;
|
||||
ring->tx_max_pending = layout.max_tx;
|
||||
|
||||
ring->rx_pending = priv->rx_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 = {
|
||||
.get_ringparam = mcp251xfd_ring_get_ringparam,
|
||||
.set_ringparam = mcp251xfd_ring_set_ringparam,
|
||||
};
|
||||
|
||||
void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)
|
||||
{
|
||||
struct can_ram_layout layout;
|
||||
|
||||
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 @@
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#include "mcp251xfd.h"
|
||||
#include "mcp251xfd-ram.h"
|
||||
|
||||
static inline u8
|
||||
mcp251xfd_cmd_prepare_write_reg(const 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)
|
||||
{
|
||||
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;
|
||||
u8 tef_obj_size, tx_obj_size, rx_obj_size;
|
||||
u8 tx_obj_num;
|
||||
u8 tx_obj_size, rx_obj_size;
|
||||
u8 rem, i;
|
||||
|
||||
tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj);
|
||||
if (mcp251xfd_is_fd_mode(priv)) {
|
||||
tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT;
|
||||
tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
|
||||
rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
|
||||
} else {
|
||||
tx_obj_num = MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT;
|
||||
tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
|
||||
rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
|
||||
/* switching from CAN-2.0 to CAN-FD mode or vice versa */
|
||||
if (fd_mode != test_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags)) {
|
||||
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;
|
||||
}
|
||||
|
||||
priv->rx_obj_num = 0;
|
||||
if (fd_mode) {
|
||||
tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_canfd);
|
||||
rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_canfd);
|
||||
set_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
|
||||
} else {
|
||||
tx_obj_size = sizeof(struct mcp251xfd_hw_tx_obj_can);
|
||||
rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
|
||||
clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
|
||||
}
|
||||
|
||||
tx_ring = priv->tx;
|
||||
tx_ring->obj_num = tx_obj_num;
|
||||
tx_ring->obj_size = tx_obj_size;
|
||||
|
||||
rem = (MCP251XFD_RAM_SIZE - tx_obj_num *
|
||||
(tef_obj_size + tx_obj_size)) / rx_obj_size;
|
||||
rem = priv->rx_obj_num;
|
||||
for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) {
|
||||
u8 rx_obj_num;
|
||||
|
||||
@ -319,8 +350,6 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
|
||||
MCP251XFD_FIFO_DEPTH);
|
||||
rem -= rx_obj_num;
|
||||
|
||||
priv->rx_obj_num += rx_obj_num;
|
||||
|
||||
rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
|
||||
GFP_KERNEL);
|
||||
if (!rx_ring) {
|
||||
|
@ -582,6 +582,12 @@ struct mcp251xfd_devtype_data {
|
||||
u32 quirks;
|
||||
};
|
||||
|
||||
enum mcp251xfd_flags {
|
||||
MCP251XFD_FLAGS_FD_MODE,
|
||||
|
||||
__MCP251XFD_FLAGS_SIZE__
|
||||
};
|
||||
|
||||
struct mcp251xfd_priv {
|
||||
struct can_priv can;
|
||||
struct can_rx_offload offload;
|
||||
@ -607,6 +613,8 @@ struct mcp251xfd_priv {
|
||||
struct mcp251xfd_rx_ring *rx[MCP251XFD_FIFO_RX_NUM];
|
||||
struct mcp251xfd_tx_ring tx[MCP251XFD_FIFO_TX_NUM];
|
||||
|
||||
DECLARE_BITMAP(flags, __MCP251XFD_FLAGS_SIZE__);
|
||||
|
||||
u8 rx_ring_num;
|
||||
u8 rx_obj_num;
|
||||
|
||||
@ -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);
|
||||
void mcp251xfd_ethtool_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);
|
||||
void mcp251xfd_ring_free(struct mcp251xfd_priv *priv);
|
||||
int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv);
|
||||
|
Loading…
Reference in New Issue
Block a user