Commit a1439a5a authored by Marc Kleine-Budde's avatar Marc Kleine-Budde

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.deSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent c47675b1
......@@ -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
......
// 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;
}
}
/* 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
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