[can-next-rfc 03/12] can: mcp251xfd: ram: coalescing support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds support for coalescing to the RAM layout calculation.

Signed-off-by: Marc Kleine-Budde <mkl@xxxxxxxxxxxxxx>
---
 drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c | 70 +++++++++++++++++--
 drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h |  5 ++
 2 files changed, 68 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;
 	}
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h
index c998a033c9cb..7558c1510cbf 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h
@@ -28,6 +28,7 @@ struct can_ram_obj_config {
 
 	u8 fifo_num;
 	u8 fifo_depth_min;
+	u8 fifo_depth_coalesce_min;
 };
 
 struct can_ram_config {
@@ -47,11 +48,15 @@ struct can_ram_layout {
 
 	u8 cur_rx;
 	u8 cur_tx;
+
+	u8 rx_coalesce;
+	u8 tx_coalesce;
 };
 
 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);
 
 #endif
-- 
2.35.1





[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux