All of lore.kernel.org
 help / color / mirror / Atom feed
* can-next 2022-03-13: mcp251xfd: add
@ 2022-03-13  8:36 Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 01/12] can: mcp251xfd: mcp251xfd_ring_init(): use %d to print free RAM Marc Kleine-Budde
                   ` (13 more replies)
  0 siblings, 14 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp

Hello,

this series for the mcp251xfd adds IRQ coalescing support.

It turned out, that I cannot reproduce the no-RX with activated
coalescing support on busy busses problem anymore. I added proper
patch descriptions and fixed some checkpatch long lines problems. I've
also removed the #define debug, which was only for testing. The rest
of the series in unchanged.

- What is IRQ coalescing and how does the mcp251xfd driver implement it?

The idea behind IRQ coalescing is to not serve every interrupt (CAN
frame RX'ed and CAN frame TX complete) as soon as possible, but to
delay it and handle several RX/TX complete frames at once. This
reduces the number of IRQs and SPI transfers.

With activated RX IRQ coalescing, the RX IRQ handler deactivated the
"RX FIFO not empty interrupt" and activated the "FIFO half full" (or
"FIFO full IRQ" - depending on configuration) instead.

To ensure that a single RX'ed CAN frame (which doesn't trigger the
FIFO half full IRQ) doesn't starve in the FIFO, a hrtimer is started
that activates the "FIFO not empty" IRQ after a configurable delay.

TX IRQ coalescing does the same thing, but for TX complete IRQs

- How to configure this?

Configuration is a bit tricky, it consists of several parameters,
which are all influencing each other and the number of buffers is
limited to power-of-two, to up to 32 per FIFO.

1) Configure the CAN mode (classical CAN-2.0 or CAN-FD) mode. Do not
   bring the interface up.

2) Configure RX and TX FIFOs. In ethtool's speak this is called "ring"
   configuration. The current ring configuration is shown with the
   "-g" parameter:

| $ ethtool -g mcp251xfd1
|
| Ring parameters for mcp251xfd1:
| Pre-set maximums:
| RX:             96
| RX Mini:        n/a
| RX Jumbo:       n/a
| TX:             16
| Current hardware settings:
| RX:             80
| RX Mini:        n/a
| RX Jumbo:       n/a
| TX:             8

   For TX, 1 FIFO is used with the default depth 8 (CAN-2.0 mode) and
   4 (CAN-FD mode). In default configuration the driver uses the
   remaining space for RX. In CAN-2.0 mode, this leads to 80 RX
   buffers and 8 TX buffers. A more detailed overview is printed when
   the interface is brought up:

| FIFO setup: TEF:         0x400:  8*12 bytes =   96 bytes
| FIFO setup: RX-0: FIFO 1/0x460: 32*20 bytes =  640 bytes
| FIFO setup: RX-1: FIFO 2/0x6e0: 32*20 bytes =  640 bytes
| FIFO setup: RX-2: FIFO 3/0x960: 16*20 bytes =  320 bytes
| FIFO setup: TX:   FIFO 4/0xaa0:  8*16 bytes =  128 bytes
| FIFO setup: free:                              224 bytes

   Note:
   - The number of RX buffers takes more priority than the number of
     TX buffers.
   - Ring configuration is reset by CAN mode configuration.
   - Ring configuration resets coalescing configuration.
   - Configuration is only possible if the interface is down.

   Let's increase the number of RX buffers to the max of 96.

| $ ethtool -G mcp251xfd1 rx 96 tx 4

   Check config with "-g":

| $ sudo ethtool -g mcp251xfd1
| Ring parameters for mcp251xfd1:
| Pre-set maximums:
| RX:             96
| RX Mini:        n/a
| RX Jumbo:       n/a
| TX:             16
| Current hardware settings:
| RX:             96
| RX Mini:        n/a
| RX Jumbo:       n/a
| TX:             4

   The detailed output during ifup:

| FIFO setup: TEF:         0x400:  4*12 bytes =   48 bytes
| FIFO setup: RX-0: FIFO 1/0x430: 32*20 bytes =  640 bytes
| FIFO setup: RX-1: FIFO 2/0x6b0: 32*20 bytes =  640 bytes
| FIFO setup: RX-2: FIFO 3/0x930: 32*20 bytes =  640 bytes
| FIFO setup: TX:   FIFO 4/0xbb0:  4*16 bytes =   64 bytes
| FIFO setup: free:                               16 bytes

3) Configure the RX/TX IRQ coalescing.
   The driver supports both RX and TX coalescing. The configuration is
   done again with ethtool, the interface must be down for this.

   There are 2 parameters to configure:
   1) FIFO fill level that triggers IRQ
   2) Delay after IRQ processing to enable FIFO not empty IRQ

   In this example we configure RX coalescing for 32 buffers with a
   delay of 10ms:

| $ ethtool -C mcp251xfd1 rx-usecs-irq 10000 rx-frames-irq 32

   Check with "-c":

| $ ethtool -c mcp251xfd1
|
| Coalesce parameters for mcp251xfd1:
| Adaptive RX: n/a  TX: n/a
| stats-block-usecs: n/a
| sample-interval: n/a
| pkt-rate-low: n/a
| pkt-rate-high: n/a
|
| rx-usecs: n/a
| rx-frames: n/a
| rx-usecs-irq: 10000
| rx-frames-irq: 32
|
| tx-usecs: n/a
| tx-frames: n/a
| tx-usecs-irq: 0
| tx-frames-irq: 1
|
| rx-usecs-low: n/a
| rx-frame-low: n/a
| tx-usecs-low: n/a
| tx-frame-low: n/a
|
| rx-usecs-high: n/a
| rx-frame-high: n/a
| tx-usecs-high: n/a
| tx-frame-high: n/a

   The TX IRQ coalescing parameters we see in this example output are
   "tx-usecs-irq=0" and "tx-frames-irq=1". This means no coalescing,
   i.e. every TX complete event triggers an IRQ and is directly served
   in the driver.

   Note:
   - Use "rx-usecs-irq=0" and "rx-frames-irq=1" to switch off RX
     coalescing, accordingly for TX.
   - Coalescing configuration is reset by ring configuration.
   - Configuration is only possible if the interface is down.

regards,
Marc




^ permalink raw reply	[flat|nested] 20+ messages in thread

* [can-next-rfc 01/12] can: mcp251xfd: mcp251xfd_ring_init(): use %d to print free RAM
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 02/12] can: mcp251xfd: ram: add helper function for runtime ring size calculation Marc Kleine-Budde
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

In case of an erroneous ring configuration more RAM than available
might be used. Change the printf modifier to a signed int to properly
print this erroneous value.

Fixes: 83daa863f16b ("can: mcp251xfd: ring: update FIFO setup debug info")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index 848b8b2ecb5f..b1c4d9b19347 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -261,7 +261,7 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
 		   priv->tx->obj_num * priv->tx->obj_size);
 
 	netdev_dbg(priv->ndev,
-		   "FIFO setup: free:                             %4u bytes\n",
+		   "FIFO setup: free:                             %4d bytes\n",
 		   MCP251XFD_RAM_SIZE - (base - MCP251XFD_RAM_START));
 
 	ram_used = base - MCP251XFD_RAM_START;

base-commit: 97aeb877de7f14f819fc2cf8388d7a2d8090489d
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 02/12] can: mcp251xfd: ram: add helper function for runtime ring size calculation
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 01/12] can: mcp251xfd: mcp251xfd_ring_init(): use %d to print free RAM Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 03/12] can: mcp251xfd: ram: coalescing support Marc Kleine-Budde
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

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.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/spi/mcp251xfd/Makefile        |  1 +
 drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c | 97 +++++++++++++++++++
 drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h | 57 +++++++++++
 3 files changed, 155 insertions(+)
 create mode 100644 drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.c
 create mode 100644 drivers/net/can/spi/mcp251xfd/mcp251xfd-ram.h

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
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 03/12] can: mcp251xfd: ram: coalescing support
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 01/12] can: mcp251xfd: mcp251xfd_ring_init(): use %d to print free RAM Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 02/12] can: mcp251xfd: ram: add helper function for runtime ring size calculation Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 04/12] can: mcp251xfd: ethtool: add support Marc Kleine-Budde
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

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

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 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



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 04/12] can: mcp251xfd: ethtool: add support
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 03/12] can: mcp251xfd: ram: coalescing support Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 05/12] can: mcp251xfd: ring: prepare support for runtime configurable RX/TX ring parameters Marc Kleine-Budde
                   ` (9 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch adds basic ethtool support (to query the current and
maximum ring parameters) to the driver.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/spi/mcp251xfd/Makefile        |  1 +
 .../net/can/spi/mcp251xfd/mcp251xfd-core.c    |  2 ++
 .../net/can/spi/mcp251xfd/mcp251xfd-ethtool.c | 35 +++++++++++++++++++
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    |  4 +++
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  2 ++
 5 files changed, 44 insertions(+)
 create mode 100644 drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c

diff --git a/drivers/net/can/spi/mcp251xfd/Makefile b/drivers/net/can/spi/mcp251xfd/Makefile
index 10c4f886d1f7..94d7de954294 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-ethtool.o
 mcp251xfd-objs += mcp251xfd-ram.o
 mcp251xfd-objs += mcp251xfd-regmap.o
 mcp251xfd-objs += mcp251xfd-ring.o
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 3da17cadbd63..ebb4dc999bac 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -1871,6 +1871,8 @@ static int mcp251xfd_register(struct mcp251xfd_priv *priv)
 	if (err)
 		goto out_chip_sleep;
 
+	mcp251xfd_ethtool_init(priv);
+
 	err = register_candev(ndev);
 	if (err)
 		goto out_chip_sleep;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
new file mode 100644
index 000000000000..4131185eaf5a
--- /dev/null
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
@@ -0,0 +1,35 @@
+// 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 <linux/ethtool.h>
+
+#include "mcp251xfd.h"
+
+static void
+mcp251xfd_ring_get_ringparam(struct net_device *ndev,
+			     struct ethtool_ringparam *ring,
+			     struct kernel_ethtool_ringparam *kernel_ring,
+			     struct netlink_ext_ack *extack)
+{
+	const struct mcp251xfd_priv *priv = netdev_priv(ndev);
+
+	ring->rx_max_pending = MCP251XFD_RX_OBJ_NUM_MAX;
+	ring->tx_max_pending = MCP251XFD_TX_OBJ_NUM_MAX;
+
+	ring->rx_pending = priv->rx_obj_num;
+	ring->tx_pending = priv->tx->obj_num;
+}
+
+static const struct ethtool_ops mcp251xfd_ethtool_ops = {
+	.get_ringparam = mcp251xfd_ring_get_ringparam,
+};
+
+void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)
+{
+	priv->ndev->ethtool_ops = &mcp251xfd_ethtool_ops;
+}
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index b1c4d9b19347..e540c97b4160 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -304,6 +304,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 		rx_obj_size = sizeof(struct mcp251xfd_hw_rx_obj_can);
 	}
 
