diff options
author | Marc Kleine-Budde <mkl@pengutronix.de> | 2021-10-22 19:11:57 +0200 |
---|---|---|
committer | Marc Kleine-Budde <mkl@pengutronix.de> | 2022-03-13 09:45:35 +0100 |
commit | a1439a5add6266ae1c02d2ef60c188ae16f4384a (patch) | |
tree | 41ba71be68c604380c7dcdcff2c1de57c1abf4de /drivers/net/can | |
parent | can: mcp251xfd: mcp251xfd_ring_init(): use %d to print free RAM (diff) | |
download | linux-a1439a5add6266ae1c02d2ef60c188ae16f4384a.tar.xz linux-a1439a5add6266ae1c02d2ef60c188ae16f4384a.zip |
can: mcp251xfd: ram: add helper function for runtime ring size calculation
This patch adds a helper function to calculate the ring configuration
of the controller based on various constraints, like available RAM,
size of RX and TX objects, CAN-mode, number of FIFOs and FIFO depth.
Link: https://lore.kernel.org/20220313083640.501791-3-mkl@pengutronix.de
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can')
-rw-r--r-- | drivers/net/can/spi/mcp251xfd/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c | 97 | ||||
-rw-r--r-- | drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h | 57 |
3 files changed, 155 insertions, 0 deletions
diff --git a/drivers/net/can/spi/mcp251xfd/Makefile b/drivers/net/can/spi/mcp251xfd/Makefile index a83d685d64e0..10c4f886d1f7 100644 --- a/drivers/net/can/spi/mcp251xfd/Makefile +++ b/drivers/net/can/spi/mcp251xfd/Makefile @@ -6,6 +6,7 @@ mcp251xfd-objs := mcp251xfd-objs += mcp251xfd-chip-fifo.o mcp251xfd-objs += mcp251xfd-core.o mcp251xfd-objs += mcp251xfd-crc16.o +mcp251xfd-objs += mcp251xfd-ram.o mcp251xfd-objs += mcp251xfd-regmap.o mcp251xfd-objs += mcp251xfd-ring.o mcp251xfd-objs += mcp251xfd-rx.o diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c new file mode 100644 index 000000000000..6e7293e50d2c --- /dev/null +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mcp251xfd - Microchip MCP251xFD Family CAN controller driver +// +// Copyright (c) 2021, 2022 Pengutronix, +// Marc Kleine-Budde <kernel@pengutronix.de> +// + +#include "mcp251xfd-ram.h" + +static inline u8 can_ram_clamp(const struct can_ram_config *config, + const struct can_ram_obj_config *obj, + u8 val) +{ + u8 max; + + max = min_t(u8, obj->max, obj->fifo_num * config->fifo_depth); + return clamp(val, obj->min, max); +} + +static u8 +can_ram_rounddown_pow_of_two(const struct can_ram_config *config, + const struct can_ram_obj_config *obj, u8 val) +{ + u8 fifo_num = obj->fifo_num; + u8 ret = 0, i; + + val = can_ram_clamp(config, obj, val); + + for (i = 0; i < fifo_num && val; i++) { + u8 n; + + n = min_t(u8, rounddown_pow_of_two(val), + config->fifo_depth); + + /* skip small FIFOs */ + if (n < obj->fifo_depth_min) + return ret; + + ret += n; + val -= n; + } + + return ret; +} + +void can_ram_get_layout(struct can_ram_layout *layout, + const struct can_ram_config *config, + const struct ethtool_ringparam *ring, + const bool fd_mode) +{ + u8 num_rx, num_tx; + u16 ram_free; + + /* default CAN */ + + num_tx = config->tx.def[fd_mode]; + num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, num_tx); + + ram_free = config->size; + ram_free -= config->tx.size[fd_mode] * num_tx; + + num_rx = ram_free / config->rx.size[fd_mode]; + + layout->default_rx = can_ram_rounddown_pow_of_two(config, &config->rx, num_rx); + layout->default_tx = num_tx; + + /* MAX CAN */ + + ram_free = config->size; + ram_free -= config->tx.size[fd_mode] * config->tx.min; + num_rx = ram_free / config->rx.size[fd_mode]; + + ram_free = config->size; + ram_free -= config->rx.size[fd_mode] * config->rx.min; + num_tx = ram_free / config->tx.size[fd_mode]; + + layout->max_rx = can_ram_rounddown_pow_of_two(config, &config->rx, num_rx); + layout->max_tx = can_ram_rounddown_pow_of_two(config, &config->tx, num_tx); + + /* cur CAN */ + + if (ring) { + num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, ring->rx_pending); + + ram_free = config->size - config->rx.size[fd_mode] * num_rx; + num_tx = ram_free / config->tx.size[fd_mode]; + num_tx = min_t(u8, ring->tx_pending, num_tx); + num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, num_tx); + + layout->cur_rx = num_rx; + layout->cur_tx = num_tx; + } else { + layout->cur_rx = layout->default_rx; + layout->cur_tx = layout->default_tx; + } +} diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h new file mode 100644 index 000000000000..c998a033c9cb --- /dev/null +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * mcp251xfd - Microchip MCP251xFD Family CAN controller driver + * + * Copyright (c) 2021, 2022 Pengutronix, + * Marc Kleine-Budde <kernel@pengutronix.de> + */ + +#ifndef _MCP251XFD_RAM_H +#define _MCP251XFD_RAM_H + +#include <linux/ethtool.h> + +#define CAN_RAM_NUM_MAX (-1) + +enum can_ram_mode { + CAN_RAM_MODE_CAN, + CAN_RAM_MODE_CANFD, + __CAN_RAM_MODE_MAX +}; + +struct can_ram_obj_config { + u8 size[__CAN_RAM_MODE_MAX]; + + u8 def[__CAN_RAM_MODE_MAX]; + u8 min; + u8 max; + + u8 fifo_num; + u8 fifo_depth_min; +}; + +struct can_ram_config { + const struct can_ram_obj_config rx; + const struct can_ram_obj_config tx; + + u16 size; + u8 fifo_depth; +}; + +struct can_ram_layout { + u8 default_rx; + u8 default_tx; + + u8 max_rx; + u8 max_tx; + + u8 cur_rx; + u8 cur_tx; +}; + +void can_ram_get_layout(struct can_ram_layout *layout, + const struct can_ram_config *config, + const struct ethtool_ringparam *ring, + const bool fd_mode); + +#endif |