All of lore.kernel.org
 help / color / mirror / Atom feed
* [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
@ 2021-01-09 17:40 Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 01/13] MAINTAINERS: CAN network layer: add missing header file can-ml.h Marc Kleine-Budde
                   ` (13 more replies)
  0 siblings, 14 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol

Hello,

this series splits the CAN driver related infrastructure into several files
(patches 1...6), followed by some cleanup patches (7, 8), and support for
CAN frame length handling (9...13).

I took the path and put the calculated frame length into the struct
can_skb_priv and extended the can_get_echo_skb() and
can_rx_offload_get_echo_skb() to optionally return the CAN frame length.

This patch illustrated how the new code can be used. I'll send mcp251xfd BQL
support in a separate series, once details about this code have settled.

@@ -1352,7 +1357,9 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
        }
 
        for (i = 0; i < len; i++) {
-               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]);
+               unsigned int frame_len;
+
+               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
                /* -EAGAIN means the Sequence Number in the TEF
                 * doesn't match our tef_tail. This can happen if we
                 * read the TEF objects too early. Leave loop let the
@@ -1362,6 +1369,8 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
                        goto out_netif_wake_queue;
                if (err)
                        return err;
+
+               total_frame_len += frame_len;
        }
 
  out_netif_wake_queue:
@@ -1393,6 +1402,7 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
                        return err;
 
                tx_ring->tail += len;
+               netdev_completed_queue(priv->ndev, len, total_frame_len);
 
                err = mcp251xfd_check_tef_tail(priv);
                if (err)
@@ -2433,6 +2443,7 @@ static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv,
 static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
                                        struct net_device *ndev)
 {
+       struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
        struct mcp251xfd_priv *priv = netdev_priv(ndev);
        struct mcp251xfd_tx_ring *tx_ring = priv->tx;
        struct mcp251xfd_tx_obj *tx_obj;
@@ -2455,6 +2466,8 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
                netif_stop_queue(ndev);
 
        can_put_echo_skb(skb, ndev, tx_head);
+       can_skb_priv->frame_len = can_skb_get_frame_len(skb);
+       netdev_sent_queue(priv->ndev, can_skb_priv->frame_len);
 
        err = mcp251xfd_tx_obj_write(priv, tx_obj);
        if (err)

regards,
Marc




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

* [net-next 01/13] MAINTAINERS: CAN network layer: add missing header file can-ml.h
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 02/13] can: dev: move driver related infrastructure into separate subdir Marc Kleine-Budde
                   ` (12 subsequent siblings)
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch add the can-ml.h to the list of maintained files of the CAN network
layer.

Fixes: ffd956eef69b ("can: introduce CAN midlayer private and allocate it automatically")
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 MAINTAINERS | 1 +
 1 file changed, 1 insertion(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 54fcd5fe572d..c3091a91ebbf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3960,6 +3960,7 @@ W:	https://github.com/linux-can
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
 F:	Documentation/networking/can.rst
+F:	include/linux/can/can-ml.h
 F:	include/linux/can/core.h
 F:	include/linux/can/skb.h
 F:	include/net/netns/can.h
-- 
2.29.2



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

* [net-next 02/13] can: dev: move driver related infrastructure into separate subdir
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 01/13] MAINTAINERS: CAN network layer: add missing header file can-ml.h Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 03/13] can: dev: move bittiming related code into seperate file Marc Kleine-Budde
                   ` (11 subsequent siblings)
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch moves the CAN driver related infrastructure into a separate subdir.
It will be split into more files in the coming patches.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/Makefile               | 7 +------
 drivers/net/can/dev/Makefile           | 7 +++++++
 drivers/net/can/{ => dev}/dev.c        | 0
 drivers/net/can/{ => dev}/rx-offload.c | 0
 4 files changed, 8 insertions(+), 6 deletions(-)
 create mode 100644 drivers/net/can/dev/Makefile
 rename drivers/net/can/{ => dev}/dev.c (100%)
 rename drivers/net/can/{ => dev}/rx-offload.c (100%)

diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 22164300122d..a2b4463d8480 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -7,12 +7,7 @@ obj-$(CONFIG_CAN_VCAN)		+= vcan.o
 obj-$(CONFIG_CAN_VXCAN)		+= vxcan.o
 obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
 
-obj-$(CONFIG_CAN_DEV)		+= can-dev.o
-can-dev-y			+= dev.o
-can-dev-y			+= rx-offload.o
-
-can-dev-$(CONFIG_CAN_LEDS)	+= led.o
-
+obj-y				+= dev/
 obj-y				+= rcar/
 obj-y				+= spi/
 obj-y				+= usb/
diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
new file mode 100644
index 000000000000..cba92e6bcf6f
--- /dev/null
+++ b/drivers/net/can/dev/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_CAN_DEV)		+= can-dev.o
+can-dev-y			+= dev.o
+can-dev-y			+= rx-offload.o
+
+can-dev-$(CONFIG_CAN_LEDS)	+= led.o
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev/dev.c
similarity index 100%
rename from drivers/net/can/dev.c
rename to drivers/net/can/dev/dev.c
diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/dev/rx-offload.c
similarity index 100%
rename from drivers/net/can/rx-offload.c
rename to drivers/net/can/dev/rx-offload.c
-- 
2.29.2



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

* [net-next 03/13] can: dev: move bittiming related code into seperate file
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 01/13] MAINTAINERS: CAN network layer: add missing header file can-ml.h Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 02/13] can: dev: move driver related infrastructure into separate subdir Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 04/13] can: dev: move length " Marc Kleine-Budde
                   ` (10 subsequent siblings)
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch moves the bittiming related code of the CAN device infrastructure
into a separate file.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 MAINTAINERS                     |   1 +
 drivers/net/can/dev/Makefile    |   1 +
 drivers/net/can/dev/bittiming.c | 261 ++++++++++++++++++++++++++++++++
 drivers/net/can/dev/dev.c       | 261 --------------------------------
 include/linux/can/bittiming.h   |  44 ++++++
 include/linux/can/dev.h         |  16 +-
 6 files changed, 308 insertions(+), 276 deletions(-)
 create mode 100644 drivers/net/can/dev/bittiming.c
 create mode 100644 include/linux/can/bittiming.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c3091a91ebbf..d17662df1cd7 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3943,6 +3943,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can.git
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next.git
 F:	Documentation/devicetree/bindings/net/can/
 F:	drivers/net/can/
+F:	include/linux/can/bittiming.h
 F:	include/linux/can/dev.h
 F:	include/linux/can/led.h
 F:	include/linux/can/platform/
diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
index cba92e6bcf6f..b5c6bb848d9d 100644
--- a/drivers/net/can/dev/Makefile
+++ b/drivers/net/can/dev/Makefile
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
+can-dev-y			+= bittiming.o
 can-dev-y			+= dev.o
 can-dev-y			+= rx-offload.o
 
diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c
new file mode 100644
index 000000000000..f7fe226bb395
--- /dev/null
+++ b/drivers/net/can/dev/bittiming.c
@@ -0,0 +1,261 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ */
+
+#include <linux/can/dev.h>
+
+#ifdef CONFIG_CAN_CALC_BITTIMING
+#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
+
+/* Bit-timing calculation derived from:
+ *
+ * Code based on LinCAN sources and H8S2638 project
+ * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
+ * Copyright 2005      Stanislav Marek
+ * email: pisa@cmp.felk.cvut.cz
+ *
+ * Calculates proper bit-timing parameters for a specified bit-rate
+ * and sample-point, which can then be used to set the bit-timing
+ * registers of the CAN controller. You can find more information
+ * in the header file linux/can/netlink.h.
+ */
+static int
+can_update_sample_point(const struct can_bittiming_const *btc,
+			unsigned int sample_point_nominal, unsigned int tseg,
+			unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
+			unsigned int *sample_point_error_ptr)
+{
+	unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
+	unsigned int sample_point, best_sample_point = 0;
+	unsigned int tseg1, tseg2;
+	int i;
+
+	for (i = 0; i <= 1; i++) {
+		tseg2 = tseg + CAN_SYNC_SEG -
+			(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
+			1000 - i;
+		tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
+		tseg1 = tseg - tseg2;
+		if (tseg1 > btc->tseg1_max) {
+			tseg1 = btc->tseg1_max;
+			tseg2 = tseg - tseg1;
+		}
+
+		sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
+			(tseg + CAN_SYNC_SEG);
+		sample_point_error = abs(sample_point_nominal - sample_point);
+
+		if (sample_point <= sample_point_nominal &&
+		    sample_point_error < best_sample_point_error) {
+			best_sample_point = sample_point;
+			best_sample_point_error = sample_point_error;
+			*tseg1_ptr = tseg1;
+			*tseg2_ptr = tseg2;
+		}
+	}
+
+	if (sample_point_error_ptr)
+		*sample_point_error_ptr = best_sample_point_error;
+
+	return best_sample_point;
+}
+
+int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
+		       const struct can_bittiming_const *btc)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	unsigned int bitrate;			/* current bitrate */
+	unsigned int bitrate_error;		/* difference between current and nominal value */
+	unsigned int best_bitrate_error = UINT_MAX;
+	unsigned int sample_point_error;	/* difference between current and nominal value */
+	unsigned int best_sample_point_error = UINT_MAX;
+	unsigned int sample_point_nominal;	/* nominal sample point */
+	unsigned int best_tseg = 0;		/* current best value for tseg */
+	unsigned int best_brp = 0;		/* current best value for brp */
+	unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
+	u64 v64;
+
+	/* Use CiA recommended sample points */
+	if (bt->sample_point) {
+		sample_point_nominal = bt->sample_point;
+	} else {
+		if (bt->bitrate > 800000)
+			sample_point_nominal = 750;
+		else if (bt->bitrate > 500000)
+			sample_point_nominal = 800;
+		else
+			sample_point_nominal = 875;
+	}
+
+	/* tseg even = round down, odd = round up */
+	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
+	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
+		tsegall = CAN_SYNC_SEG + tseg / 2;
+
+		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
+		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
+
+		/* choose brp step which is possible in system */
+		brp = (brp / btc->brp_inc) * btc->brp_inc;
+		if (brp < btc->brp_min || brp > btc->brp_max)
+			continue;
+
+		bitrate = priv->clock.freq / (brp * tsegall);
+		bitrate_error = abs(bt->bitrate - bitrate);
+
+		/* tseg brp biterror */
+		if (bitrate_error > best_bitrate_error)
+			continue;
+
+		/* reset sample point error if we have a better bitrate */
+		if (bitrate_error < best_bitrate_error)
+			best_sample_point_error = UINT_MAX;
+
+		can_update_sample_point(btc, sample_point_nominal, tseg / 2,
+					&tseg1, &tseg2, &sample_point_error);
+		if (sample_point_error > best_sample_point_error)
+			continue;
+
+		best_sample_point_error = sample_point_error;
+		best_bitrate_error = bitrate_error;
+		best_tseg = tseg / 2;
+		best_brp = brp;
+
+		if (bitrate_error == 0 && sample_point_error == 0)
+			break;
+	}
+
+	if (best_bitrate_error) {
+		/* Error in one-tenth of a percent */
+		v64 = (u64)best_bitrate_error * 1000;
+		do_div(v64, bt->bitrate);
+		bitrate_error = (u32)v64;
+		if (bitrate_error > CAN_CALC_MAX_ERROR) {
+			netdev_err(dev,
+				   "bitrate error %d.%d%% too high\n",
+				   bitrate_error / 10, bitrate_error % 10);
+			return -EDOM;
+		}
+		netdev_warn(dev, "bitrate error %d.%d%%\n",
+			    bitrate_error / 10, bitrate_error % 10);
+	}
+
+	/* real sample point */
+	bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
+						   best_tseg, &tseg1, &tseg2,
+						   NULL);
+
+	v64 = (u64)best_brp * 1000 * 1000 * 1000;
+	do_div(v64, priv->clock.freq);
+	bt->tq = (u32)v64;
+	bt->prop_seg = tseg1 / 2;
+	bt->phase_seg1 = tseg1 - bt->prop_seg;
+	bt->phase_seg2 = tseg2;
+
+	/* check for sjw user settings */
+	if (!bt->sjw || !btc->sjw_max) {
+		bt->sjw = 1;
+	} else {
+		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
+		if (bt->sjw > btc->sjw_max)
+			bt->sjw = btc->sjw_max;
+		/* bt->sjw must not be higher than tseg2 */
+		if (tseg2 < bt->sjw)
+			bt->sjw = tseg2;
+	}
+
+	bt->brp = best_brp;
+
+	/* real bitrate */
+	bt->bitrate = priv->clock.freq /
+		(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
+
+	return 0;
+}
+#endif /* CONFIG_CAN_CALC_BITTIMING */
+
+/* Checks the validity of the specified bit-timing parameters prop_seg,
+ * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
+ * prescaler value brp. You can find more information in the header
+ * file linux/can/netlink.h.
+ */
+static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
+			       const struct can_bittiming_const *btc)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int tseg1, alltseg;
+	u64 brp64;
+
+	tseg1 = bt->prop_seg + bt->phase_seg1;
+	if (!bt->sjw)
+		bt->sjw = 1;
+	if (bt->sjw > btc->sjw_max ||
+	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
+	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
+		return -ERANGE;
+
+	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
+	if (btc->brp_inc > 1)
+		do_div(brp64, btc->brp_inc);
+	brp64 += 500000000UL - 1;
+	do_div(brp64, 1000000000UL); /* the practicable BRP */
+	if (btc->brp_inc > 1)
+		brp64 *= btc->brp_inc;
+	bt->brp = (u32)brp64;
+
+	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
+		return -EINVAL;
+
+	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
+	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
+	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
+
+	return 0;
+}
+
+/* Checks the validity of predefined bitrate settings */
+static int
+can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
+		     const u32 *bitrate_const,
+		     const unsigned int bitrate_const_cnt)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	unsigned int i;
+
+	for (i = 0; i < bitrate_const_cnt; i++) {
+		if (bt->bitrate == bitrate_const[i])
+			break;
+	}
+
+	if (i >= priv->bitrate_const_cnt)
+		return -EINVAL;
+
+	return 0;
+}
+
+int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
+		      const struct can_bittiming_const *btc,
+		      const u32 *bitrate_const,
+		      const unsigned int bitrate_const_cnt)
+{
+	int err;
+
+	/* Depending on the given can_bittiming parameter structure the CAN
+	 * timing parameters are calculated based on the provided bitrate OR
+	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
+	 * provided directly which are then checked and fixed up.
+	 */
+	if (!bt->tq && bt->bitrate && btc)
+		err = can_calc_bittiming(dev, bt, btc);
+	else if (bt->tq && !bt->bitrate && btc)
+		err = can_fixup_bittiming(dev, bt, btc);
+	else if (!bt->tq && bt->bitrate && bitrate_const)
+		err = can_validate_bitrate(dev, bt, bitrate_const,
+					   bitrate_const_cnt);
+	else
+		err = -EINVAL;
+
+	return err;
+}
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 3486704c8a95..1b3ab95b3fd1 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -58,267 +58,6 @@ u8 can_fd_len2dlc(u8 len)
 }
 EXPORT_SYMBOL_GPL(can_fd_len2dlc);
 
-#ifdef CONFIG_CAN_CALC_BITTIMING
-#define CAN_CALC_MAX_ERROR 50 /* in one-tenth of a percent */
-
-/* Bit-timing calculation derived from:
- *
- * Code based on LinCAN sources and H8S2638 project
- * Copyright 2004-2006 Pavel Pisa - DCE FELK CVUT cz
- * Copyright 2005      Stanislav Marek
- * email: pisa@cmp.felk.cvut.cz
- *
- * Calculates proper bit-timing parameters for a specified bit-rate
- * and sample-point, which can then be used to set the bit-timing
- * registers of the CAN controller. You can find more information
- * in the header file linux/can/netlink.h.
- */
-static int
-can_update_sample_point(const struct can_bittiming_const *btc,
-			unsigned int sample_point_nominal, unsigned int tseg,
-			unsigned int *tseg1_ptr, unsigned int *tseg2_ptr,
-			unsigned int *sample_point_error_ptr)
-{
-	unsigned int sample_point_error, best_sample_point_error = UINT_MAX;
-	unsigned int sample_point, best_sample_point = 0;
-	unsigned int tseg1, tseg2;
-	int i;
-
-	for (i = 0; i <= 1; i++) {
-		tseg2 = tseg + CAN_SYNC_SEG -
-			(sample_point_nominal * (tseg + CAN_SYNC_SEG)) /
-			1000 - i;
-		tseg2 = clamp(tseg2, btc->tseg2_min, btc->tseg2_max);
-		tseg1 = tseg - tseg2;
-		if (tseg1 > btc->tseg1_max) {
-			tseg1 = btc->tseg1_max;
-			tseg2 = tseg - tseg1;
-		}
-
-		sample_point = 1000 * (tseg + CAN_SYNC_SEG - tseg2) /
-			(tseg + CAN_SYNC_SEG);
-		sample_point_error = abs(sample_point_nominal - sample_point);
-
-		if (sample_point <= sample_point_nominal &&
-		    sample_point_error < best_sample_point_error) {
-			best_sample_point = sample_point;
-			best_sample_point_error = sample_point_error;
-			*tseg1_ptr = tseg1;
-			*tseg2_ptr = tseg2;
-		}
-	}
-
-	if (sample_point_error_ptr)
-		*sample_point_error_ptr = best_sample_point_error;
-
-	return best_sample_point;
-}
-
-static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
-			      const struct can_bittiming_const *btc)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	unsigned int bitrate;			/* current bitrate */
-	unsigned int bitrate_error;		/* difference between current and nominal value */
-	unsigned int best_bitrate_error = UINT_MAX;
-	unsigned int sample_point_error;	/* difference between current and nominal value */
-	unsigned int best_sample_point_error = UINT_MAX;
-	unsigned int sample_point_nominal;	/* nominal sample point */
-	unsigned int best_tseg = 0;		/* current best value for tseg */
-	unsigned int best_brp = 0;		/* current best value for brp */
-	unsigned int brp, tsegall, tseg, tseg1 = 0, tseg2 = 0;
-	u64 v64;
-
-	/* Use CiA recommended sample points */
-	if (bt->sample_point) {
-		sample_point_nominal = bt->sample_point;
-	} else {
-		if (bt->bitrate > 800000)
-			sample_point_nominal = 750;
-		else if (bt->bitrate > 500000)
-			sample_point_nominal = 800;
-		else
-			sample_point_nominal = 875;
-	}
-
-	/* tseg even = round down, odd = round up */
-	for (tseg = (btc->tseg1_max + btc->tseg2_max) * 2 + 1;
-	     tseg >= (btc->tseg1_min + btc->tseg2_min) * 2; tseg--) {
-		tsegall = CAN_SYNC_SEG + tseg / 2;
-
-		/* Compute all possible tseg choices (tseg=tseg1+tseg2) */
-		brp = priv->clock.freq / (tsegall * bt->bitrate) + tseg % 2;
-
-		/* choose brp step which is possible in system */
-		brp = (brp / btc->brp_inc) * btc->brp_inc;
-		if (brp < btc->brp_min || brp > btc->brp_max)
-			continue;
-
-		bitrate = priv->clock.freq / (brp * tsegall);
-		bitrate_error = abs(bt->bitrate - bitrate);
-
-		/* tseg brp biterror */
-		if (bitrate_error > best_bitrate_error)
-			continue;
-
-		/* reset sample point error if we have a better bitrate */
-		if (bitrate_error < best_bitrate_error)
-			best_sample_point_error = UINT_MAX;
-
-		can_update_sample_point(btc, sample_point_nominal, tseg / 2,
-					&tseg1, &tseg2, &sample_point_error);
-		if (sample_point_error > best_sample_point_error)
-			continue;
-
-		best_sample_point_error = sample_point_error;
-		best_bitrate_error = bitrate_error;
-		best_tseg = tseg / 2;
-		best_brp = brp;
-
-		if (bitrate_error == 0 && sample_point_error == 0)
-			break;
-	}
-
-	if (best_bitrate_error) {
-		/* Error in one-tenth of a percent */
-		v64 = (u64)best_bitrate_error * 1000;
-		do_div(v64, bt->bitrate);
-		bitrate_error = (u32)v64;
-		if (bitrate_error > CAN_CALC_MAX_ERROR) {
-			netdev_err(dev,
-				   "bitrate error %d.%d%% too high\n",
-				   bitrate_error / 10, bitrate_error % 10);
-			return -EDOM;
-		}
-		netdev_warn(dev, "bitrate error %d.%d%%\n",
-			    bitrate_error / 10, bitrate_error % 10);
-	}
-
-	/* real sample point */
-	bt->sample_point = can_update_sample_point(btc, sample_point_nominal,
-						   best_tseg, &tseg1, &tseg2,
-						   NULL);
-
-	v64 = (u64)best_brp * 1000 * 1000 * 1000;
-	do_div(v64, priv->clock.freq);
-	bt->tq = (u32)v64;
-	bt->prop_seg = tseg1 / 2;
-	bt->phase_seg1 = tseg1 - bt->prop_seg;
-	bt->phase_seg2 = tseg2;
-
-	/* check for sjw user settings */
-	if (!bt->sjw || !btc->sjw_max) {
-		bt->sjw = 1;
-	} else {
-		/* bt->sjw is at least 1 -> sanitize upper bound to sjw_max */
-		if (bt->sjw > btc->sjw_max)
-			bt->sjw = btc->sjw_max;
-		/* bt->sjw must not be higher than tseg2 */
-		if (tseg2 < bt->sjw)
-			bt->sjw = tseg2;
-	}
-
-	bt->brp = best_brp;
-
-	/* real bitrate */
-	bt->bitrate = priv->clock.freq /
-		(bt->brp * (CAN_SYNC_SEG + tseg1 + tseg2));
-
-	return 0;
-}
-#else /* !CONFIG_CAN_CALC_BITTIMING */
-static int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
-			      const struct can_bittiming_const *btc)
-{
-	netdev_err(dev, "bit-timing calculation not available\n");
-	return -EINVAL;
-}
-#endif /* CONFIG_CAN_CALC_BITTIMING */
-
-/* Checks the validity of the specified bit-timing parameters prop_seg,
- * phase_seg1, phase_seg2 and sjw and tries to determine the bitrate
- * prescaler value brp. You can find more information in the header
- * file linux/can/netlink.h.
- */
-static int can_fixup_bittiming(struct net_device *dev, struct can_bittiming *bt,
-			       const struct can_bittiming_const *btc)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	int tseg1, alltseg;
-	u64 brp64;
-
-	tseg1 = bt->prop_seg + bt->phase_seg1;
-	if (!bt->sjw)
-		bt->sjw = 1;
-	if (bt->sjw > btc->sjw_max ||
-	    tseg1 < btc->tseg1_min || tseg1 > btc->tseg1_max ||
-	    bt->phase_seg2 < btc->tseg2_min || bt->phase_seg2 > btc->tseg2_max)
-		return -ERANGE;
-
-	brp64 = (u64)priv->clock.freq * (u64)bt->tq;
-	if (btc->brp_inc > 1)
-		do_div(brp64, btc->brp_inc);
-	brp64 += 500000000UL - 1;
-	do_div(brp64, 1000000000UL); /* the practicable BRP */
-	if (btc->brp_inc > 1)
-		brp64 *= btc->brp_inc;
-	bt->brp = (u32)brp64;
-
-	if (bt->brp < btc->brp_min || bt->brp > btc->brp_max)
-		return -EINVAL;
-
-	alltseg = bt->prop_seg + bt->phase_seg1 + bt->phase_seg2 + 1;
-	bt->bitrate = priv->clock.freq / (bt->brp * alltseg);
-	bt->sample_point = ((tseg1 + 1) * 1000) / alltseg;
-
-	return 0;
-}
-
-/* Checks the validity of predefined bitrate settings */
-static int
-can_validate_bitrate(struct net_device *dev, struct can_bittiming *bt,
-		     const u32 *bitrate_const,
-		     const unsigned int bitrate_const_cnt)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	unsigned int i;
-
-	for (i = 0; i < bitrate_const_cnt; i++) {
-		if (bt->bitrate == bitrate_const[i])
-			break;
-	}
-
-	if (i >= priv->bitrate_const_cnt)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
-			     const struct can_bittiming_const *btc,
-			     const u32 *bitrate_const,
-			     const unsigned int bitrate_const_cnt)
-{
-	int err;
-
-	/* Depending on the given can_bittiming parameter structure the CAN
-	 * timing parameters are calculated based on the provided bitrate OR
-	 * alternatively the CAN timing parameters (tq, prop_seg, etc.) are
-	 * provided directly which are then checked and fixed up.
-	 */
-	if (!bt->tq && bt->bitrate && btc)
-		err = can_calc_bittiming(dev, bt, btc);
-	else if (bt->tq && !bt->bitrate && btc)
-		err = can_fixup_bittiming(dev, bt, btc);
-	else if (!bt->tq && bt->bitrate && bitrate_const)
-		err = can_validate_bitrate(dev, bt, bitrate_const,
-					   bitrate_const_cnt);
-	else
-		err = -EINVAL;
-
-	return err;
-}
-
 static void can_update_state_error_stats(struct net_device *dev,
 					 enum can_state new_state)
 {
diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h
new file mode 100644
index 000000000000..707575c668f4
--- /dev/null
+++ b/include/linux/can/bittiming.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* Copyright (c) 2020 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.de>
+ */
+
+#ifndef _CAN_BITTIMING_H
+#define _CAN_BITTIMING_H
+
+#include <linux/netdevice.h>
+#include <linux/can/netlink.h>
+
+#define CAN_SYNC_SEG 1
+
+#ifdef CONFIG_CAN_CALC_BITTIMING
+int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
+		       const struct can_bittiming_const *btc);
+#else /* !CONFIG_CAN_CALC_BITTIMING */
+static inline int
+can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
+		   const struct can_bittiming_const *btc)
+{
+	netdev_err(dev, "bit-timing calculation not available\n");
+	return -EINVAL;
+}
+#endif /* CONFIG_CAN_CALC_BITTIMING */
+
+int can_get_bittiming(struct net_device *dev, struct can_bittiming *bt,
+		      const struct can_bittiming_const *btc,
+		      const u32 *bitrate_const,
+		      const unsigned int bitrate_const_cnt);
+
+/*
+ * can_bit_time() - Duration of one bit
+ *
+ * Please refer to ISO 11898-1:2015, section 11.3.1.1 "Bit time" for
+ * additional information.
+ *
+ * Return: the number of time quanta in one bit.
+ */
+static inline unsigned int can_bit_time(const struct can_bittiming *bt)
+{
+	return CAN_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2;
+}
+
+#endif /* !_CAN_BITTIMING_H */
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 197a79535cc2..054c3bed190b 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -15,6 +15,7 @@
 #define _CAN_DEV_H
 
 #include <linux/can.h>
+#include <linux/can/bittiming.h>
 #include <linux/can/error.h>
 #include <linux/can/led.h>
 #include <linux/can/netlink.h>
@@ -82,21 +83,6 @@ struct can_priv {
 #endif
 };
 
-#define CAN_SYNC_SEG 1
-
-/*
- * can_bit_time() - Duration of one bit
- *
- * Please refer to ISO 11898-1:2015, section 11.3.1.1 "Bit time" for
- * additional information.
- *
- * Return: the number of time quanta in one bit.
- */
-static inline unsigned int can_bit_time(const struct can_bittiming *bt)
-{
-	return CAN_SYNC_SEG + bt->prop_seg + bt->phase_seg1 + bt->phase_seg2;
-}
-
 /*
  * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
  * Classical CAN frame into a valid data length of max. 8 bytes.
-- 
2.29.2



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

* [net-next 04/13] can: dev: move length related code into seperate file
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (2 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 03/13] can: dev: move bittiming related code into seperate file Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-11  8:49   ` Oliver Hartkopp
  2021-01-09 17:40 ` [net-next 05/13] can: dev: move skb related " Marc Kleine-Budde
                   ` (9 subsequent siblings)
  13 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch moves all CAN frame length related code of the CAN device
infrastructure into a separate file.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 MAINTAINERS                  |  1 +
 drivers/net/can/dev/Makefile |  1 +
 drivers/net/can/dev/dev.c    | 33 -----------------------
 drivers/net/can/dev/length.c | 40 ++++++++++++++++++++++++++++
 include/linux/can/dev.h      | 41 +----------------------------
 include/linux/can/length.h   | 51 ++++++++++++++++++++++++++++++++++++
 6 files changed, 94 insertions(+), 73 deletions(-)
 create mode 100644 drivers/net/can/dev/length.c
 create mode 100644 include/linux/can/length.h

diff --git a/MAINTAINERS b/MAINTAINERS
index d17662df1cd7..21780c4e2e71 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3946,6 +3946,7 @@ F:	drivers/net/can/
 F:	include/linux/can/bittiming.h
 F:	include/linux/can/dev.h
 F:	include/linux/can/led.h
+F:	include/linux/can/length.h
 F:	include/linux/can/platform/
 F:	include/linux/can/rx-offload.h
 F:	include/uapi/linux/can/error.h
diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
index b5c6bb848d9d..5c647951e06d 100644
--- a/drivers/net/can/dev/Makefile
+++ b/drivers/net/can/dev/Makefile
@@ -3,6 +3,7 @@
 obj-$(CONFIG_CAN_DEV)		+= can-dev.o
 can-dev-y			+= bittiming.o
 can-dev-y			+= dev.o
+can-dev-y			+= length.o
 can-dev-y			+= rx-offload.o
 
 can-dev-$(CONFIG_CAN_LEDS)	+= led.o
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 1b3ab95b3fd1..3372e99d5db7 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -25,39 +25,6 @@ MODULE_DESCRIPTION(MOD_DESC);
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
 
-/* CAN DLC to real data length conversion helpers */
-
-static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
-			     8, 12, 16, 20, 24, 32, 48, 64};
-
-/* get data length from raw data length code (DLC) */
-u8 can_fd_dlc2len(u8 dlc)
-{
-	return dlc2len[dlc & 0x0F];
-}
-EXPORT_SYMBOL_GPL(can_fd_dlc2len);
-
-static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
-			     9, 9, 9, 9,			/* 9 - 12 */
-			     10, 10, 10, 10,			/* 13 - 16 */
-			     11, 11, 11, 11,			/* 17 - 20 */
-			     12, 12, 12, 12,			/* 21 - 24 */
-			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
-			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
-			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
-			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
-			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
-
-/* map the sanitized data length to an appropriate data length code */
-u8 can_fd_len2dlc(u8 len)
-{
-	if (unlikely(len > 64))
-		return 0xF;
-
-	return len2dlc[len];
-}
-EXPORT_SYMBOL_GPL(can_fd_len2dlc);
-
 static void can_update_state_error_stats(struct net_device *dev,
 					 enum can_state new_state)
 {
diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
new file mode 100644
index 000000000000..540d40dc0bc2
--- /dev/null
+++ b/drivers/net/can/dev/length.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ */
+
+#include <linux/can/dev.h>
+
+/* CAN DLC to real data length conversion helpers */
+
+static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
+			     8, 12, 16, 20, 24, 32, 48, 64};
+
+/* get data length from raw data length code (DLC) */
+u8 can_fd_dlc2len(u8 dlc)
+{
+	return dlc2len[dlc & 0x0F];
+}
+EXPORT_SYMBOL_GPL(can_fd_dlc2len);
+
+static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
+			     9, 9, 9, 9,			/* 9 - 12 */
+			     10, 10, 10, 10,			/* 13 - 16 */
+			     11, 11, 11, 11,			/* 17 - 20 */
+			     12, 12, 12, 12,			/* 21 - 24 */
+			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
+			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
+			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
+			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
+			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
+
+/* map the sanitized data length to an appropriate data length code */
+u8 can_fd_len2dlc(u8 len)
+{
+	if (unlikely(len > 64))
+		return 0xF;
+
+	return len2dlc[len];
+}
+EXPORT_SYMBOL_GPL(can_fd_len2dlc);
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 054c3bed190b..d75fba1d030a 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -18,6 +18,7 @@
 #include <linux/can/bittiming.h>
 #include <linux/can/error.h>
 #include <linux/can/led.h>
+#include <linux/can/length.h>
 #include <linux/can/netlink.h>
 #include <linux/can/skb.h>
 #include <linux/netdevice.h>
@@ -83,15 +84,6 @@ struct can_priv {
 #endif
 };
 
-/*
- * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
- * Classical CAN frame into a valid data length of max. 8 bytes.
- *
- * To be used in the CAN netdriver receive path to ensure conformance with
- * ISO 11898-1 Chapter 8.4.2.3 (DLC field)
- */
-#define can_cc_dlc2len(dlc)	(min_t(u8, (dlc), CAN_MAX_DLEN))
-
 /* Check for outgoing skbs that have not been created by the CAN subsystem */
 static inline bool can_skb_headroom_valid(struct net_device *dev,
 					  struct sk_buff *skb)
@@ -156,31 +148,6 @@ static inline bool can_is_canfd_skb(const struct sk_buff *skb)
 	return skb->len == CANFD_MTU;
 }
 
-/* helper to get the data length code (DLC) for Classical CAN raw DLC access */
-static inline u8 can_get_cc_dlc(const struct can_frame *cf, const u32 ctrlmode)
-{
-	/* return len8_dlc as dlc value only if all conditions apply */
-	if ((ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC) &&
-	    (cf->len == CAN_MAX_DLEN) &&
-	    (cf->len8_dlc > CAN_MAX_DLEN && cf->len8_dlc <= CAN_MAX_RAW_DLC))
-		return cf->len8_dlc;
-
-	/* return the payload length as dlc value */
-	return cf->len;
-}
-
-/* helper to set len and len8_dlc value for Classical CAN raw DLC access */
-static inline void can_frame_set_cc_len(struct can_frame *cf, const u8 dlc,
-					const u32 ctrlmode)
-{
-	/* the caller already ensured that dlc is a value from 0 .. 15 */
-	if (ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC && dlc > CAN_MAX_DLEN)
-		cf->len8_dlc = dlc;
-
-	/* limit the payload length 'len' to CAN_MAX_DLEN */
-	cf->len = can_cc_dlc2len(dlc);
-}
-
 /* helper to define static CAN controller features at device creation time */
 static inline void can_set_static_ctrlmode(struct net_device *dev,
 					   u32 static_mode)
@@ -196,12 +163,6 @@ static inline void can_set_static_ctrlmode(struct net_device *dev,
 		dev->mtu = CANFD_MTU;
 }
 
-/* get data length from raw data length code (DLC) */
-u8 can_fd_dlc2len(u8 dlc);
-
-/* map the sanitized data length to an appropriate data length code */
-u8 can_fd_len2dlc(u8 len);
-
 struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
 				    unsigned int txqs, unsigned int rxqs);
 #define alloc_candev(sizeof_priv, echo_skb_max) \
diff --git a/include/linux/can/length.h b/include/linux/can/length.h
new file mode 100644
index 000000000000..fabd93bcde3e
--- /dev/null
+++ b/include/linux/can/length.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
+ *               Varma Electronics Oy
+ * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
+ */
+
+#ifndef _CAN_LENGTH_H
+#define _CAN_LENGTH_H
+
+/*
+ * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
+ * Classical CAN frame into a valid data length of max. 8 bytes.
+ *
+ * To be used in the CAN netdriver receive path to ensure conformance with
+ * ISO 11898-1 Chapter 8.4.2.3 (DLC field)
+ */
+#define can_cc_dlc2len(dlc)	(min_t(u8, (dlc), CAN_MAX_DLEN))
+
+/* helper to get the data length code (DLC) for Classical CAN raw DLC access */
+static inline u8 can_get_cc_dlc(const struct can_frame *cf, const u32 ctrlmode)
+{
+	/* return len8_dlc as dlc value only if all conditions apply */
+	if ((ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC) &&
+	    (cf->len == CAN_MAX_DLEN) &&
+	    (cf->len8_dlc > CAN_MAX_DLEN && cf->len8_dlc <= CAN_MAX_RAW_DLC))
+		return cf->len8_dlc;
+
+	/* return the payload length as dlc value */
+	return cf->len;
+}
+
+/* helper to set len and len8_dlc value for Classical CAN raw DLC access */
+static inline void can_frame_set_cc_len(struct can_frame *cf, const u8 dlc,
+					const u32 ctrlmode)
+{
+	/* the caller already ensured that dlc is a value from 0 .. 15 */
+	if (ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC && dlc > CAN_MAX_DLEN)
+		cf->len8_dlc = dlc;
+
+	/* limit the payload length 'len' to CAN_MAX_DLEN */
+	cf->len = can_cc_dlc2len(dlc);
+}
+
+/* get data length from raw data length code (DLC) */
+u8 can_fd_dlc2len(u8 dlc);
+
+/* map the sanitized data length to an appropriate data length code */
+u8 can_fd_len2dlc(u8 len);
+
+#endif /* !_CAN_LENGTH_H */
-- 
2.29.2



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

* [net-next 05/13] can: dev: move skb related into seperate file
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (3 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 04/13] can: dev: move length " Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-10  4:26   ` Vincent MAILHOL
  2021-01-09 17:40 ` [net-next 06/13] can: dev: move netlink related code " Marc Kleine-Budde
                   ` (8 subsequent siblings)
  13 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch moves the skb related code of the CAN device infrastructure into a
separate file.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/dev.c | 213 ------------------------------------
 drivers/net/can/dev/skb.c | 220 ++++++++++++++++++++++++++++++++++++++
 include/linux/can/dev.h   |  76 -------------
 include/linux/can/skb.h   |  77 +++++++++++++
 4 files changed, 297 insertions(+), 289 deletions(-)
 create mode 100644 drivers/net/can/dev/skb.c

diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 3372e99d5db7..fe71ff9ef8c9 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -132,149 +132,6 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,
 }
 EXPORT_SYMBOL_GPL(can_change_state);
 
-/* Local echo of CAN messages
- *
- * CAN network devices *should* support a local echo functionality
- * (see Documentation/networking/can.rst). To test the handling of CAN
- * interfaces that do not support the local echo both driver types are
- * implemented. In the case that the driver does not support the echo
- * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
- * to perform the echo as a fallback solution.
- */
-static void can_flush_echo_skb(struct net_device *dev)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	struct net_device_stats *stats = &dev->stats;
-	int i;
-
-	for (i = 0; i < priv->echo_skb_max; i++) {
-		if (priv->echo_skb[i]) {
-			kfree_skb(priv->echo_skb[i]);
-			priv->echo_skb[i] = NULL;
-			stats->tx_dropped++;
-			stats->tx_aborted_errors++;
-		}
-	}
-}
-
-/* Put the skb on the stack to be looped backed locally lateron
- *
- * The function is typically called in the start_xmit function
- * of the device driver. The driver must protect access to
- * priv->echo_skb, if necessary.
- */
-int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
-		     unsigned int idx)
-{
-	struct can_priv *priv = netdev_priv(dev);
-
-	BUG_ON(idx >= priv->echo_skb_max);
-
-	/* check flag whether this packet has to be looped back */
-	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
-	    (skb->protocol != htons(ETH_P_CAN) &&
-	     skb->protocol != htons(ETH_P_CANFD))) {
-		kfree_skb(skb);
-		return 0;
-	}
-
-	if (!priv->echo_skb[idx]) {
-		skb = can_create_echo_skb(skb);
-		if (!skb)
-			return -ENOMEM;
-
-		/* make settings for echo to reduce code in irq context */
-		skb->pkt_type = PACKET_BROADCAST;
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-		skb->dev = dev;
-
-		/* save this skb for tx interrupt echo handling */
-		priv->echo_skb[idx] = skb;
-	} else {
-		/* locking problem with netif_stop_queue() ?? */
-		netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
-		kfree_skb(skb);
-		return -EBUSY;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL_GPL(can_put_echo_skb);
-
-struct sk_buff *
-__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
-{
-	struct can_priv *priv = netdev_priv(dev);
-
-	if (idx >= priv->echo_skb_max) {
-		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
-			   __func__, idx, priv->echo_skb_max);
-		return NULL;
-	}
-
-	if (priv->echo_skb[idx]) {
-		/* Using "struct canfd_frame::len" for the frame
-		 * length is supported on both CAN and CANFD frames.
-		 */
-		struct sk_buff *skb = priv->echo_skb[idx];
-		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
-
-		/* get the real payload length for netdev statistics */
-		if (cf->can_id & CAN_RTR_FLAG)
-			*len_ptr = 0;
-		else
-			*len_ptr = cf->len;
-
-		priv->echo_skb[idx] = NULL;
-
-		return skb;
-	}
-
-	return NULL;
-}
-
-/* Get the skb from the stack and loop it back locally
- *
- * The function is typically called when the TX done interrupt
- * is handled in the device driver. The driver must protect
- * access to priv->echo_skb, if necessary.
- */
-unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
-{
-	struct sk_buff *skb;
-	u8 len;
-
-	skb = __can_get_echo_skb(dev, idx, &len);
-	if (!skb)
-		return 0;
-
-	skb_get(skb);
-	if (netif_rx(skb) == NET_RX_SUCCESS)
-		dev_consume_skb_any(skb);
-	else
-		dev_kfree_skb_any(skb);
-
-	return len;
-}
-EXPORT_SYMBOL_GPL(can_get_echo_skb);
-
-/* Remove the skb from the stack and free it.
- *
- * The function is typically called when TX failed.
- */
-void can_free_echo_skb(struct net_device *dev, unsigned int idx)
-{
-	struct can_priv *priv = netdev_priv(dev);
-
-	BUG_ON(idx >= priv->echo_skb_max);
-
-	if (priv->echo_skb[idx]) {
-		dev_kfree_skb_any(priv->echo_skb[idx]);
-		priv->echo_skb[idx] = NULL;
-	}
-}
-EXPORT_SYMBOL_GPL(can_free_echo_skb);
-
 /* CAN device restart for bus-off recovery */
 static void can_restart(struct net_device *dev)
 {
@@ -379,76 +236,6 @@ static void can_setup(struct net_device *dev)
 	dev->features = NETIF_F_HW_CSUM;
 }
 
-struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
-{
-	struct sk_buff *skb;
-
-	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
-			       sizeof(struct can_frame));
-	if (unlikely(!skb))
-		return NULL;
-
-	skb->protocol = htons(ETH_P_CAN);
-	skb->pkt_type = PACKET_BROADCAST;
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	skb_reset_transport_header(skb);
-
-	can_skb_reserve(skb);
-	can_skb_prv(skb)->ifindex = dev->ifindex;
-	can_skb_prv(skb)->skbcnt = 0;
-
-	*cf = skb_put_zero(skb, sizeof(struct can_frame));
-
-	return skb;
-}
-EXPORT_SYMBOL_GPL(alloc_can_skb);
-
-struct sk_buff *alloc_canfd_skb(struct net_device *dev,
-				struct canfd_frame **cfd)
-{
-	struct sk_buff *skb;
-
-	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
-			       sizeof(struct canfd_frame));
-	if (unlikely(!skb))
-		return NULL;
-
-	skb->protocol = htons(ETH_P_CANFD);
-	skb->pkt_type = PACKET_BROADCAST;
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	skb_reset_transport_header(skb);
-
-	can_skb_reserve(skb);
-	can_skb_prv(skb)->ifindex = dev->ifindex;
-	can_skb_prv(skb)->skbcnt = 0;
-
-	*cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
-
-	return skb;
-}
-EXPORT_SYMBOL_GPL(alloc_canfd_skb);
-
-struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
-{
-	struct sk_buff *skb;
-
-	skb = alloc_can_skb(dev, cf);
-	if (unlikely(!skb))
-		return NULL;
-
-	(*cf)->can_id = CAN_ERR_FLAG;
-	(*cf)->len = CAN_ERR_DLC;
-
-	return skb;
-}
-EXPORT_SYMBOL_GPL(alloc_can_err_skb);
-
 /* Allocate and setup space for the CAN network device */
 struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
 				    unsigned int txqs, unsigned int rxqs)
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
new file mode 100644
index 000000000000..26cd597ff771
--- /dev/null
+++ b/drivers/net/can/dev/skb.c
@@ -0,0 +1,220 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ */
+
+#include <linux/can/dev.h>
+
+/* Local echo of CAN messages
+ *
+ * CAN network devices *should* support a local echo functionality
+ * (see Documentation/networking/can.rst). To test the handling of CAN
+ * interfaces that do not support the local echo both driver types are
+ * implemented. In the case that the driver does not support the echo
+ * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
+ * to perform the echo as a fallback solution.
+ */
+void can_flush_echo_skb(struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	int i;
+
+	for (i = 0; i < priv->echo_skb_max; i++) {
+		if (priv->echo_skb[i]) {
+			kfree_skb(priv->echo_skb[i]);
+			priv->echo_skb[i] = NULL;
+			stats->tx_dropped++;
+			stats->tx_aborted_errors++;
+		}
+	}
+}
+
+/* Put the skb on the stack to be looped backed locally lateron
+ *
+ * The function is typically called in the start_xmit function
+ * of the device driver. The driver must protect access to
+ * priv->echo_skb, if necessary.
+ */
+int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+		     unsigned int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	BUG_ON(idx >= priv->echo_skb_max);
+
+	/* check flag whether this packet has to be looped back */
+	if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
+	    (skb->protocol != htons(ETH_P_CAN) &&
+	     skb->protocol != htons(ETH_P_CANFD))) {
+		kfree_skb(skb);
+		return 0;
+	}
+
+	if (!priv->echo_skb[idx]) {
+		skb = can_create_echo_skb(skb);
+		if (!skb)
+			return -ENOMEM;
+
+		/* make settings for echo to reduce code in irq context */
+		skb->pkt_type = PACKET_BROADCAST;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		skb->dev = dev;
+
+		/* save this skb for tx interrupt echo handling */
+		priv->echo_skb[idx] = skb;
+	} else {
+		/* locking problem with netif_stop_queue() ?? */
+		netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
+		kfree_skb(skb);
+		return -EBUSY;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(can_put_echo_skb);
+
+struct sk_buff *
+__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (idx >= priv->echo_skb_max) {
+		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
+			   __func__, idx, priv->echo_skb_max);
+		return NULL;
+	}
+
+	if (priv->echo_skb[idx]) {
+		/* Using "struct canfd_frame::len" for the frame
+		 * length is supported on both CAN and CANFD frames.
+		 */
+		struct sk_buff *skb = priv->echo_skb[idx];
+		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+
+		/* get the real payload length for netdev statistics */
+		if (cf->can_id & CAN_RTR_FLAG)
+			*len_ptr = 0;
+		else
+			*len_ptr = cf->len;
+
+		priv->echo_skb[idx] = NULL;
+
+		return skb;
+	}
+
+	return NULL;
+}
+
+/* Get the skb from the stack and loop it back locally
+ *
+ * The function is typically called when the TX done interrupt
+ * is handled in the device driver. The driver must protect
+ * access to priv->echo_skb, if necessary.
+ */
+unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
+{
+	struct sk_buff *skb;
+	u8 len;
+
+	skb = __can_get_echo_skb(dev, idx, &len);
+	if (!skb)
+		return 0;
+
+	skb_get(skb);
+	if (netif_rx(skb) == NET_RX_SUCCESS)
+		dev_consume_skb_any(skb);
+	else
+		dev_kfree_skb_any(skb);
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(can_get_echo_skb);
+
+/* Remove the skb from the stack and free it.
+ *
+ * The function is typically called when TX failed.
+ */
+void can_free_echo_skb(struct net_device *dev, unsigned int idx)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	BUG_ON(idx >= priv->echo_skb_max);
+
+	if (priv->echo_skb[idx]) {
+		dev_kfree_skb_any(priv->echo_skb[idx]);
+		priv->echo_skb[idx] = NULL;
+	}
+}
+EXPORT_SYMBOL_GPL(can_free_echo_skb);
+
+struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
+			       sizeof(struct can_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CAN);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb_reset_transport_header(skb);
+
+	can_skb_reserve(skb);
+	can_skb_prv(skb)->ifindex = dev->ifindex;
+	can_skb_prv(skb)->skbcnt = 0;
+
+	*cf = skb_put_zero(skb, sizeof(struct can_frame));
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_can_skb);
+
+struct sk_buff *alloc_canfd_skb(struct net_device *dev,
+				struct canfd_frame **cfd)
+{
+	struct sk_buff *skb;
+
+	skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
+			       sizeof(struct canfd_frame));
+	if (unlikely(!skb))
+		return NULL;
+
+	skb->protocol = htons(ETH_P_CANFD);
+	skb->pkt_type = PACKET_BROADCAST;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb_reset_transport_header(skb);
+
+	can_skb_reserve(skb);
+	can_skb_prv(skb)->ifindex = dev->ifindex;
+	can_skb_prv(skb)->skbcnt = 0;
+
+	*cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_canfd_skb);
+
+struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
+{
+	struct sk_buff *skb;
+
+	skb = alloc_can_skb(dev, cf);
+	if (unlikely(!skb))
+		return NULL;
+
+	(*cf)->can_id = CAN_ERR_FLAG;
+	(*cf)->len = CAN_ERR_DLC;
+
+	return skb;
+}
+EXPORT_SYMBOL_GPL(alloc_can_err_skb);
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index d75fba1d030a..4a26e128af7f 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -84,69 +84,6 @@ struct can_priv {
 #endif
 };
 
-/* Check for outgoing skbs that have not been created by the CAN subsystem */
-static inline bool can_skb_headroom_valid(struct net_device *dev,
-					  struct sk_buff *skb)
-{
-	/* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
-	if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
-		return false;
-
-	/* af_packet does not apply CAN skb specific settings */
-	if (skb->ip_summed == CHECKSUM_NONE) {
-		/* init headroom */
-		can_skb_prv(skb)->ifindex = dev->ifindex;
-		can_skb_prv(skb)->skbcnt = 0;
-
-		skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-		/* perform proper loopback on capable devices */
-		if (dev->flags & IFF_ECHO)
-			skb->pkt_type = PACKET_LOOPBACK;
-		else
-			skb->pkt_type = PACKET_HOST;
-
-		skb_reset_mac_header(skb);
-		skb_reset_network_header(skb);
-		skb_reset_transport_header(skb);
-	}
-
-	return true;
-}
-
-/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
-static inline bool can_dropped_invalid_skb(struct net_device *dev,
-					  struct sk_buff *skb)
-{
-	const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
-
-	if (skb->protocol == htons(ETH_P_CAN)) {
-		if (unlikely(skb->len != CAN_MTU ||
-			     cfd->len > CAN_MAX_DLEN))
-			goto inval_skb;
-	} else if (skb->protocol == htons(ETH_P_CANFD)) {
-		if (unlikely(skb->len != CANFD_MTU ||
-			     cfd->len > CANFD_MAX_DLEN))
-			goto inval_skb;
-	} else
-		goto inval_skb;
-
-	if (!can_skb_headroom_valid(dev, skb))
-		goto inval_skb;
-
-	return false;
-
-inval_skb:
-	kfree_skb(skb);
-	dev->stats.tx_dropped++;
-	return true;
-}
-
-static inline bool can_is_canfd_skb(const struct sk_buff *skb)
-{
-	/* the CAN specific type of skb is identified by its data length */
-	return skb->len == CANFD_MTU;
-}
 
 /* helper to define static CAN controller features at device creation time */
 static inline void can_set_static_ctrlmode(struct net_device *dev,
@@ -187,23 +124,10 @@ void can_bus_off(struct net_device *dev);
 void can_change_state(struct net_device *dev, struct can_frame *cf,
 		      enum can_state tx_state, enum can_state rx_state);
 
-int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
-		     unsigned int idx);
-struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
-				   u8 *len_ptr);
-unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
-void can_free_echo_skb(struct net_device *dev, unsigned int idx);
-
 #ifdef CONFIG_OF
 void of_can_transceiver(struct net_device *dev);
 #else
 static inline void of_can_transceiver(struct net_device *dev) { }
 #endif
 
-struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
-struct sk_buff *alloc_canfd_skb(struct net_device *dev,
-				struct canfd_frame **cfd);
-struct sk_buff *alloc_can_err_skb(struct net_device *dev,
-				  struct can_frame **cf);
-
 #endif /* !_CAN_DEV_H */
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index fc61cf4eff1c..c90ebbd3008c 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -16,6 +16,19 @@
 #include <linux/can.h>
 #include <net/sock.h>
 
+void can_flush_echo_skb(struct net_device *dev);
+int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
+		     unsigned int idx);
+struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
+				   u8 *len_ptr);
+unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
+void can_free_echo_skb(struct net_device *dev, unsigned int idx);
+struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
+struct sk_buff *alloc_canfd_skb(struct net_device *dev,
+				struct canfd_frame **cfd);
+struct sk_buff *alloc_can_err_skb(struct net_device *dev,
+				  struct can_frame **cf);
+
 /*
  * The struct can_skb_priv is used to transport additional information along
  * with the stored struct can(fd)_frame that can not be contained in existing
@@ -74,4 +87,68 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
 	return nskb;
 }
 
+/* Check for outgoing skbs that have not been created by the CAN subsystem */
+static inline bool can_skb_headroom_valid(struct net_device *dev,
+					  struct sk_buff *skb)
+{
+	/* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
+	if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
+		return false;
+
+	/* af_packet does not apply CAN skb specific settings */
+	if (skb->ip_summed == CHECKSUM_NONE) {
+		/* init headroom */
+		can_skb_prv(skb)->ifindex = dev->ifindex;
+		can_skb_prv(skb)->skbcnt = 0;
+
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		/* perform proper loopback on capable devices */
+		if (dev->flags & IFF_ECHO)
+			skb->pkt_type = PACKET_LOOPBACK;
+		else
+			skb->pkt_type = PACKET_HOST;
+
+		skb_reset_mac_header(skb);
+		skb_reset_network_header(skb);
+		skb_reset_transport_header(skb);
+	}
+
+	return true;
+}
+
+/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
+static inline bool can_dropped_invalid_skb(struct net_device *dev,
+					  struct sk_buff *skb)
+{
+	const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
+
+	if (skb->protocol == htons(ETH_P_CAN)) {
+		if (unlikely(skb->len != CAN_MTU ||
+			     cfd->len > CAN_MAX_DLEN))
+			goto inval_skb;
+	} else if (skb->protocol == htons(ETH_P_CANFD)) {
+		if (unlikely(skb->len != CANFD_MTU ||
+			     cfd->len > CANFD_MAX_DLEN))
+			goto inval_skb;
+	} else
+		goto inval_skb;
+
+	if (!can_skb_headroom_valid(dev, skb))
+		goto inval_skb;
+
+	return false;
+
+inval_skb:
+	kfree_skb(skb);
+	dev->stats.tx_dropped++;
+	return true;
+}
+
+static inline bool can_is_canfd_skb(const struct sk_buff *skb)
+{
+	/* the CAN specific type of skb is identified by its data length */
+	return skb->len == CANFD_MTU;
+}
+
 #endif /* !_CAN_SKB_H */
-- 
2.29.2



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

* [net-next 06/13] can: dev: move netlink related code into seperate file
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (4 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 05/13] can: dev: move skb related " Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-10  4:27   ` Vincent MAILHOL
  2021-01-09 17:40 ` [net-next 07/13] can: length: convert to kernel coding style Marc Kleine-Budde
                   ` (7 subsequent siblings)
  13 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch moves the netlink related code of the CAN device infrastructure into
a separate file.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/dev.c     | 370 +--------------------------------
 drivers/net/can/dev/netlink.c | 379 ++++++++++++++++++++++++++++++++++
 include/linux/can/dev.h       |   6 +
 3 files changed, 388 insertions(+), 367 deletions(-)
 create mode 100644 drivers/net/can/dev/netlink.c

diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index fe71ff9ef8c9..f580f0ac6497 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -14,10 +14,8 @@
 #include <linux/can/can-ml.h>
 #include <linux/can/dev.h>
 #include <linux/can/skb.h>
-#include <linux/can/netlink.h>
 #include <linux/can/led.h>
 #include <linux/of.h>
-#include <net/rtnetlink.h>
 
 #define MOD_DESC "CAN device driver interface"
 
@@ -223,7 +221,7 @@ void can_bus_off(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(can_bus_off);
 
-static void can_setup(struct net_device *dev)
+void can_setup(struct net_device *dev)
 {
 	dev->type = ARPHRD_CAN;
 	dev->mtu = CAN_MTU;
@@ -399,368 +397,6 @@ void close_candev(struct net_device *dev)
 }
 EXPORT_SYMBOL_GPL(close_candev);
 
-/* CAN netlink interface */
-static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
-	[IFLA_CAN_STATE]	= { .type = NLA_U32 },
-	[IFLA_CAN_CTRLMODE]	= { .len = sizeof(struct can_ctrlmode) },
-	[IFLA_CAN_RESTART_MS]	= { .type = NLA_U32 },
-	[IFLA_CAN_RESTART]	= { .type = NLA_U32 },
-	[IFLA_CAN_BITTIMING]	= { .len = sizeof(struct can_bittiming) },
-	[IFLA_CAN_BITTIMING_CONST]
-				= { .len = sizeof(struct can_bittiming_const) },
-	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },
-	[IFLA_CAN_BERR_COUNTER]	= { .len = sizeof(struct can_berr_counter) },
-	[IFLA_CAN_DATA_BITTIMING]
-				= { .len = sizeof(struct can_bittiming) },
-	[IFLA_CAN_DATA_BITTIMING_CONST]
-				= { .len = sizeof(struct can_bittiming_const) },
-	[IFLA_CAN_TERMINATION]	= { .type = NLA_U16 },
-};
-
-static int can_validate(struct nlattr *tb[], struct nlattr *data[],
-			struct netlink_ext_ack *extack)
-{
-	bool is_can_fd = false;
-
-	/* Make sure that valid CAN FD configurations always consist of
-	 * - nominal/arbitration bittiming
-	 * - data bittiming
-	 * - control mode with CAN_CTRLMODE_FD set
-	 */
-
-	if (!data)
-		return 0;
-
-	if (data[IFLA_CAN_CTRLMODE]) {
-		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
-
-		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
-	}
-
-	if (is_can_fd) {
-		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
-			return -EOPNOTSUPP;
-	}
-
-	if (data[IFLA_CAN_DATA_BITTIMING]) {
-		if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
-			return -EOPNOTSUPP;
-	}
-
-	return 0;
-}
-
-static int can_changelink(struct net_device *dev, struct nlattr *tb[],
-			  struct nlattr *data[],
-			  struct netlink_ext_ack *extack)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	int err;
-
-	/* We need synchronization with dev->stop() */
-	ASSERT_RTNL();
-
-	if (data[IFLA_CAN_BITTIMING]) {
-		struct can_bittiming bt;
-
-		/* Do not allow changing bittiming while running */
-		if (dev->flags & IFF_UP)
-			return -EBUSY;
-
-		/* Calculate bittiming parameters based on
-		 * bittiming_const if set, otherwise pass bitrate
-		 * directly via do_set_bitrate(). Bail out if neither
-		 * is given.
-		 */
-		if (!priv->bittiming_const && !priv->do_set_bittiming)
-			return -EOPNOTSUPP;
-
-		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
-		err = can_get_bittiming(dev, &bt,
-					priv->bittiming_const,
-					priv->bitrate_const,
-					priv->bitrate_const_cnt);
-		if (err)
-			return err;
-
-		if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
-			netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
-				   priv->bitrate_max);
-			return -EINVAL;
-		}
-
-		memcpy(&priv->bittiming, &bt, sizeof(bt));
-
-		if (priv->do_set_bittiming) {
-			/* Finally, set the bit-timing registers */
-			err = priv->do_set_bittiming(dev);
-			if (err)
-				return err;
-		}
-	}
-
-	if (data[IFLA_CAN_CTRLMODE]) {
-		struct can_ctrlmode *cm;
-		u32 ctrlstatic;
-		u32 maskedflags;
-
-		/* Do not allow changing controller mode while running */
-		if (dev->flags & IFF_UP)
-			return -EBUSY;
-		cm = nla_data(data[IFLA_CAN_CTRLMODE]);
-		ctrlstatic = priv->ctrlmode_static;
-		maskedflags = cm->flags & cm->mask;
-
-		/* check whether provided bits are allowed to be passed */
-		if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
-			return -EOPNOTSUPP;
-
-		/* do not check for static fd-non-iso if 'fd' is disabled */
-		if (!(maskedflags & CAN_CTRLMODE_FD))
-			ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
-
-		/* make sure static options are provided by configuration */
-		if ((maskedflags & ctrlstatic) != ctrlstatic)
-			return -EOPNOTSUPP;
-
-		/* clear bits to be modified and copy the flag values */
-		priv->ctrlmode &= ~cm->mask;
-		priv->ctrlmode |= maskedflags;
-
-		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
-		if (priv->ctrlmode & CAN_CTRLMODE_FD)
-			dev->mtu = CANFD_MTU;
-		else
-			dev->mtu = CAN_MTU;
-	}
-
-	if (data[IFLA_CAN_RESTART_MS]) {
-		/* Do not allow changing restart delay while running */
-		if (dev->flags & IFF_UP)
-			return -EBUSY;
-		priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
-	}
-
-	if (data[IFLA_CAN_RESTART]) {
-		/* Do not allow a restart while not running */
-		if (!(dev->flags & IFF_UP))
-			return -EINVAL;
-		err = can_restart_now(dev);
-		if (err)
-			return err;
-	}
-
-	if (data[IFLA_CAN_DATA_BITTIMING]) {
-		struct can_bittiming dbt;
-
-		/* Do not allow changing bittiming while running */
-		if (dev->flags & IFF_UP)
-			return -EBUSY;
-
-		/* Calculate bittiming parameters based on
-		 * data_bittiming_const if set, otherwise pass bitrate
-		 * directly via do_set_bitrate(). Bail out if neither
-		 * is given.
-		 */
-		if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
-			return -EOPNOTSUPP;
-
-		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
-		       sizeof(dbt));
-		err = can_get_bittiming(dev, &dbt,
-					priv->data_bittiming_const,
-					priv->data_bitrate_const,
-					priv->data_bitrate_const_cnt);
-		if (err)
-			return err;
-
-		if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
-			netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
-				   priv->bitrate_max);
-			return -EINVAL;
-		}
-
-		memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
-
-		if (priv->do_set_data_bittiming) {
-			/* Finally, set the bit-timing registers */
-			err = priv->do_set_data_bittiming(dev);
-			if (err)
-				return err;
-		}
-	}
-
-	if (data[IFLA_CAN_TERMINATION]) {
-		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
-		const unsigned int num_term = priv->termination_const_cnt;
-		unsigned int i;
-
-		if (!priv->do_set_termination)
-			return -EOPNOTSUPP;
-
-		/* check whether given value is supported by the interface */
-		for (i = 0; i < num_term; i++) {
-			if (termval == priv->termination_const[i])
-				break;
-		}
-		if (i >= num_term)
-			return -EINVAL;
-
-		/* Finally, set the termination value */
-		err = priv->do_set_termination(dev, termval);
-		if (err)
-			return err;
-
-		priv->termination = termval;
-	}
-
-	return 0;
-}
-
-static size_t can_get_size(const struct net_device *dev)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	size_t size = 0;
-
-	if (priv->bittiming.bitrate)				/* IFLA_CAN_BITTIMING */
-		size += nla_total_size(sizeof(struct can_bittiming));
-	if (priv->bittiming_const)				/* IFLA_CAN_BITTIMING_CONST */
-		size += nla_total_size(sizeof(struct can_bittiming_const));
-	size += nla_total_size(sizeof(struct can_clock));	/* IFLA_CAN_CLOCK */
-	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */
-	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */
-	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */
-	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */
-		size += nla_total_size(sizeof(struct can_berr_counter));
-	if (priv->data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */
-		size += nla_total_size(sizeof(struct can_bittiming));
-	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */
-		size += nla_total_size(sizeof(struct can_bittiming_const));
-	if (priv->termination_const) {
-		size += nla_total_size(sizeof(priv->termination));		/* IFLA_CAN_TERMINATION */
-		size += nla_total_size(sizeof(*priv->termination_const) *	/* IFLA_CAN_TERMINATION_CONST */
-				       priv->termination_const_cnt);
-	}
-	if (priv->bitrate_const)				/* IFLA_CAN_BITRATE_CONST */
-		size += nla_total_size(sizeof(*priv->bitrate_const) *
-				       priv->bitrate_const_cnt);
-	if (priv->data_bitrate_const)				/* IFLA_CAN_DATA_BITRATE_CONST */
-		size += nla_total_size(sizeof(*priv->data_bitrate_const) *
-				       priv->data_bitrate_const_cnt);
-	size += sizeof(priv->bitrate_max);			/* IFLA_CAN_BITRATE_MAX */
-
-	return size;
-}
-
-static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
-{
-	struct can_priv *priv = netdev_priv(dev);
-	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
-	struct can_berr_counter bec;
-	enum can_state state = priv->state;
-
-	if (priv->do_get_state)
-		priv->do_get_state(dev, &state);
-
-	if ((priv->bittiming.bitrate &&
-	     nla_put(skb, IFLA_CAN_BITTIMING,
-		     sizeof(priv->bittiming), &priv->bittiming)) ||
-
-	    (priv->bittiming_const &&
-	     nla_put(skb, IFLA_CAN_BITTIMING_CONST,
-		     sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
-
-	    nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
-	    nla_put_u32(skb, IFLA_CAN_STATE, state) ||
-	    nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
-	    nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
-
-	    (priv->do_get_berr_counter &&
-	     !priv->do_get_berr_counter(dev, &bec) &&
-	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
-
-	    (priv->data_bittiming.bitrate &&
-	     nla_put(skb, IFLA_CAN_DATA_BITTIMING,
-		     sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
-
-	    (priv->data_bittiming_const &&
-	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
-		     sizeof(*priv->data_bittiming_const),
-		     priv->data_bittiming_const)) ||
-
-	    (priv->termination_const &&
-	     (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
-	      nla_put(skb, IFLA_CAN_TERMINATION_CONST,
-		      sizeof(*priv->termination_const) *
-		      priv->termination_const_cnt,
-		      priv->termination_const))) ||
-
-	    (priv->bitrate_const &&
-	     nla_put(skb, IFLA_CAN_BITRATE_CONST,
-		     sizeof(*priv->bitrate_const) *
-		     priv->bitrate_const_cnt,
-		     priv->bitrate_const)) ||
-
-	    (priv->data_bitrate_const &&
-	     nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
-		     sizeof(*priv->data_bitrate_const) *
-		     priv->data_bitrate_const_cnt,
-		     priv->data_bitrate_const)) ||
-
-	    (nla_put(skb, IFLA_CAN_BITRATE_MAX,
-		     sizeof(priv->bitrate_max),
-		     &priv->bitrate_max))
-	    )
-
-		return -EMSGSIZE;
-
-	return 0;
-}
-
-static size_t can_get_xstats_size(const struct net_device *dev)
-{
-	return sizeof(struct can_device_stats);
-}
-
-static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
-{
-	struct can_priv *priv = netdev_priv(dev);
-
-	if (nla_put(skb, IFLA_INFO_XSTATS,
-		    sizeof(priv->can_stats), &priv->can_stats))
-		goto nla_put_failure;
-	return 0;
-
-nla_put_failure:
-	return -EMSGSIZE;
-}
-
-static int can_newlink(struct net *src_net, struct net_device *dev,
-		       struct nlattr *tb[], struct nlattr *data[],
-		       struct netlink_ext_ack *extack)
-{
-	return -EOPNOTSUPP;
-}
-
-static void can_dellink(struct net_device *dev, struct list_head *head)
-{
-}
-
-static struct rtnl_link_ops can_link_ops __read_mostly = {
-	.kind		= "can",
-	.maxtype	= IFLA_CAN_MAX,
-	.policy		= can_policy,
-	.setup		= can_setup,
-	.validate	= can_validate,
-	.newlink	= can_newlink,
-	.changelink	= can_changelink,
-	.dellink	= can_dellink,
-	.get_size	= can_get_size,
-	.fill_info	= can_fill_info,
-	.get_xstats_size = can_get_xstats_size,
-	.fill_xstats	= can_fill_xstats,
-};
-
 /* Register the CAN network device */
 int register_candev(struct net_device *dev)
 {
@@ -812,7 +448,7 @@ static __init int can_dev_init(void)
 
 	can_led_notifier_init();
 
-	err = rtnl_link_register(&can_link_ops);
+	err = can_netlink_register();
 	if (!err)
 		pr_info(MOD_DESC "\n");
 
@@ -822,7 +458,7 @@ module_init(can_dev_init);
 
 static __exit void can_dev_exit(void)
 {
-	rtnl_link_unregister(&can_link_ops);
+	can_netlink_unregister();
 
 	can_led_notifier_exit();
 }
diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
new file mode 100644
index 000000000000..3ae884cdf677
--- /dev/null
+++ b/drivers/net/can/dev/netlink.c
@@ -0,0 +1,379 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
+ * Copyright (C) 2006 Andrey Volkov, Varma Electronics
+ * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
+ */
+
+#include <linux/can/dev.h>
+#include <net/rtnetlink.h>
+
+static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
+	[IFLA_CAN_STATE]	= { .type = NLA_U32 },
+	[IFLA_CAN_CTRLMODE]	= { .len = sizeof(struct can_ctrlmode) },
+	[IFLA_CAN_RESTART_MS]	= { .type = NLA_U32 },
+	[IFLA_CAN_RESTART]	= { .type = NLA_U32 },
+	[IFLA_CAN_BITTIMING]	= { .len = sizeof(struct can_bittiming) },
+	[IFLA_CAN_BITTIMING_CONST]
+				= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_CLOCK]	= { .len = sizeof(struct can_clock) },
+	[IFLA_CAN_BERR_COUNTER]	= { .len = sizeof(struct can_berr_counter) },
+	[IFLA_CAN_DATA_BITTIMING]
+				= { .len = sizeof(struct can_bittiming) },
+	[IFLA_CAN_DATA_BITTIMING_CONST]
+				= { .len = sizeof(struct can_bittiming_const) },
+	[IFLA_CAN_TERMINATION]	= { .type = NLA_U16 },
+};
+
+static int can_validate(struct nlattr *tb[], struct nlattr *data[],
+			struct netlink_ext_ack *extack)
+{
+	bool is_can_fd = false;
+
+	/* Make sure that valid CAN FD configurations always consist of
+	 * - nominal/arbitration bittiming
+	 * - data bittiming
+	 * - control mode with CAN_CTRLMODE_FD set
+	 */
+
+	if (!data)
+		return 0;
+
+	if (data[IFLA_CAN_CTRLMODE]) {
+		struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+
+		is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
+	}
+
+	if (is_can_fd) {
+		if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
+			return -EOPNOTSUPP;
+	}
+
+	if (data[IFLA_CAN_DATA_BITTIMING]) {
+		if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
+			return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int can_changelink(struct net_device *dev, struct nlattr *tb[],
+			  struct nlattr *data[],
+			  struct netlink_ext_ack *extack)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	int err;
+
+	/* We need synchronization with dev->stop() */
+	ASSERT_RTNL();
+
+	if (data[IFLA_CAN_BITTIMING]) {
+		struct can_bittiming bt;
+
+		/* Do not allow changing bittiming while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+
+		/* Calculate bittiming parameters based on
+		 * bittiming_const if set, otherwise pass bitrate
+		 * directly via do_set_bitrate(). Bail out if neither
+		 * is given.
+		 */
+		if (!priv->bittiming_const && !priv->do_set_bittiming)
+			return -EOPNOTSUPP;
+
+		memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
+		err = can_get_bittiming(dev, &bt,
+					priv->bittiming_const,
+					priv->bitrate_const,
+					priv->bitrate_const_cnt);
+		if (err)
+			return err;
+
+		if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
+			netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
+				   priv->bitrate_max);
+			return -EINVAL;
+		}
+
+		memcpy(&priv->bittiming, &bt, sizeof(bt));
+
+		if (priv->do_set_bittiming) {
+			/* Finally, set the bit-timing registers */
+			err = priv->do_set_bittiming(dev);
+			if (err)
+				return err;
+		}
+	}
+
+	if (data[IFLA_CAN_CTRLMODE]) {
+		struct can_ctrlmode *cm;
+		u32 ctrlstatic;
+		u32 maskedflags;
+
+		/* Do not allow changing controller mode while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		cm = nla_data(data[IFLA_CAN_CTRLMODE]);
+		ctrlstatic = priv->ctrlmode_static;
+		maskedflags = cm->flags & cm->mask;
+
+		/* check whether provided bits are allowed to be passed */
+		if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
+			return -EOPNOTSUPP;
+
+		/* do not check for static fd-non-iso if 'fd' is disabled */
+		if (!(maskedflags & CAN_CTRLMODE_FD))
+			ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
+
+		/* make sure static options are provided by configuration */
+		if ((maskedflags & ctrlstatic) != ctrlstatic)
+			return -EOPNOTSUPP;
+
+		/* clear bits to be modified and copy the flag values */
+		priv->ctrlmode &= ~cm->mask;
+		priv->ctrlmode |= maskedflags;
+
+		/* CAN_CTRLMODE_FD can only be set when driver supports FD */
+		if (priv->ctrlmode & CAN_CTRLMODE_FD)
+			dev->mtu = CANFD_MTU;
+		else
+			dev->mtu = CAN_MTU;
+	}
+
+	if (data[IFLA_CAN_RESTART_MS]) {
+		/* Do not allow changing restart delay while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+		priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
+	}
+
+	if (data[IFLA_CAN_RESTART]) {
+		/* Do not allow a restart while not running */
+		if (!(dev->flags & IFF_UP))
+			return -EINVAL;
+		err = can_restart_now(dev);
+		if (err)
+			return err;
+	}
+
+	if (data[IFLA_CAN_DATA_BITTIMING]) {
+		struct can_bittiming dbt;
+
+		/* Do not allow changing bittiming while running */
+		if (dev->flags & IFF_UP)
+			return -EBUSY;
+
+		/* Calculate bittiming parameters based on
+		 * data_bittiming_const if set, otherwise pass bitrate
+		 * directly via do_set_bitrate(). Bail out if neither
+		 * is given.
+		 */
+		if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
+			return -EOPNOTSUPP;
+
+		memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
+		       sizeof(dbt));
+		err = can_get_bittiming(dev, &dbt,
+					priv->data_bittiming_const,
+					priv->data_bitrate_const,
+					priv->data_bitrate_const_cnt);
+		if (err)
+			return err;
+
+		if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
+			netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
+				   priv->bitrate_max);
+			return -EINVAL;
+		}
+
+		memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
+
+		if (priv->do_set_data_bittiming) {
+			/* Finally, set the bit-timing registers */
+			err = priv->do_set_data_bittiming(dev);
+			if (err)
+				return err;
+		}
+	}
+
+	if (data[IFLA_CAN_TERMINATION]) {
+		const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
+		const unsigned int num_term = priv->termination_const_cnt;
+		unsigned int i;
+
+		if (!priv->do_set_termination)
+			return -EOPNOTSUPP;
+
+		/* check whether given value is supported by the interface */
+		for (i = 0; i < num_term; i++) {
+			if (termval == priv->termination_const[i])
+				break;
+		}
+		if (i >= num_term)
+			return -EINVAL;
+
+		/* Finally, set the termination value */
+		err = priv->do_set_termination(dev, termval);
+		if (err)
+			return err;
+
+		priv->termination = termval;
+	}
+
+	return 0;
+}
+
+static size_t can_get_size(const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	size_t size = 0;
+
+	if (priv->bittiming.bitrate)				/* IFLA_CAN_BITTIMING */
+		size += nla_total_size(sizeof(struct can_bittiming));
+	if (priv->bittiming_const)				/* IFLA_CAN_BITTIMING_CONST */
+		size += nla_total_size(sizeof(struct can_bittiming_const));
+	size += nla_total_size(sizeof(struct can_clock));	/* IFLA_CAN_CLOCK */
+	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_STATE */
+	size += nla_total_size(sizeof(struct can_ctrlmode));	/* IFLA_CAN_CTRLMODE */
+	size += nla_total_size(sizeof(u32));			/* IFLA_CAN_RESTART_MS */
+	if (priv->do_get_berr_counter)				/* IFLA_CAN_BERR_COUNTER */
+		size += nla_total_size(sizeof(struct can_berr_counter));
+	if (priv->data_bittiming.bitrate)			/* IFLA_CAN_DATA_BITTIMING */
+		size += nla_total_size(sizeof(struct can_bittiming));
+	if (priv->data_bittiming_const)				/* IFLA_CAN_DATA_BITTIMING_CONST */
+		size += nla_total_size(sizeof(struct can_bittiming_const));
+	if (priv->termination_const) {
+		size += nla_total_size(sizeof(priv->termination));		/* IFLA_CAN_TERMINATION */
+		size += nla_total_size(sizeof(*priv->termination_const) *	/* IFLA_CAN_TERMINATION_CONST */
+				       priv->termination_const_cnt);
+	}
+	if (priv->bitrate_const)				/* IFLA_CAN_BITRATE_CONST */
+		size += nla_total_size(sizeof(*priv->bitrate_const) *
+				       priv->bitrate_const_cnt);
+	if (priv->data_bitrate_const)				/* IFLA_CAN_DATA_BITRATE_CONST */
+		size += nla_total_size(sizeof(*priv->data_bitrate_const) *
+				       priv->data_bitrate_const_cnt);
+	size += sizeof(priv->bitrate_max);			/* IFLA_CAN_BITRATE_MAX */
+
+	return size;
+}
+
+static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
+	struct can_berr_counter bec;
+	enum can_state state = priv->state;
+
+	if (priv->do_get_state)
+		priv->do_get_state(dev, &state);
+
+	if ((priv->bittiming.bitrate &&
+	     nla_put(skb, IFLA_CAN_BITTIMING,
+		     sizeof(priv->bittiming), &priv->bittiming)) ||
+
+	    (priv->bittiming_const &&
+	     nla_put(skb, IFLA_CAN_BITTIMING_CONST,
+		     sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
+
+	    nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
+	    nla_put_u32(skb, IFLA_CAN_STATE, state) ||
+	    nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
+	    nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
+
+	    (priv->do_get_berr_counter &&
+	     !priv->do_get_berr_counter(dev, &bec) &&
+	     nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
+
+	    (priv->data_bittiming.bitrate &&
+	     nla_put(skb, IFLA_CAN_DATA_BITTIMING,
+		     sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
+
+	    (priv->data_bittiming_const &&
+	     nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
+		     sizeof(*priv->data_bittiming_const),
+		     priv->data_bittiming_const)) ||
+
+	    (priv->termination_const &&
+	     (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
+	      nla_put(skb, IFLA_CAN_TERMINATION_CONST,
+		      sizeof(*priv->termination_const) *
+		      priv->termination_const_cnt,
+		      priv->termination_const))) ||
+
+	    (priv->bitrate_const &&
+	     nla_put(skb, IFLA_CAN_BITRATE_CONST,
+		     sizeof(*priv->bitrate_const) *
+		     priv->bitrate_const_cnt,
+		     priv->bitrate_const)) ||
+
+	    (priv->data_bitrate_const &&
+	     nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
+		     sizeof(*priv->data_bitrate_const) *
+		     priv->data_bitrate_const_cnt,
+		     priv->data_bitrate_const)) ||
+
+	    (nla_put(skb, IFLA_CAN_BITRATE_MAX,
+		     sizeof(priv->bitrate_max),
+		     &priv->bitrate_max))
+	    )
+
+		return -EMSGSIZE;
+
+	return 0;
+}
+
+static size_t can_get_xstats_size(const struct net_device *dev)
+{
+	return sizeof(struct can_device_stats);
+}
+
+static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
+{
+	struct can_priv *priv = netdev_priv(dev);
+
+	if (nla_put(skb, IFLA_INFO_XSTATS,
+		    sizeof(priv->can_stats), &priv->can_stats))
+		goto nla_put_failure;
+	return 0;
+
+nla_put_failure:
+	return -EMSGSIZE;
+}
+
+static int can_newlink(struct net *src_net, struct net_device *dev,
+		       struct nlattr *tb[], struct nlattr *data[],
+		       struct netlink_ext_ack *extack)
+{
+	return -EOPNOTSUPP;
+}
+
+static void can_dellink(struct net_device *dev, struct list_head *head)
+{
+}
+
+struct rtnl_link_ops can_link_ops __read_mostly = {
+	.kind		= "can",
+	.maxtype	= IFLA_CAN_MAX,
+	.policy		= can_policy,
+	.setup		= can_setup,
+	.validate	= can_validate,
+	.newlink	= can_newlink,
+	.changelink	= can_changelink,
+	.dellink	= can_dellink,
+	.get_size	= can_get_size,
+	.fill_info	= can_fill_info,
+	.get_xstats_size = can_get_xstats_size,
+	.fill_xstats	= can_fill_xstats,
+};
+
+int can_netlink_register(void)
+{
+	return rtnl_link_register(&can_link_ops);
+}
+
+void can_netlink_unregister(void)
+{
+	rtnl_link_unregister(&can_link_ops);
+}
diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
index 4a26e128af7f..7faf6a37d5b2 100644
--- a/include/linux/can/dev.h
+++ b/include/linux/can/dev.h
@@ -100,6 +100,8 @@ static inline void can_set_static_ctrlmode(struct net_device *dev,
 		dev->mtu = CANFD_MTU;
 }
 
+void can_setup(struct net_device *dev);
+
 struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
 				    unsigned int txqs, unsigned int rxqs);
 #define alloc_candev(sizeof_priv, echo_skb_max) \
@@ -130,4 +132,8 @@ void of_can_transceiver(struct net_device *dev);
 static inline void of_can_transceiver(struct net_device *dev) { }
 #endif
 
+extern struct rtnl_link_ops can_link_ops;
+int can_netlink_register(void);
+void can_netlink_unregister(void);
+
 #endif /* !_CAN_DEV_H */
-- 
2.29.2



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

* [net-next 07/13] can: length: convert to kernel coding style
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (5 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 06/13] can: dev: move netlink related code " Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 08/13] can: length: can_fd_len2dlc(): simplify length calculcation Marc Kleine-Budde
                   ` (6 subsequent siblings)
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

This patch converts the file into the kernel coding style.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/length.c | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
index 540d40dc0bc2..4bf3847ec508 100644
--- a/drivers/net/can/dev/length.c
+++ b/drivers/net/can/dev/length.c
@@ -8,8 +8,10 @@
 
 /* CAN DLC to real data length conversion helpers */
 
-static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
-			     8, 12, 16, 20, 24, 32, 48, 64};
+static const u8 dlc2len[] = {
+	0, 1, 2, 3, 4, 5, 6, 7,
+	8, 12, 16, 20, 24, 32, 48, 64
+};
 
 /* get data length from raw data length code (DLC) */
 u8 can_fd_dlc2len(u8 dlc)
@@ -18,16 +20,18 @@ u8 can_fd_dlc2len(u8 dlc)
 }
 EXPORT_SYMBOL_GPL(can_fd_dlc2len);
 
-static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
-			     9, 9, 9, 9,			/* 9 - 12 */
-			     10, 10, 10, 10,			/* 13 - 16 */
-			     11, 11, 11, 11,			/* 17 - 20 */
-			     12, 12, 12, 12,			/* 21 - 24 */
-			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
-			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
-			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
-			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
-			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
+static const u8 len2dlc[] = {
+	0, 1, 2, 3, 4, 5, 6, 7, 8,	/* 0 - 8 */
+	9, 9, 9, 9,			/* 9 - 12 */
+	10, 10, 10, 10,			/* 13 - 16 */
+	11, 11, 11, 11,			/* 17 - 20 */
+	12, 12, 12, 12,			/* 21 - 24 */
+	13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
+	14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
+	14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
+	15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
+	15, 15, 15, 15, 15, 15, 15, 15	/* 57 - 64 */
+};
 
 /* map the sanitized data length to an appropriate data length code */
 u8 can_fd_len2dlc(u8 len)
-- 
2.29.2



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

* [net-next 08/13] can: length: can_fd_len2dlc(): simplify length calculcation
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (6 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 07/13] can: length: convert to kernel coding style Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 09/13] can: length: canfd_sanitize_len(): add function to sanitize CAN-FD data length Marc Kleine-Budde
                   ` (5 subsequent siblings)
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

If the length paramter in len2dlc() exceeds the size of the len2dlc array, we
return 0xF. This is equal to the last 16 members of the array.

This patch removes these members from the array, uses ARRAY_SIZE() for the
length check, and returns CANFD_MAX_DLC (which is 0xf).

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

diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
index 4bf3847ec508..b90d30858935 100644
--- a/drivers/net/can/dev/length.c
+++ b/drivers/net/can/dev/length.c
@@ -29,15 +29,13 @@ static const u8 len2dlc[] = {
 	13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
 	14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
 	14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
-	15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
-	15, 15, 15, 15, 15, 15, 15, 15	/* 57 - 64 */
 };
 
 /* map the sanitized data length to an appropriate data length code */
 u8 can_fd_len2dlc(u8 len)
 {
-	if (unlikely(len > 64))
-		return 0xF;
+	if (len > ARRAY_SIZE(len2dlc))
+		return CANFD_MAX_DLC;
 
 	return len2dlc[len];
 }
-- 
2.29.2



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

* [net-next 09/13] can: length: canfd_sanitize_len(): add function to sanitize CAN-FD data length
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (7 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 08/13] can: length: can_fd_len2dlc(): simplify length calculcation Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer Marc Kleine-Budde
                   ` (4 subsequent siblings)
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

The data field in CAN-FD frames have specifig frame length (0, 1, 2, 3, 4, 5,
6, 7, 8, 12, 16, 20, 24, 32, 48, 64). This function "rounds" up a given length
to the next valid CAN-FD frame length.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 include/linux/can/length.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/can/length.h b/include/linux/can/length.h
index fabd93bcde3e..0d796f96266b 100644
--- a/include/linux/can/length.h
+++ b/include/linux/can/length.h
@@ -48,4 +48,10 @@ u8 can_fd_dlc2len(u8 dlc);
 /* map the sanitized data length to an appropriate data length code */
 u8 can_fd_len2dlc(u8 len);
 
+/* map the data length to an appropriate data link layer length */
+static inline u8 canfd_sanitize_len(u8 len)
+{
+	return can_fd_dlc2len(can_fd_len2dlc(len));
+}
+
 #endif /* !_CAN_LENGTH_H */
-- 
2.29.2



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

* [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (8 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 09/13] can: length: canfd_sanitize_len(): add function to sanitize CAN-FD data length Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-10  3:32   ` Vincent MAILHOL
  2021-01-09 17:40 ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
                   ` (3 subsequent siblings)
  13 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can
  Cc: Oliver Hartkopp, Vincent Mailhol, Arunachalam Santhanam,
	Marc Kleine-Budde

From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>

This patch adds the function can_skb_get_frame_len() which returns the length
of a CAN frame on the data link layer, including Start-of-frame, Identifier,
various other bits, the actual data, the CRC, the End-of-frame, the Inter frame
spacing.

Co-developed-by: Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>
Not-Signed-off-by: Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>
Co-developed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Not-Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Co-developed-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/length.c |  50 +++++++++++++++
 include/linux/can/length.h   | 121 +++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
index b90d30858935..5b9fa51a3ca3 100644
--- a/drivers/net/can/dev/length.c
+++ b/drivers/net/can/dev/length.c
@@ -40,3 +40,53 @@ u8 can_fd_len2dlc(u8 len)
 	return len2dlc[len];
 }
 EXPORT_SYMBOL_GPL(can_fd_len2dlc);
+
+/**
+ * can_skb_get_frame_len() - Calculate the CAN Frame length in bytes
+ * 	of a given skb.
+ * @skb: socket buffer of a CAN message.
+ *
+ * Do a rough calculation: bit stuffing is ignored and length in bits
+ * is rounded up to a length in bytes.
+ *
+ * Rationale: this function is to be used for the BQL functions
+ * (netdev_sent_queue() and netdev_completed_queue()) which expect a
+ * value in bytes. Just using skb->len is insufficient because it will
+ * return the constant value of CAN(FD)_MTU. Doing the bit stuffing
+ * calculation would be too expensive in term of computing resources
+ * for no noticeable gain.
+ *
+ * Remarks: The payload of CAN FD frames with BRS flag are sent at a
+ * different bitrate. Currently, the can-utils canbusload tool does
+ * not support CAN-FD yet and so we could not run any benchmark to
+ * measure the impact. There might be possible improvement here.
+ *
+ * Return: length in bytes.
+ */
+unsigned int can_skb_get_frame_len(const struct sk_buff *skb)
+{
+	const struct canfd_frame *cf = (const struct canfd_frame *)skb->data;
+	u8 len;
+
+	if (can_is_canfd_skb(skb))
+		len = canfd_sanitize_len(cf->len);
+	else if (cf->can_id & CAN_RTR_FLAG)
+		len = 0;
+	else
+		len = cf->len;
+
+	if (can_is_canfd_skb(skb)) {
+		if (cf->can_id & CAN_EFF_FLAG)
+			len += CANFD_FRAME_OVERHEAD_EFF;
+		else
+			len += CANFD_FRAME_OVERHEAD_SFF;
+	} else {
+		if (cf->can_id & CAN_EFF_FLAG)
+			len += CAN_FRAME_OVERHEAD_EFF;
+		else
+			len += CAN_FRAME_OVERHEAD_SFF;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(can_skb_get_frame_len);
diff --git a/include/linux/can/length.h b/include/linux/can/length.h
index 0d796f96266b..7d8affcc3d9f 100644
--- a/include/linux/can/length.h
+++ b/include/linux/can/length.h
@@ -3,11 +3,129 @@
  * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
  *               Varma Electronics Oy
  * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
+ * Copyright (C) 2020 Marc Kleine-Budde <kernel@pengutronix.de>
  */
 
 #ifndef _CAN_LENGTH_H
 #define _CAN_LENGTH_H
 
+/*
+ * Size of a Classical CAN Standard Frame
+ *
+ * Name of Field			Bits
+ * ---------------------------------------------------------
+ * Start-of-frame			1
+ * Identifier				11
+ * Remote transmission request (RTR)	1
+ * Identifier extension bit (IDE)	1
+ * Reserved bit (r0)			1
+ * Data length code (DLC)		4
+ * Data field				0...64
+ * CRC					15
+ * CRC delimiter			1
+ * ACK slot				1
+ * ACK delimiter			1
+ * End-of-frame (EOF)			7
+ * Inter frame spacing			3
+ *
+ * rounded up and ignoring bitstuffing
+ */
+#define CAN_FRAME_OVERHEAD_SFF DIV_ROUND_UP(47, 8)
+
+/*
+ * Size of a Classical CAN Extended Frame
+ *
+ * Name of Field			Bits
+ * ---------------------------------------------------------
+ * Start-of-frame			1
+ * Identifier A				11
+ * Substitute remote request (SRR)	1
+ * Identifier extension bit (IDE)	1
+ * Identifier B				18
+ * Remote transmission request (RTR)	1
+ * Reserved bits (r1, r0)		2
+ * Data length code (DLC)		4
+ * Data field				0...64
+ * CRC					15
+ * CRC delimiter			1
+ * ACK slot				1
+ * ACK delimiter			1
+ * End-of-frame (EOF)			7
+ * Inter frame spacing			3
+ *
+ * rounded up and ignoring bitstuffing
+ */
+#define CAN_FRAME_OVERHEAD_EFF DIV_ROUND_UP(67, 8)
+
+/*
+ * Size of a CAN-FD Standard Frame
+ *
+ * Name of Field			Bits
+ * ---------------------------------------------------------
+ * Start-of-frame			1
+ * Identifier				11
+ * Reserved bit (r1)			1
+ * Identifier extension bit (IDE)	1
+ * Flexible data rate format (FDF)	1
+ * Reserved bit (r0)			1
+ * Bit Rate Switch (BRS)		1
+ * Error Status Indicator (ESI)		1
+ * Data length code (DLC)		4
+ * Data field				0...512
+ * Stuff Bit Count (SBC)		0...16: 4 20...64:5
+ * CRC					0...16: 17 20...64:21
+ * CRC delimiter (CD)			1
+ * ACK slot (AS)			1
+ * ACK delimiter (AD)			1
+ * End-of-frame (EOF)			7
+ * Inter frame spacing			3
+ *
+ * assuming CRC21, rounded up and ignoring bitstuffing
+ */
+#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(61, 8)
+
+/*
+ * Size of a CAN-FD Extended Frame
+ *
+ * Name of Field			Bits
+ * ---------------------------------------------------------
+ * Start-of-frame			1
+ * Identifier A				11
+ * Substitute remote request (SRR)	1
+ * Identifier extension bit (IDE)	1
+ * Identifier B				18
+ * Reserved bit (r1)			1
+ * Flexible data rate format (FDF)	1
+ * Reserved bit (r0)			1
+ * Bit Rate Switch (BRS)		1
+ * Error Status Indicator (ESI)		1
+ * Data length code (DLC)		4
+ * Data field				0...512
+ * Stuff Bit Count (SBC)		0...16: 4 20...64:5
+ * CRC					0...16: 17 20...64:21
+ * CRC delimiter (CD)			1
+ * ACK slot (AS)			1
+ * ACK delimiter (AD)			1
+ * End-of-frame (EOF)			7
+ * Inter frame spacing			3
+ *
+ * assuming CRC21, rounded up and ignoring bitstuffing
+ */
+#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(80, 8)
+
+/*
+ * Maximum size of a Classical CAN frame
+ * (rounded up and ignoring bitstuffing)
+ */
+#define CAN_FRAME_LEN_MAX (CAN_FRAME_OVERHEAD_EFF + CAN_MAX_DLEN)
+
+/*
+ * Maximum size of a CAN-FD frame (rough estimation because
+ * ES58X_SFF_BYTES() and ES58X_EFF_BYTES() macros are using the
+ * constant values for Classical CAN, not CAN-FD).
+ */
+#define CANFD_FRAME_LEN_MAX (CANFD_FRAME_OVERHEAD_EFF + CANFD_MAX_DLEN)
+
 /*
  * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
  * Classical CAN frame into a valid data length of max. 8 bytes.
@@ -48,6 +166,9 @@ u8 can_fd_dlc2len(u8 dlc);
 /* map the sanitized data length to an appropriate data length code */
 u8 can_fd_len2dlc(u8 len);
 
+/* calculate the CAN Frame length in bytes of a given skb */
+unsigned int can_skb_get_frame_len(const struct sk_buff *skb);
+
 /* map the data length to an appropriate data link layer length */
 static inline u8 canfd_sanitize_len(u8 len)
 {
-- 
2.29.2



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

* [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (9 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-10  6:52   ` Vincent MAILHOL
  2021-01-09 17:40 ` [net-next 12/13] can: dev: can_get_echo_skb(): extend to return can " Marc Kleine-Budde
                   ` (2 subsequent siblings)
  13 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

In order to implement byte queue limits (bql) in CAN drivers, the length of the
CAN frame needs to be passed into the networking stack after queueing and after
transmission completion.

To avoid to calculate this length twice, extend the struct can_skb_priv to hold
the length of the CAN frame and extend __can_get_echo_skb() to return that
value.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/rx-offload.c | 2 +-
 drivers/net/can/dev/skb.c        | 9 +++++++--
 include/linux/can/skb.h          | 4 +++-
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index 3c1912c0430b..6a26b5282df1 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -271,7 +271,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
 	u8 len;
 	int err;
 
-	skb = __can_get_echo_skb(dev, idx, &len);
+	skb = __can_get_echo_skb(dev, idx, &len, NULL);
 	if (!skb)
 		return 0;
 
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 26cd597ff771..24f782a23409 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -76,7 +76,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 EXPORT_SYMBOL_GPL(can_put_echo_skb);
 
 struct sk_buff *
-__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
+__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
+		   unsigned int *frame_len_ptr)
 {
 	struct can_priv *priv = netdev_priv(dev);
 
@@ -91,6 +92,7 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 		 * length is supported on both CAN and CANFD frames.
 		 */
 		struct sk_buff *skb = priv->echo_skb[idx];
+		struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
 		struct canfd_frame *cf = (struct canfd_frame *)skb->data;
 
 		/* get the real payload length for netdev statistics */
@@ -99,6 +101,9 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 		else
 			*len_ptr = cf->len;
 
+		if (frame_len_ptr)
+			*frame_len_ptr = can_skb_priv->frame_len;
+
 		priv->echo_skb[idx] = NULL;
 
 		return skb;
@@ -118,7 +123,7 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
 	struct sk_buff *skb;
 	u8 len;
 
-	skb = __can_get_echo_skb(dev, idx, &len);
+	skb = __can_get_echo_skb(dev, idx, &len, NULL);
 	if (!skb)
 		return 0;
 
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index c90ebbd3008c..5db9da30843c 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -20,7 +20,7 @@ void can_flush_echo_skb(struct net_device *dev);
 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 		     unsigned int idx);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
-				   u8 *len_ptr);
+				   u8 *len_ptr, unsigned int *frame_len_ptr);
 unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
 void can_free_echo_skb(struct net_device *dev, unsigned int idx);
 struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
@@ -42,11 +42,13 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev,
  * struct can_skb_priv - private additional data inside CAN sk_buffs
  * @ifindex:	ifindex of the first interface the CAN frame appeared on
  * @skbcnt:	atomic counter to have an unique id together with skb pointer
+ * @frame_len:	length of CAN frame in data link layer
  * @cf:		align to the following CAN frame at skb->data
  */
 struct can_skb_priv {
 	int ifindex;
 	int skbcnt;
+	unsigned int frame_len;
 	struct can_frame cf[];
 };
 
-- 
2.29.2



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

* [net-next 12/13] can: dev: can_get_echo_skb(): extend to return can frame length
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (10 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-09 17:40 ` [net-next 13/13] can: dev: can_rx_offload_get_echo_skb(): " Marc Kleine-Budde
  2021-01-10  8:55 ` [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Vincent MAILHOL
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

In order to implement byte queue limits (bql) in CAN drivers, the length of the
CAN frame needs to be passed into the networking stack after queueing and after
transmission completion.

To avoid to calculate this length twice, extend can_get_echo_skb() to return
that value. Convert all users of this function, too.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/at91_can.c                        | 2 +-
 drivers/net/can/c_can/c_can.c                     | 2 +-
 drivers/net/can/cc770/cc770.c                     | 2 +-
 drivers/net/can/dev/skb.c                         | 5 +++--
 drivers/net/can/grcan.c                           | 2 +-
 drivers/net/can/ifi_canfd/ifi_canfd.c             | 2 +-
 drivers/net/can/kvaser_pciefd.c                   | 4 ++--
 drivers/net/can/m_can/m_can.c                     | 4 ++--
 drivers/net/can/mscan/mscan.c                     | 2 +-
 drivers/net/can/pch_can.c                         | 2 +-
 drivers/net/can/peak_canfd/peak_canfd.c           | 2 +-
 drivers/net/can/rcar/rcar_can.c                   | 2 +-
 drivers/net/can/rcar/rcar_canfd.c                 | 2 +-
 drivers/net/can/sja1000/sja1000.c                 | 2 +-
 drivers/net/can/softing/softing_main.c            | 2 +-
 drivers/net/can/spi/hi311x.c                      | 2 +-
 drivers/net/can/spi/mcp251x.c                     | 2 +-
 drivers/net/can/sun4i_can.c                       | 2 +-
 drivers/net/can/usb/ems_usb.c                     | 2 +-
 drivers/net/can/usb/esd_usb2.c                    | 2 +-
 drivers/net/can/usb/gs_usb.c                      | 2 +-
 drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 2 +-
 drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c  | 2 +-
 drivers/net/can/usb/mcba_usb.c                    | 2 +-
 drivers/net/can/usb/peak_usb/pcan_usb_core.c      | 2 +-
 drivers/net/can/usb/ucan.c                        | 2 +-
 drivers/net/can/usb/usb_8dev.c                    | 2 +-
 drivers/net/can/xilinx_can.c                      | 2 +-
 include/linux/can/skb.h                           | 3 ++-
 29 files changed, 34 insertions(+), 32 deletions(-)

diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index 5284f0ab3b06..ae015ec227d4 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -856,7 +856,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
 		if (likely(reg_msr & AT91_MSR_MRDY &&
 			   ~reg_msr & AT91_MSR_MABT)) {
 			/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
-			can_get_echo_skb(dev, mb - get_mb_tx_first(priv));
+			can_get_echo_skb(dev, mb - get_mb_tx_first(priv), NULL);
 			dev->stats.tx_packets++;
 			can_led_event(dev, CAN_LED_EVENT_TX);
 		}
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 63f48b016ecd..e7ee60b2c76b 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -733,7 +733,7 @@ static void c_can_do_tx(struct net_device *dev)
 		pend &= ~(1 << idx);
 		obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
 		c_can_inval_tx_object(dev, IF_RX, obj);
-		can_get_echo_skb(dev, idx);
+		can_get_echo_skb(dev, idx, NULL);
 		bytes += priv->dlc[idx];
 		pkts++;
 	}
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index 8d9f332c35e0..5ecb2afd6bbf 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -703,7 +703,7 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
 	stats->tx_packets++;
 
 	can_put_echo_skb(priv->tx_skb, dev, 0);
-	can_get_echo_skb(dev, 0);
+	can_get_echo_skb(dev, 0, NULL);
 	priv->tx_skb = NULL;
 
 	netif_wake_queue(dev);
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 24f782a23409..568dc28f7a4e 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -118,12 +118,13 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
  * is handled in the device driver. The driver must protect
  * access to priv->echo_skb, if necessary.
  */
-unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
+unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
+			      unsigned int *frame_len_ptr)
 {
 	struct sk_buff *skb;
 	u8 len;
 
-	skb = __can_get_echo_skb(dev, idx, &len, NULL);
+	skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
 	if (!skb)
 		return 0;
 
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index f5d94a692576..6aaebbcb7e76 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -517,7 +517,7 @@ static int catch_up_echo_skb(struct net_device *dev, int budget, bool echo)
 			stats->tx_packets++;
 			stats->tx_bytes += priv->txdlc[i];
 			priv->txdlc[i] = 0;
-			can_get_echo_skb(dev, i);
+			can_get_echo_skb(dev, i, NULL);
 		} else {
 			/* For cleanup of untransmitted messages */
 			can_free_echo_skb(dev, i);
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index 86b0e1406a21..b3ec32f60e67 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -629,7 +629,7 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
 
 	/* TX IRQ */
 	if (isr & IFI_CANFD_INTERRUPT_TXFIFO_REMOVE) {
-		stats->tx_bytes += can_get_echo_skb(ndev, 0);
+		stats->tx_bytes += can_get_echo_skb(ndev, 0, NULL);
 		stats->tx_packets++;
 		can_led_event(ndev, CAN_LED_EVENT_TX);
 	}
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index 969cedb9b0b6..6602791b3b81 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -1467,7 +1467,7 @@ static int kvaser_pciefd_handle_eack_packet(struct kvaser_pciefd *pcie,
 				  can->reg_base + KVASER_PCIEFD_KCAN_CTRL_REG);
 	} else {
 		int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
-		int dlc = can_get_echo_skb(can->can.dev, echo_idx);
+		int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL);
 		struct net_device_stats *stats = &can->can.dev->stats;
 
 		stats->tx_bytes += dlc;
@@ -1533,7 +1533,7 @@ static int kvaser_pciefd_handle_ack_packet(struct kvaser_pciefd *pcie,
 		netdev_dbg(can->can.dev, "Packet was flushed\n");
 	} else {
 		int echo_idx = p->header[0] & KVASER_PCIEFD_PACKET_SEQ_MSK;
-		int dlc = can_get_echo_skb(can->can.dev, echo_idx);
+		int dlc = can_get_echo_skb(can->can.dev, echo_idx, NULL);
 		u8 count = ioread32(can->reg_base +
 				    KVASER_PCIEFD_KCAN_TX_NPACKETS_REG) & 0xff;
 
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index da551fd0f502..1e35c6ce75a9 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -930,7 +930,7 @@ static void m_can_echo_tx_event(struct net_device *dev)
 						(fgi << TXEFA_EFAI_SHIFT)));
 
 		/* update stats */
-		stats->tx_bytes += can_get_echo_skb(dev, msg_mark);
+		stats->tx_bytes += can_get_echo_skb(dev, msg_mark, NULL);
 		stats->tx_packets++;
 	}
 }
@@ -972,7 +972,7 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
 	if (cdev->version == 30) {
 		if (ir & IR_TC) {
 			/* Transmission Complete Interrupt*/
-			stats->tx_bytes += can_get_echo_skb(dev, 0);
+			stats->tx_bytes += can_get_echo_skb(dev, 0, NULL);
 			stats->tx_packets++;
 			can_led_event(dev, CAN_LED_EVENT_TX);
 			netif_wake_queue(dev);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 5ed00a1558e1..6caa89fe7184 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -448,7 +448,7 @@ static irqreturn_t mscan_isr(int irq, void *dev_id)
 			out_8(&regs->cantbsel, mask);
 			stats->tx_bytes += in_8(&regs->tx.dlr);
 			stats->tx_packets++;
-			can_get_echo_skb(dev, entry->id);
+			can_get_echo_skb(dev, entry->id, NULL);
 			priv->tx_active &= ~mask;
 			list_del(pos);
 		}
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 4f9e7ec192aa..6faadac983b6 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -711,7 +711,7 @@ static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
 	struct net_device_stats *stats = &(priv->ndev->stats);
 	u32 dlc;
 
-	can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
+	can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1, NULL);
 	iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
 		  &priv->regs->ifregs[1].cmask);
 	pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, int_stat);
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
index c5334b0c3038..86df3b2b701a 100644
--- a/drivers/net/can/peak_canfd/peak_canfd.c
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
@@ -266,7 +266,7 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
 		unsigned long flags;
 
 		spin_lock_irqsave(&priv->echo_lock, flags);
-		can_get_echo_skb(priv->ndev, msg->client);
+		can_get_echo_skb(priv->ndev, msg->client, NULL);
 
 		/* count bytes of the echo instead of skb */
 		stats->tx_bytes += cf_len;
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index c803327f8f79..ae76ea3ae0e6 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -386,7 +386,7 @@ static void rcar_can_tx_done(struct net_device *ndev)
 		stats->tx_bytes += priv->tx_dlc[priv->tx_tail %
 						RCAR_CAN_FIFO_DEPTH];
 		priv->tx_dlc[priv->tx_tail % RCAR_CAN_FIFO_DEPTH] = 0;
-		can_get_echo_skb(ndev, priv->tx_tail % RCAR_CAN_FIFO_DEPTH);
+		can_get_echo_skb(ndev, priv->tx_tail % RCAR_CAN_FIFO_DEPTH, NULL);
 		priv->tx_tail++;
 		netif_wake_queue(ndev);
 	}
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index 2778ed5c61d1..ba658664e7ee 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1044,7 +1044,7 @@ static void rcar_canfd_tx_done(struct net_device *ndev)
 		stats->tx_packets++;
 		stats->tx_bytes += priv->tx_len[sent];
 		priv->tx_len[sent] = 0;
-		can_get_echo_skb(ndev, sent);
+		can_get_echo_skb(ndev, sent, NULL);
 
 		spin_lock_irqsave(&priv->tx_lock, flags);
 		priv->tx_tail++;
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index b6a7003c51d2..ded7dacaecd1 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -531,7 +531,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
 				stats->tx_bytes +=
 					priv->read_reg(priv, SJA1000_FI) & 0xf;
 				stats->tx_packets++;
-				can_get_echo_skb(dev, 0);
+				can_get_echo_skb(dev, 0, NULL);
 			}
 			netif_wake_queue(dev);
 			can_led_event(dev, CAN_LED_EVENT_TX);
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 40070c930202..583e1246ac92 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -284,7 +284,7 @@ static int softing_handle_1(struct softing *card)
 			skb = priv->can.echo_skb[priv->tx.echo_get];
 			if (skb)
 				skb->tstamp = ktime;
-			can_get_echo_skb(netdev, priv->tx.echo_get);
+			can_get_echo_skb(netdev, priv->tx.echo_get, NULL);
 			++priv->tx.echo_get;
 			if (priv->tx.echo_get >= TX_ECHO_SKB_MAX)
 				priv->tx.echo_get = 0;
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index f9455de94786..c1358826074f 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -725,7 +725,7 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
 			net->stats.tx_bytes += priv->tx_len - 1;
 			can_led_event(net, CAN_LED_EVENT_TX);
 			if (priv->tx_len) {
-				can_get_echo_skb(net, 0);
+				can_get_echo_skb(net, 0, NULL);
 				priv->tx_len = 0;
 			}
 			netif_wake_queue(net);
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 25859d16d06f..114ac4c303b6 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1171,7 +1171,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
 			net->stats.tx_bytes += priv->tx_len - 1;
 			can_led_event(net, CAN_LED_EVENT_TX);
 			if (priv->tx_len) {
-				can_get_echo_skb(net, 0);
+				can_get_echo_skb(net, 0, NULL);
 				priv->tx_len = 0;
 			}
 			netif_wake_queue(net);
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index 783b63218b7b..faabfe74c19e 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -655,7 +655,7 @@ static irqreturn_t sun4i_can_interrupt(int irq, void *dev_id)
 			    readl(priv->base +
 				  SUN4I_REG_RBUF_RBACK_START_ADDR) & 0xf;
 			stats->tx_packets++;
-			can_get_echo_skb(dev, 0);
+			can_get_echo_skb(dev, 0, NULL);
 			netif_wake_queue(dev);
 			can_led_event(dev, CAN_LED_EVENT_TX);
 		}
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 25eee4466364..d27567139935 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -518,7 +518,7 @@ static void ems_usb_write_bulk_callback(struct urb *urb)
 	netdev->stats.tx_packets++;
 	netdev->stats.tx_bytes += context->dlc;
 
-	can_get_echo_skb(netdev, context->echo_index);
+	can_get_echo_skb(netdev, context->echo_index, NULL);
 
 	/* Release context */
 	context->echo_index = MAX_TX_URBS;
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index 9eed75a4b678..4f653e221a5b 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -357,7 +357,7 @@ static void esd_usb2_tx_done_msg(struct esd_usb2_net_priv *priv,
 	if (!msg->msg.txdone.status) {
 		stats->tx_packets++;
 		stats->tx_bytes += context->len;
-		can_get_echo_skb(netdev, context->echo_index);
+		can_get_echo_skb(netdev, context->echo_index, NULL);
 	} else {
 		stats->tx_errors++;
 		can_free_echo_skb(netdev, context->echo_index);
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 0487095e1fd0..992a511bcd95 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -370,7 +370,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
 			goto resubmit_urb;
 		}
 
-		can_get_echo_skb(netdev, hf->echo_id);
+		can_get_echo_skb(netdev, hf->echo_id, NULL);
 
 		gs_free_tx_context(txc);
 
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
index 480bd2ecb296..dcee8dc828ec 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
@@ -1151,7 +1151,7 @@ static void kvaser_usb_hydra_tx_acknowledge(const struct kvaser_usb *dev,
 
 	spin_lock_irqsave(&priv->tx_contexts_lock, irq_flags);
 
-	can_get_echo_skb(priv->netdev, context->echo_index);
+	can_get_echo_skb(priv->netdev, context->echo_index, NULL);
 	context->echo_index = dev->max_tx_urbs;
 	--priv->active_tx_contexts;
 	netif_wake_queue(priv->netdev);
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
index 98c016ef0607..59ba7c7beec0 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
@@ -594,7 +594,7 @@ static void kvaser_usb_leaf_tx_acknowledge(const struct kvaser_usb *dev,
 
 	spin_lock_irqsave(&priv->tx_contexts_lock, flags);
 
-	can_get_echo_skb(priv->netdev, context->echo_index);
+	can_get_echo_skb(priv->netdev, context->echo_index, NULL);
 	context->echo_index = dev->max_tx_urbs;
 	--priv->active_tx_contexts;
 	netif_wake_queue(priv->netdev);
diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c
index df54eb7d4b36..23cec88aafc3 100644
--- a/drivers/net/can/usb/mcba_usb.c
+++ b/drivers/net/can/usb/mcba_usb.c
@@ -237,7 +237,7 @@ static void mcba_usb_write_bulk_callback(struct urb *urb)
 		netdev->stats.tx_bytes += ctx->dlc;
 
 		can_led_event(netdev, CAN_LED_EVENT_TX);
-		can_get_echo_skb(netdev, ctx->ndx);
+		can_get_echo_skb(netdev, ctx->ndx, NULL);
 	}
 
 	if (urb->status)
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 251835ea15aa..6a97c29e25e7 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -309,7 +309,7 @@ static void peak_usb_write_bulk_callback(struct urb *urb)
 	}
 
 	/* should always release echo skb and corresponding context */
-	can_get_echo_skb(netdev, context->echo_index);
+	can_get_echo_skb(netdev, context->echo_index, NULL);
 	context->echo_index = PCAN_USB_MAX_TX_URBS;
 
 	/* do wakeup tx queue in case of success only */
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index 7d92da8954fe..cceb142afc3e 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -672,7 +672,7 @@ static void ucan_tx_complete_msg(struct ucan_priv *up,
 			/* update statistics */
 			up->netdev->stats.tx_packets++;
 			up->netdev->stats.tx_bytes += dlc;
-			can_get_echo_skb(up->netdev, echo_index);
+			can_get_echo_skb(up->netdev, echo_index, NULL);
 		} else {
 			up->netdev->stats.tx_dropped++;
 			can_free_echo_skb(up->netdev, echo_index);
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
index 44478304ff46..e16efdbb8f39 100644
--- a/drivers/net/can/usb/usb_8dev.c
+++ b/drivers/net/can/usb/usb_8dev.c
@@ -585,7 +585,7 @@ static void usb_8dev_write_bulk_callback(struct urb *urb)
 	netdev->stats.tx_packets++;
 	netdev->stats.tx_bytes += context->dlc;
 
-	can_get_echo_skb(netdev, context->echo_index);
+	can_get_echo_skb(netdev, context->echo_index, NULL);
 
 	can_led_event(netdev, CAN_LED_EVENT_TX);
 
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 3f54edee92eb..7cda3d64cc05 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -1292,7 +1292,7 @@ static void xcan_tx_interrupt(struct net_device *ndev, u32 isr)
 
 	while (frames_sent--) {
 		stats->tx_bytes += can_get_echo_skb(ndev, priv->tx_tail %
-						    priv->tx_max);
+						    priv->tx_max, NULL);
 		priv->tx_tail++;
 		stats->tx_packets++;
 	}
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 5db9da30843c..3296e2144d5a 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -21,7 +21,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 		     unsigned int idx);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
 				   u8 *len_ptr, unsigned int *frame_len_ptr);
-unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
+unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
+			      unsigned int *frame_len_ptr);
 void can_free_echo_skb(struct net_device *dev, unsigned int idx);
 struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
 struct sk_buff *alloc_canfd_skb(struct net_device *dev,
-- 
2.29.2



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

* [net-next 13/13] can: dev: can_rx_offload_get_echo_skb(): extend to return can frame length
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (11 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 12/13] can: dev: can_get_echo_skb(): extend to return can " Marc Kleine-Budde
@ 2021-01-09 17:40 ` Marc Kleine-Budde
  2021-01-10  8:55 ` [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Vincent MAILHOL
  13 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-09 17:40 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol, Marc Kleine-Budde

In order to implement byte queue limits (bql) in CAN drivers, the length of the
CAN frame needs to be passed into the networking stack after queueing and after
transmission completion.

To avoid to calculate this length twice, extend can_rx_offload_get_echo_skb()
to return that value. Convert all users of this function, too.

Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
 drivers/net/can/dev/rx-offload.c               | 5 +++--
 drivers/net/can/flexcan.c                      | 5 +++--
 drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c | 2 +-
 drivers/net/can/ti_hecc.c                      | 2 +-
 include/linux/can/rx-offload.h                 | 3 ++-
 5 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
index 6a26b5282df1..ab2c1543786c 100644
--- a/drivers/net/can/dev/rx-offload.c
+++ b/drivers/net/can/dev/rx-offload.c
@@ -263,7 +263,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
 EXPORT_SYMBOL_GPL(can_rx_offload_queue_sorted);
 
 unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
-					 unsigned int idx, u32 timestamp)
+					 unsigned int idx, u32 timestamp,
+					 unsigned int *frame_len_ptr)
 {
 	struct net_device *dev = offload->dev;
 	struct net_device_stats *stats = &dev->stats;
@@ -271,7 +272,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
 	u8 len;
 	int err;
 
-	skb = __can_get_echo_skb(dev, idx, &len, NULL);
+	skb = __can_get_echo_skb(dev, idx, &len, frame_len_ptr);
 	if (!skb)
 		return 0;
 
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 7ab20a6b0d1d..ca6018beb79b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1122,8 +1122,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
 		u32 reg_ctrl = priv->read(&priv->tx_mb->can_ctrl);
 
 		handled = IRQ_HANDLED;
-		stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload,
-							       0, reg_ctrl << 16);
+		stats->tx_bytes +=
+			can_rx_offload_get_echo_skb(&priv->offload, 0,
+						    reg_ctrl << 16, NULL);
 		stats->tx_packets++;
 		can_led_event(dev, CAN_LED_EVENT_TX);
 
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 36235afb0bc6..03c94ddd6dee 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -1271,7 +1271,7 @@ mcp251xfd_handle_tefif_one(struct mcp251xfd_priv *priv,
 	stats->tx_bytes +=
 		can_rx_offload_get_echo_skb(&priv->offload,
 					    mcp251xfd_get_tef_tail(priv),
-					    hw_tef_obj->ts);
+					    hw_tef_obj->ts, NULL);
 	stats->tx_packets++;
 	priv->tef->tail++;
 
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index a6850ff0b55b..8ff383ee45d3 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -757,7 +757,7 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
 			stamp = hecc_read_stamp(priv, mbxno);
 			stats->tx_bytes +=
 				can_rx_offload_get_echo_skb(&priv->offload,
-							    mbxno, stamp);
+							    mbxno, stamp, NULL);
 			stats->tx_packets++;
 			can_led_event(ndev, CAN_LED_EVENT_TX);
 			--priv->tx_tail;
diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h
index f1b38088b765..40882df7105e 100644
--- a/include/linux/can/rx-offload.h
+++ b/include/linux/can/rx-offload.h
@@ -44,7 +44,8 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload);
 int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
 				struct sk_buff *skb, u32 timestamp);
 unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
-					 unsigned int idx, u32 timestamp);
+					 unsigned int idx, u32 timestamp,
+					 unsigned int *frame_len_ptr);
 int can_rx_offload_queue_tail(struct can_rx_offload *offload,
 			      struct sk_buff *skb);
 void can_rx_offload_del(struct can_rx_offload *offload);
-- 
2.29.2



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

* Re: [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer
  2021-01-09 17:40 ` [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer Marc Kleine-Budde
@ 2021-01-10  3:32   ` Vincent MAILHOL
  2021-01-11  8:12     ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-10  3:32 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp, Arunachalam Santhanam

On Sun. 10 Jan 2021 at 02:40, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> From: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
>
> This patch adds the function can_skb_get_frame_len() which returns the length
> of a CAN frame on the data link layer, including Start-of-frame, Identifier,
> various other bits, the actual data, the CRC, the End-of-frame, the Inter frame
> spacing.
>
> Co-developed-by: Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>
> Not-Signed-off-by: Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>
> Co-developed-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> Not-Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> Co-developed-by: Marc Kleine-Budde <mkl@pengutronix.de>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/net/can/dev/length.c |  50 +++++++++++++++
>  include/linux/can/length.h   | 121 +++++++++++++++++++++++++++++++++++
>  2 files changed, 171 insertions(+)
>
> diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
> index b90d30858935..5b9fa51a3ca3 100644
> --- a/drivers/net/can/dev/length.c
> +++ b/drivers/net/can/dev/length.c
> @@ -40,3 +40,53 @@ u8 can_fd_len2dlc(u8 len)
>         return len2dlc[len];
>  }
>  EXPORT_SYMBOL_GPL(can_fd_len2dlc);
> +
> +/**
> + * can_skb_get_frame_len() - Calculate the CAN Frame length in bytes
> + *     of a given skb.
> + * @skb: socket buffer of a CAN message.
> + *
> + * Do a rough calculation: bit stuffing is ignored and length in bits
> + * is rounded up to a length in bytes.
> + *
> + * Rationale: this function is to be used for the BQL functions
> + * (netdev_sent_queue() and netdev_completed_queue()) which expect a
> + * value in bytes. Just using skb->len is insufficient because it will
> + * return the constant value of CAN(FD)_MTU. Doing the bit stuffing
> + * calculation would be too expensive in term of computing resources
> + * for no noticeable gain.
> + *
> + * Remarks: The payload of CAN FD frames with BRS flag are sent at a
> + * different bitrate. Currently, the can-utils canbusload tool does
> + * not support CAN-FD yet and so we could not run any benchmark to
> + * measure the impact. There might be possible improvement here.
> + *
> + * Return: length in bytes.
> + */
> +unsigned int can_skb_get_frame_len(const struct sk_buff *skb)
> +{
> +       const struct canfd_frame *cf = (const struct canfd_frame *)skb->data;
> +       u8 len;
> +
> +       if (can_is_canfd_skb(skb))
> +               len = canfd_sanitize_len(cf->len);
> +       else if (cf->can_id & CAN_RTR_FLAG)
> +               len = 0;
> +       else
> +               len = cf->len;
> +
> +       if (can_is_canfd_skb(skb)) {
> +               if (cf->can_id & CAN_EFF_FLAG)
> +                       len += CANFD_FRAME_OVERHEAD_EFF;
> +               else
> +                       len += CANFD_FRAME_OVERHEAD_SFF;
> +       } else {
> +               if (cf->can_id & CAN_EFF_FLAG)
> +                       len += CAN_FRAME_OVERHEAD_EFF;
> +               else
> +                       len += CAN_FRAME_OVERHEAD_SFF;
> +       }
> +
> +       return len;
> +}
> +EXPORT_SYMBOL_GPL(can_skb_get_frame_len);
> diff --git a/include/linux/can/length.h b/include/linux/can/length.h
> index 0d796f96266b..7d8affcc3d9f 100644
> --- a/include/linux/can/length.h
> +++ b/include/linux/can/length.h
> @@ -3,11 +3,129 @@
>   * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
>   *               Varma Electronics Oy
>   * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
> + * Copyright (C) 2020 Marc Kleine-Budde <kernel@pengutronix.de>
>   */
>
>  #ifndef _CAN_LENGTH_H
>  #define _CAN_LENGTH_H
>
> +/*
> + * Size of a Classical CAN Standard Frame
> + *
> + * Name of Field                       Bits
> + * ---------------------------------------------------------
> + * Start-of-frame                      1
> + * Identifier                          11
> + * Remote transmission request (RTR)   1
> + * Identifier extension bit (IDE)      1
> + * Reserved bit (r0)                   1
> + * Data length code (DLC)              4
> + * Data field                          0...64
> + * CRC                                 15
> + * CRC delimiter                       1
> + * ACK slot                            1
> + * ACK delimiter                       1
> + * End-of-frame (EOF)                  7
> + * Inter frame spacing                 3
> + *
> + * rounded up and ignoring bitstuffing
> + */
> +#define CAN_FRAME_OVERHEAD_SFF DIV_ROUND_UP(47, 8)
> +
> +/*
> + * Size of a Classical CAN Extended Frame
> + *
> + * Name of Field                       Bits
> + * ---------------------------------------------------------
> + * Start-of-frame                      1
> + * Identifier A                                11
> + * Substitute remote request (SRR)     1
> + * Identifier extension bit (IDE)      1
> + * Identifier B                                18
> + * Remote transmission request (RTR)   1
> + * Reserved bits (r1, r0)              2
> + * Data length code (DLC)              4
> + * Data field                          0...64
> + * CRC                                 15
> + * CRC delimiter                       1
> + * ACK slot                            1
> + * ACK delimiter                       1
> + * End-of-frame (EOF)                  7
> + * Inter frame spacing                 3
> + *
> + * rounded up and ignoring bitstuffing
> + */
> +#define CAN_FRAME_OVERHEAD_EFF DIV_ROUND_UP(67, 8)
> +
> +/*
> + * Size of a CAN-FD Standard Frame
> + *
> + * Name of Field                       Bits
> + * ---------------------------------------------------------
> + * Start-of-frame                      1
> + * Identifier                          11
> + * Reserved bit (r1)                   1
> + * Identifier extension bit (IDE)      1
> + * Flexible data rate format (FDF)     1
> + * Reserved bit (r0)                   1
> + * Bit Rate Switch (BRS)               1
> + * Error Status Indicator (ESI)                1
> + * Data length code (DLC)              4
> + * Data field                          0...512
> + * Stuff Bit Count (SBC)               0...16: 4 20...64:5
> + * CRC                                 0...16: 17 20...64:21
> + * CRC delimiter (CD)                  1
> + * ACK slot (AS)                       1
> + * ACK delimiter (AD)                  1
> + * End-of-frame (EOF)                  7
> + * Inter frame spacing                 3
> + *
> + * assuming CRC21, rounded up and ignoring bitstuffing
> + */
> +#define CANFD_FRAME_OVERHEAD_SFF DIV_ROUND_UP(61, 8)
> +
> +/*
> + * Size of a CAN-FD Extended Frame
> + *
> + * Name of Field                       Bits
> + * ---------------------------------------------------------
> + * Start-of-frame                      1
> + * Identifier A                                11
> + * Substitute remote request (SRR)     1
> + * Identifier extension bit (IDE)      1
> + * Identifier B                                18
> + * Reserved bit (r1)                   1
> + * Flexible data rate format (FDF)     1
> + * Reserved bit (r0)                   1
> + * Bit Rate Switch (BRS)               1
> + * Error Status Indicator (ESI)                1
> + * Data length code (DLC)              4
> + * Data field                          0...512
> + * Stuff Bit Count (SBC)               0...16: 4 20...64:5
> + * CRC                                 0...16: 17 20...64:21
> + * CRC delimiter (CD)                  1
> + * ACK slot (AS)                       1
> + * ACK delimiter (AD)                  1
> + * End-of-frame (EOF)                  7
> + * Inter frame spacing                 3
> + *
> + * assuming CRC21, rounded up and ignoring bitstuffing
> + */
> +#define CANFD_FRAME_OVERHEAD_EFF DIV_ROUND_UP(80, 8)
> +
> +/*
> + * Maximum size of a Classical CAN frame
> + * (rounded up and ignoring bitstuffing)
> + */
> +#define CAN_FRAME_LEN_MAX (CAN_FRAME_OVERHEAD_EFF + CAN_MAX_DLEN)
> +
> +/*
> + * Maximum size of a CAN-FD frame (rough estimation because
> + * ES58X_SFF_BYTES() and ES58X_EFF_BYTES() macros are using the
> + * constant values for Classical CAN, not CAN-FD).
> + */
/*
 * Maximum size of a CAN-FD frame
 * (rounded up and ignoring bitstuffing)
 */
It is a leftover from my original comment. Does not apply anymore
thanks to your newly introduced CANFD_FRAME_OVERHEAD_EFF macro.

> +#define CANFD_FRAME_LEN_MAX (CANFD_FRAME_OVERHEAD_EFF + CANFD_MAX_DLEN)
> +
>  /*
>   * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
>   * Classical CAN frame into a valid data length of max. 8 bytes.
> @@ -48,6 +166,9 @@ u8 can_fd_dlc2len(u8 dlc);
>  /* map the sanitized data length to an appropriate data length code */
>  u8 can_fd_len2dlc(u8 len);
>
> +/* calculate the CAN Frame length in bytes of a given skb */
> +unsigned int can_skb_get_frame_len(const struct sk_buff *skb);
> +
>  /* map the data length to an appropriate data link layer length */
>  static inline u8 canfd_sanitize_len(u8 len)
>  {

Thanks for your patch series :)
Still reviewing but so far so good. Will also apply the changes
to the ES58X driver and send the v10 of the patch.

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

* Re: [net-next 05/13] can: dev: move skb related into seperate file
  2021-01-09 17:40 ` [net-next 05/13] can: dev: move skb related " Marc Kleine-Budde
@ 2021-01-10  4:26   ` Vincent MAILHOL
  2021-01-11  8:14     ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-10  4:26 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Sun. 10 Jan. 2021 at 02:40, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> This patch moves the skb related code of the CAN device infrastructure into a