+	priv->rx_obj_num = 0;
+
 	tx_ring = priv->tx;
 	tx_ring->obj_num = tx_obj_num;
 	tx_ring->obj_size = tx_obj_size;
@@ -320,6 +322,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 		rx_obj_num = min(1 << (fls(rx_obj_num) - 1),
 				 MCP251XFD_RX_OBJ_NUM_MAX);
 
+		priv->rx_obj_num += rx_obj_num;
+
 		rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
 				  GFP_KERNEL);
 		if (!rx_ring) {
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 87cc13d455c1..5c7a672464b1 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -610,6 +610,7 @@ struct mcp251xfd_priv {
 	struct mcp251xfd_tx_ring tx[MCP251XFD_FIFO_TX_NUM];
 
 	u8 rx_ring_num;
+	u8 rx_obj_num;
 
 	struct mcp251xfd_ecc ecc;
 	struct mcp251xfd_regs_status regs_status;
@@ -891,6 +892,7 @@ int mcp251xfd_chip_fifo_init(const struct mcp251xfd_priv *priv);
 u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size,
 			     const void *data, size_t data_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);
 int mcp251xfd_ring_init(struct mcp251xfd_priv *priv);
 void mcp251xfd_ring_free(struct mcp251xfd_priv *priv);
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 05/12] can: mcp251xfd: ring: prepare support for runtime configurable RX/TX ring parameters
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 04/12] can: mcp251xfd: ethtool: add support Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 06/12] can: mcp251xfd: update macros describing ring, FIFO and RAM layout Marc Kleine-Budde
                   ` (8 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch prepares the driver for runtime configurable RX and TX ring
parameters. The actual runtime config support will be added in the
next patch.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    | 26 ++++++++-----------
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  2 ++
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index e540c97b4160..0e78941601bf 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -289,9 +289,9 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 {
 	struct mcp251xfd_tx_ring *tx_ring;
 	struct mcp251xfd_rx_ring *rx_ring;
-	int tef_obj_size, tx_obj_size, rx_obj_size;
-	int tx_obj_num;
-	int ram_free, i;
+	u8 tef_obj_size, tx_obj_size, rx_obj_size;
+	u8 tx_obj_num;
+	u8 rem, i;
 
 	tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj);
 	if (mcp251xfd_is_fd_mode(priv)) {
@@ -310,17 +310,14 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 	tx_ring->obj_num = tx_obj_num;
 	tx_ring->obj_size = tx_obj_size;
 
-	ram_free = MCP251XFD_RAM_SIZE - tx_obj_num *
-		(tef_obj_size + tx_obj_size);
+	rem = (MCP251XFD_RAM_SIZE - tx_obj_num *
+	       (tef_obj_size + tx_obj_size)) / rx_obj_size;
+	for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) {
+		u8 rx_obj_num;
 
-	for (i = 0;
-	     i < ARRAY_SIZE(priv->rx) && ram_free >= rx_obj_size;
-	     i++) {
-		int rx_obj_num;
-
-		rx_obj_num = ram_free / rx_obj_size;
-		rx_obj_num = min(1 << (fls(rx_obj_num) - 1),
-				 MCP251XFD_RX_OBJ_NUM_MAX);
+		rx_obj_num = min_t(u8, rounddown_pow_of_two(rem),
+				   MCP251XFD_FIFO_DEPTH);
+		rem -= rx_obj_num;
 
 		priv->rx_obj_num += rx_obj_num;
 
@@ -330,11 +327,10 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 			mcp251xfd_ring_free(priv);
 			return -ENOMEM;
 		}
+
 		rx_ring->obj_num = rx_obj_num;
 		rx_ring->obj_size = rx_obj_size;
 		priv->rx[i] = rx_ring;
-
-		ram_free -= rx_ring->obj_num * rx_ring->obj_size;
 	}
 	priv->rx_ring_num = i;
 
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 5c7a672464b1..bd7a9999b5e3 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -415,6 +415,8 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_FIFO_RX_NUM_MAX 1U
 #define MCP251XFD_FIFO_TX_NUM 1U
 
+#define MCP251XFD_FIFO_DEPTH 32U
+
 static_assert(MCP251XFD_FIFO_TEF_NUM == 1U);
 static_assert(MCP251XFD_FIFO_TEF_NUM == MCP251XFD_FIFO_TX_NUM);
 static_assert(MCP251XFD_FIFO_RX_NUM_MAX <= 4U);
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 06/12] can: mcp251xfd: update macros describing ring, FIFO and RAM layout
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 05/12] can: mcp251xfd: ring: prepare support for runtime configurable RX/TX ring parameters Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 07/12] can: mcp251xfd: ring: add support for runtime configurable RX/TX ring parameters Marc Kleine-Budde
                   ` (7 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

So far the configuration of the hardware FIFOs is hard coded and
depend only on the selected CAN mode (CAN-2.0 or CAN-FD).

This patch updates the macros describing the ring, FIFO and RAM layout
to prepare for the next patches that add support for runtime
configurable ring parameters via ethtool.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    |  4 +-
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     | 38 +++++++++----------
 2 files changed, 19 insertions(+), 23 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index 0e78941601bf..bb0e342c2d15 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -295,11 +295,11 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 
 	tef_obj_size = sizeof(struct mcp251xfd_hw_tef_obj);
 	if (mcp251xfd_is_fd_mode(priv)) {
-		tx_obj_num = MCP251XFD_TX_OBJ_NUM_CANFD;
+		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;
+		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);
 	}
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index bd7a9999b5e3..b1cc8d19438e 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -367,23 +367,6 @@
 #define MCP251XFD_REG_DEVID_ID_MASK GENMASK(7, 4)
 #define MCP251XFD_REG_DEVID_REV_MASK GENMASK(3, 0)
 
-/* number of TX FIFO objects, depending on CAN mode
- *
- * FIFO setup: tef: 8*12 bytes = 96 bytes, tx: 8*16 bytes = 128 bytes
- * FIFO setup: tef: 4*12 bytes = 48 bytes, tx: 4*72 bytes = 288 bytes
- */
-#define MCP251XFD_RX_OBJ_NUM_MAX 32
-#define MCP251XFD_TX_OBJ_NUM_CAN 8
-#define MCP251XFD_TX_OBJ_NUM_CANFD 4
-
-#if MCP251XFD_TX_OBJ_NUM_CAN > MCP251XFD_TX_OBJ_NUM_CANFD
-#define MCP251XFD_TX_OBJ_NUM_MAX MCP251XFD_TX_OBJ_NUM_CAN
-#else
-#define MCP251XFD_TX_OBJ_NUM_MAX MCP251XFD_TX_OBJ_NUM_CANFD
-#endif
-
-#define MCP251XFD_NAPI_WEIGHT 32
-
 /* SPI commands */
 #define MCP251XFD_SPI_INSTRUCTION_RESET 0x0000
 #define MCP251XFD_SPI_INSTRUCTION_WRITE 0x2000
@@ -404,6 +387,9 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
 #define MCP251XFD_POLL_SLEEP_US (10)
 #define MCP251XFD_POLL_TIMEOUT_US (USEC_PER_MSEC)
+
+/* Misc */
+#define MCP251XFD_NAPI_WEIGHT 32
 #define MCP251XFD_SOFTRESET_RETRIES_MAX 3
 #define MCP251XFD_READ_CRC_RETRIES_MAX 3
 #define MCP251XFD_ECC_CNT_MAX 2
@@ -412,14 +398,24 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 
 /* FIFO and Ring */
 #define MCP251XFD_FIFO_TEF_NUM 1U
-#define MCP251XFD_FIFO_RX_NUM_MAX 1U
+#define MCP251XFD_FIFO_RX_NUM 1U
 #define MCP251XFD_FIFO_TX_NUM 1U
 
 #define MCP251XFD_FIFO_DEPTH 32U
 
+#define MCP251XFD_RX_OBJ_NUM_MIN 16U
+#define MCP251XFD_RX_OBJ_NUM_MAX (MCP251XFD_FIFO_RX_NUM * MCP251XFD_FIFO_DEPTH)
+#define MCP251XFD_RX_FIFO_DEPTH_MIN 4U
+
+#define MCP251XFD_TX_OBJ_NUM_MIN 2U
+#define MCP251XFD_TX_OBJ_NUM_MAX 8U
+#define MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT 8U
+#define MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT 4U
+#define MCP251XFD_TX_FIFO_DEPTH_MIN 2U
+
 static_assert(MCP251XFD_FIFO_TEF_NUM == 1U);
 static_assert(MCP251XFD_FIFO_TEF_NUM == MCP251XFD_FIFO_TX_NUM);
-static_assert(MCP251XFD_FIFO_RX_NUM_MAX <= 4U);
+static_assert(MCP251XFD_FIFO_RX_NUM <= 4U);
 
 /* Silence TX MAB overflow warnings */
 #define MCP251XFD_QUIRK_MAB_NO_WARN BIT(0)
@@ -550,7 +546,7 @@ struct mcp251xfd_rx_ring {
 	u8 obj_size;
 
 	union mcp251xfd_write_reg_buf uinc_buf;
-	struct spi_transfer uinc_xfer[MCP251XFD_RX_OBJ_NUM_MAX];
+	struct spi_transfer uinc_xfer[MCP251XFD_FIFO_DEPTH];
 	struct mcp251xfd_hw_rx_obj_canfd obj[];
 };
 
@@ -608,7 +604,7 @@ struct mcp251xfd_priv {
 	u32 spi_max_speed_hz_slow;
 
 	struct mcp251xfd_tef_ring tef[MCP251XFD_FIFO_TEF_NUM];
-	struct mcp251xfd_rx_ring *rx[MCP251XFD_FIFO_RX_NUM_MAX];
+	struct mcp251xfd_rx_ring *rx[MCP251XFD_FIFO_RX_NUM];
 	struct mcp251xfd_tx_ring tx[MCP251XFD_FIFO_TX_NUM];
 
 	u8 rx_ring_num;
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 07/12] can: mcp251xfd: ring: add support for runtime configurable RX/TX ring parameters
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 06/12] can: mcp251xfd: update macros describing ring, FIFO and RAM layout Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 08/12] can: mcp251xfd: add RX IRQ coalescing support Marc Kleine-Budde
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch adds runtime configurable RX and TX ring parameters via
ethtool to the driver.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ethtool.c | 37 +++++++++++-
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    | 59 ++++++++++++++-----
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  9 +++
 3 files changed, 88 insertions(+), 17 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
index 4131185eaf5a..8825195fa05f 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
@@ -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;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index bb0e342c2d15..2ff4d4e803b0 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -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;
+	/* 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;
+	}
+
+	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_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);
+		clear_bit(MCP251XFD_FLAGS_FD_MODE, priv->flags);
 	}
 
-	priv->rx_obj_num = 0;
-
-	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) {
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index b1cc8d19438e..c61df2036fdf 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -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);
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 08/12] can: mcp251xfd: add RX IRQ coalescing support
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 07/12] can: mcp251xfd: ring: add support for runtime configurable RX/TX ring parameters Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 09/12] can: mcp251xfd: add RX IRQ coalescing ethtool support Marc Kleine-Budde
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch adds RX IRQ coalescing support to the driver.

The mcp251xfd chip doesn't support proper hardware based coalescing,
so this patch tries to implemented it in software. The RX-FIFO offers
a "FIFO not empty" interrupt, which is used if no coalescing is
active.

With activated RX IRQ coalescing the "FIFO not empty" interrupt is
disabled in the RX IRQ handler and the "FIFO half full" or "FIFO full
interrupt" (depending on RX max coalesced frames IRQ) is used instead.
To avoid RX CAN frame starvation a hrtimer is setup with RX coalesce
usecs IRQ,on timer expiration the "FIFO not empty" is enabled again.

Support for ethtool configuration is added in the next patch.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-core.c    |   5 +
 .../net/can/spi/mcp251xfd/mcp251xfd-ethtool.c |   3 +
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    | 103 ++++++++++++++++--
 drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c  |  12 +-
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  10 ++
 5 files changed, 123 insertions(+), 10 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index ebb4dc999bac..325024be7b04 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -1598,6 +1598,7 @@ static int mcp251xfd_open(struct net_device *ndev)
 		goto out_transceiver_disable;
 
 	mcp251xfd_timestamp_init(priv);
+	clear_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
 	can_rx_offload_enable(&priv->offload);
 
 	err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq,
@@ -1618,6 +1619,7 @@ static int mcp251xfd_open(struct net_device *ndev)
 	free_irq(spi->irq, priv);
  out_can_rx_offload_disable:
 	can_rx_offload_disable(&priv->offload);
+	set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
 	mcp251xfd_timestamp_stop(priv);
  out_transceiver_disable:
 	mcp251xfd_transceiver_disable(priv);
@@ -1637,6 +1639,8 @@ static int mcp251xfd_stop(struct net_device *ndev)
 	struct mcp251xfd_priv *priv = netdev_priv(ndev);
 
 	netif_stop_queue(ndev);
+	set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
+	hrtimer_cancel(&priv->rx_irq_timer);
 	mcp251xfd_chip_interrupts_disable(priv);
 	free_irq(ndev->irq, priv);
 	can_rx_offload_disable(&priv->offload);
@@ -2036,6 +2040,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
 		CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING |
 		CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
 		CAN_CTRLMODE_CC_LEN8_DLC;
+	set_bit(MCP251XFD_FLAGS_DOWN, priv->flags);
 	priv->ndev = ndev;
 	priv->spi = spi;
 	priv->rx_int = rx_int;
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
index 8825195fa05f..8f14c9c08929 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
@@ -65,4 +65,7 @@ void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)
 	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;
+
+	priv->rx_obj_num_coalesce_irq = 0;
+	priv->rx_coalesce_usecs_irq = 0;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index 2ff4d4e803b0..6dbbc5b8a069 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -182,8 +182,18 @@ mcp251xfd_ring_init_rx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
 		*base = mcp251xfd_get_rx_obj_addr(rx_ring, rx_ring->obj_num);
 		*fifo_nr += 1;
 
-		/* FIFO increment RX tail pointer */
+		/* FIFO IRQ enable */
 		addr = MCP251XFD_REG_FIFOCON(rx_ring->fifo_nr);
+		val = MCP251XFD_REG_FIFOCON_RXOVIE |
+			MCP251XFD_REG_FIFOCON_TFNRFNIE;
+		len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->irq_enable_buf,
+						      addr, val, val);
+		rx_ring->irq_enable_xfer.tx_buf = &rx_ring->irq_enable_buf;
+		rx_ring->irq_enable_xfer.len = len;
+		spi_message_init_with_transfers(&rx_ring->irq_enable_msg,
+						&rx_ring->irq_enable_xfer, 1);
+
+		/* FIFO increment RX tail pointer */
 		val = MCP251XFD_REG_FIFOCON_UINC;
 		len = mcp251xfd_cmd_prepare_write_reg(priv, &rx_ring->uinc_buf,
 						      addr, val, val);
@@ -205,6 +215,39 @@ mcp251xfd_ring_init_rx(struct mcp251xfd_priv *priv, u16 *base, u8 *fifo_nr)
 		 * the chip select at the end of the message.
 		 */
 		xfer->cs_change = 0;
+
+		/* Use 1st RX-FIFO for IRQ coalescing. If enabled
+		 * (rx_coalesce_usecs_irq or rx_max_coalesce_frames_irq
+		 * is activated), use the last transfer to disable:
+		 *
+		 * - TFNRFNIE (Receive FIFO Not Empty Interrupt)
+		 *
+		 * and enable:
+		 *
+		 * - TFHRFHIE (Receive FIFO Half Full Interrupt)
+		 *   - or -
+		 * - TFERFFIE (Receive FIFO Full Interrupt)
+		 *
+		 * depending on rx_max_coalesce_frames_irq.
+		 *
+		 * The RXOVIE (Overflow Interrupt) is always enabled.
+		 */
+		if (rx_ring->nr == 0 && (priv->rx_coalesce_usecs_irq ||
+					 priv->rx_obj_num_coalesce_irq)) {
+			val = MCP251XFD_REG_FIFOCON_UINC |
+				MCP251XFD_REG_FIFOCON_RXOVIE;
+
+			if (priv->rx_obj_num_coalesce_irq == rx_ring->obj_num)
+				val |= MCP251XFD_REG_FIFOCON_TFERFFIE;
+			else if (priv->rx_obj_num_coalesce_irq)
+				val |= MCP251XFD_REG_FIFOCON_TFHRFHIE;
+
+			len = mcp251xfd_cmd_prepare_write_reg(priv,
+							      &rx_ring->uinc_irq_disable_buf,
+							      addr, val, val);
+			xfer->tx_buf = &rx_ring->uinc_irq_disable_buf;
+			xfer->len = len;
+		}
 	}
 }
 
@@ -246,12 +289,33 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
 		   priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
 
 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
-		netdev_dbg(priv->ndev,
-			   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
-			   rx_ring->nr, rx_ring->fifo_nr,
-			   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
-			   rx_ring->obj_num, rx_ring->obj_size,
-			   rx_ring->obj_num * rx_ring->obj_size);
+		if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
+			netdev_dbg(priv->ndev,
+				   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes (coalesce)\n",
+				   rx_ring->nr, rx_ring->fifo_nr,
+				   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
+				   priv->rx_obj_num_coalesce_irq, rx_ring->obj_size,
+				   priv->rx_obj_num_coalesce_irq * rx_ring->obj_size);
+
+			if (priv->rx_obj_num_coalesce_irq == MCP251XFD_FIFO_DEPTH)
+				continue;
+
+			netdev_dbg(priv->ndev,
+				   "                         0x%03x: %2u*%u bytes = %4u bytes\n",
+				   mcp251xfd_get_rx_obj_addr(rx_ring,
+							     priv->rx_obj_num_coalesce_irq),
+				   rx_ring->obj_num - priv->rx_obj_num_coalesce_irq,
+				   rx_ring->obj_size,
+				   (rx_ring->obj_num - priv->rx_obj_num_coalesce_irq) *
+				   rx_ring->obj_size);
+		} else {
+			netdev_dbg(priv->ndev,
+				   "FIFO setup: RX-%u: FIFO %u/0x%03x: %2u*%u bytes = %4u bytes\n",
+				   rx_ring->nr, rx_ring->fifo_nr,
+				   mcp251xfd_get_rx_obj_addr(rx_ring, 0),
+				   rx_ring->obj_num, rx_ring->obj_size,
+				   rx_ring->obj_num * rx_ring->obj_size);
+		}
 	}
 
 	netdev_dbg(priv->ndev,
@@ -286,6 +350,20 @@ void mcp251xfd_ring_free(struct mcp251xfd_priv *priv)
 	}
 }
 
+static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
+{
+	struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
+						   rx_irq_timer);
+	struct mcp251xfd_rx_ring *ring = priv->rx[0];
+
+	if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
+		return HRTIMER_NORESTART;
+
+	spi_async(priv->spi, &ring->irq_enable_msg);
+
+	return HRTIMER_NORESTART;
+}
+
 const struct can_ram_config mcp251xfd_ram_config = {
 	.rx = {
 		.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
@@ -346,8 +424,12 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 	for (i = 0; i < ARRAY_SIZE(priv->rx) && rem; i++) {
 		u8 rx_obj_num;
 
-		rx_obj_num = min_t(u8, rounddown_pow_of_two(rem),
-				   MCP251XFD_FIFO_DEPTH);
+		if (i == 0 && priv->rx_obj_num_coalesce_irq)
+			rx_obj_num = min_t(u8, priv->rx_obj_num_coalesce_irq * 2,
+					   MCP251XFD_FIFO_DEPTH);
+		else
+			rx_obj_num = min_t(u8, rounddown_pow_of_two(rem),
+					   MCP251XFD_FIFO_DEPTH);
 		rem -= rx_obj_num;
 
 		rx_ring = kzalloc(sizeof(*rx_ring) + rx_obj_size * rx_obj_num,
@@ -363,5 +445,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 	}
 	priv->rx_ring_num = i;
 
+	hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer;
+
 	return 0;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c
index e6d39876065a..d09f7fbf2ba7 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-rx.c
@@ -254,7 +254,11 @@ int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
 	int err, n;
 
 	mcp251xfd_for_each_rx_ring(priv, ring, n) {
-		if (!(priv->regs_status.rxif & BIT(ring->fifo_nr)))
+		/* - if RX IRQ coalescing is active always handle ring 0
+		 * - only handle rings if RX IRQ is active
+		 */
+		if ((ring->nr > 0 || !priv->rx_obj_num_coalesce_irq) &&
+		    !(priv->regs_status.rxif & BIT(ring->fifo_nr)))
 			continue;
 
 		err = mcp251xfd_handle_rxif_ring(priv, ring);
@@ -262,5 +266,11 @@ int mcp251xfd_handle_rxif(struct mcp251xfd_priv *priv)
 			return err;
 	}
 
+	if (priv->rx_coalesce_usecs_irq)
+		hrtimer_start(&priv->rx_irq_timer,
+			      ns_to_ktime(priv->rx_coalesce_usecs_irq *
+					  NSEC_PER_USEC),
+			      HRTIMER_MODE_REL);
+
 	return 0;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index c61df2036fdf..ef4728039998 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -545,7 +545,12 @@ struct mcp251xfd_rx_ring {
 	u8 obj_num;
 	u8 obj_size;
 
+	union mcp251xfd_write_reg_buf irq_enable_buf;
+	struct spi_transfer irq_enable_xfer;
+	struct spi_message irq_enable_msg;
+
 	union mcp251xfd_write_reg_buf uinc_buf;
+	union mcp251xfd_write_reg_buf uinc_irq_disable_buf;
 	struct spi_transfer uinc_xfer[MCP251XFD_FIFO_DEPTH];
 	struct mcp251xfd_hw_rx_obj_canfd obj[];
 };
@@ -583,6 +588,7 @@ struct mcp251xfd_devtype_data {
 };
 
 enum mcp251xfd_flags {
+	MCP251XFD_FLAGS_DOWN,
 	MCP251XFD_FLAGS_FD_MODE,
 
 	__MCP251XFD_FLAGS_SIZE__
@@ -617,6 +623,10 @@ struct mcp251xfd_priv {
 
 	u8 rx_ring_num;
 	u8 rx_obj_num;
+	u8 rx_obj_num_coalesce_irq;
+
+	u32 rx_coalesce_usecs_irq;
+	struct hrtimer rx_irq_timer;
 
 	struct mcp251xfd_ecc ecc;
 	struct mcp251xfd_regs_status regs_status;
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 09/12] can: mcp251xfd: add RX IRQ coalescing ethtool support
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 08/12] can: mcp251xfd: add RX IRQ coalescing support Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 10/12] can: mcp251xfd: add TX IRQ coalesce support Marc Kleine-Budde
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch adds support ethtool based configuration for the RX IRQ
coalescing added in the previous patch.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ethtool.c | 55 +++++++++++++++++++
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    |  1 +
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  1 +
 3 files changed, 57 insertions(+)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
index 8f14c9c08929..6e49cf3411a2 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
@@ -46,14 +46,69 @@ mcp251xfd_ring_set_ringparam(struct net_device *ndev,
 		return -EBUSY;
 
 	priv->rx_obj_num = layout.cur_rx;
+	priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
+	priv->tx->obj_num = layout.cur_tx;
+
+	return 0;
+}
+
+static int mcp251xfd_ring_get_coalesce(struct net_device *ndev,
+				       struct ethtool_coalesce *ec,
+				       struct kernel_ethtool_coalesce *kec,
+				       struct netlink_ext_ack *ext_ack)
+{
+	struct mcp251xfd_priv *priv = netdev_priv(ndev);
+	u32 rx_max_frames;
+
+	/* The ethtool doc says:
+	 * To disable coalescing, set usecs = 0 and max_frames = 1.
+	 */
+	if (priv->rx_obj_num_coalesce_irq == 0)
+		rx_max_frames = 1;
+	else
+		rx_max_frames = priv->rx_obj_num_coalesce_irq;
+
+	ec->rx_max_coalesced_frames_irq = rx_max_frames;
+	ec->rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq;
+
+	return 0;
+}
+
+static int mcp251xfd_ring_set_coalesce(struct net_device *ndev,
+				       struct ethtool_coalesce *ec,
+				       struct kernel_ethtool_coalesce *kec,
+				       struct netlink_ext_ack *ext_ack)
+{
+	struct mcp251xfd_priv *priv = netdev_priv(ndev);
+	const bool fd_mode = mcp251xfd_is_fd_mode(priv);
+	const struct ethtool_ringparam ring = {
+		.rx_pending = priv->rx_obj_num,
+		.tx_pending = priv->tx->obj_num,
+	};
+	struct can_ram_layout layout;
+
+	can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, ec, fd_mode);
+
+	if ((layout.rx_coalesce != priv->rx_obj_num_coalesce_irq ||
+	     ec->rx_coalesce_usecs_irq != priv->rx_coalesce_usecs_irq) &&
+	    netif_running(ndev))
+		return -EBUSY;
+
+	priv->rx_obj_num = layout.cur_rx;
+	priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
+	priv->rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq;
 	priv->tx->obj_num = layout.cur_tx;
 
 	return 0;
 }
 
 static const struct ethtool_ops mcp251xfd_ethtool_ops = {
+	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |
+		ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ,
 	.get_ringparam = mcp251xfd_ring_get_ringparam,
 	.set_ringparam = mcp251xfd_ring_set_ringparam,
+	.get_coalesce = mcp251xfd_ring_get_coalesce,
+	.set_coalesce = mcp251xfd_ring_set_coalesce,
 };
 
 void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index 6dbbc5b8a069..f12a7aa8af14 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -374,6 +374,7 @@ const struct can_ram_config mcp251xfd_ram_config = {
 		.def[CAN_RAM_MODE_CANFD] = CAN_RAM_NUM_MAX,
 		.fifo_num = MCP251XFD_FIFO_RX_NUM,
 		.fifo_depth_min = MCP251XFD_RX_FIFO_DEPTH_MIN,
+		.fifo_depth_coalesce_min = MCP251XFD_RX_FIFO_DEPTH_COALESCE_MIN,
 	},
 	.tx = {
 		.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_tef_obj) +
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index ef4728039998..8d912bacd2f1 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -406,6 +406,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_RX_OBJ_NUM_MIN 16U
 #define MCP251XFD_RX_OBJ_NUM_MAX (MCP251XFD_FIFO_RX_NUM * MCP251XFD_FIFO_DEPTH)
 #define MCP251XFD_RX_FIFO_DEPTH_MIN 4U
+#define MCP251XFD_RX_FIFO_DEPTH_COALESCE_MIN 8U
 
 #define MCP251XFD_TX_OBJ_NUM_MIN 2U
 #define MCP251XFD_TX_OBJ_NUM_MAX 8U
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 10/12] can: mcp251xfd: add TX IRQ coalesce support
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (8 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 09/12] can: mcp251xfd: add RX IRQ coalescing ethtool support Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 11/12] can: mcp251xfd: add TX IRQ coalesce ethtool support Marc Kleine-Budde
                   ` (3 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch adds TX IRQ coalescing support to the driver.

The implemented algorithm is similar to the RX IRQ coalescing support
added in the previous patch.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    | 68 +++++++++++++++++--
 drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c |  6 ++
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  8 +++
 3 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index f12a7aa8af14..3037ad3dd46b 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -71,6 +71,17 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
 	/* TEF- and TX-FIFO have same number of objects */
 	*base = mcp251xfd_get_tef_obj_addr(priv->tx->obj_num);
 
+	/* FIFO IRQ enable */
+	addr = MCP251XFD_REG_TEFCON;
+	val = MCP251XFD_REG_TEFCON_TEFOVIE | MCP251XFD_REG_TEFCON_TEFNEIE;
+
+	len = mcp251xfd_cmd_prepare_write_reg(priv, &tef_ring->irq_enable_buf,
+					      addr, val, val);
+	tef_ring->irq_enable_xfer.tx_buf = &tef_ring->irq_enable_buf;
+	tef_ring->irq_enable_xfer.len = len;
+	spi_message_init_with_transfers(&tef_ring->irq_enable_msg,
+					&tef_ring->irq_enable_xfer, 1);
+
 	/* FIFO increment TEF tail pointer */
 	addr = MCP251XFD_REG_TEFCON;
 	val = MCP251XFD_REG_TEFCON_UINC;
@@ -94,6 +105,18 @@ mcp251xfd_ring_init_tef(struct mcp251xfd_priv *priv, u16 *base)
 	 * message.
 	 */
 	xfer->cs_change = 0;
+
+	if (priv->tx_coalesce_usecs_irq || priv->tx_obj_num_coalesce_irq) {
+		val = MCP251XFD_REG_TEFCON_UINC |
+			MCP251XFD_REG_TEFCON_TEFOVIE |
+			MCP251XFD_REG_TEFCON_TEFHIE;
+
+		len = mcp251xfd_cmd_prepare_write_reg(priv,
+						      &tef_ring->uinc_irq_disable_buf,
+						      addr, val, val);
+		xfer->tx_buf = &tef_ring->uinc_irq_disable_buf;
+		xfer->len = len;
+	}
 }
 
 static void
@@ -282,11 +305,29 @@ int mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
 	 */
 	priv->regs_status.rxif = BIT(priv->rx[0]->fifo_nr);
 
-	netdev_dbg(priv->ndev,
-		   "FIFO setup: TEF:         0x%03x: %2d*%zu bytes = %4zu bytes\n",
-		   mcp251xfd_get_tef_obj_addr(0),
-		   priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj),
-		   priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
+	if (priv->tx_obj_num_coalesce_irq) {
+		netdev_dbg(priv->ndev,
+			   "FIFO setup: TEF:         0x%03x: %2d*%zu bytes = %4zu bytes (coalesce)\n",
+			   mcp251xfd_get_tef_obj_addr(0),
+			   priv->tx_obj_num_coalesce_irq,
+			   sizeof(struct mcp251xfd_hw_tef_obj),
+			   priv->tx_obj_num_coalesce_irq *
+			   sizeof(struct mcp251xfd_hw_tef_obj));
+
+		netdev_dbg(priv->ndev,
+			   "                         0x%03x: %2d*%zu bytes = %4zu bytes\n",
+			   mcp251xfd_get_tef_obj_addr(priv->tx_obj_num_coalesce_irq),
+			   priv->tx->obj_num - priv->tx_obj_num_coalesce_irq,
+			   sizeof(struct mcp251xfd_hw_tef_obj),
+			   (priv->tx->obj_num - priv->tx_obj_num_coalesce_irq) *
+			   sizeof(struct mcp251xfd_hw_tef_obj));
+	} else {
+		netdev_dbg(priv->ndev,
+			   "FIFO setup: TEF:         0x%03x: %2d*%zu bytes = %4zu bytes\n",
+			   mcp251xfd_get_tef_obj_addr(0),
+			   priv->tx->obj_num, sizeof(struct mcp251xfd_hw_tef_obj),
+			   priv->tx->obj_num * sizeof(struct mcp251xfd_hw_tef_obj));
+	}
 
 	mcp251xfd_for_each_rx_ring(priv, rx_ring, i) {
 		if (rx_ring->nr == 0 && priv->rx_obj_num_coalesce_irq) {
@@ -364,6 +405,20 @@ static enum hrtimer_restart mcp251xfd_rx_irq_timer(struct hrtimer *t)
 	return HRTIMER_NORESTART;
 }
 
+static enum hrtimer_restart mcp251xfd_tx_irq_timer(struct hrtimer *t)
+{
+	struct mcp251xfd_priv *priv = container_of(t, struct mcp251xfd_priv,
+						   tx_irq_timer);
+	struct mcp251xfd_tef_ring *ring = priv->tef;
+
+	if (test_bit(MCP251XFD_FLAGS_DOWN, priv->flags))
+		return HRTIMER_NORESTART;
+
+	spi_async(priv->spi, &ring->irq_enable_msg);
+
+	return HRTIMER_NORESTART;
+}
+
 const struct can_ram_config mcp251xfd_ram_config = {
 	.rx = {
 		.size[CAN_RAM_MODE_CAN] = sizeof(struct mcp251xfd_hw_rx_obj_can),
@@ -449,5 +504,8 @@ int mcp251xfd_ring_alloc(struct mcp251xfd_priv *priv)
 	hrtimer_init(&priv->rx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
 	priv->rx_irq_timer.function = mcp251xfd_rx_irq_timer;
 
+	hrtimer_init(&priv->tx_irq_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	priv->tx_irq_timer.function = mcp251xfd_tx_irq_timer;
+
 	return 0;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
index 406166005b99..237617b0c125 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
@@ -256,5 +256,11 @@ int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
 		netif_wake_queue(priv->ndev);
 	}
 
+	if (priv->tx_coalesce_usecs_irq)
+		hrtimer_start(&priv->tx_irq_timer,
+			      ns_to_ktime(priv->tx_coalesce_usecs_irq *
+					  NSEC_PER_USEC),
+			      HRTIMER_MODE_REL);
+
 	return 0;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index 8d912bacd2f1..ee2c93ddc5ed 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -518,7 +518,12 @@ struct mcp251xfd_tef_ring {
 	/* u8 obj_num equals tx_ring->obj_num */
 	/* u8 obj_size equals sizeof(struct mcp251xfd_hw_tef_obj) */
 
+	union mcp251xfd_write_reg_buf irq_enable_buf;
+	struct spi_transfer irq_enable_xfer;
+	struct spi_message irq_enable_msg;
+
 	union mcp251xfd_write_reg_buf uinc_buf;
+	union mcp251xfd_write_reg_buf uinc_irq_disable_buf;
 	struct spi_transfer uinc_xfer[MCP251XFD_TX_OBJ_NUM_MAX];
 };
 
@@ -625,9 +630,12 @@ struct mcp251xfd_priv {
 	u8 rx_ring_num;
 	u8 rx_obj_num;
 	u8 rx_obj_num_coalesce_irq;
+	u8 tx_obj_num_coalesce_irq;
 
 	u32 rx_coalesce_usecs_irq;
+	u32 tx_coalesce_usecs_irq;
 	struct hrtimer rx_irq_timer;
+	struct hrtimer tx_irq_timer;
 
 	struct mcp251xfd_ecc ecc;
 	struct mcp251xfd_regs_status regs_status;
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 11/12] can: mcp251xfd: add TX IRQ coalesce ethtool support
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (9 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 10/12] can: mcp251xfd: add TX IRQ coalesce support Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-13  8:36 ` [can-next-rfc 12/12] can: mcp251xfd: ring: increase number of RX-FIFOs to 3 and increase max TX-FIFO depth to 16 Marc Kleine-Budde
                   ` (2 subsequent siblings)
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch adds support ethtool based configuration for the TX IRQ
coalescing added in the previous patch.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 .../net/can/spi/mcp251xfd/mcp251xfd-ethtool.c | 23 ++++++++++++++++---
 .../net/can/spi/mcp251xfd/mcp251xfd-ring.c    |  1 +
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h     |  1 +
 3 files changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
index 6e49cf3411a2..6c7a57f16cc6 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ethtool.c
@@ -58,7 +58,7 @@ static int mcp251xfd_ring_get_coalesce(struct net_device *ndev,
 				       struct netlink_ext_ack *ext_ack)
 {
 	struct mcp251xfd_priv *priv = netdev_priv(ndev);
-	u32 rx_max_frames;
+	u32 rx_max_frames, tx_max_frames;
 
 	/* The ethtool doc says:
 	 * To disable coalescing, set usecs = 0 and max_frames = 1.
@@ -71,6 +71,14 @@ static int mcp251xfd_ring_get_coalesce(struct net_device *ndev,
 	ec->rx_max_coalesced_frames_irq = rx_max_frames;
 	ec->rx_coalesce_usecs_irq = priv->rx_coalesce_usecs_irq;
 
+	if (priv->tx_obj_num_coalesce_irq == 0)
+		tx_max_frames = 1;
+	else
+		tx_max_frames = priv->tx_obj_num_coalesce_irq;
+
+	ec->tx_max_coalesced_frames_irq = tx_max_frames;
+	ec->tx_coalesce_usecs_irq = priv->tx_coalesce_usecs_irq;
+
 	return 0;
 }
 
@@ -90,21 +98,28 @@ static int mcp251xfd_ring_set_coalesce(struct net_device *ndev,
 	can_ram_get_layout(&layout, &mcp251xfd_ram_config, &ring, ec, fd_mode);
 
 	if ((layout.rx_coalesce != priv->rx_obj_num_coalesce_irq ||
-	     ec->rx_coalesce_usecs_irq != priv->rx_coalesce_usecs_irq) &&
+	     ec->rx_coalesce_usecs_irq != priv->rx_coalesce_usecs_irq ||
+	     layout.tx_coalesce != priv->tx_obj_num_coalesce_irq ||
+	     ec->tx_coalesce_usecs_irq != priv->tx_coalesce_usecs_irq) &&
 	    netif_running(ndev))
 		return -EBUSY;
 
 	priv->rx_obj_num = layout.cur_rx;
 	priv->rx_obj_num_coalesce_irq = layout.rx_coalesce;
 	priv->rx_coalesce_usecs_irq = ec->rx_coalesce_usecs_irq;
+
 	priv->tx->obj_num = layout.cur_tx;
+	priv->tx_obj_num_coalesce_irq = layout.tx_coalesce;
+	priv->tx_coalesce_usecs_irq = ec->tx_coalesce_usecs_irq;
 
 	return 0;
 }
 
 static const struct ethtool_ops mcp251xfd_ethtool_ops = {
 	.supported_coalesce_params = ETHTOOL_COALESCE_RX_USECS_IRQ |
-		ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ,
+		ETHTOOL_COALESCE_RX_MAX_FRAMES_IRQ |
+		ETHTOOL_COALESCE_TX_USECS_IRQ |
+		ETHTOOL_COALESCE_TX_MAX_FRAMES_IRQ,
 	.get_ringparam = mcp251xfd_ring_get_ringparam,
 	.set_ringparam = mcp251xfd_ring_set_ringparam,
 	.get_coalesce = mcp251xfd_ring_get_coalesce,
@@ -122,5 +137,7 @@ void mcp251xfd_ethtool_init(struct mcp251xfd_priv *priv)
 	priv->tx->obj_num = layout.default_tx;
 
 	priv->rx_obj_num_coalesce_irq = 0;
+	priv->tx_obj_num_coalesce_irq = 0;
 	priv->rx_coalesce_usecs_irq = 0;
+	priv->tx_coalesce_usecs_irq = 0;
 }
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
index 3037ad3dd46b..bf3f0f150199 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-ring.c
@@ -442,6 +442,7 @@ const struct can_ram_config mcp251xfd_ram_config = {
 		.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,
+		.fifo_depth_coalesce_min = MCP251XFD_TX_FIFO_DEPTH_COALESCE_MIN,
 	},
 	.size = MCP251XFD_RAM_SIZE,
 	.fifo_depth = MCP251XFD_FIFO_DEPTH,
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index ee2c93ddc5ed..c6cb8c3391b3 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -413,6 +413,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT 8U
 #define MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT 4U
 #define MCP251XFD_TX_FIFO_DEPTH_MIN 2U
+#define MCP251XFD_TX_FIFO_DEPTH_COALESCE_MIN 2U
 
 static_assert(MCP251XFD_FIFO_TEF_NUM == 1U);
 static_assert(MCP251XFD_FIFO_TEF_NUM == MCP251XFD_FIFO_TX_NUM);
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [can-next-rfc 12/12] can: mcp251xfd: ring: increase number of RX-FIFOs to 3 and increase max TX-FIFO depth to 16
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (10 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 11/12] can: mcp251xfd: add TX IRQ coalesce ethtool support Marc Kleine-Budde
@ 2022-03-13  8:36 ` Marc Kleine-Budde
  2022-03-23 13:28 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp
  2022-03-29  9:08 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp
  13 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-13  8:36 UTC (permalink / raw)
  To: linux-can; +Cc: kernel, Manivannan Sadhasivam, Thomas Kopp, Marc Kleine-Budde

This patch increases the number of RX-FIFOs to 3 and the max TX-FIFO
depth to 16. This leads to the following default ring configuration.

CAN-2.0 mode:

| FIFO setup: TEF:         0x400:  8*12 bytes =   96 bytes
| FIFO setup: RX-0: FIFO 1/0x460: 32*20 bytes =  640 bytes
| FIFO setup: RX-1: FIFO 2/0x6e0: 32*20 bytes =  640 bytes
| FIFO setup: RX-2: FIFO 3/0x960: 16*20 bytes =  320 bytes
| FIFO setup: TX:   FIFO 4/0xaa0:  8*16 bytes =  128 bytes
| FIFO setup: free:                              224 bytes

CAN-FD mode:

| FIFO setup: TEF:         0x400:  4*12 bytes =   48 bytes
| FIFO setup: RX-0: FIFO 1/0x430: 16*76 bytes = 1216 bytes
| FIFO setup: RX-1: FIFO 2/0x8f0:  4*76 bytes =  304 bytes
| FIFO setup: TX:   FIFO 3/0xa20:  4*72 bytes =  288 bytes
| FIFO setup: free:                              192 bytes

With the previously added ethtool ring configuration support the RAM
on the chip can now be runtime configured between RX and TX buffers.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/spi/mcp251xfd/mcp251xfd.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
index c6cb8c3391b3..9cb6b5ad8dda 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd.h
@@ -398,7 +398,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 
 /* FIFO and Ring */
 #define MCP251XFD_FIFO_TEF_NUM 1U
-#define MCP251XFD_FIFO_RX_NUM 1U
+#define MCP251XFD_FIFO_RX_NUM 3U
 #define MCP251XFD_FIFO_TX_NUM 1U
 
 #define MCP251XFD_FIFO_DEPTH 32U
@@ -409,7 +409,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_RX_FIFO_DEPTH_COALESCE_MIN 8U
 
 #define MCP251XFD_TX_OBJ_NUM_MIN 2U
-#define MCP251XFD_TX_OBJ_NUM_MAX 8U
+#define MCP251XFD_TX_OBJ_NUM_MAX 16U
 #define MCP251XFD_TX_OBJ_NUM_CAN_DEFAULT 8U
 #define MCP251XFD_TX_OBJ_NUM_CANFD_DEFAULT 4U
 #define MCP251XFD_TX_FIFO_DEPTH_MIN 2U
-- 
2.35.1



^ permalink raw reply related	[flat|nested] 20+ messages in thread

* RE: can-next 2022-03-13: mcp251xfd: add
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (11 preceding siblings ...)
  2022-03-13  8:36 ` [can-next-rfc 12/12] can: mcp251xfd: ring: increase number of RX-FIFOs to 3 and increase max TX-FIFO depth to 16 Marc Kleine-Budde
@ 2022-03-23 13:28 ` Thomas.Kopp
  2022-03-23 14:03   ` Marc Kleine-Budde
  2022-03-29  9:08 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp
  13 siblings, 1 reply; 20+ messages in thread
From: Thomas.Kopp @ 2022-03-23 13:28 UTC (permalink / raw)
  To: mkl, linux-can; +Cc: kernel, manivannan.sadhasivam

Hi Marc,

> this series for the mcp251xfd adds IRQ coalescing support.
> 

Thanks for these patches, the performance gains with activated coalescing look awesome!
Testing on a Pi4 mostly 1 channel RX-only Full busload scenarios I see significantly reduced CPU utilization. This is both for CAN 2.0 and CAN-FD use-cases.

I tested this patch series against 5.17 mainline and I think the performance when NOT using coalescing regressed slightly ("measured"  via sar -u 1, not sure if that is a valid benchmark?)
I had both driver versions configured for the same fifo sizes and coalescing turned off. The mainline driver actually generates slighty more SPI interrupts in this scenario (20k CAN 2.0 Frames RXed in CAN-FD mode). Not really sure what causes the higher CPU utilization or if it's even relevant (maybe on smaller systems than a Pi4)

Best Regards,
Thomas




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: can-next 2022-03-13: mcp251xfd: add
  2022-03-23 13:28 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp
@ 2022-03-23 14:03   ` Marc Kleine-Budde
  2022-03-23 15:00     ` Thomas.Kopp
  0 siblings, 1 reply; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-23 14:03 UTC (permalink / raw)
  To: Thomas.Kopp; +Cc: linux-can, kernel, manivannan.sadhasivam

[-- Attachment #1: Type: text/plain, Size: 2042 bytes --]

On 23.03.2022 13:28:20, Thomas.Kopp@microchip.com wrote:
> > this series for the mcp251xfd adds IRQ coalescing support.
>
> Thanks for these patches, the performance gains with activated
> coalescing look awesome!

\o/

> Testing on a Pi4 mostly 1 channel RX-only Full busload scenarios I see
> significantly reduced CPU utilization. This is both for CAN 2.0 and
> CAN-FD use-cases.

\o/

> I tested this patch series against 5.17 mainline

Thanks for testing.
Does the coalescing series apply to v5.17 without the other series?

> and I think the performance when NOT using coalescing regressed
> slightly ("measured" via sar -u 1, not sure if that is a valid
> benchmark?)

"sar" don't know that tool, which Debian package do I have to install?

> I had both driver versions configured for the same fifo sizes and
> coalescing turned off. The mainline driver actually generates slighty
> more SPI interrupts in this scenario (20k CAN 2.0 Frames RXed in
> CAN-FD mode). Not really sure what causes the higher CPU utilization
> or if it's even relevant (maybe on smaller systems than a Pi4)

I don't know the length of the SPI transfers, where the raspi SPI driver
switched from PIO to IRQ mode. If more CAN frames are read in one
transfer (this can happen with deactivated IRQ coalescing, too) the
transfer size might be big enough to trigger an IRQ transfer, especially
in CAN-FD mode.

For better reproducibility I set the scaling_governor to performance:

| echo performance | sudo tee /sys/devices/system/cpu/cpufreq/policy0/scaling_governor

I've no idea why an unpachted v5.17 generates more SPI IRQs.

Can you re-test with performance mode activated, I'm not sure when I
find time to look into this.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: can-next 2022-03-13: mcp251xfd: add
  2022-03-23 14:03   ` Marc Kleine-Budde
@ 2022-03-23 15:00     ` Thomas.Kopp
  2022-03-23 19:28       ` Marc Kleine-Budde
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas.Kopp @ 2022-03-23 15:00 UTC (permalink / raw)
  To: mkl; +Cc: linux-can, kernel, manivannan.sadhasivam

> Thanks for testing.
> Does the coalescing series apply to v5.17 without the other series?

I took the latest state of the driver from can-next testing branch(and reverted the pending patch that changes the return value from int to void) and build the .ko from those files. So I suppose I had the other series as well?

 
> > and I think the performance when NOT using coalescing regressed
> > slightly ("measured" via sar -u 1, not sure if that is a valid
> > benchmark?)
> 
> "sar" don't know that tool, which Debian package do I have to install?

Sar from the sysstat package, again no idea whether that's a good benchmark but I didn't do any device driver benchmarking yet so that's what I found.

> > I had both driver versions configured for the same fifo sizes and
> > coalescing turned off. The mainline driver actually generates slighty
> > more SPI interrupts in this scenario (20k CAN 2.0 Frames RXed in
> > CAN-FD mode). Not really sure what causes the higher CPU utilization
> > or if it's even relevant (maybe on smaller systems than a Pi4)
> 
> I don't know the length of the SPI transfers, where the raspi SPI driver
> switched from PIO to IRQ mode. If more CAN frames are read in one
> transfer (this can happen with deactivated IRQ coalescing, too) the
> transfer size might be big enough to trigger an IRQ transfer, especially
> in CAN-FD mode.
> 
> For better reproducibility I set the scaling_governor to performance:
> 
> | echo performance | sudo tee
> /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
> 
> I've no idea why an unpachted v5.17 generates more SPI IRQs.
> 
> Can you re-test with performance mode activated, I'm not sure when I
> find time to look into this.
> 
Yes, will do. For the record, the difference was really marginal. On 20k frames I had 39182 vs. 39139 SPI interrupts.

Regards,
Thomas 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: can-next 2022-03-13: mcp251xfd: add
  2022-03-23 15:00     ` Thomas.Kopp
@ 2022-03-23 19:28       ` Marc Kleine-Budde
  2022-03-24 12:28         ` Thomas.Kopp
  0 siblings, 1 reply; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-23 19:28 UTC (permalink / raw)
  To: Thomas.Kopp; +Cc: linux-can, kernel, manivannan.sadhasivam

[-- Attachment #1: Type: text/plain, Size: 969 bytes --]

On 23.03.2022 15:00:31, Thomas.Kopp@microchip.com wrote:
> > For better reproducibility I set the scaling_governor to performance:
> > 
> > | echo performance | sudo tee
> > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor
> > 
> > I've no idea why an unpachted v5.17 generates more SPI IRQs.
> > 
> > Can you re-test with performance mode activated, I'm not sure when I
> > find time to look into this.
> > 
> Yes, will do. For the record, the difference was really marginal. On
> 20k frames I had 39182 vs. 39139 SPI interrupts.

I assume in some case the RX processing took so long that there was
another RX CAN frame ready in the same IRQ handler run.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: can-next 2022-03-13: mcp251xfd: add
  2022-03-23 19:28       ` Marc Kleine-Budde
@ 2022-03-24 12:28         ` Thomas.Kopp
  2022-03-24 13:45           ` can-next 2022-03-13: mcp251xfd: add coalescing support Marc Kleine-Budde
  0 siblings, 1 reply; 20+ messages in thread
From: Thomas.Kopp @ 2022-03-24 12:28 UTC (permalink / raw)
  To: mkl; +Cc: linux-can, kernel, manivannan.sadhasivam

> > Yes, will do. For the record, the difference was really marginal. On
> > 20k frames I had 39182 vs. 39139 SPI interrupts.
> 
> I assume in some case the RX processing took so long that there was
> another RX CAN frame ready in the same IRQ handler run.

Hrm, good point. Now with frequency scaling set to performance I don't see the difference anymore and see a consistent 2 SPI interrupts per CAN-FD message. So at least in performance mode this seems to be the same. Would be interesting to see the effects on a weaker system than the Pi4.

In CAN-FD mode I can't get the driver to allocate less than 1 Fifo with a depth of 16 to RX. Is that intended? I.e. I try to use ethtool -G can0 rx 8 tx 8 and it still leads to the following setup:
FIFO setup: TEF:         0x400:  8*12 bytes =   96 bytes
FIFO setup: RX-0: FIFO 1/0x418: 16*76 bytes = 1216 bytes
FIFO setup: TX:   FIFO 2/0x8d8:  8*72 bytes =  576 bytes
FIFO setup: free:                              160 bytes

Best Regards,
Thomas 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: can-next 2022-03-13: mcp251xfd: add coalescing support
  2022-03-24 12:28         ` Thomas.Kopp
@ 2022-03-24 13:45           ` Marc Kleine-Budde
  0 siblings, 0 replies; 20+ messages in thread
From: Marc Kleine-Budde @ 2022-03-24 13:45 UTC (permalink / raw)
  To: Thomas.Kopp; +Cc: linux-can, kernel, manivannan.sadhasivam

[-- Attachment #1: Type: text/plain, Size: 1739 bytes --]

On 24.03.2022 12:28:10, Thomas.Kopp@microchip.com wrote:
> Hrm, good point. Now with frequency scaling set to performance I don't
> see the difference anymore and see a consistent 2 SPI interrupts per
> CAN-FD message. So at least in performance mode this seems to be the
> same. Would be interesting to see the effects on a weaker system than
> the Pi4.
> 
> In CAN-FD mode I can't get the driver to allocate less than 1 Fifo
> with a depth of 16 to RX. Is that intended?

Yes, take a look at:

| const struct can_ram_config mcp251xfd_ram_config

The struct describes the hardware and gives configuration constraints.
E.g. the minimum RX is set to 16.

> I.e. I try to use ethtool -G can0 rx 8 tx 8 and it still leads to the
> following setup:
> 
> FIFO setup: TEF:         0x400:  8*12 bytes =   96 bytes
> FIFO setup: RX-0: FIFO 1/0x418: 16*76 bytes = 1216 bytes
> FIFO setup: TX:   FIFO 2/0x8d8:  8*72 bytes =  576 bytes
> FIFO setup: free:                              160 bytes

From my point of view a lower value for RX brings more negative impact
(RX FIFO overflows, etc...), than the increase of TX buffers from 8 to
16 brings positive impact (increased CAN bus load).

If there are use cases where 16 TX buffers are beneficial, I'm happy to
discuss them and change the defaults.

BTW: There are other/better TX optimizations options like implementing
TX byte queue limits with netdev_xmit_more() support.

regards,
Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 20+ messages in thread

* RE: can-next 2022-03-13: mcp251xfd: add
  2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
                   ` (12 preceding siblings ...)
  2022-03-23 13:28 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp
@ 2022-03-29  9:08 ` Thomas.Kopp
  13 siblings, 0 replies; 20+ messages in thread
From: Thomas.Kopp @ 2022-03-29  9:08 UTC (permalink / raw)
  To: mkl, linux-can; +Cc: kernel, manivannan.sadhasivam

Hi Marc,

> From: Marc Kleine-Budde <mkl@pengutronix.de>
> Subject: can-next 2022-03-13: mcp251xfd: add
> Hello,
> 
> this series for the mcp251xfd adds IRQ coalescing support.
> 

For the patch series: tested-by Thomas Kopp <thomas.kopp@microchip.com>

I'm fine with the default min values for the FIFOs changing them didn't yield a significant improvement.

Thanks,
Thomas

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2022-03-29  9:08 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-03-13  8:36 can-next 2022-03-13: mcp251xfd: add Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 01/12] can: mcp251xfd: mcp251xfd_ring_init(): use %d to print free RAM Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 02/12] can: mcp251xfd: ram: add helper function for runtime ring size calculation Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 03/12] can: mcp251xfd: ram: coalescing support Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 04/12] can: mcp251xfd: ethtool: add support Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 05/12] can: mcp251xfd: ring: prepare support for runtime configurable RX/TX ring parameters Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 06/12] can: mcp251xfd: update macros describing ring, FIFO and RAM layout Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 07/12] can: mcp251xfd: ring: add support for runtime configurable RX/TX ring parameters Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 08/12] can: mcp251xfd: add RX IRQ coalescing support Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 09/12] can: mcp251xfd: add RX IRQ coalescing ethtool support Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 10/12] can: mcp251xfd: add TX IRQ coalesce support Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 11/12] can: mcp251xfd: add TX IRQ coalesce ethtool support Marc Kleine-Budde
2022-03-13  8:36 ` [can-next-rfc 12/12] can: mcp251xfd: ring: increase number of RX-FIFOs to 3 and increase max TX-FIFO depth to 16 Marc Kleine-Budde
2022-03-23 13:28 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp
2022-03-23 14:03   ` Marc Kleine-Budde
2022-03-23 15:00     ` Thomas.Kopp
2022-03-23 19:28       ` Marc Kleine-Budde
2022-03-24 12:28         ` Thomas.Kopp
2022-03-24 13:45           ` can-next 2022-03-13: mcp251xfd: add coalescing support Marc Kleine-Budde
2022-03-29  9:08 ` can-next 2022-03-13: mcp251xfd: add Thomas.Kopp

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.