summaryrefslogtreecommitdiff
path: root/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
diff options
context:
space:
mode:
authorMarc Kleine-Budde <mkl@pengutronix.de>2021-02-16 11:46:16 +0100
committerMarc Kleine-Budde <mkl@pengutronix.de>2022-03-13 09:45:35 +0100
commitb8123d94f58cdd1f3d476f60156fc356194bec55 (patch)
treecffadcd9ccfcd1a59f8b5bb97f688ad39921d27b /drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
parenta1439a5add6266ae1c02d2ef60c188ae16f4384a (diff)
can: mcp251xfd: ram: coalescing support
This patch adds support for coalescing to the RAM layout calculation. Link: https://lore.kernel.org/20220313083640.501791-4-mkl@pengutronix.de Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
Diffstat (limited to 'drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c')
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c70
1 files changed, 63 insertions, 7 deletions
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
index 6e7293e50d2c..9e8e82cdba46 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
@@ -20,13 +20,26 @@ static inline u8 can_ram_clamp(const struct can_ram_config *config,
static u8
can_ram_rounddown_pow_of_two(const struct can_ram_config *config,
- const struct can_ram_obj_config *obj, u8 val)
+ const struct can_ram_obj_config *obj,
+ const u8 coalesce, u8 val)
{
u8 fifo_num = obj->fifo_num;
u8 ret = 0, i;
val = can_ram_clamp(config, obj, val);
+ if (coalesce) {
+ /* Use 1st FIFO for coalescing, if requested.
+ *
+ * Either use complete FIFO (and FIFO Full IRQ) for
+ * coalescing or only half of FIFO (FIFO Half Full
+ * IRQ) and use remaining half for normal objects.
+ */
+ ret = min_t(u8, coalesce * 2, config->fifo_depth);
+ val -= ret;
+ fifo_num--;
+ }
+
for (i = 0; i < fifo_num && val; i++) {
u8 n;
@@ -47,6 +60,7 @@ can_ram_rounddown_pow_of_two(const struct can_ram_config *config,
void can_ram_get_layout(struct can_ram_layout *layout,
const struct can_ram_config *config,
const struct ethtool_ringparam *ring,
+ const struct ethtool_coalesce *ec,
const bool fd_mode)
{
u8 num_rx, num_tx;
@@ -55,14 +69,14 @@ void can_ram_get_layout(struct can_ram_layout *layout,
/* default CAN */
num_tx = config->tx.def[fd_mode];
- num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, num_tx);
+ num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, 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_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
layout->default_tx = num_tx;
/* MAX CAN */
@@ -75,23 +89,65 @@ void can_ram_get_layout(struct can_ram_layout *layout,
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);
+ layout->max_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, num_rx);
+ layout->max_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
/* cur CAN */
if (ring) {
- num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, ring->rx_pending);
+ u8 num_rx_coalesce = 0, num_tx_coalesce = 0;
+
+ num_rx = can_ram_rounddown_pow_of_two(config, &config->rx, 0, ring->rx_pending);
+
+ /* The ethtool doc says:
+ * To disable coalescing, set usecs = 0 and max_frames = 1.
+ */
+ if (ec && !(ec->rx_coalesce_usecs_irq == 0 &&
+ ec->rx_max_coalesced_frames_irq == 1)) {
+ u8 max;
+
+ /* use only max half of available objects for coalescing */
+ max = min_t(u8, num_rx / 2, config->fifo_depth);
+ num_rx_coalesce = clamp(ec->rx_max_coalesced_frames_irq,
+ (u32)config->rx.fifo_depth_coalesce_min,
+ (u32)max);
+ num_rx_coalesce = rounddown_pow_of_two(num_rx_coalesce);
+
+ num_rx = can_ram_rounddown_pow_of_two(config, &config->rx,
+ num_rx_coalesce, num_rx);
+ }
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);
+ num_tx = can_ram_rounddown_pow_of_two(config, &config->tx, 0, num_tx);
+
+ /* The ethtool doc says:
+ * To disable coalescing, set usecs = 0 and max_frames = 1.
+ */
+ if (ec && !(ec->tx_coalesce_usecs_irq == 0 &&
+ ec->tx_max_coalesced_frames_irq == 1)) {
+ u8 max;
+
+ /* use only max half of available objects for coalescing */
+ max = min_t(u8, num_tx / 2, config->fifo_depth);
+ num_tx_coalesce = clamp(ec->tx_max_coalesced_frames_irq,
+ (u32)config->tx.fifo_depth_coalesce_min,
+ (u32)max);
+ num_tx_coalesce = rounddown_pow_of_two(num_tx_coalesce);
+
+ num_tx = can_ram_rounddown_pow_of_two(config, &config->tx,
+ num_tx_coalesce, num_tx);
+ }
layout->cur_rx = num_rx;
layout->cur_tx = num_tx;
+ layout->rx_coalesce = num_rx_coalesce;
+ layout->tx_coalesce = num_tx_coalesce;
} else {
layout->cur_rx = layout->default_rx;
layout->cur_tx = layout->default_tx;
+ layout->rx_coalesce = 0;
+ layout->tx_coalesce = 0;
}
}