> separate file.
>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/net/can/dev/dev.c | 213 ------------------------------------
>  drivers/net/can/dev/skb.c | 220 ++++++++++++++++++++++++++++++++++++++
>  include/linux/can/dev.h   |  76 -------------
>  include/linux/can/skb.h   |  77 +++++++++++++
>  4 files changed, 297 insertions(+), 289 deletions(-)
>  create mode 100644 drivers/net/can/dev/skb.c
>
> diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
> index 3372e99d5db7..fe71ff9ef8c9 100644
> --- a/drivers/net/can/dev/dev.c
> +++ b/drivers/net/can/dev/dev.c
> @@ -132,149 +132,6 @@ void can_change_state(struct net_device *dev, struct can_frame *cf,
>  }
>  EXPORT_SYMBOL_GPL(can_change_state);
>
> -/* Local echo of CAN messages
> - *
> - * CAN network devices *should* support a local echo functionality
> - * (see Documentation/networking/can.rst). To test the handling of CAN
> - * interfaces that do not support the local echo both driver types are
> - * implemented. In the case that the driver does not support the echo
> - * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
> - * to perform the echo as a fallback solution.
> - */
> -static void can_flush_echo_skb(struct net_device *dev)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -       struct net_device_stats *stats = &dev->stats;
> -       int i;
> -
> -       for (i = 0; i < priv->echo_skb_max; i++) {
> -               if (priv->echo_skb[i]) {
> -                       kfree_skb(priv->echo_skb[i]);
> -                       priv->echo_skb[i] = NULL;
> -                       stats->tx_dropped++;
> -                       stats->tx_aborted_errors++;
> -               }
> -       }
> -}
> -
> -/* Put the skb on the stack to be looped backed locally lateron
> - *
> - * The function is typically called in the start_xmit function
> - * of the device driver. The driver must protect access to
> - * priv->echo_skb, if necessary.
> - */
> -int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> -                    unsigned int idx)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -
> -       BUG_ON(idx >= priv->echo_skb_max);
> -
> -       /* check flag whether this packet has to be looped back */
> -       if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
> -           (skb->protocol != htons(ETH_P_CAN) &&
> -            skb->protocol != htons(ETH_P_CANFD))) {
> -               kfree_skb(skb);
> -               return 0;
> -       }
> -
> -       if (!priv->echo_skb[idx]) {
> -               skb = can_create_echo_skb(skb);
> -               if (!skb)
> -                       return -ENOMEM;
> -
> -               /* make settings for echo to reduce code in irq context */
> -               skb->pkt_type = PACKET_BROADCAST;
> -               skb->ip_summed = CHECKSUM_UNNECESSARY;
> -               skb->dev = dev;
> -
> -               /* save this skb for tx interrupt echo handling */
> -               priv->echo_skb[idx] = skb;
> -       } else {
> -               /* locking problem with netif_stop_queue() ?? */
> -               netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
> -               kfree_skb(skb);
> -               return -EBUSY;
> -       }
> -
> -       return 0;
> -}
> -EXPORT_SYMBOL_GPL(can_put_echo_skb);
> -
> -struct sk_buff *
> -__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -
> -       if (idx >= priv->echo_skb_max) {
> -               netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
> -                          __func__, idx, priv->echo_skb_max);
> -               return NULL;
> -       }
> -
> -       if (priv->echo_skb[idx]) {
> -               /* Using "struct canfd_frame::len" for the frame
> -                * length is supported on both CAN and CANFD frames.
> -                */
> -               struct sk_buff *skb = priv->echo_skb[idx];
> -               struct canfd_frame *cf = (struct canfd_frame *)skb->data;
> -
> -               /* get the real payload length for netdev statistics */
> -               if (cf->can_id & CAN_RTR_FLAG)
> -                       *len_ptr = 0;
> -               else
> -                       *len_ptr = cf->len;
> -
> -               priv->echo_skb[idx] = NULL;
> -
> -               return skb;
> -       }
> -
> -       return NULL;
> -}
> -
> -/* Get the skb from the stack and loop it back locally
> - *
> - * The function is typically called when the TX done interrupt
> - * is handled in the device driver. The driver must protect
> - * access to priv->echo_skb, if necessary.
> - */
> -unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
> -{
> -       struct sk_buff *skb;
> -       u8 len;
> -
> -       skb = __can_get_echo_skb(dev, idx, &len);
> -       if (!skb)
> -               return 0;
> -
> -       skb_get(skb);
> -       if (netif_rx(skb) == NET_RX_SUCCESS)
> -               dev_consume_skb_any(skb);
> -       else
> -               dev_kfree_skb_any(skb);
> -
> -       return len;
> -}
> -EXPORT_SYMBOL_GPL(can_get_echo_skb);
> -
> -/* Remove the skb from the stack and free it.
> - *
> - * The function is typically called when TX failed.
> - */
> -void can_free_echo_skb(struct net_device *dev, unsigned int idx)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -
> -       BUG_ON(idx >= priv->echo_skb_max);
> -
> -       if (priv->echo_skb[idx]) {
> -               dev_kfree_skb_any(priv->echo_skb[idx]);
> -               priv->echo_skb[idx] = NULL;
> -       }
> -}
> -EXPORT_SYMBOL_GPL(can_free_echo_skb);
> -
>  /* CAN device restart for bus-off recovery */
>  static void can_restart(struct net_device *dev)
>  {
> @@ -379,76 +236,6 @@ static void can_setup(struct net_device *dev)
>         dev->features = NETIF_F_HW_CSUM;
>  }
>
> -struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
> -{
> -       struct sk_buff *skb;
> -
> -       skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
> -                              sizeof(struct can_frame));
> -       if (unlikely(!skb))
> -               return NULL;
> -
> -       skb->protocol = htons(ETH_P_CAN);
> -       skb->pkt_type = PACKET_BROADCAST;
> -       skb->ip_summed = CHECKSUM_UNNECESSARY;
> -
> -       skb_reset_mac_header(skb);
> -       skb_reset_network_header(skb);
> -       skb_reset_transport_header(skb);
> -
> -       can_skb_reserve(skb);
> -       can_skb_prv(skb)->ifindex = dev->ifindex;
> -       can_skb_prv(skb)->skbcnt = 0;
> -
> -       *cf = skb_put_zero(skb, sizeof(struct can_frame));
> -
> -       return skb;
> -}
> -EXPORT_SYMBOL_GPL(alloc_can_skb);
> -
> -struct sk_buff *alloc_canfd_skb(struct net_device *dev,
> -                               struct canfd_frame **cfd)
> -{
> -       struct sk_buff *skb;
> -
> -       skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
> -                              sizeof(struct canfd_frame));
> -       if (unlikely(!skb))
> -               return NULL;
> -
> -       skb->protocol = htons(ETH_P_CANFD);
> -       skb->pkt_type = PACKET_BROADCAST;
> -       skb->ip_summed = CHECKSUM_UNNECESSARY;
> -
> -       skb_reset_mac_header(skb);
> -       skb_reset_network_header(skb);
> -       skb_reset_transport_header(skb);
> -
> -       can_skb_reserve(skb);
> -       can_skb_prv(skb)->ifindex = dev->ifindex;
> -       can_skb_prv(skb)->skbcnt = 0;
> -
> -       *cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
> -
> -       return skb;
> -}
> -EXPORT_SYMBOL_GPL(alloc_canfd_skb);
> -
> -struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
> -{
> -       struct sk_buff *skb;
> -
> -       skb = alloc_can_skb(dev, cf);
> -       if (unlikely(!skb))
> -               return NULL;
> -
> -       (*cf)->can_id = CAN_ERR_FLAG;
> -       (*cf)->len = CAN_ERR_DLC;
> -
> -       return skb;
> -}
> -EXPORT_SYMBOL_GPL(alloc_can_err_skb);
> -
>  /* Allocate and setup space for the CAN network device */
>  struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
>                                     unsigned int txqs, unsigned int rxqs)
> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> new file mode 100644
> index 000000000000..26cd597ff771
> --- /dev/null
> +++ b/drivers/net/can/dev/skb.c
> @@ -0,0 +1,220 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
> + * Copyright (C) 2006 Andrey Volkov, Varma Electronics
> + * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
> + */
> +
> +#include <linux/can/dev.h>
> +
> +/* Local echo of CAN messages
> + *
> + * CAN network devices *should* support a local echo functionality
> + * (see Documentation/networking/can.rst). To test the handling of CAN
> + * interfaces that do not support the local echo both driver types are
> + * implemented. In the case that the driver does not support the echo
> + * the IFF_ECHO remains clear in dev->flags. This causes the PF_CAN core
> + * to perform the echo as a fallback solution.
> + */
> +void can_flush_echo_skb(struct net_device *dev)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +       struct net_device_stats *stats = &dev->stats;
> +       int i;
> +
> +       for (i = 0; i < priv->echo_skb_max; i++) {
> +               if (priv->echo_skb[i]) {
> +                       kfree_skb(priv->echo_skb[i]);
> +                       priv->echo_skb[i] = NULL;
> +                       stats->tx_dropped++;
> +                       stats->tx_aborted_errors++;
> +               }
> +       }
> +}
> +
> +/* Put the skb on the stack to be looped backed locally lateron
> + *
> + * The function is typically called in the start_xmit function
> + * of the device driver. The driver must protect access to
> + * priv->echo_skb, if necessary.
> + */
> +int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> +                    unsigned int idx)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +
> +       BUG_ON(idx >= priv->echo_skb_max);
> +
> +       /* check flag whether this packet has to be looped back */
> +       if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK ||
> +           (skb->protocol != htons(ETH_P_CAN) &&
> +            skb->protocol != htons(ETH_P_CANFD))) {
> +               kfree_skb(skb);
> +               return 0;
> +       }
> +
> +       if (!priv->echo_skb[idx]) {
> +               skb = can_create_echo_skb(skb);
> +               if (!skb)
> +                       return -ENOMEM;
> +
> +               /* make settings for echo to reduce code in irq context */
> +               skb->pkt_type = PACKET_BROADCAST;
> +               skb->ip_summed = CHECKSUM_UNNECESSARY;
> +               skb->dev = dev;
> +
> +               /* save this skb for tx interrupt echo handling */
> +               priv->echo_skb[idx] = skb;
> +       } else {
> +               /* locking problem with netif_stop_queue() ?? */
> +               netdev_err(dev, "%s: BUG! echo_skb %d is occupied!\n", __func__, idx);
> +               kfree_skb(skb);
> +               return -EBUSY;
> +       }
> +
> +       return 0;
> +}
> +EXPORT_SYMBOL_GPL(can_put_echo_skb);
> +
> +struct sk_buff *
> +__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +
> +       if (idx >= priv->echo_skb_max) {
> +               netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
> +                          __func__, idx, priv->echo_skb_max);
> +               return NULL;
> +       }
> +
> +       if (priv->echo_skb[idx]) {
> +               /* Using "struct canfd_frame::len" for the frame
> +                * length is supported on both CAN and CANFD frames.
> +                */
> +               struct sk_buff *skb = priv->echo_skb[idx];
> +               struct canfd_frame *cf = (struct canfd_frame *)skb->data;
> +
> +               /* get the real payload length for netdev statistics */
> +               if (cf->can_id & CAN_RTR_FLAG)
> +                       *len_ptr = 0;
> +               else
> +                       *len_ptr = cf->len;
> +
> +               priv->echo_skb[idx] = NULL;
> +
> +               return skb;
> +       }
> +
> +       return NULL;
> +}
> +
> +/* Get the skb from the stack and loop it back locally
> + *
> + * The function is typically called when the TX done interrupt
> + * is handled in the device driver. The driver must protect
> + * access to priv->echo_skb, if necessary.
> + */
> +unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
> +{
> +       struct sk_buff *skb;
> +       u8 len;
> +
> +       skb = __can_get_echo_skb(dev, idx, &len);
> +       if (!skb)
> +               return 0;
> +
> +       skb_get(skb);
> +       if (netif_rx(skb) == NET_RX_SUCCESS)
> +               dev_consume_skb_any(skb);
> +       else
> +               dev_kfree_skb_any(skb);
> +
> +       return len;
> +}
> +EXPORT_SYMBOL_GPL(can_get_echo_skb);
> +
> +/* Remove the skb from the stack and free it.
> + *
> + * The function is typically called when TX failed.
> + */
> +void can_free_echo_skb(struct net_device *dev, unsigned int idx)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +
> +       BUG_ON(idx >= priv->echo_skb_max);
> +
> +       if (priv->echo_skb[idx]) {
> +               dev_kfree_skb_any(priv->echo_skb[idx]);
> +               priv->echo_skb[idx] = NULL;
> +       }
> +}
> +EXPORT_SYMBOL_GPL(can_free_echo_skb);
> +
> +struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
> +{
> +       struct sk_buff *skb;
> +
> +       skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
> +                              sizeof(struct can_frame));
> +       if (unlikely(!skb))
> +               return NULL;
> +
> +       skb->protocol = htons(ETH_P_CAN);
> +       skb->pkt_type = PACKET_BROADCAST;
> +       skb->ip_summed = CHECKSUM_UNNECESSARY;
> +
> +       skb_reset_mac_header(skb);
> +       skb_reset_network_header(skb);
> +       skb_reset_transport_header(skb);
> +
> +       can_skb_reserve(skb);
> +       can_skb_prv(skb)->ifindex = dev->ifindex;
> +       can_skb_prv(skb)->skbcnt = 0;
> +
> +       *cf = skb_put_zero(skb, sizeof(struct can_frame));
> +
> +       return skb;
> +}
> +EXPORT_SYMBOL_GPL(alloc_can_skb);
> +
> +struct sk_buff *alloc_canfd_skb(struct net_device *dev,
> +                               struct canfd_frame **cfd)
> +{
> +       struct sk_buff *skb;
> +
> +       skb = netdev_alloc_skb(dev, sizeof(struct can_skb_priv) +
> +                              sizeof(struct canfd_frame));
> +       if (unlikely(!skb))
> +               return NULL;
> +
> +       skb->protocol = htons(ETH_P_CANFD);
> +       skb->pkt_type = PACKET_BROADCAST;
> +       skb->ip_summed = CHECKSUM_UNNECESSARY;
> +
> +       skb_reset_mac_header(skb);
> +       skb_reset_network_header(skb);
> +       skb_reset_transport_header(skb);
> +
> +       can_skb_reserve(skb);
> +       can_skb_prv(skb)->ifindex = dev->ifindex;
> +       can_skb_prv(skb)->skbcnt = 0;
> +
> +       *cfd = skb_put_zero(skb, sizeof(struct canfd_frame));
> +
> +       return skb;
> +}
> +EXPORT_SYMBOL_GPL(alloc_canfd_skb);
> +
> +struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
> +{
> +       struct sk_buff *skb;
> +
> +       skb = alloc_can_skb(dev, cf);
> +       if (unlikely(!skb))
> +               return NULL;
> +
> +       (*cf)->can_id = CAN_ERR_FLAG;
> +       (*cf)->len = CAN_ERR_DLC;
> +
> +       return skb;
> +}
> +EXPORT_SYMBOL_GPL(alloc_can_err_skb);
> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
> index d75fba1d030a..4a26e128af7f 100644
> --- a/include/linux/can/dev.h
> +++ b/include/linux/can/dev.h
> @@ -84,69 +84,6 @@ struct can_priv {
>  #endif
>  };
>
> -/* Check for outgoing skbs that have not been created by the CAN subsystem */
> -static inline bool can_skb_headroom_valid(struct net_device *dev,
> -                                         struct sk_buff *skb)
> -{
> -       /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
> -       if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
> -               return false;
> -
> -       /* af_packet does not apply CAN skb specific settings */
> -       if (skb->ip_summed == CHECKSUM_NONE) {
> -               /* init headroom */
> -               can_skb_prv(skb)->ifindex = dev->ifindex;
> -               can_skb_prv(skb)->skbcnt = 0;
> -
> -               skb->ip_summed = CHECKSUM_UNNECESSARY;
> -
> -               /* perform proper loopback on capable devices */
> -               if (dev->flags & IFF_ECHO)
> -                       skb->pkt_type = PACKET_LOOPBACK;
> -               else
> -                       skb->pkt_type = PACKET_HOST;
> -
> -               skb_reset_mac_header(skb);
> -               skb_reset_network_header(skb);
> -               skb_reset_transport_header(skb);
> -       }
> -
> -       return true;
> -}
> -
> -/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
> -static inline bool can_dropped_invalid_skb(struct net_device *dev,
> -                                         struct sk_buff *skb)
> -{
> -       const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
> -
> -       if (skb->protocol == htons(ETH_P_CAN)) {
> -               if (unlikely(skb->len != CAN_MTU ||
> -                            cfd->len > CAN_MAX_DLEN))
> -                       goto inval_skb;
> -       } else if (skb->protocol == htons(ETH_P_CANFD)) {
> -               if (unlikely(skb->len != CANFD_MTU ||
> -                            cfd->len > CANFD_MAX_DLEN))
> -                       goto inval_skb;
> -       } else
> -               goto inval_skb;
> -
> -       if (!can_skb_headroom_valid(dev, skb))
> -               goto inval_skb;
> -
> -       return false;
> -
> -inval_skb:
> -       kfree_skb(skb);
> -       dev->stats.tx_dropped++;
> -       return true;
> -}
> -
> -static inline bool can_is_canfd_skb(const struct sk_buff *skb)
> -{
> -       /* the CAN specific type of skb is identified by its data length */
> -       return skb->len == CANFD_MTU;
> -}
>
>  /* helper to define static CAN controller features at device creation time */
>  static inline void can_set_static_ctrlmode(struct net_device *dev,
> @@ -187,23 +124,10 @@ void can_bus_off(struct net_device *dev);
>  void can_change_state(struct net_device *dev, struct can_frame *cf,
>                       enum can_state tx_state, enum can_state rx_state);
>
> -int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> -                    unsigned int idx);
> -struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
> -                                  u8 *len_ptr);
> -unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
> -void can_free_echo_skb(struct net_device *dev, unsigned int idx);
> -
>  #ifdef CONFIG_OF
>  void of_can_transceiver(struct net_device *dev);
>  #else
>  static inline void of_can_transceiver(struct net_device *dev) { }
>  #endif
>
> -struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
> -struct sk_buff *alloc_canfd_skb(struct net_device *dev,
> -                               struct canfd_frame **cfd);
> -struct sk_buff *alloc_can_err_skb(struct net_device *dev,
> -                                 struct can_frame **cf);
> -
>  #endif /* !_CAN_DEV_H */
> diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
> index fc61cf4eff1c..c90ebbd3008c 100644
> --- a/include/linux/can/skb.h
> +++ b/include/linux/can/skb.h
> @@ -16,6 +16,19 @@
>  #include <linux/can.h>
>  #include <net/sock.h>
>
> +void can_flush_echo_skb(struct net_device *dev);
> +int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> +                    unsigned int idx);
> +struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
> +                                  u8 *len_ptr);
> +unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
> +void can_free_echo_skb(struct net_device *dev, unsigned int idx);
> +struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
> +struct sk_buff *alloc_canfd_skb(struct net_device *dev,
> +                               struct canfd_frame **cfd);
> +struct sk_buff *alloc_can_err_skb(struct net_device *dev,
> +                                 struct can_frame **cf);
> +
>  /*
>   * The struct can_skb_priv is used to transport additional information along
>   * with the stored struct can(fd)_frame that can not be contained in existing
> @@ -74,4 +87,68 @@ static inline struct sk_buff *can_create_echo_skb(struct sk_buff *skb)
>         return nskb;
>  }
>
> +/* Check for outgoing skbs that have not been created by the CAN subsystem */
> +static inline bool can_skb_headroom_valid(struct net_device *dev,
> +                                         struct sk_buff *skb)
> +{
> +       /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
> +       if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
> +               return false;
> +
> +       /* af_packet does not apply CAN skb specific settings */
> +       if (skb->ip_summed == CHECKSUM_NONE) {
> +               /* init headroom */
> +               can_skb_prv(skb)->ifindex = dev->ifindex;
> +               can_skb_prv(skb)->skbcnt = 0;
> +
> +               skb->ip_summed = CHECKSUM_UNNECESSARY;
> +
> +               /* perform proper loopback on capable devices */
> +               if (dev->flags & IFF_ECHO)
> +                       skb->pkt_type = PACKET_LOOPBACK;
> +               else
> +                       skb->pkt_type = PACKET_HOST;
> +
> +               skb_reset_mac_header(skb);
> +               skb_reset_network_header(skb);
> +               skb_reset_transport_header(skb);
> +       }
> +
> +       return true;
> +}
> +
> +/* Drop a given socketbuffer if it does not contain a valid CAN frame. */
> +static inline bool can_dropped_invalid_skb(struct net_device *dev,
> +                                         struct sk_buff *skb)
> +{
> +       const struct canfd_frame *cfd = (struct canfd_frame *)skb->data;
> +
> +       if (skb->protocol == htons(ETH_P_CAN)) {
> +               if (unlikely(skb->len != CAN_MTU ||
> +                            cfd->len > CAN_MAX_DLEN))
> +                       goto inval_skb;
> +       } else if (skb->protocol == htons(ETH_P_CANFD)) {
> +               if (unlikely(skb->len != CANFD_MTU ||
> +                            cfd->len > CANFD_MAX_DLEN))
> +                       goto inval_skb;
> +       } else
> +               goto inval_skb;
> +
> +       if (!can_skb_headroom_valid(dev, skb))
> +               goto inval_skb;
> +
> +       return false;
> +
> +inval_skb:
> +       kfree_skb(skb);
> +       dev->stats.tx_dropped++;
> +       return true;
> +}
> +
> +static inline bool can_is_canfd_skb(const struct sk_buff *skb)
> +{
> +       /* the CAN specific type of skb is identified by its data length */
> +       return skb->len == CANFD_MTU;
> +}
> +
>  #endif /* !_CAN_SKB_H */
> --
> 2.29.2
>
>

Fails to build. I think you just forgot to include the changes on
drivers/net/can/dev/Makefile (c.f. below).

diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
index 5c647951e06d..2c38bd532157 100644
--- a/drivers/net/can/dev/Makefile
+++ b/drivers/net/can/dev/Makefile
@@ -5,5 +5,6 @@ can-dev-y            += bittiming.o
 can-dev-y            += dev.o
 can-dev-y            += length.o
 can-dev-y            += rx-offload.o
+can-dev-y            += skb.o

 can-dev-$(CONFIG_CAN_LEDS)    += led.o

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

* Re: [net-next 06/13] can: dev: move netlink related code into seperate file
  2021-01-09 17:40 ` [net-next 06/13] can: dev: move netlink related code " Marc Kleine-Budde
@ 2021-01-10  4:27   ` Vincent MAILHOL
  2021-01-11  8:17     ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-10  4:27 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

Le dim. 10 janv. 2021 à 02:40, Marc Kleine-Budde <mkl@pengutronix.de> a écrit :
>
> This patch moves the netlink related code of the CAN device infrastructure into
> a separate file.
>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/net/can/dev/dev.c     | 370 +--------------------------------
>  drivers/net/can/dev/netlink.c | 379 ++++++++++++++++++++++++++++++++++
>  include/linux/can/dev.h       |   6 +
>  3 files changed, 388 insertions(+), 367 deletions(-)
>  create mode 100644 drivers/net/can/dev/netlink.c
>
> diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
> index fe71ff9ef8c9..f580f0ac6497 100644
> --- a/drivers/net/can/dev/dev.c
> +++ b/drivers/net/can/dev/dev.c
> @@ -14,10 +14,8 @@
>  #include <linux/can/can-ml.h>
>  #include <linux/can/dev.h>
>  #include <linux/can/skb.h>
> -#include <linux/can/netlink.h>
>  #include <linux/can/led.h>
>  #include <linux/of.h>
> -#include <net/rtnetlink.h>
>
>  #define MOD_DESC "CAN device driver interface"
>
> @@ -223,7 +221,7 @@ void can_bus_off(struct net_device *dev)
>  }
>  EXPORT_SYMBOL_GPL(can_bus_off);
>
> -static void can_setup(struct net_device *dev)
> +void can_setup(struct net_device *dev)
>  {
>         dev->type = ARPHRD_CAN;
>         dev->mtu = CAN_MTU;
> @@ -399,368 +397,6 @@ void close_candev(struct net_device *dev)
>  }
>  EXPORT_SYMBOL_GPL(close_candev);
>
> -/* CAN netlink interface */
> -static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
> -       [IFLA_CAN_STATE]        = { .type = NLA_U32 },
> -       [IFLA_CAN_CTRLMODE]     = { .len = sizeof(struct can_ctrlmode) },
> -       [IFLA_CAN_RESTART_MS]   = { .type = NLA_U32 },
> -       [IFLA_CAN_RESTART]      = { .type = NLA_U32 },
> -       [IFLA_CAN_BITTIMING]    = { .len = sizeof(struct can_bittiming) },
> -       [IFLA_CAN_BITTIMING_CONST]
> -                               = { .len = sizeof(struct can_bittiming_const) },
> -       [IFLA_CAN_CLOCK]        = { .len = sizeof(struct can_clock) },
> -       [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
> -       [IFLA_CAN_DATA_BITTIMING]
> -                               = { .len = sizeof(struct can_bittiming) },
> -       [IFLA_CAN_DATA_BITTIMING_CONST]
> -                               = { .len = sizeof(struct can_bittiming_const) },
> -       [IFLA_CAN_TERMINATION]  = { .type = NLA_U16 },
> -};
> -
> -static int can_validate(struct nlattr *tb[], struct nlattr *data[],
> -                       struct netlink_ext_ack *extack)
> -{
> -       bool is_can_fd = false;
> -
> -       /* Make sure that valid CAN FD configurations always consist of
> -        * - nominal/arbitration bittiming
> -        * - data bittiming
> -        * - control mode with CAN_CTRLMODE_FD set
> -        */
> -
> -       if (!data)
> -               return 0;
> -
> -       if (data[IFLA_CAN_CTRLMODE]) {
> -               struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
> -
> -               is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
> -       }
> -
> -       if (is_can_fd) {
> -               if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
> -                       return -EOPNOTSUPP;
> -       }
> -
> -       if (data[IFLA_CAN_DATA_BITTIMING]) {
> -               if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
> -                       return -EOPNOTSUPP;
> -       }
> -
> -       return 0;
> -}
> -
> -static int can_changelink(struct net_device *dev, struct nlattr *tb[],
> -                         struct nlattr *data[],
> -                         struct netlink_ext_ack *extack)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -       int err;
> -
> -       /* We need synchronization with dev->stop() */
> -       ASSERT_RTNL();
> -
> -       if (data[IFLA_CAN_BITTIMING]) {
> -               struct can_bittiming bt;
> -
> -               /* Do not allow changing bittiming while running */
> -               if (dev->flags & IFF_UP)
> -                       return -EBUSY;
> -
> -               /* Calculate bittiming parameters based on
> -                * bittiming_const if set, otherwise pass bitrate
> -                * directly via do_set_bitrate(). Bail out if neither
> -                * is given.
> -                */
> -               if (!priv->bittiming_const && !priv->do_set_bittiming)
> -                       return -EOPNOTSUPP;
> -
> -               memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
> -               err = can_get_bittiming(dev, &bt,
> -                                       priv->bittiming_const,
> -                                       priv->bitrate_const,
> -                                       priv->bitrate_const_cnt);
> -               if (err)
> -                       return err;
> -
> -               if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
> -                       netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
> -                                  priv->bitrate_max);
> -                       return -EINVAL;
> -               }
> -
> -               memcpy(&priv->bittiming, &bt, sizeof(bt));
> -
> -               if (priv->do_set_bittiming) {
> -                       /* Finally, set the bit-timing registers */
> -                       err = priv->do_set_bittiming(dev);
> -                       if (err)
> -                               return err;
> -               }
> -       }
> -
> -       if (data[IFLA_CAN_CTRLMODE]) {
> -               struct can_ctrlmode *cm;
> -               u32 ctrlstatic;
> -               u32 maskedflags;
> -
> -               /* Do not allow changing controller mode while running */
> -               if (dev->flags & IFF_UP)
> -                       return -EBUSY;
> -               cm = nla_data(data[IFLA_CAN_CTRLMODE]);
> -               ctrlstatic = priv->ctrlmode_static;
> -               maskedflags = cm->flags & cm->mask;
> -
> -               /* check whether provided bits are allowed to be passed */
> -               if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
> -                       return -EOPNOTSUPP;
> -
> -               /* do not check for static fd-non-iso if 'fd' is disabled */
> -               if (!(maskedflags & CAN_CTRLMODE_FD))
> -                       ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
> -
> -               /* make sure static options are provided by configuration */
> -               if ((maskedflags & ctrlstatic) != ctrlstatic)
> -                       return -EOPNOTSUPP;
> -
> -               /* clear bits to be modified and copy the flag values */
> -               priv->ctrlmode &= ~cm->mask;
> -               priv->ctrlmode |= maskedflags;
> -
> -               /* CAN_CTRLMODE_FD can only be set when driver supports FD */
> -               if (priv->ctrlmode & CAN_CTRLMODE_FD)
> -                       dev->mtu = CANFD_MTU;
> -               else
> -                       dev->mtu = CAN_MTU;
> -       }
> -
> -       if (data[IFLA_CAN_RESTART_MS]) {
> -               /* Do not allow changing restart delay while running */
> -               if (dev->flags & IFF_UP)
> -                       return -EBUSY;
> -               priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
> -       }
> -
> -       if (data[IFLA_CAN_RESTART]) {
> -               /* Do not allow a restart while not running */
> -               if (!(dev->flags & IFF_UP))
> -                       return -EINVAL;
> -               err = can_restart_now(dev);
> -               if (err)
> -                       return err;
> -       }
> -
> -       if (data[IFLA_CAN_DATA_BITTIMING]) {
> -               struct can_bittiming dbt;
> -
> -               /* Do not allow changing bittiming while running */
> -               if (dev->flags & IFF_UP)
> -                       return -EBUSY;
> -
> -               /* Calculate bittiming parameters based on
> -                * data_bittiming_const if set, otherwise pass bitrate
> -                * directly via do_set_bitrate(). Bail out if neither
> -                * is given.
> -                */
> -               if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
> -                       return -EOPNOTSUPP;
> -
> -               memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
> -                      sizeof(dbt));
> -               err = can_get_bittiming(dev, &dbt,
> -                                       priv->data_bittiming_const,
> -                                       priv->data_bitrate_const,
> -                                       priv->data_bitrate_const_cnt);
> -               if (err)
> -                       return err;
> -
> -               if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
> -                       netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
> -                                  priv->bitrate_max);
> -                       return -EINVAL;
> -               }
> -
> -               memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
> -
> -               if (priv->do_set_data_bittiming) {
> -                       /* Finally, set the bit-timing registers */
> -                       err = priv->do_set_data_bittiming(dev);
> -                       if (err)
> -                               return err;
> -               }
> -       }
> -
> -       if (data[IFLA_CAN_TERMINATION]) {
> -               const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
> -               const unsigned int num_term = priv->termination_const_cnt;
> -               unsigned int i;
> -
> -               if (!priv->do_set_termination)
> -                       return -EOPNOTSUPP;
> -
> -               /* check whether given value is supported by the interface */
> -               for (i = 0; i < num_term; i++) {
> -                       if (termval == priv->termination_const[i])
> -                               break;
> -               }
> -               if (i >= num_term)
> -                       return -EINVAL;
> -
> -               /* Finally, set the termination value */
> -               err = priv->do_set_termination(dev, termval);
> -               if (err)
> -                       return err;
> -
> -               priv->termination = termval;
> -       }
> -
> -       return 0;
> -}
> -
> -static size_t can_get_size(const struct net_device *dev)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -       size_t size = 0;
> -
> -       if (priv->bittiming.bitrate)                            /* IFLA_CAN_BITTIMING */
> -               size += nla_total_size(sizeof(struct can_bittiming));
> -       if (priv->bittiming_const)                              /* IFLA_CAN_BITTIMING_CONST */
> -               size += nla_total_size(sizeof(struct can_bittiming_const));
> -       size += nla_total_size(sizeof(struct can_clock));       /* IFLA_CAN_CLOCK */
> -       size += nla_total_size(sizeof(u32));                    /* IFLA_CAN_STATE */
> -       size += nla_total_size(sizeof(struct can_ctrlmode));    /* IFLA_CAN_CTRLMODE */
> -       size += nla_total_size(sizeof(u32));                    /* IFLA_CAN_RESTART_MS */
> -       if (priv->do_get_berr_counter)                          /* IFLA_CAN_BERR_COUNTER */
> -               size += nla_total_size(sizeof(struct can_berr_counter));
> -       if (priv->data_bittiming.bitrate)                       /* IFLA_CAN_DATA_BITTIMING */
> -               size += nla_total_size(sizeof(struct can_bittiming));
> -       if (priv->data_bittiming_const)                         /* IFLA_CAN_DATA_BITTIMING_CONST */
> -               size += nla_total_size(sizeof(struct can_bittiming_const));
> -       if (priv->termination_const) {
> -               size += nla_total_size(sizeof(priv->termination));              /* IFLA_CAN_TERMINATION */
> -               size += nla_total_size(sizeof(*priv->termination_const) *       /* IFLA_CAN_TERMINATION_CONST */
> -                                      priv->termination_const_cnt);
> -       }
> -       if (priv->bitrate_const)                                /* IFLA_CAN_BITRATE_CONST */
> -               size += nla_total_size(sizeof(*priv->bitrate_const) *
> -                                      priv->bitrate_const_cnt);
> -       if (priv->data_bitrate_const)                           /* IFLA_CAN_DATA_BITRATE_CONST */
> -               size += nla_total_size(sizeof(*priv->data_bitrate_const) *
> -                                      priv->data_bitrate_const_cnt);
> -       size += sizeof(priv->bitrate_max);                      /* IFLA_CAN_BITRATE_MAX */
> -
> -       return size;
> -}
> -
> -static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -       struct can_ctrlmode cm = {.flags = priv->ctrlmode};
> -       struct can_berr_counter bec;
> -       enum can_state state = priv->state;
> -
> -       if (priv->do_get_state)
> -               priv->do_get_state(dev, &state);
> -
> -       if ((priv->bittiming.bitrate &&
> -            nla_put(skb, IFLA_CAN_BITTIMING,
> -                    sizeof(priv->bittiming), &priv->bittiming)) ||
> -
> -           (priv->bittiming_const &&
> -            nla_put(skb, IFLA_CAN_BITTIMING_CONST,
> -                    sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
> -
> -           nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
> -           nla_put_u32(skb, IFLA_CAN_STATE, state) ||
> -           nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
> -           nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
> -
> -           (priv->do_get_berr_counter &&
> -            !priv->do_get_berr_counter(dev, &bec) &&
> -            nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
> -
> -           (priv->data_bittiming.bitrate &&
> -            nla_put(skb, IFLA_CAN_DATA_BITTIMING,
> -                    sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
> -
> -           (priv->data_bittiming_const &&
> -            nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
> -                    sizeof(*priv->data_bittiming_const),
> -                    priv->data_bittiming_const)) ||
> -
> -           (priv->termination_const &&
> -            (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
> -             nla_put(skb, IFLA_CAN_TERMINATION_CONST,
> -                     sizeof(*priv->termination_const) *
> -                     priv->termination_const_cnt,
> -                     priv->termination_const))) ||
> -
> -           (priv->bitrate_const &&
> -            nla_put(skb, IFLA_CAN_BITRATE_CONST,
> -                    sizeof(*priv->bitrate_const) *
> -                    priv->bitrate_const_cnt,
> -                    priv->bitrate_const)) ||
> -
> -           (priv->data_bitrate_const &&
> -            nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
> -                    sizeof(*priv->data_bitrate_const) *
> -                    priv->data_bitrate_const_cnt,
> -                    priv->data_bitrate_const)) ||
> -
> -           (nla_put(skb, IFLA_CAN_BITRATE_MAX,
> -                    sizeof(priv->bitrate_max),
> -                    &priv->bitrate_max))
> -           )
> -
> -               return -EMSGSIZE;
> -
> -       return 0;
> -}
> -
> -static size_t can_get_xstats_size(const struct net_device *dev)
> -{
> -       return sizeof(struct can_device_stats);
> -}
> -
> -static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
> -{
> -       struct can_priv *priv = netdev_priv(dev);
> -
> -       if (nla_put(skb, IFLA_INFO_XSTATS,
> -                   sizeof(priv->can_stats), &priv->can_stats))
> -               goto nla_put_failure;
> -       return 0;
> -
> -nla_put_failure:
> -       return -EMSGSIZE;
> -}
> -
> -static int can_newlink(struct net *src_net, struct net_device *dev,
> -                      struct nlattr *tb[], struct nlattr *data[],
> -                      struct netlink_ext_ack *extack)
> -{
> -       return -EOPNOTSUPP;
> -}
> -
> -static void can_dellink(struct net_device *dev, struct list_head *head)
> -{
> -}
> -
> -static struct rtnl_link_ops can_link_ops __read_mostly = {
> -       .kind           = "can",
> -       .maxtype        = IFLA_CAN_MAX,
> -       .policy         = can_policy,
> -       .setup          = can_setup,
> -       .validate       = can_validate,
> -       .newlink        = can_newlink,
> -       .changelink     = can_changelink,
> -       .dellink        = can_dellink,
> -       .get_size       = can_get_size,
> -       .fill_info      = can_fill_info,
> -       .get_xstats_size = can_get_xstats_size,
> -       .fill_xstats    = can_fill_xstats,
> -};
> -
>  /* Register the CAN network device */
>  int register_candev(struct net_device *dev)
>  {
> @@ -812,7 +448,7 @@ static __init int can_dev_init(void)
>
>         can_led_notifier_init();
>
> -       err = rtnl_link_register(&can_link_ops);
> +       err = can_netlink_register();
>         if (!err)
>                 pr_info(MOD_DESC "\n");
>
> @@ -822,7 +458,7 @@ module_init(can_dev_init);
>
>  static __exit void can_dev_exit(void)
>  {
> -       rtnl_link_unregister(&can_link_ops);
> +       can_netlink_unregister();
>
>         can_led_notifier_exit();
>  }
> diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
> new file mode 100644
> index 000000000000..3ae884cdf677
> --- /dev/null
> +++ b/drivers/net/can/dev/netlink.c
> @@ -0,0 +1,379 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
> + * Copyright (C) 2006 Andrey Volkov, Varma Electronics
> + * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
> + */
> +
> +#include <linux/can/dev.h>
> +#include <net/rtnetlink.h>
> +
> +static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = {
> +       [IFLA_CAN_STATE]        = { .type = NLA_U32 },
> +       [IFLA_CAN_CTRLMODE]     = { .len = sizeof(struct can_ctrlmode) },
> +       [IFLA_CAN_RESTART_MS]   = { .type = NLA_U32 },
> +       [IFLA_CAN_RESTART]      = { .type = NLA_U32 },
> +       [IFLA_CAN_BITTIMING]    = { .len = sizeof(struct can_bittiming) },
> +       [IFLA_CAN_BITTIMING_CONST]
> +                               = { .len = sizeof(struct can_bittiming_const) },
> +       [IFLA_CAN_CLOCK]        = { .len = sizeof(struct can_clock) },
> +       [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) },
> +       [IFLA_CAN_DATA_BITTIMING]
> +                               = { .len = sizeof(struct can_bittiming) },
> +       [IFLA_CAN_DATA_BITTIMING_CONST]
> +                               = { .len = sizeof(struct can_bittiming_const) },
> +       [IFLA_CAN_TERMINATION]  = { .type = NLA_U16 },
> +};
> +
> +static int can_validate(struct nlattr *tb[], struct nlattr *data[],
> +                       struct netlink_ext_ack *extack)
> +{
> +       bool is_can_fd = false;
> +
> +       /* Make sure that valid CAN FD configurations always consist of
> +        * - nominal/arbitration bittiming
> +        * - data bittiming
> +        * - control mode with CAN_CTRLMODE_FD set
> +        */
> +
> +       if (!data)
> +               return 0;
> +
> +       if (data[IFLA_CAN_CTRLMODE]) {
> +               struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]);
> +
> +               is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD;
> +       }
> +
> +       if (is_can_fd) {
> +               if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING])
> +                       return -EOPNOTSUPP;
> +       }
> +
> +       if (data[IFLA_CAN_DATA_BITTIMING]) {
> +               if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
> +                       return -EOPNOTSUPP;
> +       }
> +
> +       return 0;
> +}
> +
> +static int can_changelink(struct net_device *dev, struct nlattr *tb[],
> +                         struct nlattr *data[],
> +                         struct netlink_ext_ack *extack)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +       int err;
> +
> +       /* We need synchronization with dev->stop() */
> +       ASSERT_RTNL();
> +
> +       if (data[IFLA_CAN_BITTIMING]) {
> +               struct can_bittiming bt;
> +
> +               /* Do not allow changing bittiming while running */
> +               if (dev->flags & IFF_UP)
> +                       return -EBUSY;
> +
> +               /* Calculate bittiming parameters based on
> +                * bittiming_const if set, otherwise pass bitrate
> +                * directly via do_set_bitrate(). Bail out if neither
> +                * is given.
> +                */
> +               if (!priv->bittiming_const && !priv->do_set_bittiming)
> +                       return -EOPNOTSUPP;
> +
> +               memcpy(&bt, nla_data(data[IFLA_CAN_BITTIMING]), sizeof(bt));
> +               err = can_get_bittiming(dev, &bt,
> +                                       priv->bittiming_const,
> +                                       priv->bitrate_const,
> +                                       priv->bitrate_const_cnt);
> +               if (err)
> +                       return err;
> +
> +               if (priv->bitrate_max && bt.bitrate > priv->bitrate_max) {
> +                       netdev_err(dev, "arbitration bitrate surpasses transceiver capabilities of %d bps\n",
> +                                  priv->bitrate_max);
> +                       return -EINVAL;
> +               }
> +
> +               memcpy(&priv->bittiming, &bt, sizeof(bt));
> +
> +               if (priv->do_set_bittiming) {
> +                       /* Finally, set the bit-timing registers */
> +                       err = priv->do_set_bittiming(dev);
> +                       if (err)
> +                               return err;
> +               }
> +       }
> +
> +       if (data[IFLA_CAN_CTRLMODE]) {
> +               struct can_ctrlmode *cm;
> +               u32 ctrlstatic;
> +               u32 maskedflags;
> +
> +               /* Do not allow changing controller mode while running */
> +               if (dev->flags & IFF_UP)
> +                       return -EBUSY;
> +               cm = nla_data(data[IFLA_CAN_CTRLMODE]);
> +               ctrlstatic = priv->ctrlmode_static;
> +               maskedflags = cm->flags & cm->mask;
> +
> +               /* check whether provided bits are allowed to be passed */
> +               if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic))
> +                       return -EOPNOTSUPP;
> +
> +               /* do not check for static fd-non-iso if 'fd' is disabled */
> +               if (!(maskedflags & CAN_CTRLMODE_FD))
> +                       ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO;
> +
> +               /* make sure static options are provided by configuration */
> +               if ((maskedflags & ctrlstatic) != ctrlstatic)
> +                       return -EOPNOTSUPP;
> +
> +               /* clear bits to be modified and copy the flag values */
> +               priv->ctrlmode &= ~cm->mask;
> +               priv->ctrlmode |= maskedflags;
> +
> +               /* CAN_CTRLMODE_FD can only be set when driver supports FD */
> +               if (priv->ctrlmode & CAN_CTRLMODE_FD)
> +                       dev->mtu = CANFD_MTU;
> +               else
> +                       dev->mtu = CAN_MTU;
> +       }
> +
> +       if (data[IFLA_CAN_RESTART_MS]) {
> +               /* Do not allow changing restart delay while running */
> +               if (dev->flags & IFF_UP)
> +                       return -EBUSY;
> +               priv->restart_ms = nla_get_u32(data[IFLA_CAN_RESTART_MS]);
> +       }
> +
> +       if (data[IFLA_CAN_RESTART]) {
> +               /* Do not allow a restart while not running */
> +               if (!(dev->flags & IFF_UP))
> +                       return -EINVAL;
> +               err = can_restart_now(dev);
> +               if (err)
> +                       return err;
> +       }
> +
> +       if (data[IFLA_CAN_DATA_BITTIMING]) {
> +               struct can_bittiming dbt;
> +
> +               /* Do not allow changing bittiming while running */
> +               if (dev->flags & IFF_UP)
> +                       return -EBUSY;
> +
> +               /* Calculate bittiming parameters based on
> +                * data_bittiming_const if set, otherwise pass bitrate
> +                * directly via do_set_bitrate(). Bail out if neither
> +                * is given.
> +                */
> +               if (!priv->data_bittiming_const && !priv->do_set_data_bittiming)
> +                       return -EOPNOTSUPP;
> +
> +               memcpy(&dbt, nla_data(data[IFLA_CAN_DATA_BITTIMING]),
> +                      sizeof(dbt));
> +               err = can_get_bittiming(dev, &dbt,
> +                                       priv->data_bittiming_const,
> +                                       priv->data_bitrate_const,
> +                                       priv->data_bitrate_const_cnt);
> +               if (err)
> +                       return err;
> +
> +               if (priv->bitrate_max && dbt.bitrate > priv->bitrate_max) {
> +                       netdev_err(dev, "canfd data bitrate surpasses transceiver capabilities of %d bps\n",
> +                                  priv->bitrate_max);
> +                       return -EINVAL;
> +               }
> +
> +               memcpy(&priv->data_bittiming, &dbt, sizeof(dbt));
> +
> +               if (priv->do_set_data_bittiming) {
> +                       /* Finally, set the bit-timing registers */
> +                       err = priv->do_set_data_bittiming(dev);
> +                       if (err)
> +                               return err;
> +               }
> +       }
> +
> +       if (data[IFLA_CAN_TERMINATION]) {
> +               const u16 termval = nla_get_u16(data[IFLA_CAN_TERMINATION]);
> +               const unsigned int num_term = priv->termination_const_cnt;
> +               unsigned int i;
> +
> +               if (!priv->do_set_termination)
> +                       return -EOPNOTSUPP;
> +
> +               /* check whether given value is supported by the interface */
> +               for (i = 0; i < num_term; i++) {
> +                       if (termval == priv->termination_const[i])
> +                               break;
> +               }
> +               if (i >= num_term)
> +                       return -EINVAL;
> +
> +               /* Finally, set the termination value */
> +               err = priv->do_set_termination(dev, termval);
> +               if (err)
> +                       return err;
> +
> +               priv->termination = termval;
> +       }
> +
> +       return 0;
> +}
> +
> +static size_t can_get_size(const struct net_device *dev)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +       size_t size = 0;
> +
> +       if (priv->bittiming.bitrate)                            /* IFLA_CAN_BITTIMING */
> +               size += nla_total_size(sizeof(struct can_bittiming));
> +       if (priv->bittiming_const)                              /* IFLA_CAN_BITTIMING_CONST */
> +               size += nla_total_size(sizeof(struct can_bittiming_const));
> +       size += nla_total_size(sizeof(struct can_clock));       /* IFLA_CAN_CLOCK */
> +       size += nla_total_size(sizeof(u32));                    /* IFLA_CAN_STATE */
> +       size += nla_total_size(sizeof(struct can_ctrlmode));    /* IFLA_CAN_CTRLMODE */
> +       size += nla_total_size(sizeof(u32));                    /* IFLA_CAN_RESTART_MS */
> +       if (priv->do_get_berr_counter)                          /* IFLA_CAN_BERR_COUNTER */
> +               size += nla_total_size(sizeof(struct can_berr_counter));
> +       if (priv->data_bittiming.bitrate)                       /* IFLA_CAN_DATA_BITTIMING */
> +               size += nla_total_size(sizeof(struct can_bittiming));
> +       if (priv->data_bittiming_const)                         /* IFLA_CAN_DATA_BITTIMING_CONST */
> +               size += nla_total_size(sizeof(struct can_bittiming_const));
> +       if (priv->termination_const) {
> +               size += nla_total_size(sizeof(priv->termination));              /* IFLA_CAN_TERMINATION */
> +               size += nla_total_size(sizeof(*priv->termination_const) *       /* IFLA_CAN_TERMINATION_CONST */
> +                                      priv->termination_const_cnt);
> +       }
> +       if (priv->bitrate_const)                                /* IFLA_CAN_BITRATE_CONST */
> +               size += nla_total_size(sizeof(*priv->bitrate_const) *
> +                                      priv->bitrate_const_cnt);
> +       if (priv->data_bitrate_const)                           /* IFLA_CAN_DATA_BITRATE_CONST */
> +               size += nla_total_size(sizeof(*priv->data_bitrate_const) *
> +                                      priv->data_bitrate_const_cnt);
> +       size += sizeof(priv->bitrate_max);                      /* IFLA_CAN_BITRATE_MAX */
> +
> +       return size;
> +}
> +
> +static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +       struct can_ctrlmode cm = {.flags = priv->ctrlmode};
> +       struct can_berr_counter bec;
> +       enum can_state state = priv->state;
> +
> +       if (priv->do_get_state)
> +               priv->do_get_state(dev, &state);
> +
> +       if ((priv->bittiming.bitrate &&
> +            nla_put(skb, IFLA_CAN_BITTIMING,
> +                    sizeof(priv->bittiming), &priv->bittiming)) ||
> +
> +           (priv->bittiming_const &&
> +            nla_put(skb, IFLA_CAN_BITTIMING_CONST,
> +                    sizeof(*priv->bittiming_const), priv->bittiming_const)) ||
> +
> +           nla_put(skb, IFLA_CAN_CLOCK, sizeof(priv->clock), &priv->clock) ||
> +           nla_put_u32(skb, IFLA_CAN_STATE, state) ||
> +           nla_put(skb, IFLA_CAN_CTRLMODE, sizeof(cm), &cm) ||
> +           nla_put_u32(skb, IFLA_CAN_RESTART_MS, priv->restart_ms) ||
> +
> +           (priv->do_get_berr_counter &&
> +            !priv->do_get_berr_counter(dev, &bec) &&
> +            nla_put(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec)) ||
> +
> +           (priv->data_bittiming.bitrate &&
> +            nla_put(skb, IFLA_CAN_DATA_BITTIMING,
> +                    sizeof(priv->data_bittiming), &priv->data_bittiming)) ||
> +
> +           (priv->data_bittiming_const &&
> +            nla_put(skb, IFLA_CAN_DATA_BITTIMING_CONST,
> +                    sizeof(*priv->data_bittiming_const),
> +                    priv->data_bittiming_const)) ||
> +
> +           (priv->termination_const &&
> +            (nla_put_u16(skb, IFLA_CAN_TERMINATION, priv->termination) ||
> +             nla_put(skb, IFLA_CAN_TERMINATION_CONST,
> +                     sizeof(*priv->termination_const) *
> +                     priv->termination_const_cnt,
> +                     priv->termination_const))) ||
> +
> +           (priv->bitrate_const &&
> +            nla_put(skb, IFLA_CAN_BITRATE_CONST,
> +                    sizeof(*priv->bitrate_const) *
> +                    priv->bitrate_const_cnt,
> +                    priv->bitrate_const)) ||
> +
> +           (priv->data_bitrate_const &&
> +            nla_put(skb, IFLA_CAN_DATA_BITRATE_CONST,
> +                    sizeof(*priv->data_bitrate_const) *
> +                    priv->data_bitrate_const_cnt,
> +                    priv->data_bitrate_const)) ||
> +
> +           (nla_put(skb, IFLA_CAN_BITRATE_MAX,
> +                    sizeof(priv->bitrate_max),
> +                    &priv->bitrate_max))
> +           )
> +
> +               return -EMSGSIZE;
> +
> +       return 0;
> +}
> +
> +static size_t can_get_xstats_size(const struct net_device *dev)
> +{
> +       return sizeof(struct can_device_stats);
> +}
> +
> +static int can_fill_xstats(struct sk_buff *skb, const struct net_device *dev)
> +{
> +       struct can_priv *priv = netdev_priv(dev);
> +
> +       if (nla_put(skb, IFLA_INFO_XSTATS,
> +                   sizeof(priv->can_stats), &priv->can_stats))
> +               goto nla_put_failure;
> +       return 0;
> +
> +nla_put_failure:
> +       return -EMSGSIZE;
> +}
> +
> +static int can_newlink(struct net *src_net, struct net_device *dev,
> +                      struct nlattr *tb[], struct nlattr *data[],
> +                      struct netlink_ext_ack *extack)
> +{
> +       return -EOPNOTSUPP;
> +}
> +
> +static void can_dellink(struct net_device *dev, struct list_head *head)
> +{
> +}
> +
> +struct rtnl_link_ops can_link_ops __read_mostly = {
> +       .kind           = "can",
> +       .maxtype        = IFLA_CAN_MAX,
> +       .policy         = can_policy,
> +       .setup          = can_setup,
> +       .validate       = can_validate,
> +       .newlink        = can_newlink,
> +       .changelink     = can_changelink,
> +       .dellink        = can_dellink,
> +       .get_size       = can_get_size,
> +       .fill_info      = can_fill_info,
> +       .get_xstats_size = can_get_xstats_size,
> +       .fill_xstats    = can_fill_xstats,
> +};
> +
> +int can_netlink_register(void)
> +{
> +       return rtnl_link_register(&can_link_ops);
> +}
> +
> +void can_netlink_unregister(void)
> +{
> +       rtnl_link_unregister(&can_link_ops);
> +}
> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
> index 4a26e128af7f..7faf6a37d5b2 100644
> --- a/include/linux/can/dev.h
> +++ b/include/linux/can/dev.h
> @@ -100,6 +100,8 @@ static inline void can_set_static_ctrlmode(struct net_device *dev,
>                 dev->mtu = CANFD_MTU;
>  }
>
> +void can_setup(struct net_device *dev);
> +
>  struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max,
>                                     unsigned int txqs, unsigned int rxqs);
>  #define alloc_candev(sizeof_priv, echo_skb_max) \
> @@ -130,4 +132,8 @@ void of_can_transceiver(struct net_device *dev);
>  static inline void of_can_transceiver(struct net_device *dev) { }
>  #endif
>
> +extern struct rtnl_link_ops can_link_ops;
> +int can_netlink_register(void);
> +void can_netlink_unregister(void);
> +
>  #endif /* !_CAN_DEV_H */
> --
> 2.29.2
>
>

Same as previous message but for netlink: fails to build. I think
you just forgot to include the changes on
drivers/net/can/dev/Makefile (c.f. below).

diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
index 2c38bd532157..6624be65de6f 100644
--- a/drivers/net/can/dev/Makefile
+++ b/drivers/net/can/dev/Makefile
@@ -6,5 +6,6 @@ can-dev-y            += dev.o
 can-dev-y            += length.o
 can-dev-y            += rx-offload.o
 can-dev-y            += skb.o
+can-dev-y            += netlink.o

 can-dev-$(CONFIG_CAN_LEDS)    += led.o

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

* Re: [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length
  2021-01-09 17:40 ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
@ 2021-01-10  6:52   ` Vincent MAILHOL
  2021-01-10  8:38     ` Vincent MAILHOL
  2021-01-11  8:22     ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
  0 siblings, 2 replies; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-10  6:52 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Sun. 10 Jan 2021 at 02:40, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> In order to implement byte queue limits (bql) in CAN drivers, the length of the
> CAN frame needs to be passed into the networking stack after queueing and after
> transmission completion.
>
> To avoid to calculate this length twice, extend the struct can_skb_priv to hold
> the length of the CAN frame and extend __can_get_echo_skb() to return that
> value.
>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
>  drivers/net/can/dev/rx-offload.c | 2 +-
>  drivers/net/can/dev/skb.c        | 9 +++++++--
>  include/linux/can/skb.h          | 4 +++-
>  3 files changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
> index 3c1912c0430b..6a26b5282df1 100644
> --- a/drivers/net/can/dev/rx-offload.c
> +++ b/drivers/net/can/dev/rx-offload.c
> @@ -271,7 +271,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
>         u8 len;
>         int err;
>
> -       skb = __can_get_echo_skb(dev, idx, &len);
> +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
>         if (!skb)
>                 return 0;
>
> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> index 26cd597ff771..24f782a23409 100644
> --- a/drivers/net/can/dev/skb.c
> +++ b/drivers/net/can/dev/skb.c
> @@ -76,7 +76,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>  EXPORT_SYMBOL_GPL(can_put_echo_skb);
>
>  struct sk_buff *
> -__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> +__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
> +                  unsigned int *frame_len_ptr)
>  {
>         struct can_priv *priv = netdev_priv(dev);
>
> @@ -91,6 +92,7 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
>                  * length is supported on both CAN and CANFD frames.
>                  */
>                 struct sk_buff *skb = priv->echo_skb[idx];
> +               struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
>                 struct canfd_frame *cf = (struct canfd_frame *)skb->data;
>
>                 /* get the real payload length for netdev statistics */
> @@ -99,6 +101,9 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
>                 else
>                         *len_ptr = cf->len;
>
> +               if (frame_len_ptr)
> +                       *frame_len_ptr = can_skb_priv->frame_len;
> +
>                 priv->echo_skb[idx] = NULL;
>
>                 return skb;
> @@ -118,7 +123,7 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
>         struct sk_buff *skb;
>         u8 len;
>
> -       skb = __can_get_echo_skb(dev, idx, &len);
> +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
>         if (!skb)
>                 return 0;
>

The can_skb_priv->frame_len is smart. Nice change :)

I have one knit pick concerning the symmetry between
can_put_echo_skb() and can_get_echo_skb().

My current understanding is that:
  * In the tx branch, we need to manually set can_skb_priv->frame_len. Example:
        can_skb_prv(skb)->frame_len = can_skb_get_frame_len(skb);
        can_put_echo_skb(skb, netdev, skb_idx);
  * In the rx branch, it is accessed through the function can_get_echo_skb():
        unsigned int frame_len;
        can_get_echo_skb(skb, netdev, skb_idx, &frame_len);

Please correct me if my understanding is wrong.

I think that you did not modify can_put_echo_skb() so that the
drivers which do not implement the BQL would not have to call
can_skb_get_frame_len(skb) and thus saving computing resources. I
also understand that the motivation to modify can_put_echo_skb()
is to factorise the code.

But the absence of symmetry in the final result bothers me a
bit. Reading manually can_skb_prv(skb)->frame_len by hand would
look as below, which I think is short enough not to be
factorized within can_get_echo_skb():
        struct sk_buff *skb = priv->echo_skb[skb_idx];
        unsigned int frame_len = can_skb_prv(skb)->frame_len;
        can_get_echo_skb(skb, netdev, skb_idx);

So at the end, I would suggest not to modify can_get_echo_skb()
so that it is a better "mirror" of can_put_echo_skb().

> diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
> index c90ebbd3008c..5db9da30843c 100644
> --- a/include/linux/can/skb.h
> +++ b/include/linux/can/skb.h
> @@ -20,7 +20,7 @@ void can_flush_echo_skb(struct net_device *dev);
>  int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>                      unsigned int idx);
>  struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
> -                                  u8 *len_ptr);
> +                                  u8 *len_ptr, unsigned int *frame_len_ptr);
>  unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
>  void can_free_echo_skb(struct net_device *dev, unsigned int idx);
>  struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
> @@ -42,11 +42,13 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev,
>   * struct can_skb_priv - private additional data inside CAN sk_buffs
>   * @ifindex:   ifindex of the first interface the CAN frame appeared on
>   * @skbcnt:    atomic counter to have an unique id together with skb pointer
> + * @frame_len: length of CAN frame in data link layer
>   * @cf:                align to the following CAN frame at skb->data
>   */
>  struct can_skb_priv {
>         int ifindex;
>         int skbcnt;
> +       unsigned int frame_len;
>         struct can_frame cf[];
>  };
>
> --
> 2.29.2
>
>

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

* Re: [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length
  2021-01-10  6:52   ` Vincent MAILHOL
@ 2021-01-10  8:38     ` Vincent MAILHOL
  2021-01-11  6:13       ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Vincent Mailhol
  2021-01-11  8:22     ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
  1 sibling, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-10  8:38 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

Le dim. 10 janv. 2021 à 15:52, Vincent MAILHOL
<mailhol.vincent@wanadoo.fr> a écrit :
>
> On Sun. 10 Jan 2021 at 02:40, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> >
> > In order to implement byte queue limits (bql) in CAN drivers, the length of the
> > CAN frame needs to be passed into the networking stack after queueing and after
> > transmission completion.
> >
> > To avoid to calculate this length twice, extend the struct can_skb_priv to hold
> > the length of the CAN frame and extend __can_get_echo_skb() to return that
> > value.
> >
> > Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> > ---
> >  drivers/net/can/dev/rx-offload.c | 2 +-
> >  drivers/net/can/dev/skb.c        | 9 +++++++--
> >  include/linux/can/skb.h          | 4 +++-
> >  3 files changed, 11 insertions(+), 4 deletions(-)
> >
> > diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c
> > index 3c1912c0430b..6a26b5282df1 100644
> > --- a/drivers/net/can/dev/rx-offload.c
> > +++ b/drivers/net/can/dev/rx-offload.c
> > @@ -271,7 +271,7 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
> >         u8 len;
> >         int err;
> >
> > -       skb = __can_get_echo_skb(dev, idx, &len);
> > +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
> >         if (!skb)
> >                 return 0;
> >
> > diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> > index 26cd597ff771..24f782a23409 100644
> > --- a/drivers/net/can/dev/skb.c
> > +++ b/drivers/net/can/dev/skb.c
> > @@ -76,7 +76,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> >  EXPORT_SYMBOL_GPL(can_put_echo_skb);
> >
> >  struct sk_buff *
> > -__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> > +__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr,
> > +                  unsigned int *frame_len_ptr)
> >  {
> >         struct can_priv *priv = netdev_priv(dev);
> >
> > @@ -91,6 +92,7 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> >                  * length is supported on both CAN and CANFD frames.
> >                  */
> >                 struct sk_buff *skb = priv->echo_skb[idx];
> > +               struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
> >                 struct canfd_frame *cf = (struct canfd_frame *)skb->data;
> >
> >                 /* get the real payload length for netdev statistics */
> > @@ -99,6 +101,9 @@ __can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
> >                 else
> >                         *len_ptr = cf->len;
> >
> > +               if (frame_len_ptr)
> > +                       *frame_len_ptr = can_skb_priv->frame_len;
> > +
> >                 priv->echo_skb[idx] = NULL;
> >
> >                 return skb;
> > @@ -118,7 +123,7 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
> >         struct sk_buff *skb;
> >         u8 len;
> >
> > -       skb = __can_get_echo_skb(dev, idx, &len);
> > +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
> >         if (!skb)
> >                 return 0;
> >
>
> The can_skb_priv->frame_len is smart. Nice change :)
>
> I have one knit pick concerning the symmetry between
> can_put_echo_skb() and can_get_echo_skb().
>
> My current understanding is that:
>   * In the tx branch, we need to manually set can_skb_priv->frame_len. Example:
>         can_skb_prv(skb)->frame_len = can_skb_get_frame_len(skb);
>         can_put_echo_skb(skb, netdev, skb_idx);
>   * In the rx branch, it is accessed through the function can_get_echo_skb():
>         unsigned int frame_len;
>         can_get_echo_skb(skb, netdev, skb_idx, &frame_len);
>
> Please correct me if my understanding is wrong.
>
> I think that you did not modify can_put_echo_skb() so that the
> drivers which do not implement the BQL would not have to call
> can_skb_get_frame_len(skb) and thus saving computing resources. I
> also understand that the motivation to modify can_put_echo_skb()
> is to factorise the code.
>
> But the absence of symmetry in the final result bothers me a
> bit. Reading manually can_skb_prv(skb)->frame_len by hand would
> look as below, which I think is short enough not to be
> factorized within can_get_echo_skb():
>         struct sk_buff *skb = priv->echo_skb[skb_idx];
>         unsigned int frame_len = can_skb_prv(skb)->frame_len;
>         can_get_echo_skb(skb, netdev, skb_idx);
>
> So at the end, I would suggest not to modify can_get_echo_skb()
> so that it is a better "mirror" of can_put_echo_skb().

Or another option is to change can_put_echo_skb to:

int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
             unsigned int idx, unsigned int frame_len)

Drivers which implement BQL call it with the output of
can_skb_get_frame_len(skb) and drivers which do not simply pass
zero as an input (in the same way that NULL would be given to
can_get_echo_skb()). This way, we have a nice symmetry between
the two echo functions.

>
> > diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
> > index c90ebbd3008c..5db9da30843c 100644
> > --- a/include/linux/can/skb.h
> > +++ b/include/linux/can/skb.h
> > @@ -20,7 +20,7 @@ void can_flush_echo_skb(struct net_device *dev);
> >  int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> >                      unsigned int idx);
> >  struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
> > -                                  u8 *len_ptr);
> > +                                  u8 *len_ptr, unsigned int *frame_len_ptr);
> >  unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx);
> >  void can_free_echo_skb(struct net_device *dev, unsigned int idx);
> >  struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
> > @@ -42,11 +42,13 @@ struct sk_buff *alloc_can_err_skb(struct net_device *dev,
> >   * struct can_skb_priv - private additional data inside CAN sk_buffs
> >   * @ifindex:   ifindex of the first interface the CAN frame appeared on
> >   * @skbcnt:    atomic counter to have an unique id together with skb pointer
> > + * @frame_len: length of CAN frame in data link layer
> >   * @cf:                align to the following CAN frame at skb->data
> >   */
> >  struct can_skb_priv {
> >         int ifindex;
> >         int skbcnt;
> > +       unsigned int frame_len;
> >         struct can_frame cf[];
> >  };
> >
> > --
> > 2.29.2
> >
> >

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

* Re: [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
  2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
                   ` (12 preceding siblings ...)
  2021-01-09 17:40 ` [net-next 13/13] can: dev: can_rx_offload_get_echo_skb(): " Marc Kleine-Budde
@ 2021-01-10  8:55 ` Vincent MAILHOL
  2021-01-11  8:26   ` Marc Kleine-Budde
  13 siblings, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-10  8:55 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Sun. 10 Jan 2021 at 02:40, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> Hello,
>
> this series splits the CAN driver related infrastructure into several files
> (patches 1...6), followed by some cleanup patches (7, 8), and support for
> CAN frame length handling (9...13).
>
> I took the path and put the calculated frame length into the struct
> can_skb_priv and extended the can_get_echo_skb() and
> can_rx_offload_get_echo_skb() to optionally return the CAN frame length.
>
> This patch illustrated how the new code can be used. I'll send mcp251xfd BQL
> support in a separate series, once details about this code have settled.
>
> @@ -1352,7 +1357,9 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
>         }
>
>         for (i = 0; i < len; i++) {
> -               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i]);
> +               unsigned int frame_len;
> +
> +               err = mcp251xfd_handle_tefif_one(priv, &hw_tef_obj[i], &frame_len);
>                 /* -EAGAIN means the Sequence Number in the TEF
>                  * doesn't match our tef_tail. This can happen if we
>                  * read the TEF objects too early. Leave loop let the
> @@ -1362,6 +1369,8 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
>                         goto out_netif_wake_queue;
>                 if (err)
>                         return err;
> +
> +               total_frame_len += frame_len;
>         }
>
>   out_netif_wake_queue:
> @@ -1393,6 +1402,7 @@ static int mcp251xfd_handle_tefif(struct mcp251xfd_priv *priv)
>                         return err;
>
>                 tx_ring->tail += len;
> +               netdev_completed_queue(priv->ndev, len, total_frame_len);
>
>                 err = mcp251xfd_check_tef_tail(priv);
>                 if (err)
> @@ -2433,6 +2443,7 @@ static bool mcp251xfd_tx_busy(const struct mcp251xfd_priv *priv,
>  static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
>                                         struct net_device *ndev)
>  {
> +       struct can_skb_priv *can_skb_priv = can_skb_prv(skb);
>         struct mcp251xfd_priv *priv = netdev_priv(ndev);
>         struct mcp251xfd_tx_ring *tx_ring = priv->tx;
>         struct mcp251xfd_tx_obj *tx_obj;
> @@ -2455,6 +2466,8 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
>                 netif_stop_queue(ndev);
>
>         can_put_echo_skb(skb, ndev, tx_head);
> +       can_skb_priv->frame_len = can_skb_get_frame_len(skb);
> +       netdev_sent_queue(priv->ndev, can_skb_priv->frame_len);
>
>         err = mcp251xfd_tx_obj_write(priv, tx_obj);
>         if (err)
>
> regards,
> Marc
>

Did you test it after the occurence of a can_bus_off() event?

When the device restarts, you normally have to call
netdev_reset_queue(netdev) in order to reset all the BQL
statistics.

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

* [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len
  2021-01-10  8:38     ` Vincent MAILHOL
@ 2021-01-11  6:13       ` Vincent Mailhol
  2021-01-11  9:38         ` Marc Kleine-Budde
  2021-01-11 10:26         ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Marc Kleine-Budde
  0 siblings, 2 replies; 40+ messages in thread
From: Vincent Mailhol @ 2021-01-11  6:13 UTC (permalink / raw)
  To: Marc Kleine-Budde, linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol

Add a frame_len argument to can_put_echo_skb() which is used to save
length of the CAN frame into field frame_len of struct can_skb_priv so
that it can be later used after transmission completion. Convert all
users of this function, too.

Drivers which implement BQL call can_put_echo_skb() with the output of
can_skb_get_frame_len(skb) and drivers which do not simply pass zero
as an input (in the same way that NULL would be given to
can_get_echo_skb()). This way, we have a nice symmetry between the two
echo functions.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
--
Hi Marc,

If you like the idea to modify can_put_echo_skb(), you can use this
patch. Just put it between patches 12 and 13 of your series.

Yours sincerely,
Vincent Mailhol
---
 drivers/net/can/at91_can.c                       | 2 +-
 drivers/net/can/c_can/c_can.c                    | 2 +-
 drivers/net/can/cc770/cc770.c                    | 2 +-
 drivers/net/can/dev/skb.c                        | 6 +++++-
 drivers/net/can/flexcan.c                        | 2 +-
 drivers/net/can/grcan.c                          | 2 +-
 drivers/net/can/ifi_canfd/ifi_canfd.c            | 2 +-
 drivers/net/can/kvaser_pciefd.c                  | 2 +-
 drivers/net/can/m_can/m_can.c                    | 2 +-
 drivers/net/can/mscan/mscan.c                    | 2 +-
 drivers/net/can/pch_can.c                        | 2 +-
 drivers/net/can/peak_canfd/peak_canfd.c          | 2 +-
 drivers/net/can/rcar/rcar_can.c                  | 2 +-
 drivers/net/can/rcar/rcar_canfd.c                | 2 +-
 drivers/net/can/sja1000/sja1000.c                | 2 +-
 drivers/net/can/softing/softing_main.c           | 2 +-
 drivers/net/can/spi/hi311x.c                     | 2 +-
 drivers/net/can/spi/mcp251x.c                    | 2 +-
 drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c   | 2 +-
 drivers/net/can/sun4i_can.c                      | 2 +-
 drivers/net/can/ti_hecc.c                        | 2 +-
 drivers/net/can/usb/ems_usb.c                    | 2 +-
 drivers/net/can/usb/esd_usb2.c                   | 2 +-
 drivers/net/can/usb/gs_usb.c                     | 2 +-
 drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 2 +-
 drivers/net/can/usb/mcba_usb.c                   | 2 +-
 drivers/net/can/usb/peak_usb/pcan_usb_core.c     | 2 +-
 drivers/net/can/usb/ucan.c                       | 2 +-
 drivers/net/can/usb/usb_8dev.c                   | 2 +-
 drivers/net/can/xilinx_can.c                     | 4 ++--
 include/linux/can/skb.h                          | 2 +-
 31 files changed, 36 insertions(+), 32 deletions(-)

diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index ae015ec227d4..9ad9b39f480e 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -484,7 +484,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	stats->tx_bytes += cf->len;
 
 	/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
-	can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));
+	can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv), 0);
 
 	/*
 	 * we have to stop the queue and deliver all messages in case
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index e7ee60b2c76b..ef474bae47a1 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -476,7 +476,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
 	 */
 	c_can_setup_tx_object(dev, IF_TX, frame, idx);
 	priv->dlc[idx] = frame->len;
-	can_put_echo_skb(skb, dev, idx);
+	can_put_echo_skb(skb, dev, idx, 0);
 
 	/* Update the active bits */
 	atomic_add((1 << idx), &priv->tx_active);
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index 5ecb2afd6bbf..f8a130f594e2 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -702,7 +702,7 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
 	stats->tx_bytes += cf->len;
 	stats->tx_packets++;
 
-	can_put_echo_skb(priv->tx_skb, dev, 0);
+	can_put_echo_skb(priv->tx_skb, dev, 0, 0);
 	can_get_echo_skb(dev, 0, NULL);
 	priv->tx_skb = NULL;
 
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 568dc28f7a4e..64bd2b60febc 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -38,7 +38,7 @@ void can_flush_echo_skb(struct net_device *dev)
  * priv->echo_skb, if necessary.
  */
 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
-		     unsigned int idx)
+		     unsigned int idx, unsigned int frame_len)
 {
 	struct can_priv *priv = netdev_priv(dev);
 
@@ -62,6 +62,10 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		skb->dev = dev;
 
+		/* save frame_len to reuse it when transmission is completed */
+		if (frame_len)
+			can_skb_prv(skb)->frame_len = frame_len;
+
 		/* save this skb for tx interrupt echo handling */
 		priv->echo_skb[idx] = skb;
 	} else {
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 038fe1036df2..5e51e040ea09 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -776,7 +776,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
 	}
 
-	can_put_echo_skb(skb, dev, 0);
+	can_put_echo_skb(skb, dev, 0, 0);
 
 	priv->write(can_id, &priv->tx_mb->can_id);
 	priv->write(ctrl, &priv->tx_mb->can_ctrl);
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 6aaebbcb7e76..4a8453290530 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1448,7 +1448,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
 	 * taken.
 	 */
 	priv->txdlc[slotindex] = cf->len; /* Store dlc for statistics */
-	can_put_echo_skb(skb, dev, slotindex);
+	can_put_echo_skb(skb, dev, slotindex, 0);
 
 	/* Make sure everything is written before allowing hardware to
 	 * read from the memory
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index b3ec32f60e67..5bb957a26bc6 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -922,7 +922,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb,
 	writel(0, priv->base + IFI_CANFD_TXFIFO_REPEATCOUNT);
 	writel(0, priv->base + IFI_CANFD_TXFIFO_SUSPEND_US);
 
-	can_put_echo_skb(skb, ndev, 0);
+	can_put_echo_skb(skb, ndev, 0, 0);
 
 	/* Start the transmission */
 	writel(IFI_CANFD_TXSTCMD_ADD_MSG, priv->base + IFI_CANFD_TXSTCMD);
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index 6602791b3b81..37e05010ca91 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -778,7 +778,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
 	spin_lock_irqsave(&can->echo_lock, irq_flags);
 
 	/* Prepare and save echo skb in internal slot */
-	can_put_echo_skb(skb, netdev, can->echo_idx);
+	can_put_echo_skb(skb, netdev, can->echo_idx, 0);
 
 	/* Move echo index to the next slot */
 	can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max;
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 262ca98cc2b1..8c71b3a5a27b 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1483,7 +1483,7 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
 					 M_CAN_FIFO_DATA(i / 4),
 					 *(u32 *)(cf->data + i));
 
-		can_put_echo_skb(skb, dev, 0);
+		can_put_echo_skb(skb, dev, 0, 0);
 
 		if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) {
 			cccr = m_can_read(cdev, M_CAN_CCCR);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 6caa89fe7184..fa32e418eb29 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -270,7 +270,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head);
 
-	can_put_echo_skb(skb, dev, buf_id);
+	can_put_echo_skb(skb, dev, buf_id, 0);
 
 	/* Enable interrupt. */
 	priv->tx_active |= 1 << buf_id;
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 6faadac983b6..92a54a5fd4c5 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -924,7 +924,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
 			  &priv->regs->ifregs[1].data[i / 2]);
 	}
 
-	can_put_echo_skb(skb, ndev, tx_obj_no - PCH_RX_OBJ_END - 1);
+	can_put_echo_skb(skb, ndev, tx_obj_no - PCH_RX_OBJ_END - 1, 0);
 
 	/* Set the size of the data. Update if2_mcont */
 	iowrite32(cf->len | PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_TXRQXT |
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
index 86df3b2b701a..00847cbaf7b6 100644
--- a/drivers/net/can/peak_canfd/peak_canfd.c
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
@@ -716,7 +716,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
 	spin_lock_irqsave(&priv->echo_lock, flags);
 
 	/* prepare and save echo skb in internal slot */
-	can_put_echo_skb(skb, ndev, priv->echo_idx);
+	can_put_echo_skb(skb, ndev, priv->echo_idx, 0);
 
 	/* move echo index to the next slot */
 	priv->echo_idx = (priv->echo_idx + 1) % priv->can.echo_skb_max;
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index ae76ea3ae0e6..4870c4ea190a 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -617,7 +617,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
 	writeb(cf->len, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].dlc);
 
 	priv->tx_dlc[priv->tx_head % RCAR_CAN_FIFO_DEPTH] = cf->len;
-	can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH);
+	can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH, 0);
 	priv->tx_head++;
 	/* Start Tx: write 0xff to the TFPCR register to increment
 	 * the CPU-side pointer for the transmit FIFO to the next
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index ba658664e7ee..d8d233e62990 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1390,7 +1390,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
 	}
 
 	priv->tx_len[priv->tx_head % RCANFD_FIFO_DEPTH] = cf->len;
-	can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH);
+	can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH, 0);
 
 	spin_lock_irqsave(&priv->tx_lock, flags);
 	priv->tx_head++;
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index ded7dacaecd1..9e86488ba55f 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -318,7 +318,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
 	for (i = 0; i < cf->len; i++)
 		priv->write_reg(priv, dreg++, cf->data[i]);
 
-	can_put_echo_skb(skb, dev, 0);
+	can_put_echo_skb(skb, dev, 0, 0);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
 		cmd_reg_val |= CMD_AT;
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 583e1246ac92..c44f3411e561 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -104,7 +104,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
 	card->tx.last_bus = priv->index;
 	++card->tx.pending;
 	++priv->tx.pending;
-	can_put_echo_skb(skb, dev, priv->tx.echo_put);
+	can_put_echo_skb(skb, dev, priv->tx.echo_put, 0);
 	++priv->tx.echo_put;
 	if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
 		priv->tx.echo_put = 0;
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index c1358826074f..c3e020c90111 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -586,7 +586,7 @@ static void hi3110_tx_work_handler(struct work_struct *ws)
 			frame = (struct can_frame *)priv->tx_skb->data;
 			hi3110_hw_tx(spi, frame);
 			priv->tx_len = 1 + frame->len;
-			can_put_echo_skb(priv->tx_skb, net, 0);
+			can_put_echo_skb(priv->tx_skb, net, 0, 0);
 			priv->tx_skb = NULL;
 		}
 	}
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 114ac4c303b6..f69fb4238a65 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1002,7 +1002,7 @@ static void mcp251x_tx_work_handler(struct work_struct *ws)
 				frame->len = CAN_FRAME_MAX_DATA_LEN;
 			mcp251x_hw_tx(spi, frame, 0);
 			priv->tx_len = 1 + frame->len;
-			can_put_echo_skb(priv->tx_skb, net, 0);
+			can_put_echo_skb(priv->tx_skb, net, 0, 0);
 			priv->tx_skb = NULL;
 		}
 	}
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 77129d5f410b..978f29d624db 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -2437,7 +2437,7 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
 	if (tx_ring->head - tx_ring->tail >= tx_ring->obj_num)
 		netif_stop_queue(ndev);
 
-	can_put_echo_skb(skb, ndev, tx_head);
+	can_put_echo_skb(skb, ndev, tx_head, 0);
 
 	err = mcp251xfd_tx_obj_write(priv, tx_obj);
 	if (err)
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index faabfe74c19e..54aa7c25c4de 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -448,7 +448,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d
 
 	writel(msg_flag_n, priv->base + SUN4I_REG_BUF0_ADDR);
 
-	can_put_echo_skb(skb, dev, 0);
+	can_put_echo_skb(skb, dev, 0, 0);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
 		sun4i_can_write_cmdreg(priv, SUN4I_CMD_SELF_RCV_REQ);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index a6850ff0b55b..485c19bc98c2 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -513,7 +513,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
 			       be32_to_cpu(*(__be32 *)(cf->data + 4)));
 	else
 		*(u32 *)(cf->data + 4) = 0;
-	can_put_echo_skb(skb, ndev, mbxno);
+	can_put_echo_skb(skb, ndev, mbxno, 0);
 
 	spin_lock_irqsave(&priv->mbx_lock, flags);
 	--priv->tx_head;
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index d27567139935..18f40eb20360 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -801,7 +801,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &dev->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&dev->active_tx_urbs);
 
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index 4f653e221a5b..562acbf454fd 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -783,7 +783,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
 
 	usb_anchor_urb(urb, &priv->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&priv->active_tx_jobs);
 
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 992a511bcd95..a00dc1904415 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -525,7 +525,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &dev->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, idx);
+	can_put_echo_skb(skb, netdev, idx, 0);
 
 	atomic_inc(&dev->active_tx_urbs);
 
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index e2d58846c40c..2b7efd296758 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -578,7 +578,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 
 	context->priv = priv;
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	usb_fill_bulk_urb(urb, dev->udev,
 			  usb_sndbulkpipe(dev->udev,
diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c
index 23cec88aafc3..4232a7126c1b 100644
--- a/drivers/net/can/usb/mcba_usb.c
+++ b/drivers/net/can/usb/mcba_usb.c
@@ -355,7 +355,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
 	if (cf->can_id & CAN_RTR_FLAG)
 		usb_msg.dlc |= MCBA_DLC_RTR_MASK;
 
-	can_put_echo_skb(skb, priv->netdev, ctx->ndx);
+	can_put_echo_skb(skb, priv->netdev, ctx->ndx, 0);
 
 	err = mcba_usb_xmit(priv, (struct mcba_usb_msg *)&usb_msg, ctx);
 	if (err)
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 6a97c29e25e7..573b11559d73 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -365,7 +365,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb,
 
 	usb_anchor_urb(urb, &dev->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&dev->active_tx_urbs);
 
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index cceb142afc3e..fa403c080871 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -1137,7 +1137,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
 
 	/* put the skb on can loopback stack */
 	spin_lock_irqsave(&up->echo_skb_lock, flags);
-	can_put_echo_skb(skb, up->netdev, echo_index);
+	can_put_echo_skb(skb, up->netdev, echo_index, 0);
 	spin_unlock_irqrestore(&up->echo_skb_lock, flags);
 
 	/* transmit it */
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
index e16efdbb8f39..e8c42430a4fc 100644
--- a/drivers/net/can/usb/usb_8dev.c
+++ b/drivers/net/can/usb/usb_8dev.c
@@ -664,7 +664,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &priv->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&priv->active_tx_urbs);
 
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 7cda3d64cc05..37fa19c62d73 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -592,9 +592,9 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
 
 	if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
 	    (priv->devtype.flags & XCAN_FLAG_TXFEMP))
-		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max);
+		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
 	else
-		can_put_echo_skb(skb, ndev, 0);
+		can_put_echo_skb(skb, ndev, 0, 0);
 
 	priv->tx_head++;
 
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 3296e2144d5a..685f34cfba20 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -18,7 +18,7 @@
 
 void can_flush_echo_skb(struct net_device *dev);
 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
-		     unsigned int idx);
+		     unsigned int idx, unsigned int frame_len);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
 				   u8 *len_ptr, unsigned int *frame_len_ptr);
 unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
-- 
2.26.2


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

* Re: [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer
  2021-01-10  3:32   ` Vincent MAILHOL
@ 2021-01-11  8:12     ` Marc Kleine-Budde
  0 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  8:12 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp, Arunachalam Santhanam


[-- Attachment #1.1: Type: text/plain, Size: 781 bytes --]

On 1/10/21 4:32 AM, Vincent MAILHOL wrote:
[...]

>> +/*
>> + * Maximum size of a CAN-FD frame (rough estimation because
>> + * ES58X_SFF_BYTES() and ES58X_EFF_BYTES() macros are using the
>> + * constant values for Classical CAN, not CAN-FD).
>> + */
> /*
>  * Maximum size of a CAN-FD frame
>  * (rounded up and ignoring bitstuffing)
>  */
> It is a leftover from my original comment. Does not apply anymore
> thanks to your newly introduced CANFD_FRAME_OVERHEAD_EFF macro.

Fixed.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 05/13] can: dev: move skb related into seperate file
  2021-01-10  4:26   ` Vincent MAILHOL
@ 2021-01-11  8:14     ` Marc Kleine-Budde
  0 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  8:14 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 916 bytes --]

On 1/10/21 5:26 AM, Vincent MAILHOL wrote:
> Fails to build. I think you just forgot to include the changes on
> drivers/net/can/dev/Makefile (c.f. below).
> 
> diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
> index 5c647951e06d..2c38bd532157 100644
> --- a/drivers/net/can/dev/Makefile
> +++ b/drivers/net/can/dev/Makefile
> @@ -5,5 +5,6 @@ can-dev-y            += bittiming.o
>  can-dev-y            += dev.o
>  can-dev-y            += length.o
>  can-dev-y            += rx-offload.o
> +can-dev-y            += skb.o
> 
>  can-dev-$(CONFIG_CAN_LEDS)    += led.o

squashed into 05/13

tnx,
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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 06/13] can: dev: move netlink related code into seperate file
  2021-01-10  4:27   ` Vincent MAILHOL
@ 2021-01-11  8:17     ` Marc Kleine-Budde
  0 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  8:17 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1057 bytes --]

On 1/10/21 5:27 AM, Vincent MAILHOL wrote:
> Same as previous message but for netlink: fails to build. I think
> you just forgot to include the changes on
> drivers/net/can/dev/Makefile (c.f. below).
> 
> diff --git a/drivers/net/can/dev/Makefile b/drivers/net/can/dev/Makefile
> index 2c38bd532157..6624be65de6f 100644
> --- a/drivers/net/can/dev/Makefile
> +++ b/drivers/net/can/dev/Makefile
> @@ -6,5 +6,6 @@ can-dev-y            += dev.o
>  can-dev-y            += length.o
>  can-dev-y            += rx-offload.o
>  can-dev-y            += skb.o
> +can-dev-y            += netlink.o
> 
>  can-dev-$(CONFIG_CAN_LEDS)    += led.o

squashed - I somehow lost some changes, between iteration, when moving the files
from net/can to net/can/dev....

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length
  2021-01-10  6:52   ` Vincent MAILHOL
  2021-01-10  8:38     ` Vincent MAILHOL
@ 2021-01-11  8:22     ` Marc Kleine-Budde
  2021-01-11  8:29       ` Marc Kleine-Budde
  1 sibling, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  8:22 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 2228 bytes --]

On 1/10/21 7:52 AM, Vincent MAILHOL wrote:
[...]

>> @@ -118,7 +123,7 @@ unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)
>>         struct sk_buff *skb;
>>         u8 len;
>>
>> -       skb = __can_get_echo_skb(dev, idx, &len);
>> +       skb = __can_get_echo_skb(dev, idx, &len, NULL);
>>         if (!skb)
>>                 return 0;
>>
> 
> The can_skb_priv->frame_len is smart. Nice change :)

tnx :)

> I have one knit pick concerning the symmetry between
> can_put_echo_skb() and can_get_echo_skb().
> 
> My current understanding is that:
>   * In the tx branch, we need to manually set can_skb_priv->frame_len. Example:
>         can_skb_prv(skb)->frame_len = can_skb_get_frame_len(skb);
>         can_put_echo_skb(skb, netdev, skb_idx);

ack

>   * In the rx branch, it is accessed through the function can_get_echo_skb():
>         unsigned int frame_len;
>         can_get_echo_skb(skb, netdev, skb_idx, &frame_len);

ack

> Please correct me if my understanding is wrong.
> 
> I think that you did not modify can_put_echo_skb() so that the
> drivers which do not implement the BQL would not have to call
> can_skb_get_frame_len(skb) and thus saving computing resources. I
> also understand that the motivation to modify can_put_echo_skb()
> is to factorise the code.
> 
> But the absence of symmetry in the final result bothers me a
> bit. Reading manually can_skb_prv(skb)->frame_len by hand would
> look as below, which I think is short enough not to be
> factorized within can_get_echo_skb():
>         struct sk_buff *skb = priv->echo_skb[skb_idx];
>         unsigned int frame_len = can_skb_prv(skb)->frame_len;
>         can_get_echo_skb(skb, netdev, skb_idx);
> 
> So at the end, I would suggest not to modify can_get_echo_skb()
> so that it is a better "mirror" of can_put_echo_skb().

That is the logical next step, which I didn't take :)

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
  2021-01-10  8:55 ` [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Vincent MAILHOL
@ 2021-01-11  8:26   ` Marc Kleine-Budde
  2021-01-11  9:42     ` Vincent MAILHOL
  0 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  8:26 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1015 bytes --]

On 1/10/21 9:55 AM, Vincent MAILHOL wrote:
[...]

> Did you test it after the occurence of a can_bus_off() event?

Not yet...

> When the device restarts, you normally have to call
> netdev_reset_queue(netdev) in order to reset all the BQL
> statistics.

I only included the relevant parts to illustrate the use of the changed API.
There is a netdev_reset_queue() in mcp251xfd_ring_init(), which is called via:
mcp251xfd_chip_start(), mcp251xfd_set_mode()

> @@ -335,6 +335,8 @@ static void mcp251xfd_ring_init(struct mcp251xfd_priv *priv)
>         u8 len;
>         int i, j;
>  
> +       netdev_reset_queue(priv->ndev);
> +
>         /* TEF */
>         tef_ring = priv->tef;
>         tef_ring->head = 0;

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length
  2021-01-11  8:22     ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
@ 2021-01-11  8:29       ` Marc Kleine-Budde
  0 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  8:29 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1069 bytes --]

On 1/11/21 9:22 AM, Marc Kleine-Budde wrote:
[...]

>> But the absence of symmetry in the final result bothers me a
>> bit. Reading manually can_skb_prv(skb)->frame_len by hand would
>> look as below, which I think is short enough not to be
>> factorized within can_get_echo_skb():
>>         struct sk_buff *skb = priv->echo_skb[skb_idx];
>>         unsigned int frame_len = can_skb_prv(skb)->frame_len;
>>         can_get_echo_skb(skb, netdev, skb_idx);
>>
>> So at the end, I would suggest not to modify can_get_echo_skb()
>> so that it is a better "mirror" of can_put_echo_skb().
> 
> That is the logical next step, which I didn't take :)

need more tee! I ment to say your "[PATCH] can: dev: extend can_put_echo_skb()
to handle frame_len" is the next logical step.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 04/13] can: dev: move length related code into seperate file
  2021-01-09 17:40 ` [net-next 04/13] can: dev: move length " Marc Kleine-Budde
@ 2021-01-11  8:49   ` Oliver Hartkopp
  2021-01-11  9:58     ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Oliver Hartkopp @ 2021-01-11  8:49 UTC (permalink / raw)
  To: Marc Kleine-Budde, linux-can; +Cc: Vincent Mailhol

Hi Marc,

nice cleanup!

On 09.01.21 18:40, Marc Kleine-Budde wrote:
> This patch moves all CAN frame length related code of the CAN device
> infrastructure into a separate file.
> 


> diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
> new file mode 100644
> index 000000000000..540d40dc0bc2
> --- /dev/null
> +++ b/drivers/net/can/dev/length.c
> @@ -0,0 +1,40 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
> + * Copyright (C) 2006 Andrey Volkov, Varma Electronics
> + * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
> + */

See comment below ...

> +
> +#include <linux/can/dev.h>
> +
> +/* CAN DLC to real data length conversion helpers */
> +
> +static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
> +			     8, 12, 16, 20, 24, 32, 48, 64};
> +
> +/* get data length from raw data length code (DLC) */
> +u8 can_fd_dlc2len(u8 dlc)
> +{
> +	return dlc2len[dlc & 0x0F];
> +}
> +EXPORT_SYMBOL_GPL(can_fd_dlc2len);
> +
> +static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
> +			     9, 9, 9, 9,			/* 9 - 12 */
> +			     10, 10, 10, 10,			/* 13 - 16 */
> +			     11, 11, 11, 11,			/* 17 - 20 */
> +			     12, 12, 12, 12,			/* 21 - 24 */
> +			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
> +			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
> +			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
> +			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
> +			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
> +
> +/* map the sanitized data length to an appropriate data length code */
> +u8 can_fd_len2dlc(u8 len)
> +{
> +	if (unlikely(len > 64))
> +		return 0xF;
> +
> +	return len2dlc[len];
> +}
> +EXPORT_SYMBOL_GPL(can_fd_len2dlc);
> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
> index 054c3bed190b..d75fba1d030a 100644
> --- a/include/linux/can/dev.h
> +++ b/include/linux/can/dev.h
> @@ -18,6 +18,7 @@
>   #include <linux/can/bittiming.h>
>   #include <linux/can/error.h>
>   #include <linux/can/led.h>
> +#include <linux/can/length.h>
>   #include <linux/can/netlink.h>
>   #include <linux/can/skb.h>
>   #include <linux/netdevice.h>
> @@ -83,15 +84,6 @@ struct can_priv {


(..)

> diff --git a/include/linux/can/length.h b/include/linux/can/length.h
> new file mode 100644
> index 000000000000..fabd93bcde3e
> --- /dev/null
> +++ b/include/linux/can/length.h
> @@ -0,0 +1,51 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +/*
> + * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
> + *               Varma Electronics Oy
> + * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>

The CAN FD and len8_dlc length stuff was completely contributed by myself.

So if this code is now moved to a separate file the former Copyrights 
should be replaced with

Copyright (C) 2020 Oliver Hartkopp <socketcan@hartkopp.net>

;-)

Best,
Oliver


> + */
> +
> +#ifndef _CAN_LENGTH_H
> +#define _CAN_LENGTH_H
> +
> +/*
> + * can_cc_dlc2len(value) - convert a given data length code (dlc) of a
> + * Classical CAN frame into a valid data length of max. 8 bytes.
> + *
> + * To be used in the CAN netdriver receive path to ensure conformance with
> + * ISO 11898-1 Chapter 8.4.2.3 (DLC field)
> + */
> +#define can_cc_dlc2len(dlc)	(min_t(u8, (dlc), CAN_MAX_DLEN))
> +
> +/* helper to get the data length code (DLC) for Classical CAN raw DLC access */
> +static inline u8 can_get_cc_dlc(const struct can_frame *cf, const u32 ctrlmode)
> +{
> +	/* return len8_dlc as dlc value only if all conditions apply */
> +	if ((ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC) &&
> +	    (cf->len == CAN_MAX_DLEN) &&
> +	    (cf->len8_dlc > CAN_MAX_DLEN && cf->len8_dlc <= CAN_MAX_RAW_DLC))
> +		return cf->len8_dlc;
> +
> +	/* return the payload length as dlc value */
> +	return cf->len;
> +}
> +
> +/* helper to set len and len8_dlc value for Classical CAN raw DLC access */
> +static inline void can_frame_set_cc_len(struct can_frame *cf, const u8 dlc,
> +					const u32 ctrlmode)
> +{
> +	/* the caller already ensured that dlc is a value from 0 .. 15 */
> +	if (ctrlmode & CAN_CTRLMODE_CC_LEN8_DLC && dlc > CAN_MAX_DLEN)
> +		cf->len8_dlc = dlc;
> +
> +	/* limit the payload length 'len' to CAN_MAX_DLEN */
> +	cf->len = can_cc_dlc2len(dlc);
> +}
> +
> +/* get data length from raw data length code (DLC) */
> +u8 can_fd_dlc2len(u8 dlc);
> +
> +/* map the sanitized data length to an appropriate data length code */
> +u8 can_fd_len2dlc(u8 len);
> +
> +#endif /* !_CAN_LENGTH_H */
> 

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

* Re: [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len
  2021-01-11  6:13       ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Vincent Mailhol
@ 2021-01-11  9:38         ` Marc Kleine-Budde
  2021-01-11 10:35           ` Vincent MAILHOL
  2021-01-11 10:26         ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Marc Kleine-Budde
  1 sibling, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  9:38 UTC (permalink / raw)
  To: Vincent Mailhol, linux-can; +Cc: Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1306 bytes --]

On 1/11/21 7:13 AM, Vincent Mailhol wrote:
[...]

> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> index 568dc28f7a4e..64bd2b60febc 100644
> --- a/drivers/net/can/dev/skb.c
> +++ b/drivers/net/can/dev/skb.c
> @@ -38,7 +38,7 @@ void can_flush_echo_skb(struct net_device *dev)
>   * priv->echo_skb, if necessary.
>   */
>  int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> -		     unsigned int idx)
> +		     unsigned int idx, unsigned int frame_len)
>  {
>  	struct can_priv *priv = netdev_priv(dev);
>  
> @@ -62,6 +62,10 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>  		skb->ip_summed = CHECKSUM_UNNECESSARY;
>  		skb->dev = dev;
>  
> +		/* save frame_len to reuse it when transmission is completed */
> +		if (frame_len)
> +			can_skb_prv(skb)->frame_len = frame_len;
> +

I think we can assign it unconditionally?

>  		/* save this skb for tx interrupt echo handling */
>  		priv->echo_skb[idx] = skb;
>  	} else {

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
  2021-01-11  8:26   ` Marc Kleine-Budde
@ 2021-01-11  9:42     ` Vincent MAILHOL
  2021-01-11 10:00       ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-11  9:42 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Mon. 11 Jan 2021 at 17:26, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 1/10/21 9:55 AM, Vincent MAILHOL wrote:
> [...]
>
> > Did you test it after the occurence of a can_bus_off() event?
>
> Not yet...
>
> > When the device restarts, you normally have to call
> > netdev_reset_queue(netdev) in order to reset all the BQL
> > statistics.
>
> I only included the relevant parts to illustrate the use of the changed API.
> There is a netdev_reset_queue() in mcp251xfd_ring_init(), which is called via:
> mcp251xfd_chip_start(), mcp251xfd_set_mode()

Great then! I was just worried not to see it mentioned in the
patch.

As a global comment for the series: I am done with my comments,
looking forward to the v2!


Yours sincerely,
Vincent

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

* Re: [net-next 04/13] can: dev: move length related code into seperate file
  2021-01-11  8:49   ` Oliver Hartkopp
@ 2021-01-11  9:58     ` Marc Kleine-Budde
  0 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11  9:58 UTC (permalink / raw)
  To: Oliver Hartkopp, linux-can; +Cc: Vincent Mailhol


[-- Attachment #1.1: Type: text/plain, Size: 5958 bytes --]

On 1/11/21 9:49 AM, Oliver Hartkopp wrote:
>> diff --git a/drivers/net/can/dev/length.c b/drivers/net/can/dev/length.c
>> new file mode 100644
>> index 000000000000..540d40dc0bc2
>> --- /dev/null
>> +++ b/drivers/net/can/dev/length.c
>> @@ -0,0 +1,40 @@
>> +// SPDX-License-Identifier: GPL-2.0-only
>> +/* Copyright (C) 2005 Marc Kleine-Budde, Pengutronix
>> + * Copyright (C) 2006 Andrey Volkov, Varma Electronics
>> + * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
>> + */
> 
> See comment below ...
> 
>> +
>> +#include <linux/can/dev.h>
>> +
>> +/* CAN DLC to real data length conversion helpers */
>> +
>> +static const u8 dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
>> +			     8, 12, 16, 20, 24, 32, 48, 64};
>> +
>> +/* get data length from raw data length code (DLC) */
>> +u8 can_fd_dlc2len(u8 dlc)
>> +{
>> +	return dlc2len[dlc & 0x0F];
>> +}
>> +EXPORT_SYMBOL_GPL(can_fd_dlc2len);
>> +
>> +static const u8 len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8,		/* 0 - 8 */
>> +			     9, 9, 9, 9,			/* 9 - 12 */
>> +			     10, 10, 10, 10,			/* 13 - 16 */
>> +			     11, 11, 11, 11,			/* 17 - 20 */
>> +			     12, 12, 12, 12,			/* 21 - 24 */
>> +			     13, 13, 13, 13, 13, 13, 13, 13,	/* 25 - 32 */
>> +			     14, 14, 14, 14, 14, 14, 14, 14,	/* 33 - 40 */
>> +			     14, 14, 14, 14, 14, 14, 14, 14,	/* 41 - 48 */
>> +			     15, 15, 15, 15, 15, 15, 15, 15,	/* 49 - 56 */
>> +			     15, 15, 15, 15, 15, 15, 15, 15};	/* 57 - 64 */
>> +
>> +/* map the sanitized data length to an appropriate data length code */
>> +u8 can_fd_len2dlc(u8 len)
>> +{
>> +	if (unlikely(len > 64))
>> +		return 0xF;
>> +
>> +	return len2dlc[len];
>> +}
>> +EXPORT_SYMBOL_GPL(can_fd_len2dlc);
>> diff --git a/include/linux/can/dev.h b/include/linux/can/dev.h
>> index 054c3bed190b..d75fba1d030a 100644
>> --- a/include/linux/can/dev.h
>> +++ b/include/linux/can/dev.h
>> @@ -18,6 +18,7 @@
>>   #include <linux/can/bittiming.h>
>>   #include <linux/can/error.h>
>>   #include <linux/can/led.h>
>> +#include <linux/can/length.h>
>>   #include <linux/can/netlink.h>
>>   #include <linux/can/skb.h>
>>   #include <linux/netdevice.h>
>> @@ -83,15 +84,6 @@ struct can_priv {
> 
> 
> (..)
> 
>> diff --git a/include/linux/can/length.h b/include/linux/can/length.h
>> new file mode 100644
>> index 000000000000..fabd93bcde3e
>> --- /dev/null
>> +++ b/include/linux/can/length.h
>> @@ -0,0 +1,51 @@
>> +/* SPDX-License-Identifier: GPL-2.0 */
>> +/*
>> + * Copyright (C) 2006 Andrey Volkov <avolkov@varma-el.com>
>> + *               Varma Electronics Oy
>> + * Copyright (C) 2008 Wolfgang Grandegger <wg@grandegger.com>
> 
> The CAN FD and len8_dlc length stuff was completely contributed by myself.
> 
> So if this code is now moved to a separate file the former Copyrights 
> should be replaced with
> 
> Copyright (C) 2020 Oliver Hartkopp <socketcan@hartkopp.net>

Ok. I carried the copyrights from the files I move the from forward to the new file.

For dev.c -> length.c the code was added with:

> commit 1e0625facab2e871472472b7df87d8fbe6caf75a
> Author: Oliver Hartkopp <socketcan@hartkopp.net>
> Date:   Wed Jun 13 20:48:21 2012 +0200
> 
>     candev: add/update helpers for CAN FD
>     
>     - update sanity checks
>     - add DLC to length conversion helpers
>       - can_dlc2len() - get data length from can_dlc with sanitized can_dlc
>       - can_len2dlc() - map the sanitized data length to an appropriate DLC
>     
>     Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
>     Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

and then updated with:

> commit c7b74967799b1af52b3045d69d4c26836b2d41de
> Author: Oliver Hartkopp <socketcan@hartkopp.net>
> Date:   Fri Nov 20 11:04:44 2020 +0100
> 
>     can: replace can_dlc as variable/element for payload length
>     
>     The naming of can_dlc as element of struct can_frame and also as variable
>     name is misleading as it claims to be a 'data length CODE' but in reality
>     it always was a plain data length.
>     
>     With the indroduction of a new 'len' element in struct can_frame we can now
>     remove can_dlc as name and make clear which of the former uses was a plain
>     length (-> 'len') or a data length code (-> 'dlc') value.
>     
>     Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
>     Link: https://lore.kernel.org/r/20201120100444.3199-1-socketcan@hartkopp.net
>     [mkl: gs_usb: keep struct gs_host_frame::can_dlc as is]
>     Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

> commit 3ab4ce0d6fa8c93d41df4a74ec8d2c9198be2109
> Author: Oliver Hartkopp <socketcan@hartkopp.net>
> Date:   Tue Nov 10 11:18:49 2020 +0100
> 
>     can: rename CAN FD related can_len2dlc and can_dlc2len helpers
>     
>     The helper functions can_len2dlc and can_dlc2len are only relevant for
>     CAN FD data length code (DLC) conversion.
>     
>     To fit the introduced can_cc_dlc2len for Classical CAN we rename:
>     
>     can_dlc2len -> can_fd_dlc2len to get the payload length from the DLC
>     can_len2dlc -> can_fd_len2dlc to get the DLC from the payload length
>     
>     Suggested-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
>     Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
>     Link: https://lore.kernel.org/r/20201110101852.1973-6-socketcan@hartkopp.net
>     Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>

So I'll make copyright:

Copyright (C) 2012, 2020 Oliver Hartkopp <socketcan@hartkopp.net>

The changes in dev.h -> length.h were in 2020 only, using that year only.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
  2021-01-11  9:42     ` Vincent MAILHOL
@ 2021-01-11 10:00       ` Marc Kleine-Budde
  2021-01-11 10:25         ` Vincent MAILHOL
  0 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11 10:00 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1418 bytes --]

On 1/11/21 10:42 AM, Vincent MAILHOL wrote:
> On Mon. 11 Jan 2021 at 17:26, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>>
>> On 1/10/21 9:55 AM, Vincent MAILHOL wrote:
>> [...]
>>
>>> Did you test it after the occurence of a can_bus_off() event?
>>
>> Not yet...
>>
>>> When the device restarts, you normally have to call
>>> netdev_reset_queue(netdev) in order to reset all the BQL
>>> statistics.
>>
>> I only included the relevant parts to illustrate the use of the changed API.
>> There is a netdev_reset_queue() in mcp251xfd_ring_init(), which is called via:
>> mcp251xfd_chip_start(), mcp251xfd_set_mode()
> 
> Great then! I was just worried not to see it mentioned in the
> patch.
> 
> As a global comment for the series: I am done with my comments,
> looking forward to the v2!

Can I have re-add your S-o-B for "[net-next 10/13] can: length:
can_skb_get_frame_len(): introduce function to get data length of frame in data
link layer". If you have any contact to Arunachalam Santhanam, would be good to
have his ack aswell. IMHO it's not critical, as this is based on your original
patch.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
  2021-01-11 10:00       ` Marc Kleine-Budde
@ 2021-01-11 10:25         ` Vincent MAILHOL
  2021-01-11 10:34           ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-11 10:25 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Mon. 11 Jan 2021 à 19:00, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 1/11/21 10:42 AM, Vincent MAILHOL wrote:
> > On Mon. 11 Jan 2021 at 17:26, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> >>
> >> On 1/10/21 9:55 AM, Vincent MAILHOL wrote:
> >> [...]
> >>
> >>> Did you test it after the occurence of a can_bus_off() event?
> >>
> >> Not yet...
> >>
> >>> When the device restarts, you normally have to call
> >>> netdev_reset_queue(netdev) in order to reset all the BQL
> >>> statistics.
> >>
> >> I only included the relevant parts to illustrate the use of the changed API.
> >> There is a netdev_reset_queue() in mcp251xfd_ring_init(), which is called via:
> >> mcp251xfd_chip_start(), mcp251xfd_set_mode()
> >
> > Great then! I was just worried not to see it mentioned in the
> > patch.
> >
> > As a global comment for the series: I am done with my comments,
> > looking forward to the v2!
>
> Can I have re-add your S-o-B for "[net-next 10/13] can: length:
> can_skb_get_frame_len(): introduce function to get data length of frame in data
> link layer". If you have any contact to Arunachalam Santhanam, would be good to
> have his ack aswell. IMHO it's not critical, as this is based on your original
> patch.

I am not fully familiar with the process and I was thinking to
sign it off once all comments were addressed. But if you want to
directly add the sign-off-by in the v2 then yes, go ahead!

I also discussed previously with Arunachalam. He also
acknowledges the changes. So no problem to add his sign
off. Please let me know if he needs to send a message to the
mailing list.


Yours sincerely,
Vincent

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

* Re: [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len
  2021-01-11  6:13       ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Vincent Mailhol
  2021-01-11  9:38         ` Marc Kleine-Budde
@ 2021-01-11 10:26         ` Marc Kleine-Budde
  1 sibling, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11 10:26 UTC (permalink / raw)
  To: Vincent Mailhol, linux-can; +Cc: Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1374 bytes --]

On 1/11/21 7:13 AM, Vincent Mailhol wrote:
> Add a frame_len argument to can_put_echo_skb() which is used to save
> length of the CAN frame into field frame_len of struct can_skb_priv so
> that it can be later used after transmission completion. Convert all
> users of this function, too.
> 
> Drivers which implement BQL call can_put_echo_skb() with the output of
> can_skb_get_frame_len(skb) and drivers which do not simply pass zero
> as an input (in the same way that NULL would be given to
> can_get_echo_skb()). This way, we have a nice symmetry between the two
> echo functions.
> 
> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> --
> Hi Marc,
> 
> If you like the idea to modify can_put_echo_skb(), you can use this
> patch. Just put it between patches 12 and 13 of your series.

Applied.

Fixed the m_can driver aswell.

Assigned "frame_len" in can_put_echo_skb() unconditionally.

Changed the order so that is is applied before the get_echo_skb patch, although
no-one is using the added variable, it's nicer from the logical point of view.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [net-next 00/13] can: dev: cleanup and add CAN frame length handling support
  2021-01-11 10:25         ` Vincent MAILHOL
@ 2021-01-11 10:34           ` Marc Kleine-Budde
  0 siblings, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11 10:34 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1616 bytes --]

On 1/11/21 11:25 AM, Vincent MAILHOL wrote:
>> Can I have re-add your S-o-B for "[net-next 10/13] can: length:
>> can_skb_get_frame_len(): introduce function to get data length of frame in data
>> link layer". If you have any contact to Arunachalam Santhanam, would be good to
>> have his ack aswell. IMHO it's not critical, as this is based on your original
>> patch.
> 
> I am not fully familiar with the process and I was thinking to
> sign it off once all comments were addressed. But if you want to
> directly add the sign-off-by in the v2 then yes, go ahead!

Signed-off means that it's a open source patch:

>> The sign-off is a simple line at the end of the explanation for the
>> patch, which certifies that you wrote it or otherwise have the right to
>> pass it on as an open-source patch.

For details see:

https://elixir.bootlin.com/linux/v5.10/source/Documentation/process/submitting-patches.rst#L361

An OK "once all comments were addressed" is a Acked-by or a Reviewed-by.

> I also discussed previously with Arunachalam. He also
> acknowledges the changes. So no problem to add his sign
> off. Please let me know if he needs to send a message to the
> mailing list.

Anyhow, I'll send the patch, as is, without your S-o-b and you can both reply
and give ne S-o-b and Acked-by :)

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len
  2021-01-11  9:38         ` Marc Kleine-Budde
@ 2021-01-11 10:35           ` Vincent MAILHOL
  2021-01-11 10:36             ` Marc Kleine-Budde
  2021-01-11 10:41             ` [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length Vincent Mailhol
  0 siblings, 2 replies; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-11 10:35 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Mon. 11 Jan 2021 at 18:38, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 1/11/21 7:13 AM, Vincent Mailhol wrote:
> [...]
>
> > diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
> > index 568dc28f7a4e..64bd2b60febc 100644
> > --- a/drivers/net/can/dev/skb.c
> > +++ b/drivers/net/can/dev/skb.c
> > @@ -38,7 +38,7 @@ void can_flush_echo_skb(struct net_device *dev)
> >   * priv->echo_skb, if necessary.
> >   */
> >  int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> > -                  unsigned int idx)
> > +                  unsigned int idx, unsigned int frame_len)
> >  {
> >       struct can_priv *priv = netdev_priv(dev);
> >
> > @@ -62,6 +62,10 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
> >               skb->ip_summed = CHECKSUM_UNNECESSARY;
> >               skb->dev = dev;
> >
> > +             /* save frame_len to reuse it when transmission is completed */
> > +             if (frame_len)
> > +                     can_skb_prv(skb)->frame_len = frame_len;
> > +
>
> I think we can assign it unconditionally?

Ack, I prepare the v2 right away and post it in answer to this
message.

Will also rename the patch subject from
"can: dev: extend can_put_echo_skb() to handle frame_len"
to
"can: dev: can_put_echo_skb(): extend to store can frame length".

This way the name is more aligned with your patch "can: dev:
can_get_echo_skb(): extend to return can frame length".


Yours sincerely,
Vincent

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

* Re: [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len
  2021-01-11 10:35           ` Vincent MAILHOL
@ 2021-01-11 10:36             ` Marc Kleine-Budde
  2021-01-11 10:41             ` [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length Vincent Mailhol
  1 sibling, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11 10:36 UTC (permalink / raw)
  To: Vincent MAILHOL; +Cc: linux-can, Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1888 bytes --]

On 1/11/21 11:35 AM, Vincent MAILHOL wrote:
> On Mon. 11 Jan 2021 at 18:38, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>>
>> On 1/11/21 7:13 AM, Vincent Mailhol wrote:
>> [...]
>>
>>> diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
>>> index 568dc28f7a4e..64bd2b60febc 100644
>>> --- a/drivers/net/can/dev/skb.c
>>> +++ b/drivers/net/can/dev/skb.c
>>> @@ -38,7 +38,7 @@ void can_flush_echo_skb(struct net_device *dev)
>>>   * priv->echo_skb, if necessary.
>>>   */
>>>  int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>>> -                  unsigned int idx)
>>> +                  unsigned int idx, unsigned int frame_len)
>>>  {
>>>       struct can_priv *priv = netdev_priv(dev);
>>>
>>> @@ -62,6 +62,10 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
>>>               skb->ip_summed = CHECKSUM_UNNECESSARY;
>>>               skb->dev = dev;
>>>
>>> +             /* save frame_len to reuse it when transmission is completed */
>>> +             if (frame_len)
>>> +                     can_skb_prv(skb)->frame_len = frame_len;
>>> +
>>
>> I think we can assign it unconditionally?
> 
> Ack, I prepare the v2 right away and post it in answer to this
> message.
> 
> Will also rename the patch subject from
> "can: dev: extend can_put_echo_skb() to handle frame_len"
> to
> "can: dev: can_put_echo_skb(): extend to store can frame length".
> 
> This way the name is more aligned with your patch "can: dev:
> can_get_echo_skb(): extend to return can frame length".

no need to - I'll send v2 in a sec.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length
  2021-01-11 10:35           ` Vincent MAILHOL
  2021-01-11 10:36             ` Marc Kleine-Budde
@ 2021-01-11 10:41             ` Vincent Mailhol
  2021-01-11 10:54               ` Marc Kleine-Budde
  1 sibling, 1 reply; 40+ messages in thread
From: Vincent Mailhol @ 2021-01-11 10:41 UTC (permalink / raw)
  To: Marc Kleine-Budde, linux-can; +Cc: Oliver Hartkopp, Vincent Mailhol

Add a frame_len argument to can_put_echo_skb() which is used to save
length of the CAN frame into field frame_len of struct can_skb_priv so
that it can be later used after transmission completion. Convert all
users of this function, too.

Drivers which implement BQL call can_put_echo_skb() with the output of
can_skb_get_frame_len(skb) and drivers which do not simply pass zero
as an input (in the same way that NULL would be given to
can_get_echo_skb()). This way, we have a nice symmetry between the two
echo functions.

Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
--
v2: make the assignemend unconditional.

Hi Marc,

If you like the idea to modify can_put_echo_skb(), you can use this
patch. Just put it between patches 12 and 13 of your series.

Yours sincerely,
Vincent Mailhol
---
 drivers/net/can/at91_can.c                       | 2 +-
 drivers/net/can/c_can/c_can.c                    | 2 +-
 drivers/net/can/cc770/cc770.c                    | 2 +-
 drivers/net/can/dev/skb.c                        | 5 ++++-
 drivers/net/can/flexcan.c                        | 2 +-
 drivers/net/can/grcan.c                          | 2 +-
 drivers/net/can/ifi_canfd/ifi_canfd.c            | 2 +-
 drivers/net/can/kvaser_pciefd.c                  | 2 +-
 drivers/net/can/m_can/m_can.c                    | 2 +-
 drivers/net/can/mscan/mscan.c                    | 2 +-
 drivers/net/can/pch_can.c                        | 2 +-
 drivers/net/can/peak_canfd/peak_canfd.c          | 2 +-
 drivers/net/can/rcar/rcar_can.c                  | 2 +-
 drivers/net/can/rcar/rcar_canfd.c                | 2 +-
 drivers/net/can/sja1000/sja1000.c                | 2 +-
 drivers/net/can/softing/softing_main.c           | 2 +-
 drivers/net/can/spi/hi311x.c                     | 2 +-
 drivers/net/can/spi/mcp251x.c                    | 2 +-
 drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c   | 2 +-
 drivers/net/can/sun4i_can.c                      | 2 +-
 drivers/net/can/ti_hecc.c                        | 2 +-
 drivers/net/can/usb/ems_usb.c                    | 2 +-
 drivers/net/can/usb/esd_usb2.c                   | 2 +-
 drivers/net/can/usb/gs_usb.c                     | 2 +-
 drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c | 2 +-
 drivers/net/can/usb/mcba_usb.c                   | 2 +-
 drivers/net/can/usb/peak_usb/pcan_usb_core.c     | 2 +-
 drivers/net/can/usb/ucan.c                       | 2 +-
 drivers/net/can/usb/usb_8dev.c                   | 2 +-
 drivers/net/can/xilinx_can.c                     | 4 ++--
 include/linux/can/skb.h                          | 2 +-
 31 files changed, 35 insertions(+), 32 deletions(-)

diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index ae015ec227d4..9ad9b39f480e 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -484,7 +484,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	stats->tx_bytes += cf->len;
 
 	/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
-	can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv));
+	can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv), 0);
 
 	/*
 	 * we have to stop the queue and deliver all messages in case
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index e7ee60b2c76b..ef474bae47a1 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -476,7 +476,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
 	 */
 	c_can_setup_tx_object(dev, IF_TX, frame, idx);
 	priv->dlc[idx] = frame->len;
-	can_put_echo_skb(skb, dev, idx);
+	can_put_echo_skb(skb, dev, idx, 0);
 
 	/* Update the active bits */
 	atomic_add((1 << idx), &priv->tx_active);
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index 5ecb2afd6bbf..f8a130f594e2 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -702,7 +702,7 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
 	stats->tx_bytes += cf->len;
 	stats->tx_packets++;
 
-	can_put_echo_skb(priv->tx_skb, dev, 0);
+	can_put_echo_skb(priv->tx_skb, dev, 0, 0);
 	can_get_echo_skb(dev, 0, NULL);
 	priv->tx_skb = NULL;
 
diff --git a/drivers/net/can/dev/skb.c b/drivers/net/can/dev/skb.c
index 568dc28f7a4e..53683d4312f1 100644
--- a/drivers/net/can/dev/skb.c
+++ b/drivers/net/can/dev/skb.c
@@ -38,7 +38,7 @@ void can_flush_echo_skb(struct net_device *dev)
  * priv->echo_skb, if necessary.
  */
 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
-		     unsigned int idx)
+		     unsigned int idx, unsigned int frame_len)
 {
 	struct can_priv *priv = netdev_priv(dev);
 
@@ -62,6 +62,9 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
 		skb->dev = dev;
 
+		/* save frame_len to reuse it when transmission is completed */
+		can_skb_prv(skb)->frame_len = frame_len;
+
 		/* save this skb for tx interrupt echo handling */
 		priv->echo_skb[idx] = skb;
 	} else {
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 038fe1036df2..5e51e040ea09 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -776,7 +776,7 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de
 		priv->write(data, &priv->tx_mb->data[i / sizeof(u32)]);
 	}
 
-	can_put_echo_skb(skb, dev, 0);
+	can_put_echo_skb(skb, dev, 0, 0);
 
 	priv->write(can_id, &priv->tx_mb->can_id);
 	priv->write(ctrl, &priv->tx_mb->can_ctrl);
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index 6aaebbcb7e76..4a8453290530 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1448,7 +1448,7 @@ static netdev_tx_t grcan_start_xmit(struct sk_buff *skb,
 	 * taken.
 	 */
 	priv->txdlc[slotindex] = cf->len; /* Store dlc for statistics */
-	can_put_echo_skb(skb, dev, slotindex);
+	can_put_echo_skb(skb, dev, slotindex, 0);
 
 	/* Make sure everything is written before allowing hardware to
 	 * read from the memory
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index b3ec32f60e67..5bb957a26bc6 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -922,7 +922,7 @@ static netdev_tx_t ifi_canfd_start_xmit(struct sk_buff *skb,
 	writel(0, priv->base + IFI_CANFD_TXFIFO_REPEATCOUNT);
 	writel(0, priv->base + IFI_CANFD_TXFIFO_SUSPEND_US);
 
-	can_put_echo_skb(skb, ndev, 0);
+	can_put_echo_skb(skb, ndev, 0, 0);
 
 	/* Start the transmission */
 	writel(IFI_CANFD_TXSTCMD_ADD_MSG, priv->base + IFI_CANFD_TXSTCMD);
diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c
index 6602791b3b81..37e05010ca91 100644
--- a/drivers/net/can/kvaser_pciefd.c
+++ b/drivers/net/can/kvaser_pciefd.c
@@ -778,7 +778,7 @@ static netdev_tx_t kvaser_pciefd_start_xmit(struct sk_buff *skb,
 	spin_lock_irqsave(&can->echo_lock, irq_flags);
 
 	/* Prepare and save echo skb in internal slot */
-	can_put_echo_skb(skb, netdev, can->echo_idx);
+	can_put_echo_skb(skb, netdev, can->echo_idx, 0);
 
 	/* Move echo index to the next slot */
 	can->echo_idx = (can->echo_idx + 1) % can->can.echo_skb_max;
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 262ca98cc2b1..8c71b3a5a27b 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -1483,7 +1483,7 @@ static netdev_tx_t m_can_tx_handler(struct m_can_classdev *cdev)
 					 M_CAN_FIFO_DATA(i / 4),
 					 *(u32 *)(cf->data + i));
 
-		can_put_echo_skb(skb, dev, 0);
+		can_put_echo_skb(skb, dev, 0, 0);
 
 		if (cdev->can.ctrlmode & CAN_CTRLMODE_FD) {
 			cccr = m_can_read(cdev, M_CAN_CCCR);
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c
index 6caa89fe7184..fa32e418eb29 100644
--- a/drivers/net/can/mscan/mscan.c
+++ b/drivers/net/can/mscan/mscan.c
@@ -270,7 +270,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
 	list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head);
 
-	can_put_echo_skb(skb, dev, buf_id);
+	can_put_echo_skb(skb, dev, buf_id, 0);
 
 	/* Enable interrupt. */
 	priv->tx_active |= 1 << buf_id;
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 6faadac983b6..92a54a5fd4c5 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -924,7 +924,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
 			  &priv->regs->ifregs[1].data[i / 2]);
 	}
 
-	can_put_echo_skb(skb, ndev, tx_obj_no - PCH_RX_OBJ_END - 1);
+	can_put_echo_skb(skb, ndev, tx_obj_no - PCH_RX_OBJ_END - 1, 0);
 
 	/* Set the size of the data. Update if2_mcont */
 	iowrite32(cf->len | PCH_IF_MCONT_NEWDAT | PCH_IF_MCONT_TXRQXT |
diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c
index 86df3b2b701a..00847cbaf7b6 100644
--- a/drivers/net/can/peak_canfd/peak_canfd.c
+++ b/drivers/net/can/peak_canfd/peak_canfd.c
@@ -716,7 +716,7 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
 	spin_lock_irqsave(&priv->echo_lock, flags);
 
 	/* prepare and save echo skb in internal slot */
-	can_put_echo_skb(skb, ndev, priv->echo_idx);
+	can_put_echo_skb(skb, ndev, priv->echo_idx, 0);
 
 	/* move echo index to the next slot */
 	priv->echo_idx = (priv->echo_idx + 1) % priv->can.echo_skb_max;
diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c
index ae76ea3ae0e6..4870c4ea190a 100644
--- a/drivers/net/can/rcar/rcar_can.c
+++ b/drivers/net/can/rcar/rcar_can.c
@@ -617,7 +617,7 @@ static netdev_tx_t rcar_can_start_xmit(struct sk_buff *skb,
 	writeb(cf->len, &priv->regs->mb[RCAR_CAN_TX_FIFO_MBX].dlc);
 
 	priv->tx_dlc[priv->tx_head % RCAR_CAN_FIFO_DEPTH] = cf->len;
-	can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH);
+	can_put_echo_skb(skb, ndev, priv->tx_head % RCAR_CAN_FIFO_DEPTH, 0);
 	priv->tx_head++;
 	/* Start Tx: write 0xff to the TFPCR register to increment
 	 * the CPU-side pointer for the transmit FIFO to the next
diff --git a/drivers/net/can/rcar/rcar_canfd.c b/drivers/net/can/rcar/rcar_canfd.c
index ba658664e7ee..d8d233e62990 100644
--- a/drivers/net/can/rcar/rcar_canfd.c
+++ b/drivers/net/can/rcar/rcar_canfd.c
@@ -1390,7 +1390,7 @@ static netdev_tx_t rcar_canfd_start_xmit(struct sk_buff *skb,
 	}
 
 	priv->tx_len[priv->tx_head % RCANFD_FIFO_DEPTH] = cf->len;
-	can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH);
+	can_put_echo_skb(skb, ndev, priv->tx_head % RCANFD_FIFO_DEPTH, 0);
 
 	spin_lock_irqsave(&priv->tx_lock, flags);
 	priv->tx_head++;
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index ded7dacaecd1..9e86488ba55f 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -318,7 +318,7 @@ static netdev_tx_t sja1000_start_xmit(struct sk_buff *skb,
 	for (i = 0; i < cf->len; i++)
 		priv->write_reg(priv, dreg++, cf->data[i]);
 
-	can_put_echo_skb(skb, dev, 0);
+	can_put_echo_skb(skb, dev, 0, 0);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
 		cmd_reg_val |= CMD_AT;
diff --git a/drivers/net/can/softing/softing_main.c b/drivers/net/can/softing/softing_main.c
index 583e1246ac92..c44f3411e561 100644
--- a/drivers/net/can/softing/softing_main.c
+++ b/drivers/net/can/softing/softing_main.c
@@ -104,7 +104,7 @@ static netdev_tx_t softing_netdev_start_xmit(struct sk_buff *skb,
 	card->tx.last_bus = priv->index;
 	++card->tx.pending;
 	++priv->tx.pending;
-	can_put_echo_skb(skb, dev, priv->tx.echo_put);
+	can_put_echo_skb(skb, dev, priv->tx.echo_put, 0);
 	++priv->tx.echo_put;
 	if (priv->tx.echo_put >= TX_ECHO_SKB_MAX)
 		priv->tx.echo_put = 0;
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index c1358826074f..c3e020c90111 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -586,7 +586,7 @@ static void hi3110_tx_work_handler(struct work_struct *ws)
 			frame = (struct can_frame *)priv->tx_skb->data;
 			hi3110_hw_tx(spi, frame);
 			priv->tx_len = 1 + frame->len;
-			can_put_echo_skb(priv->tx_skb, net, 0);
+			can_put_echo_skb(priv->tx_skb, net, 0, 0);
 			priv->tx_skb = NULL;
 		}
 	}
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index 114ac4c303b6..f69fb4238a65 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1002,7 +1002,7 @@ static void mcp251x_tx_work_handler(struct work_struct *ws)
 				frame->len = CAN_FRAME_MAX_DATA_LEN;
 			mcp251x_hw_tx(spi, frame, 0);
 			priv->tx_len = 1 + frame->len;
-			can_put_echo_skb(priv->tx_skb, net, 0);
+			can_put_echo_skb(priv->tx_skb, net, 0, 0);
 			priv->tx_skb = NULL;
 		}
 	}
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
index 77129d5f410b..978f29d624db 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
@@ -2437,7 +2437,7 @@ static netdev_tx_t mcp251xfd_start_xmit(struct sk_buff *skb,
 	if (tx_ring->head - tx_ring->tail >= tx_ring->obj_num)
 		netif_stop_queue(ndev);
 
-	can_put_echo_skb(skb, ndev, tx_head);
+	can_put_echo_skb(skb, ndev, tx_head, 0);
 
 	err = mcp251xfd_tx_obj_write(priv, tx_obj);
 	if (err)
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index faabfe74c19e..54aa7c25c4de 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -448,7 +448,7 @@ static netdev_tx_t sun4ican_start_xmit(struct sk_buff *skb, struct net_device *d
 
 	writel(msg_flag_n, priv->base + SUN4I_REG_BUF0_ADDR);
 
-	can_put_echo_skb(skb, dev, 0);
+	can_put_echo_skb(skb, dev, 0, 0);
 
 	if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
 		sun4i_can_write_cmdreg(priv, SUN4I_CMD_SELF_RCV_REQ);
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index a6850ff0b55b..485c19bc98c2 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -513,7 +513,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev)
 			       be32_to_cpu(*(__be32 *)(cf->data + 4)));
 	else
 		*(u32 *)(cf->data + 4) = 0;
-	can_put_echo_skb(skb, ndev, mbxno);
+	can_put_echo_skb(skb, ndev, mbxno, 0);
 
 	spin_lock_irqsave(&priv->mbx_lock, flags);
 	--priv->tx_head;
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index d27567139935..18f40eb20360 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -801,7 +801,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &dev->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&dev->active_tx_urbs);
 
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index 4f653e221a5b..562acbf454fd 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -783,7 +783,7 @@ static netdev_tx_t esd_usb2_start_xmit(struct sk_buff *skb,
 
 	usb_anchor_urb(urb, &priv->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&priv->active_tx_jobs);
 
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 992a511bcd95..a00dc1904415 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -525,7 +525,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &dev->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, idx);
+	can_put_echo_skb(skb, netdev, idx, 0);
 
 	atomic_inc(&dev->active_tx_urbs);
 
diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
index e2d58846c40c..2b7efd296758 100644
--- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
+++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c
@@ -578,7 +578,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
 
 	context->priv = priv;
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	usb_fill_bulk_urb(urb, dev->udev,
 			  usb_sndbulkpipe(dev->udev,
diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c
index 23cec88aafc3..4232a7126c1b 100644
--- a/drivers/net/can/usb/mcba_usb.c
+++ b/drivers/net/can/usb/mcba_usb.c
@@ -355,7 +355,7 @@ static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
 	if (cf->can_id & CAN_RTR_FLAG)
 		usb_msg.dlc |= MCBA_DLC_RTR_MASK;
 
-	can_put_echo_skb(skb, priv->netdev, ctx->ndx);
+	can_put_echo_skb(skb, priv->netdev, ctx->ndx, 0);
 
 	err = mcba_usb_xmit(priv, (struct mcba_usb_msg *)&usb_msg, ctx);
 	if (err)
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
index 6a97c29e25e7..573b11559d73 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c
@@ -365,7 +365,7 @@ static netdev_tx_t peak_usb_ndo_start_xmit(struct sk_buff *skb,
 
 	usb_anchor_urb(urb, &dev->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&dev->active_tx_urbs);
 
diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c
index cceb142afc3e..fa403c080871 100644
--- a/drivers/net/can/usb/ucan.c
+++ b/drivers/net/can/usb/ucan.c
@@ -1137,7 +1137,7 @@ static netdev_tx_t ucan_start_xmit(struct sk_buff *skb,
 
 	/* put the skb on can loopback stack */
 	spin_lock_irqsave(&up->echo_skb_lock, flags);
-	can_put_echo_skb(skb, up->netdev, echo_index);
+	can_put_echo_skb(skb, up->netdev, echo_index, 0);
 	spin_unlock_irqrestore(&up->echo_skb_lock, flags);
 
 	/* transmit it */
diff --git a/drivers/net/can/usb/usb_8dev.c b/drivers/net/can/usb/usb_8dev.c
index e16efdbb8f39..e8c42430a4fc 100644
--- a/drivers/net/can/usb/usb_8dev.c
+++ b/drivers/net/can/usb/usb_8dev.c
@@ -664,7 +664,7 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
 	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 	usb_anchor_urb(urb, &priv->tx_submitted);
 
-	can_put_echo_skb(skb, netdev, context->echo_index);
+	can_put_echo_skb(skb, netdev, context->echo_index, 0);
 
 	atomic_inc(&priv->active_tx_urbs);
 
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 7cda3d64cc05..37fa19c62d73 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -592,9 +592,9 @@ static void xcan_write_frame(struct net_device *ndev, struct sk_buff *skb,
 
 	if (!(priv->devtype.flags & XCAN_FLAG_TX_MAILBOXES) &&
 	    (priv->devtype.flags & XCAN_FLAG_TXFEMP))
-		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max);
+		can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max, 0);
 	else
-		can_put_echo_skb(skb, ndev, 0);
+		can_put_echo_skb(skb, ndev, 0, 0);
 
 	priv->tx_head++;
 
diff --git a/include/linux/can/skb.h b/include/linux/can/skb.h
index 3296e2144d5a..685f34cfba20 100644
--- a/include/linux/can/skb.h
+++ b/include/linux/can/skb.h
@@ -18,7 +18,7 @@
 
 void can_flush_echo_skb(struct net_device *dev);
 int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
-		     unsigned int idx);
+		     unsigned int idx, unsigned int frame_len);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx,
 				   u8 *len_ptr, unsigned int *frame_len_ptr);
 unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx,
-- 
2.26.2


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

* Re: [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length
  2021-01-11 10:41             ` [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length Vincent Mailhol
@ 2021-01-11 10:54               ` Marc Kleine-Budde
  2021-01-11 12:43                 ` Vincent MAILHOL
  0 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2021-01-11 10:54 UTC (permalink / raw)
  To: Vincent Mailhol, linux-can; +Cc: Oliver Hartkopp


[-- Attachment #1.1: Type: text/plain, Size: 1274 bytes --]

On 1/11/21 11:41 AM, Vincent Mailhol wrote:
> Add a frame_len argument to can_put_echo_skb() which is used to save
> length of the CAN frame into field frame_len of struct can_skb_priv so
> that it can be later used after transmission completion. Convert all
> users of this function, too.
> 
> Drivers which implement BQL call can_put_echo_skb() with the output of
> can_skb_get_frame_len(skb) and drivers which do not simply pass zero
> as an input (in the same way that NULL would be given to
> can_get_echo_skb()). This way, we have a nice symmetry between the two
> echo functions.
> 
> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> --
> v2: make the assignemend unconditional.
> 
> Hi Marc,
> 
> If you like the idea to modify can_put_echo_skb(), you can use this
> patch. Just put it between patches 12 and 13 of your series.

I think I've done the same changes, why applying. The series I just send is
based on your v1 with my changes.

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: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length
  2021-01-11 10:54               ` Marc Kleine-Budde
@ 2021-01-11 12:43                 ` Vincent MAILHOL
  0 siblings, 0 replies; 40+ messages in thread
From: Vincent MAILHOL @ 2021-01-11 12:43 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: linux-can, Oliver Hartkopp

On Mon. 11 Jan 2021 at 19:54, Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 1/11/21 11:41 AM, Vincent Mailhol wrote:
> > Add a frame_len argument to can_put_echo_skb() which is used to save
> > length of the CAN frame into field frame_len of struct can_skb_priv so
> > that it can be later used after transmission completion. Convert all
> > users of this function, too.
> >
> > Drivers which implement BQL call can_put_echo_skb() with the output of
> > can_skb_get_frame_len(skb) and drivers which do not simply pass zero
> > as an input (in the same way that NULL would be given to
> > can_get_echo_skb()). This way, we have a nice symmetry between the two
> > echo functions.
> >
> > Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> > --
> > v2: make the assignemend unconditional.
> >
> > Hi Marc,
> >
> > If you like the idea to modify can_put_echo_skb(), you can use this
> > patch. Just put it between patches 12 and 13 of your series.
>
> I think I've done the same changes, why applying. The series I just send is
> based on your v1 with my changes.

No problem, I just missed your message saying that you will do
the changes.

The only difference is the change in the patch subject but that's
really a minor detail. The content is the same.


Yours sincerely,
Vincent

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

end of thread, other threads:[~2021-01-11 12:44 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-09 17:40 [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 01/13] MAINTAINERS: CAN network layer: add missing header file can-ml.h Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 02/13] can: dev: move driver related infrastructure into separate subdir Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 03/13] can: dev: move bittiming related code into seperate file Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 04/13] can: dev: move length " Marc Kleine-Budde
2021-01-11  8:49   ` Oliver Hartkopp
2021-01-11  9:58     ` Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 05/13] can: dev: move skb related " Marc Kleine-Budde
2021-01-10  4:26   ` Vincent MAILHOL
2021-01-11  8:14     ` Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 06/13] can: dev: move netlink related code " Marc Kleine-Budde
2021-01-10  4:27   ` Vincent MAILHOL
2021-01-11  8:17     ` Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 07/13] can: length: convert to kernel coding style Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 08/13] can: length: can_fd_len2dlc(): simplify length calculcation Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 09/13] can: length: canfd_sanitize_len(): add function to sanitize CAN-FD data length Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 10/13] can: length: can_skb_get_frame_len(): introduce function to get data length of frame in data link layer Marc Kleine-Budde
2021-01-10  3:32   ` Vincent MAILHOL
2021-01-11  8:12     ` Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
2021-01-10  6:52   ` Vincent MAILHOL
2021-01-10  8:38     ` Vincent MAILHOL
2021-01-11  6:13       ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Vincent Mailhol
2021-01-11  9:38         ` Marc Kleine-Budde
2021-01-11 10:35           ` Vincent MAILHOL
2021-01-11 10:36             ` Marc Kleine-Budde
2021-01-11 10:41             ` [PATCH v2] can: dev: can_put_echo_skb(): extend to store can frame length Vincent Mailhol
2021-01-11 10:54               ` Marc Kleine-Budde
2021-01-11 12:43                 ` Vincent MAILHOL
2021-01-11 10:26         ` [PATCH] can: dev: extend can_put_echo_skb() to handle frame_len Marc Kleine-Budde
2021-01-11  8:22     ` [net-next 11/13] can: dev: extend struct can_skb_priv to hold CAN frame length Marc Kleine-Budde
2021-01-11  8:29       ` Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 12/13] can: dev: can_get_echo_skb(): extend to return can " Marc Kleine-Budde
2021-01-09 17:40 ` [net-next 13/13] can: dev: can_rx_offload_get_echo_skb(): " Marc Kleine-Budde
2021-01-10  8:55 ` [net-next 00/13] can: dev: cleanup and add CAN frame length handling support Vincent MAILHOL
2021-01-11  8:26   ` Marc Kleine-Budde
2021-01-11  9:42     ` Vincent MAILHOL
2021-01-11 10:00       ` Marc Kleine-Budde
2021-01-11 10:25         ` Vincent MAILHOL
2021-01-11 10:34           ` Marc Kleine-Budde

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.