All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 00/13] can: slcan: extend supported features
@ 2022-06-12 21:39 Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 01/13] can: slcan: use the BIT() helper Dario Binacchi
                   ` (12 more replies)
  0 siblings, 13 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Marc Kleine-Budde, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

This series originated as a result of CAN communication tests for an
application using the USBtin adapter (https://www.fischl.de/usbtin/).
The tests showed some errors but for the driver everything was ok.
Also, being the first time I used the slcan driver, I was amazed that
it was not possible to configure the bitrate via the ip tool.
For these two reasons, I started looking at the driver code and realized
that it didn't use the CAN network device driver interface.

Starting from these assumptions, I tried to:
- Use the CAN network device driver interface.
- Set the bitrate via the ip tool.
- Send the open/close command to the adapter from the driver.
- Add ethtool support to reset the adapter errors.
- Extend the protocol to forward the adapter CAN communication
  errors and the CAN state changes to the netdev upper layers.

Except for the protocol extension patches (i. e. forward the adapter CAN
communication errors and the CAN state changes to the netdev upper
layers), the whole series has been tested under QEMU with Linux 4.19.208
using the USBtin adapter.
Testing the extension protocol patches requires updating the adapter
firmware. Before modifying the firmware I think it makes sense to know if
these extensions can be considered useful.

Before applying the series I used these commands:

slcan_attach -f -s6 -o /dev/ttyACM0
slcand ttyACM0 can0
ip link set can0 up

After applying the series I am using these commands:

slcan_attach /dev/ttyACM0
slcand ttyACM0 can0
ip link set dev can0 down
ip link set can0 type can bitrate 500000
ethtool --set-priv-flags can0 err-rst-on-open on
ip link set dev can0 up

Now there is a clearer separation between serial line and CAN,
but above all, it is possible to use the ip and ethtool commands
as it happens for any CAN device driver. The changes are backward
compatible, you can continue to use the slcand and slcan_attach
command options.


Changes in v3:
- Increment the error counter in case of decoding failure.
- Replace (-1) with (-1U) in the commit description.
- Update the commit description.
- Remove the slc_do_set_bittiming().
- Set the bitrate in the ndo_open().
- Replace -1UL with -1U in setting a fake value for the bitrate.
- Drop the patch "can: slcan: simplify the device de-allocation".
- Add the patch "can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U".

Changes in v2:
- Put the data into the allocated skb directly instead of first
  filling the "cf" on the stack and then doing a memcpy().
- Move CAN_SLCAN Kconfig option inside CAN_DEV scope.
- Improve the commit message.
- Use the CAN framework support for setting fixed bit rates.
- Improve the commit message.
- Improve the commit message.
- Protect decoding against the case the len value is longer than the
  received data.
- Continue error handling even if no skb can be allocated.
- Continue error handling even if no skb can be allocated.

Dario Binacchi (13):
  can: slcan: use the BIT() helper
  can: slcan: use netdev helpers to print out messages
  can: slcan: use the alloc_can_skb() helper
  can: slcan: use CAN network device driver API
  can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U
  can: slcan: allow to send commands to the adapter
  can: slcan: set bitrate by CAN device driver API
  can: slcan: send the open command to the adapter
  can: slcan: send the close command to the adapter
  can: slcan: move driver into separate sub directory
  can: slcan: add ethtool support to reset adapter errors
  can: slcan: extend the protocol with error info
  can: slcan: extend the protocol with CAN state info

 drivers/net/can/Kconfig                       |  40 +-
 drivers/net/can/Makefile                      |   2 +-
 drivers/net/can/dev/netlink.c                 |  12 +-
 drivers/net/can/slcan/Makefile                |   7 +
 .../net/can/{slcan.c => slcan/slcan-core.c}   | 518 ++++++++++++++----
 drivers/net/can/slcan/slcan-ethtool.c         |  65 +++
 drivers/net/can/slcan/slcan.h                 |  18 +
 7 files changed, 541 insertions(+), 121 deletions(-)
 create mode 100644 drivers/net/can/slcan/Makefile
 rename drivers/net/can/{slcan.c => slcan/slcan-core.c} (65%)
 create mode 100644 drivers/net/can/slcan/slcan-ethtool.c
 create mode 100644 drivers/net/can/slcan/slcan.h

-- 
2.32.0


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

* [PATCH v3 01/13] can: slcan: use the BIT() helper
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 02/13] can: slcan: use netdev helpers to print out messages Dario Binacchi
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

Use the BIT() helper instead of an explicit shift.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

(no changes since v1)

 drivers/net/can/slcan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 64a3aee8a7da..b37d35c2a23a 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -413,7 +413,7 @@ static int slc_open(struct net_device *dev)
 	if (sl->tty == NULL)
 		return -ENODEV;
 
-	sl->flags &= (1 << SLF_INUSE);
+	sl->flags &= BIT(SLF_INUSE);
 	netif_start_queue(dev);
 	return 0;
 }
-- 
2.32.0


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

* [PATCH v3 02/13] can: slcan: use netdev helpers to print out messages
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 01/13] can: slcan: use the BIT() helper Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 03/13] can: slcan: use the alloc_can_skb() helper Dario Binacchi
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

Replace printk() calls with corresponding netdev helpers.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

(no changes since v1)

 drivers/net/can/slcan.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index b37d35c2a23a..6162a9c21672 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -365,7 +365,7 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
 	spin_lock(&sl->lock);
 	if (!netif_running(dev))  {
 		spin_unlock(&sl->lock);
-		printk(KERN_WARNING "%s: xmit: iface is down\n", dev->name);
+		netdev_warn(dev, "xmit: iface is down\n");
 		goto out;
 	}
 	if (sl->tty == NULL) {
@@ -776,8 +776,7 @@ static void __exit slcan_exit(void)
 
 		sl = netdev_priv(dev);
 		if (sl->tty) {
-			printk(KERN_ERR "%s: tty discipline still running\n",
-			       dev->name);
+			netdev_err(dev, "tty discipline still running\n");
 		}
 
 		unregister_netdev(dev);
-- 
2.32.0


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

* [PATCH v3 03/13] can: slcan: use the alloc_can_skb() helper
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 01/13] can: slcan: use the BIT() helper Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 02/13] can: slcan: use netdev helpers to print out messages Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 04/13] can: slcan: use CAN network device driver API Dario Binacchi
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

It is used successfully by most (if not all) CAN device drivers. It
allows to remove replicated code.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v3:
- Increment the error counter in case of decoding failure.

Changes in v2:
- Put the data into the allocated skb directly instead of first
  filling the "cf" on the stack and then doing a memcpy().

 drivers/net/can/slcan.c | 70 +++++++++++++++++++----------------------
 1 file changed, 33 insertions(+), 37 deletions(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 6162a9c21672..c39580b142e0 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -54,6 +54,7 @@
 #include <linux/kernel.h>
 #include <linux/workqueue.h>
 #include <linux/can.h>
+#include <linux/can/dev.h>
 #include <linux/can/skb.h>
 #include <linux/can/can-ml.h>
 
@@ -143,85 +144,80 @@ static struct net_device **slcan_devs;
 static void slc_bump(struct slcan *sl)
 {
 	struct sk_buff *skb;
-	struct can_frame cf;
+	struct can_frame *cf;
 	int i, tmp;
 	u32 tmpid;
 	char *cmd = sl->rbuff;
 
-	memset(&cf, 0, sizeof(cf));
+	skb = alloc_can_skb(sl->dev, &cf);
+	if (unlikely(!skb)) {
+		sl->dev->stats.rx_dropped++;
+		return;
+	}
 
 	switch (*cmd) {
 	case 'r':
-		cf.can_id = CAN_RTR_FLAG;
+		cf->can_id = CAN_RTR_FLAG;
 		fallthrough;
 	case 't':
 		/* store dlc ASCII value and terminate SFF CAN ID string */
-		cf.len = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN];
+		cf->len = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN];
 		sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN] = 0;
 		/* point to payload data behind the dlc */
 		cmd += SLC_CMD_LEN + SLC_SFF_ID_LEN + 1;
 		break;
 	case 'R':
-		cf.can_id = CAN_RTR_FLAG;
+		cf->can_id = CAN_RTR_FLAG;
 		fallthrough;
 	case 'T':
-		cf.can_id |= CAN_EFF_FLAG;
+		cf->can_id |= CAN_EFF_FLAG;
 		/* store dlc ASCII value and terminate EFF CAN ID string */
-		cf.len = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN];
+		cf->len = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN];
 		sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN] = 0;
 		/* point to payload data behind the dlc */
 		cmd += SLC_CMD_LEN + SLC_EFF_ID_LEN + 1;
 		break;
 	default:
-		return;
+		goto decode_failed;
 	}
 
 	if (kstrtou32(sl->rbuff + SLC_CMD_LEN, 16, &tmpid))
-		return;
+		goto decode_failed;
 
-	cf.can_id |= tmpid;
+	cf->can_id |= tmpid;
 
 	/* get len from sanitized ASCII value */
-	if (cf.len >= '0' && cf.len < '9')
-		cf.len -= '0';
+	if (cf->len >= '0' && cf->len < '9')
+		cf->len -= '0';
 	else
-		return;
+		goto decode_failed;
 
 	/* RTR frames may have a dlc > 0 but they never have any data bytes */
-	if (!(cf.can_id & CAN_RTR_FLAG)) {
-		for (i = 0; i < cf.len; i++) {
+	if (!(cf->can_id & CAN_RTR_FLAG)) {
+		for (i = 0; i < cf->len; i++) {
 			tmp = hex_to_bin(*cmd++);
 			if (tmp < 0)
-				return;
-			cf.data[i] = (tmp << 4);
+				goto decode_failed;
+
+			cf->data[i] = (tmp << 4);
 			tmp = hex_to_bin(*cmd++);
 			if (tmp < 0)
-				return;
-			cf.data[i] |= tmp;
+				goto decode_failed;
+
+			cf->data[i] |= tmp;
 		}
 	}
 
-	skb = dev_alloc_skb(sizeof(struct can_frame) +
-			    sizeof(struct can_skb_priv));
-	if (!skb)
-		return;
-
-	skb->dev = sl->dev;
-	skb->protocol = htons(ETH_P_CAN);
-	skb->pkt_type = PACKET_BROADCAST;
-	skb->ip_summed = CHECKSUM_UNNECESSARY;
-
-	can_skb_reserve(skb);
-	can_skb_prv(skb)->ifindex = sl->dev->ifindex;
-	can_skb_prv(skb)->skbcnt = 0;
-
-	skb_put_data(skb, &cf, sizeof(struct can_frame));
-
 	sl->dev->stats.rx_packets++;
-	if (!(cf.can_id & CAN_RTR_FLAG))
-		sl->dev->stats.rx_bytes += cf.len;
+	if (!(cf->can_id & CAN_RTR_FLAG))
+		sl->dev->stats.rx_bytes += cf->len;
 
 	netif_rx(skb);
+	return;
+
+decode_failed:
+	sl->dev->stats.rx_errors++;
+	dev_kfree_skb(skb);
 }
 
 /* parse tty input stream */
-- 
2.32.0


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

* [PATCH v3 04/13] can: slcan: use CAN network device driver API
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (2 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 03/13] can: slcan: use the alloc_can_skb() helper Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-13  7:01   ` Marc Kleine-Budde
  2022-06-12 21:39 ` [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U Dario Binacchi
                   ` (8 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

As suggested by commit [1], now the driver uses the functions and the
data structures provided by the CAN network device driver interface.

Currently the driver doesn't implement a way to set bitrate for SLCAN
based devices via ip tool, so you'll have to do this by slcand or
slcan_attach invocation through the -sX parameter:

- slcan_attach -f -s6 -o /dev/ttyACM0
- slcand -f -s8 -o /dev/ttyUSB0

where -s6 in will set adapter's bitrate to 500 Kbit/s and -s8 to
1Mbit/s.
See the table below for further CAN bitrates:
- s0 ->   10 Kbit/s
- s1 ->   20 Kbit/s
- s2 ->   50 Kbit/s
- s3 ->  100 Kbit/s
- s4 ->  125 Kbit/s
- s5 ->  250 Kbit/s
- s6 ->  500 Kbit/s
- s7 ->  800 Kbit/s
- s8 -> 1000 Kbit/s

In doing so, the struct can_priv::bittiming.bitrate of the driver is not
set and since the open_candev() checks that the bitrate has been set, it
must be a non-zero value, the bitrate is set to a fake value (-1U)
before it is called.

[1] 39549eef3587f ("can: CAN Network device driver and Netlink interface")
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v3:
- Replace (-1) with (-1U) in the commit description.

Changes in v2:
- Move CAN_SLCAN Kconfig option inside CAN_DEV scope.
- Improve the commit message.

 drivers/net/can/Kconfig |  40 +++++++-------
 drivers/net/can/slcan.c | 112 ++++++++++++++++++++--------------------
 2 files changed, 77 insertions(+), 75 deletions(-)

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index b2dcc1e5a388..45997d39621c 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -28,26 +28,6 @@ config CAN_VXCAN
 	  This driver can also be built as a module.  If so, the module
 	  will be called vxcan.
 
-config CAN_SLCAN
-	tristate "Serial / USB serial CAN Adaptors (slcan)"
-	depends on TTY
-	help
-	  CAN driver for several 'low cost' CAN interfaces that are attached
-	  via serial lines or via USB-to-serial adapters using the LAWICEL
-	  ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
-
-	  As only the sending and receiving of CAN frames is implemented, this
-	  driver should work with the (serial/USB) CAN hardware from:
-	  www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
-
-	  Userspace tools to attach the SLCAN line discipline (slcan_attach,
-	  slcand) can be found in the can-utils at the linux-can project, see
-	  https://github.com/linux-can/can-utils for details.
-
-	  The slcan driver supports up to 10 CAN netdevices by default which
-	  can be changed by the 'maxdev=xx' module option. This driver can
-	  also be built as a module. If so, the module will be called slcan.
-
 config CAN_DEV
 	tristate "Platform CAN drivers with Netlink support"
 	default y
@@ -118,6 +98,26 @@ config CAN_KVASER_PCIEFD
 	    Kvaser Mini PCI Express HS v2
 	    Kvaser Mini PCI Express 2xHS v2
 
+config CAN_SLCAN
+	tristate "Serial / USB serial CAN Adaptors (slcan)"
+	depends on TTY
+	help
+	  CAN driver for several 'low cost' CAN interfaces that are attached
+	  via serial lines or via USB-to-serial adapters using the LAWICEL
+	  ASCII protocol. The driver implements the tty linediscipline N_SLCAN.
+
+	  As only the sending and receiving of CAN frames is implemented, this
+	  driver should work with the (serial/USB) CAN hardware from:
+	  www.canusb.com / www.can232.com / www.mictronics.de / www.canhack.de
+
+	  Userspace tools to attach the SLCAN line discipline (slcan_attach,
+	  slcand) can be found in the can-utils at the linux-can project, see
+	  https://github.com/linux-can/can-utils for details.
+
+	  The slcan driver supports up to 10 CAN netdevices by default which
+	  can be changed by the 'maxdev=xx' module option. This driver can
+	  also be built as a module. If so, the module will be called slcan.
+
 config CAN_SUN4I
 	tristate "Allwinner A10 CAN controller"
 	depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index c39580b142e0..a70f930b7c3a 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -56,7 +56,6 @@
 #include <linux/can.h>
 #include <linux/can/dev.h>
 #include <linux/can/skb.h>
-#include <linux/can/can-ml.h>
 
 MODULE_ALIAS_LDISC(N_SLCAN);
 MODULE_DESCRIPTION("serial line CAN interface");
@@ -79,6 +78,7 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
 #define SLC_EFF_ID_LEN 8
 
 struct slcan {
+	struct can_priv         can;
 	int			magic;
 
 	/* Various fields. */
@@ -100,6 +100,7 @@ struct slcan {
 };
 
 static struct net_device **slcan_devs;
+static DEFINE_SPINLOCK(slcan_lock);
 
  /************************************************************************
   *			SLCAN ENCAPSULATION FORMAT			 *
@@ -374,7 +375,7 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
 	spin_unlock(&sl->lock);
 
 out:
-	kfree_skb(skb);
+	can_put_echo_skb(skb, dev, 0, 0);
 	return NETDEV_TX_OK;
 }
 
@@ -394,6 +395,8 @@ static int slc_close(struct net_device *dev)
 		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
 	}
 	netif_stop_queue(dev);
+	close_candev(dev);
+	sl->can.state = CAN_STATE_STOPPED;
 	sl->rcount   = 0;
 	sl->xleft    = 0;
 	spin_unlock_bh(&sl->lock);
@@ -405,21 +408,36 @@ static int slc_close(struct net_device *dev)
 static int slc_open(struct net_device *dev)
 {
 	struct slcan *sl = netdev_priv(dev);
+	int err;
 
 	if (sl->tty == NULL)
 		return -ENODEV;
 
+	/* The baud rate is not set with the command
+	 * `ip link set <iface> type can bitrate <baud>' and therefore
+	 * can.bittiming.bitrate is 0, causing open_candev() to fail.
+	 * So let's set to a fake value.
+	 */
+	sl->can.bittiming.bitrate = -1;
+	err = open_candev(dev);
+	if (err) {
+		netdev_err(dev, "failed to open can device\n");
+		return err;
+	}
+
+	sl->can.state = CAN_STATE_ERROR_ACTIVE;
 	sl->flags &= BIT(SLF_INUSE);
 	netif_start_queue(dev);
 	return 0;
 }
 
-/* Hook the destructor so we can free slcan devs at the right point in time */
-static void slc_free_netdev(struct net_device *dev)
+static void slc_dealloc(struct slcan *sl)
 {
-	int i = dev->base_addr;
+	int i = sl->dev->base_addr;
 
-	slcan_devs[i] = NULL;
+	free_candev(sl->dev);
+	if (slcan_devs)
+		slcan_devs[i] = NULL;
 }
 
 static int slcan_change_mtu(struct net_device *dev, int new_mtu)
@@ -434,24 +452,6 @@ static const struct net_device_ops slc_netdev_ops = {
 	.ndo_change_mtu         = slcan_change_mtu,
 };
 
-static void slc_setup(struct net_device *dev)
-{
-	dev->netdev_ops		= &slc_netdev_ops;
-	dev->needs_free_netdev	= true;
-	dev->priv_destructor	= slc_free_netdev;
-
-	dev->hard_header_len	= 0;
-	dev->addr_len		= 0;
-	dev->tx_queue_len	= 10;
-
-	dev->mtu		= CAN_MTU;
-	dev->type		= ARPHRD_CAN;
-
-	/* New-style flags. */
-	dev->flags		= IFF_NOARP;
-	dev->features           = NETIF_F_HW_CSUM;
-}
-
 /******************************************
   Routines looking at TTY side.
  ******************************************/
@@ -514,11 +514,8 @@ static void slc_sync(void)
 static struct slcan *slc_alloc(void)
 {
 	int i;
-	char name[IFNAMSIZ];
 	struct net_device *dev = NULL;
-	struct can_ml_priv *can_ml;
 	struct slcan       *sl;
-	int size;
 
 	for (i = 0; i < maxdev; i++) {
 		dev = slcan_devs[i];
@@ -531,16 +528,14 @@ static struct slcan *slc_alloc(void)
 	if (i >= maxdev)
 		return NULL;
 
-	sprintf(name, "slcan%d", i);
-	size = ALIGN(sizeof(*sl), NETDEV_ALIGN) + sizeof(struct can_ml_priv);
-	dev = alloc_netdev(size, name, NET_NAME_UNKNOWN, slc_setup);
+	dev = alloc_candev(sizeof(*sl), 1);
 	if (!dev)
 		return NULL;
 
+	snprintf(dev->name, sizeof(dev->name), "slcan%d", i);
+	dev->netdev_ops = &slc_netdev_ops;
 	dev->base_addr  = i;
 	sl = netdev_priv(dev);
-	can_ml = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN);
-	can_set_ml_priv(dev, can_ml);
 
 	/* Initialize channel control data */
 	sl->magic = SLCAN_MAGIC;
@@ -573,11 +568,7 @@ static int slcan_open(struct tty_struct *tty)
 	if (tty->ops->write == NULL)
 		return -EOPNOTSUPP;
 
-	/* RTnetlink lock is misused here to serialize concurrent
-	   opens of slcan channels. There are better ways, but it is
-	   the simplest one.
-	 */
-	rtnl_lock();
+	spin_lock(&slcan_lock);
 
 	/* Collect hanged up channels. */
 	slc_sync();
@@ -605,13 +596,15 @@ static int slcan_open(struct tty_struct *tty)
 
 		set_bit(SLF_INUSE, &sl->flags);
 
-		err = register_netdevice(sl->dev);
-		if (err)
+		err = register_candev(sl->dev);
+		if (err) {
+			pr_err("slcan: can't register candev\n");
 			goto err_free_chan;
+		}
 	}
 
 	/* Done.  We have linked the TTY line to a channel. */
-	rtnl_unlock();
+	spin_unlock(&slcan_lock);
 	tty->receive_room = 65536;	/* We don't flow control */
 
 	/* TTY layer expects 0 on success */
@@ -621,14 +614,10 @@ static int slcan_open(struct tty_struct *tty)
 	sl->tty = NULL;
 	tty->disc_data = NULL;
 	clear_bit(SLF_INUSE, &sl->flags);
-	slc_free_netdev(sl->dev);
-	/* do not call free_netdev before rtnl_unlock */
-	rtnl_unlock();
-	free_netdev(sl->dev);
-	return err;
+	slc_dealloc(sl);
 
 err_exit:
-	rtnl_unlock();
+	spin_unlock(&slcan_lock);
 
 	/* Count references from TTY module */
 	return err;
@@ -658,9 +647,11 @@ static void slcan_close(struct tty_struct *tty)
 	synchronize_rcu();
 	flush_work(&sl->tx_work);
 
-	/* Flush network side */
-	unregister_netdev(sl->dev);
-	/* This will complete via sl_free_netdev */
+	slc_close(sl->dev);
+	unregister_candev(sl->dev);
+	spin_lock(&slcan_lock);
+	slc_dealloc(sl);
+	spin_unlock(&slcan_lock);
 }
 
 static void slcan_hangup(struct tty_struct *tty)
@@ -768,18 +759,29 @@ static void __exit slcan_exit(void)
 		dev = slcan_devs[i];
 		if (!dev)
 			continue;
-		slcan_devs[i] = NULL;
 
-		sl = netdev_priv(dev);
-		if (sl->tty) {
-			netdev_err(dev, "tty discipline still running\n");
-		}
+		spin_lock(&slcan_lock);
+		dev = slcan_devs[i];
+		if (dev) {
+			slcan_devs[i] = NULL;
+			spin_unlock(&slcan_lock);
+			sl = netdev_priv(dev);
+			if (sl->tty) {
+				netdev_err(dev,
+					   "tty discipline still running\n");
+			}
 
-		unregister_netdev(dev);
+			slc_close(dev);
+			unregister_candev(dev);
+		} else {
+			spin_unlock(&slcan_lock);
+		}
 	}
 
+	spin_lock(&slcan_lock);
 	kfree(slcan_devs);
 	slcan_devs = NULL;
+	spin_unlock(&slcan_lock);
 
 	tty_unregister_ldisc(&slc_ldisc);
 }
-- 
2.32.0


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

* [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (3 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 04/13] can: slcan: use CAN network device driver API Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-13  7:10   ` Marc Kleine-Budde
  2022-06-12 21:39 ` [PATCH v3 06/13] can: slcan: allow to send commands to the adapter Dario Binacchi
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	Marc Kleine-Budde, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Vincent Mailhol, Wolfgang Grandegger, linux-can,
	netdev

Adding Netlink support to the slcan driver made it necessary to set the
bitrate to a fake value (-1U) to prevent open_candev() from failing. In
this case the command `ip --details -s -s link show' would print
4294967295 as the bitrate value. The patch change this value in 0.

Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

(no changes since v1)

 drivers/net/can/dev/netlink.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
index 7633d98e3912..788a6752fcc7 100644
--- a/drivers/net/can/dev/netlink.c
+++ b/drivers/net/can/dev/netlink.c
@@ -505,11 +505,16 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
 	struct can_berr_counter bec = { };
 	enum can_state state = priv->state;
+	__u32 bitrate = priv->bittiming.bitrate;
+	int ret = 0;
 
 	if (priv->do_get_state)
 		priv->do_get_state(dev, &state);
 
-	if ((priv->bittiming.bitrate &&
+	if (bitrate == -1U)
+		priv->bittiming.bitrate = 0;
+
+	if ((bitrate &&
 	     nla_put(skb, IFLA_CAN_BITTIMING,
 		     sizeof(priv->bittiming), &priv->bittiming)) ||
 
@@ -563,9 +568,10 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
 	    can_ctrlmode_ext_fill_info(skb, priv)
 	    )
 
-		return -EMSGSIZE;
+		ret = -EMSGSIZE;
 
-	return 0;
+	priv->bittiming.bitrate = bitrate;
+	return ret;
 }
 
 static size_t can_get_xstats_size(const struct net_device *dev)
-- 
2.32.0


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

* [PATCH v3 06/13] can: slcan: allow to send commands to the adapter
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (4 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 07/13] can: slcan: set bitrate by CAN device driver API Dario Binacchi
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

This is a preparation patch for the upcoming support to change the
bitrate via ip tool, reset the adapter error states via the ethtool API
and, more generally, send commands to the adapter.

Since the close command (i. e. "C\r") will be sent in the ndo_stop()
where netif_running() returns false, a new flag bit (i. e. SLF_XCMD) for
serial transmission has to be added.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v3:
- Update the commit description.

 drivers/net/can/slcan.c | 46 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 45 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index a70f930b7c3a..4639a63c3af8 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -97,6 +97,9 @@ struct slcan {
 	unsigned long		flags;		/* Flag values/ mode etc     */
 #define SLF_INUSE		0		/* Channel in use            */
 #define SLF_ERROR		1               /* Parity, etc. error        */
+#define SLF_XCMD		2               /* Command transmission      */
+	wait_queue_head_t       xcmd_wait;      /* Wait queue for commands   */
+						/* transmission              */
 };
 
 static struct net_device **slcan_devs;
@@ -315,12 +318,22 @@ static void slcan_transmit(struct work_struct *work)
 
 	spin_lock_bh(&sl->lock);
 	/* First make sure we're connected. */
-	if (!sl->tty || sl->magic != SLCAN_MAGIC || !netif_running(sl->dev)) {
+	if (!sl->tty || sl->magic != SLCAN_MAGIC ||
+	    (unlikely(!netif_running(sl->dev)) &&
+	     likely(!test_bit(SLF_XCMD, &sl->flags)))) {
 		spin_unlock_bh(&sl->lock);
 		return;
 	}
 
 	if (sl->xleft <= 0)  {
+		if (unlikely(test_bit(SLF_XCMD, &sl->flags))) {
+			clear_bit(SLF_XCMD, &sl->flags);
+			clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+			spin_unlock_bh(&sl->lock);
+			wake_up(&sl->xcmd_wait);
+			return;
+		}
+
 		/* Now serial buffer is almost free & we can start
 		 * transmission of another packet */
 		sl->dev->stats.tx_packets++;
@@ -384,6 +397,36 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
  *   Routines looking at netdevice side.
  ******************************************/
 
+static int slcan_transmit_cmd(struct slcan *sl, const unsigned char *cmd)
+{
+	int ret, actual, n;
+
+	spin_lock(&sl->lock);
+	if (sl->tty == NULL) {
+		spin_unlock(&sl->lock);
+		return -ENODEV;
+	}
+
+	n = snprintf(sl->xbuff, sizeof(sl->xbuff), "%s", cmd);
+	set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+	actual = sl->tty->ops->write(sl->tty, sl->xbuff, n);
+	sl->xleft = n - actual;
+	sl->xhead = sl->xbuff + actual;
+	set_bit(SLF_XCMD, &sl->flags);
+	spin_unlock(&sl->lock);
+	ret = wait_event_interruptible_timeout(sl->xcmd_wait,
+					       !test_bit(SLF_XCMD, &sl->flags),
+					       HZ);
+	clear_bit(SLF_XCMD, &sl->flags);
+	if (ret == -ERESTARTSYS)
+		return ret;
+
+	if (ret == 0)
+		return -ETIMEDOUT;
+
+	return 0;
+}
+
 /* Netdevice UP -> DOWN routine */
 static int slc_close(struct net_device *dev)
 {
@@ -542,6 +585,7 @@ static struct slcan *slc_alloc(void)
 	sl->dev	= dev;
 	spin_lock_init(&sl->lock);
 	INIT_WORK(&sl->tx_work, slcan_transmit);
+	init_waitqueue_head(&sl->xcmd_wait);
 	slcan_devs[i] = dev;
 
 	return sl;
-- 
2.32.0


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

* [PATCH v3 07/13] can: slcan: set bitrate by CAN device driver API
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (5 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 06/13] can: slcan: allow to send commands to the adapter Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-13  7:17   ` Marc Kleine-Budde
  2022-06-12 21:39 ` [PATCH v3 08/13] can: slcan: send the open command to the adapter Dario Binacchi
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

It allows to set the bitrate via ip tool, as it happens for the other
CAN device drivers. It still remains possible to set the bitrate via
slcand or slcan_attach utilities. In case the ip tool is used, the
driver will send the serial command to the adapter.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v3:
- Remove the slc_do_set_bittiming().
- Set the bitrate in the ndo_open().
- Replace -1UL with -1U in setting a fake value for the bitrate.

Changes in v2:
- Use the CAN framework support for setting fixed bit rates.

 drivers/net/can/slcan.c | 39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 4639a63c3af8..be3f7e5c685b 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -105,6 +105,11 @@ struct slcan {
 static struct net_device **slcan_devs;
 static DEFINE_SPINLOCK(slcan_lock);
 
+static const u32 slcan_bitrate_const[] = {
+	10000, 20000, 50000, 100000, 125000,
+	250000, 500000, 800000, 1000000
+};
+
  /************************************************************************
   *			SLCAN ENCAPSULATION FORMAT			 *
   ************************************************************************/
@@ -440,6 +445,7 @@ static int slc_close(struct net_device *dev)
 	netif_stop_queue(dev);
 	close_candev(dev);
 	sl->can.state = CAN_STATE_STOPPED;
+	sl->can.bittiming.bitrate = 0;
 	sl->rcount   = 0;
 	sl->xleft    = 0;
 	spin_unlock_bh(&sl->lock);
@@ -451,7 +457,8 @@ static int slc_close(struct net_device *dev)
 static int slc_open(struct net_device *dev)
 {
 	struct slcan *sl = netdev_priv(dev);
-	int err;
+	unsigned char cmd[SLC_MTU];
+	int err, s;
 
 	if (sl->tty == NULL)
 		return -ENODEV;
@@ -461,15 +468,39 @@ static int slc_open(struct net_device *dev)
 	 * can.bittiming.bitrate is 0, causing open_candev() to fail.
 	 * So let's set to a fake value.
 	 */
-	sl->can.bittiming.bitrate = -1;
+	if (sl->can.bittiming.bitrate == 0)
+		sl->can.bittiming.bitrate = -1U;
+
 	err = open_candev(dev);
 	if (err) {
 		netdev_err(dev, "failed to open can device\n");
 		return err;
 	}
 
-	sl->can.state = CAN_STATE_ERROR_ACTIVE;
 	sl->flags &= BIT(SLF_INUSE);
+
+	if (sl->can.bittiming.bitrate != -1U) {
+		for (s = 0; s < ARRAY_SIZE(slcan_bitrate_const); s++) {
+			if (sl->can.bittiming.bitrate == slcan_bitrate_const[s])
+				break;
+		}
+
+		/* The CAN framework has already validate the bitrate value,
+		 * so we can avoid to check if `s' has been properly set.
+		 */
+
+		snprintf(cmd, sizeof(cmd), "C\rS%d\r", s);
+		err = slcan_transmit_cmd(sl, cmd);
+		if (err) {
+			netdev_err(dev,
+				   "failed to send bitrate command 'C\\rS%d\\r'\n",
+				   s);
+			close_candev(dev);
+			return err;
+		}
+	}
+
+	sl->can.state = CAN_STATE_ERROR_ACTIVE;
 	netif_start_queue(dev);
 	return 0;
 }
@@ -583,6 +614,8 @@ static struct slcan *slc_alloc(void)
 	/* Initialize channel control data */
 	sl->magic = SLCAN_MAGIC;
 	sl->dev	= dev;
+	sl->can.bitrate_const = slcan_bitrate_const;
+	sl->can.bitrate_const_cnt = ARRAY_SIZE(slcan_bitrate_const);
 	spin_lock_init(&sl->lock);
 	INIT_WORK(&sl->tx_work, slcan_transmit);
 	init_waitqueue_head(&sl->xcmd_wait);
-- 
2.32.0


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

* [PATCH v3 08/13] can: slcan: send the open command to the adapter
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (6 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 07/13] can: slcan: set bitrate by CAN device driver API Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 09/13] can: slcan: send the close " Dario Binacchi
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

In case the bitrate has been set via ip tool, this patch changes the
driver to send the open command ("O\r") to the adapter.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

(no changes since v2)

Changes in v2:
- Improve the commit message.

 drivers/net/can/slcan.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index be3f7e5c685b..9bbf8f363f58 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -495,14 +495,23 @@ static int slc_open(struct net_device *dev)
 			netdev_err(dev,
 				   "failed to send bitrate command 'C\\rS%d\\r'\n",
 				   s);
-			close_candev(dev);
-			return err;
+			goto cmd_transmit_failed;
+		}
+
+		err = slcan_transmit_cmd(sl, "O\r");
+		if (err) {
+			netdev_err(dev, "failed to send open command 'O\\r'\n");
+			goto cmd_transmit_failed;
 		}
 	}
 
 	sl->can.state = CAN_STATE_ERROR_ACTIVE;
 	netif_start_queue(dev);
 	return 0;
+
+cmd_transmit_failed:
+	close_candev(dev);
+	return err;
 }
 
 static void slc_dealloc(struct slcan *sl)
-- 
2.32.0


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

* [PATCH v3 09/13] can: slcan: send the close command to the adapter
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (7 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 08/13] can: slcan: send the open command to the adapter Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-13  7:22   ` Marc Kleine-Budde
  2022-06-12 21:39 ` [PATCH v3 10/13] can: slcan: move driver into separate sub directory Dario Binacchi
                   ` (3 subsequent siblings)
  12 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Marc Kleine-Budde,
	Paolo Abeni, Wolfgang Grandegger, linux-can, netdev

In case the bitrate has been set via ip tool, this patch changes the
driver to send the close command ("C\r") to the adapter.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

(no changes since v2)

Changes in v2:
- Improve the commit message.

 drivers/net/can/slcan.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
index 9bbf8f363f58..82a42cec52d3 100644
--- a/drivers/net/can/slcan.c
+++ b/drivers/net/can/slcan.c
@@ -436,9 +436,20 @@ static int slcan_transmit_cmd(struct slcan *sl, const unsigned char *cmd)
 static int slc_close(struct net_device *dev)
 {
 	struct slcan *sl = netdev_priv(dev);
+	int err;
 
 	spin_lock_bh(&sl->lock);
 	if (sl->tty) {
+		if (sl->can.bittiming.bitrate &&
+		    sl->can.bittiming.bitrate != -1) {
+			spin_unlock_bh(&sl->lock);
+			err = slcan_transmit_cmd(sl, "C\r");
+			spin_lock_bh(&sl->lock);
+			if (err)
+				netdev_warn(dev,
+					    "failed to send close command 'C\\r'\n");
+		}
+
 		/* TTY discipline is running. */
 		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
 	}
-- 
2.32.0


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

* [PATCH v3 10/13] can: slcan: move driver into separate sub directory
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (8 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 09/13] can: slcan: send the close " Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 11/13] can: slcan: add ethtool support to reset adapter errors Dario Binacchi
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Marc Kleine-Budde, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

This patch moves the slcan driver into a separate directory, a later
patch will add more files.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

(no changes since v1)

 drivers/net/can/Makefile                        | 2 +-
 drivers/net/can/slcan/Makefile                  | 6 ++++++
 drivers/net/can/{slcan.c => slcan/slcan-core.c} | 0
 3 files changed, 7 insertions(+), 1 deletion(-)
 create mode 100644 drivers/net/can/slcan/Makefile
 rename drivers/net/can/{slcan.c => slcan/slcan-core.c} (100%)

diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 0af85983634c..210354df273c 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -5,7 +5,7 @@
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
 obj-$(CONFIG_CAN_VXCAN)		+= vxcan.o
-obj-$(CONFIG_CAN_SLCAN)		+= slcan.o
+obj-$(CONFIG_CAN_SLCAN)		+= slcan/
 
 obj-y				+= dev/
 obj-y				+= rcar/
diff --git a/drivers/net/can/slcan/Makefile b/drivers/net/can/slcan/Makefile
new file mode 100644
index 000000000000..2e84f7bf7617
--- /dev/null
+++ b/drivers/net/can/slcan/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_CAN_SLCAN) += slcan.o
+
+slcan-objs :=
+slcan-objs += slcan-core.o
diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan/slcan-core.c
similarity index 100%
rename from drivers/net/can/slcan.c
rename to drivers/net/can/slcan/slcan-core.c
-- 
2.32.0


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

* [PATCH v3 11/13] can: slcan: add ethtool support to reset adapter errors
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (9 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 10/13] can: slcan: move driver into separate sub directory Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 12/13] can: slcan: extend the protocol with error info Dario Binacchi
  2022-06-12 21:39 ` [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info Dario Binacchi
  12 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Marc Kleine-Budde, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

This patch adds a private flag to the slcan driver to switch the
"err-rst-on-open" setting on and off.

"err-rst-on-open" on  - Reset error states on opening command

"err-rst-on-open" off - Don't reset error states on opening command
                        (default)

The setting can only be changed if the interface is down:

    ip link set dev can0 down
    ethtool --set-priv-flags can0 err-rst-on-open {off|on}
    ip link set dev can0 up

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
---

(no changes since v1)

 drivers/net/can/slcan/Makefile        |  1 +
 drivers/net/can/slcan/slcan-core.c    | 36 +++++++++++++++
 drivers/net/can/slcan/slcan-ethtool.c | 65 +++++++++++++++++++++++++++
 drivers/net/can/slcan/slcan.h         | 18 ++++++++
 4 files changed, 120 insertions(+)
 create mode 100644 drivers/net/can/slcan/slcan-ethtool.c
 create mode 100644 drivers/net/can/slcan/slcan.h

diff --git a/drivers/net/can/slcan/Makefile b/drivers/net/can/slcan/Makefile
index 2e84f7bf7617..8a88e484ee21 100644
--- a/drivers/net/can/slcan/Makefile
+++ b/drivers/net/can/slcan/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_CAN_SLCAN) += slcan.o
 
 slcan-objs :=
 slcan-objs += slcan-core.o
+slcan-objs += slcan-ethtool.o
diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
index 82a42cec52d3..3df35ae8f040 100644
--- a/drivers/net/can/slcan/slcan-core.c
+++ b/drivers/net/can/slcan/slcan-core.c
@@ -57,6 +57,8 @@
 #include <linux/can/dev.h>
 #include <linux/can/skb.h>
 
+#include "slcan.h"
+
 MODULE_ALIAS_LDISC(N_SLCAN);
 MODULE_DESCRIPTION("serial line CAN interface");
 MODULE_LICENSE("GPL");
@@ -98,6 +100,8 @@ struct slcan {
 #define SLF_INUSE		0		/* Channel in use            */
 #define SLF_ERROR		1               /* Parity, etc. error        */
 #define SLF_XCMD		2               /* Command transmission      */
+	unsigned long           cmd_flags;      /* Command flags             */
+#define CF_ERR_RST		0               /* Reset errors on open      */
 	wait_queue_head_t       xcmd_wait;      /* Wait queue for commands   */
 						/* transmission              */
 };
@@ -110,6 +114,28 @@ static const u32 slcan_bitrate_const[] = {
 	250000, 500000, 800000, 1000000
 };
 
+bool slcan_err_rst_on_open(struct net_device *ndev)
+{
+	struct slcan *sl = netdev_priv(ndev);
+
+	return !!test_bit(CF_ERR_RST, &sl->cmd_flags);
+}
+
+int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
+{
+	struct slcan *sl = netdev_priv(ndev);
+
+	if (netif_running(ndev))
+		return -EBUSY;
+
+	if (on)
+		set_bit(CF_ERR_RST, &sl->cmd_flags);
+	else
+		clear_bit(CF_ERR_RST, &sl->cmd_flags);
+
+	return 0;
+}
+
  /************************************************************************
   *			SLCAN ENCAPSULATION FORMAT			 *
   ************************************************************************/
@@ -509,6 +535,15 @@ static int slc_open(struct net_device *dev)
 			goto cmd_transmit_failed;
 		}
 
+		if (test_bit(CF_ERR_RST, &sl->cmd_flags)) {
+			err = slcan_transmit_cmd(sl, "F\r");
+			if (err) {
+				netdev_err(dev,
+					   "failed to send error command 'F\\r'\n");
+				goto cmd_transmit_failed;
+			}
+		}
+
 		err = slcan_transmit_cmd(sl, "O\r");
 		if (err) {
 			netdev_err(dev, "failed to send open command 'O\\r'\n");
@@ -629,6 +664,7 @@ static struct slcan *slc_alloc(void)
 	snprintf(dev->name, sizeof(dev->name), "slcan%d", i);
 	dev->netdev_ops = &slc_netdev_ops;
 	dev->base_addr  = i;
+	slcan_set_ethtool_ops(dev);
 	sl = netdev_priv(dev);
 
 	/* Initialize channel control data */
diff --git a/drivers/net/can/slcan/slcan-ethtool.c b/drivers/net/can/slcan/slcan-ethtool.c
new file mode 100644
index 000000000000..bf0afdc4e49d
--- /dev/null
+++ b/drivers/net/can/slcan/slcan-ethtool.c
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Copyright (c) 2022 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
+ *
+ */
+
+#include <linux/can/dev.h>
+#include <linux/ethtool.h>
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#include "slcan.h"
+
+static const char slcan_priv_flags_strings[][ETH_GSTRING_LEN] = {
+#define SLCAN_PRIV_FLAGS_ERR_RST_ON_OPEN BIT(0)
+	"err-rst-on-open",
+};
+
+static void slcan_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_PRIV_FLAGS:
+		memcpy(data, slcan_priv_flags_strings,
+		       sizeof(slcan_priv_flags_strings));
+	}
+}
+
+static u32 slcan_get_priv_flags(struct net_device *ndev)
+{
+	u32 flags = 0;
+
+	if (slcan_err_rst_on_open(ndev))
+		flags |= SLCAN_PRIV_FLAGS_ERR_RST_ON_OPEN;
+
+	return flags;
+}
+
+static int slcan_set_priv_flags(struct net_device *ndev, u32 flags)
+{
+	bool err_rst_op_open = !!(flags & SLCAN_PRIV_FLAGS_ERR_RST_ON_OPEN);
+
+	return slcan_enable_err_rst_on_open(ndev, err_rst_op_open);
+}
+
+static int slcan_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_PRIV_FLAGS:
+		return ARRAY_SIZE(slcan_priv_flags_strings);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static const struct ethtool_ops slcan_ethtool_ops = {
+	.get_strings = slcan_get_strings,
+	.get_priv_flags = slcan_get_priv_flags,
+	.set_priv_flags = slcan_set_priv_flags,
+	.get_sset_count = slcan_get_sset_count,
+};
+
+void slcan_set_ethtool_ops(struct net_device *netdev)
+{
+	netdev->ethtool_ops = &slcan_ethtool_ops;
+}
diff --git a/drivers/net/can/slcan/slcan.h b/drivers/net/can/slcan/slcan.h
new file mode 100644
index 000000000000..d463c8d99e22
--- /dev/null
+++ b/drivers/net/can/slcan/slcan.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * slcan.h - serial line CAN interface driver
+ *
+ * Copyright (C) Laurence Culhane <loz@holmes.demon.co.uk>
+ * Copyright (C) Fred N. van Kempen <waltje@uwalt.nl.mugnet.org>
+ * Copyright (C) Oliver Hartkopp <socketcan@hartkopp.net>
+ * Copyright (C) 2022 Amarula Solutions, Dario Binacchi <dario.binacchi@amarulasolutions.com>
+ *
+ */
+
+#ifndef _SLCAN_H
+#define _SLCAN_H
+
+bool slcan_err_rst_on_open(struct net_device *ndev);
+int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on);
+void slcan_set_ethtool_ops(struct net_device *ndev);
+
+#endif /* _SLCAN_H */
-- 
2.32.0


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

* [PATCH v3 12/13] can: slcan: extend the protocol with error info
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (10 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 11/13] can: slcan: add ethtool support to reset adapter errors Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-13  7:32   ` Marc Kleine-Budde
  2022-06-12 21:39 ` [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info Dario Binacchi
  12 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Marc Kleine-Budde, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

It extends the protocol to receive the adapter CAN communication errors
and forward them to the netdev upper levels.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

(no changes since v2)

Changes in v2:
- Protect decoding against the case the len value is longer than the
  received data.
- Continue error handling even if no skb can be allocated.

 drivers/net/can/slcan/slcan-core.c | 130 ++++++++++++++++++++++++++++-
 1 file changed, 129 insertions(+), 1 deletion(-)

diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
index 3df35ae8f040..48077edb9497 100644
--- a/drivers/net/can/slcan/slcan-core.c
+++ b/drivers/net/can/slcan/slcan-core.c
@@ -175,8 +175,118 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
   *			STANDARD SLCAN DECAPSULATION			 *
   ************************************************************************/
 
+static void slc_bump_err(struct slcan *sl)
+{
+	struct net_device *dev = sl->dev;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	char *cmd = sl->rbuff;
+	bool rx_errors = false, tx_errors = false;
+	int i, len;
+
+	if (*cmd != 'e')
+		return;
+
+	cmd += SLC_CMD_LEN;
+	/* get len from sanitized ASCII value */
+	len = *cmd++;
+	if (len >= '0' && len < '9')
+		len -= '0';
+	else
+		return;
+
+	skb = alloc_can_err_skb(dev, &cf);
+
+	if (skb)
+		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+
+	for (i = 0; i < len; i++, cmd++) {
+		switch (*cmd) {
+		case 'a':
+			netdev_dbg(dev, "ACK error\n");
+			tx_errors = true;
+			if (skb) {
+				cf->can_id |= CAN_ERR_ACK;
+				cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+			}
+
+			break;
+		case 'b':
+			netdev_dbg(dev, "Bit0 error\n");
+			tx_errors = true;
+			if (skb)
+				cf->data[2] |= CAN_ERR_PROT_BIT0;
+
+			break;
+		case 'B':
+			netdev_dbg(dev, "Bit1 error\n");
+			tx_errors = true;
+			if (skb)
+				cf->data[2] |= CAN_ERR_PROT_BIT1;
+
+			break;
+		case 'c':
+			netdev_dbg(dev, "CRC error\n");
+			rx_errors = true;
+			if (skb) {
+				cf->data[2] |= CAN_ERR_PROT_BIT;
+				cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+			}
+
+			break;
+		case 'f':
+			netdev_dbg(dev, "Form Error\n");
+			rx_errors = true;
+			if (skb)
+				cf->data[2] |= CAN_ERR_PROT_FORM;
+
+			break;
+		case 'o':
+			netdev_dbg(dev, "Rx overrun error\n");
+			dev->stats.rx_over_errors++;
+			dev->stats.rx_errors++;
+			if (skb) {
+				cf->can_id |= CAN_ERR_CRTL;
+				cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+			}
+
+			break;
+		case 'O':
+			netdev_dbg(dev, "Tx overrun error\n");
+			dev->stats.tx_errors++;
+			if (skb) {
+				cf->can_id |= CAN_ERR_CRTL;
+				cf->data[1] = CAN_ERR_CRTL_TX_OVERFLOW;
+			}
+
+			break;
+		case 's':
+			netdev_dbg(dev, "Stuff error\n");
+			rx_errors = true;
+			if (skb)
+				cf->data[2] |= CAN_ERR_PROT_STUFF;
+
+			break;
+		default:
+			if (skb)
+				dev_kfree_skb(skb);
+
+			return;
+		}
+	}
+
+	if (rx_errors)
+		dev->stats.rx_errors++;
+
+	if (tx_errors)
+		dev->stats.tx_errors++;
+
+	if (skb)
+		netif_rx(skb);
+}
+
 /* Send one completely decapsulated can_frame to the network layer */
-static void slc_bump(struct slcan *sl)
+static void slc_bump_frame(struct slcan *sl)
 {
 	struct sk_buff *skb;
 	struct can_frame *cf;
@@ -255,6 +365,24 @@ static void slc_bump(struct slcan *sl)
 	dev_kfree_skb(skb);
 }
 
+static void slc_bump(struct slcan *sl)
+{
+	switch (sl->rbuff[0]) {
+	case 'r':
+		fallthrough;
+	case 't':
+		fallthrough;
+	case 'R':
+		fallthrough;
+	case 'T':
+		return slc_bump_frame(sl);
+	case 'e':
+		return slc_bump_err(sl);
+	default:
+		return;
+	}
+}
+
 /* parse tty input stream */
 static void slcan_unesc(struct slcan *sl, unsigned char s)
 {
-- 
2.32.0


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

* [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info
  2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
                   ` (11 preceding siblings ...)
  2022-06-12 21:39 ` [PATCH v3 12/13] can: slcan: extend the protocol with error info Dario Binacchi
@ 2022-06-12 21:39 ` Dario Binacchi
  2022-06-13  7:37   ` Marc Kleine-Budde
  12 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-12 21:39 UTC (permalink / raw)
  To: linux-kernel
  Cc: michael, Amarula patchwork, Oliver Hartkopp, Dario Binacchi,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Marc Kleine-Budde, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

It extends the protocol to receive the adapter CAN state changes
(warning, busoff, etc.) and forward them to the netdev upper levels.

Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

---

Changes in v3:
- Drop the patch "can: slcan: simplify the device de-allocation".
- Add the patch "can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U".

Changes in v2:
- Continue error handling even if no skb can be allocated.

 drivers/net/can/slcan/slcan-core.c | 66 ++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
index 48077edb9497..5ba1c141f942 100644
--- a/drivers/net/can/slcan/slcan-core.c
+++ b/drivers/net/can/slcan/slcan-core.c
@@ -78,6 +78,9 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
 #define SLC_CMD_LEN 1
 #define SLC_SFF_ID_LEN 3
 #define SLC_EFF_ID_LEN 8
+#define SLC_STATE_LEN 1
+#define SLC_STATE_BE_RXCNT_LEN 3
+#define SLC_STATE_BE_TXCNT_LEN 3
 
 struct slcan {
 	struct can_priv         can;
@@ -175,6 +178,67 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
   *			STANDARD SLCAN DECAPSULATION			 *
   ************************************************************************/
 
+static void slc_bump_state(struct slcan *sl)
+{
+	struct net_device *dev = sl->dev;
+	struct sk_buff *skb;
+	struct can_frame *cf;
+	char *cmd = sl->rbuff;
+	u32 rxerr, txerr;
+	enum can_state state, rx_state, tx_state;
+
+	if (*cmd != 's')
+		return;
+
+	cmd += SLC_CMD_LEN;
+	switch (*cmd) {
+	case 'a':
+		state = CAN_STATE_ERROR_ACTIVE;
+		break;
+	case 'w':
+		state = CAN_STATE_ERROR_WARNING;
+		break;
+	case 'p':
+		state = CAN_STATE_ERROR_PASSIVE;
+		break;
+	case 'f':
+		state = CAN_STATE_BUS_OFF;
+		break;
+	default:
+		return;
+	}
+
+	if (state == sl->can.state)
+		return;
+
+	cmd += SLC_STATE_BE_RXCNT_LEN + 1;
+	cmd[SLC_STATE_BE_TXCNT_LEN] = 0;
+	if (kstrtou32(cmd, 10, &txerr))
+		return;
+
+	*cmd = 0;
+	cmd -= SLC_STATE_BE_RXCNT_LEN;
+	if (kstrtou32(cmd, 10, &rxerr))
+		return;
+
+	skb = alloc_can_err_skb(dev, &cf);
+
+	if (skb) {
+		cf->data[6] = txerr;
+		cf->data[7] = rxerr;
+	}
+
+	tx_state = txerr >= rxerr ? state : 0;
+	rx_state = txerr <= rxerr ? state : 0;
+	can_change_state(dev, skb ? cf : NULL, tx_state, rx_state);
+
+	if (state == CAN_STATE_BUS_OFF)
+		can_bus_off(dev);
+
+	if (skb)
+		netif_rx(skb);
+}
+
 static void slc_bump_err(struct slcan *sl)
 {
 	struct net_device *dev = sl->dev;
@@ -378,6 +442,8 @@ static void slc_bump(struct slcan *sl)
 		return slc_bump_frame(sl);
 	case 'e':
 		return slc_bump_err(sl);
+	case 's':
+		return slc_bump_state(sl);
 	default:
 		return;
 	}
-- 
2.32.0


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

* Re: [PATCH v3 04/13] can: slcan: use CAN network device driver API
  2022-06-12 21:39 ` [PATCH v3 04/13] can: slcan: use CAN network device driver API Dario Binacchi
@ 2022-06-13  7:01   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-13  7:01 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Wolfgang Grandegger, linux-can, netdev

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

On 12.06.2022 23:39:18, Dario Binacchi wrote:
> As suggested by commit [1], now the driver uses the functions and the
> data structures provided by the CAN network device driver interface.
> 
> Currently the driver doesn't implement a way to set bitrate for SLCAN
> based devices via ip tool, so you'll have to do this by slcand or
> slcan_attach invocation through the -sX parameter:
> 
> - slcan_attach -f -s6 -o /dev/ttyACM0
> - slcand -f -s8 -o /dev/ttyUSB0
> 
> where -s6 in will set adapter's bitrate to 500 Kbit/s and -s8 to
> 1Mbit/s.
> See the table below for further CAN bitrates:
> - s0 ->   10 Kbit/s
> - s1 ->   20 Kbit/s
> - s2 ->   50 Kbit/s
> - s3 ->  100 Kbit/s
> - s4 ->  125 Kbit/s
> - s5 ->  250 Kbit/s
> - s6 ->  500 Kbit/s
> - s7 ->  800 Kbit/s
> - s8 -> 1000 Kbit/s
> 
> In doing so, the struct can_priv::bittiming.bitrate of the driver is not
> set and since the open_candev() checks that the bitrate has been set, it
> must be a non-zero value, the bitrate is set to a fake value (-1U)
> before it is called.

The patch description doesn't mention the change of the locking from
rtnl to a spin_lock. Please test your code with a kernel that has
CONFIG_PROVE_LOCKING enabled.

Please move patch
| [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U
in front of this one.

> @@ -374,7 +375,7 @@ static netdev_tx_t slc_xmit(struct sk_buff *skb, struct net_device *dev)
>  	spin_unlock(&sl->lock);
>  
>  out:
> -	kfree_skb(skb);
> +	can_put_echo_skb(skb, dev, 0, 0);

Where's the corresponding can_get_echo_skb()?

If you convert the driver to can_put_echo_skb()/can_get_echo_skb(), you
must set "netdev->flags |= IFF_ECHO;". And you should do the put()
before triggering the send, the corresponding get() needs to be added
where you have the TX completion from the hardware. If you don't get a
response the best you can do is moving it after the triggering of the
send.

If you want to convert the driver to can_put/get_echo_skb(), please make
it a separate patch.

>  	return NETDEV_TX_OK;
>  }
>  
> @@ -394,6 +395,8 @@ static int slc_close(struct net_device *dev)
>  		clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
>  	}
>  	netif_stop_queue(dev);
> +	close_candev(dev);
> +	sl->can.state = CAN_STATE_STOPPED;
>  	sl->rcount   = 0;
>  	sl->xleft    = 0;
>  	spin_unlock_bh(&sl->lock);
> @@ -405,21 +408,36 @@ static int slc_close(struct net_device *dev)
>  static int slc_open(struct net_device *dev)
>  {
>  	struct slcan *sl = netdev_priv(dev);
> +	int err;
>  
>  	if (sl->tty == NULL)
>  		return -ENODEV;
>  
> +	/* The baud rate is not set with the command
> +	 * `ip link set <iface> type can bitrate <baud>' and therefore
> +	 * can.bittiming.bitrate is 0, causing open_candev() to fail.
> +	 * So let's set to a fake value.
> +	 */
> +	sl->can.bittiming.bitrate = -1;
> +	err = open_candev(dev);
> +	if (err) {
> +		netdev_err(dev, "failed to open can device\n");
> +		return err;
> +	}
> +
> +	sl->can.state = CAN_STATE_ERROR_ACTIVE;
>  	sl->flags &= BIT(SLF_INUSE);
>  	netif_start_queue(dev);
>  	return 0;
>  }
>  
> -/* Hook the destructor so we can free slcan devs at the right point in time */
> -static void slc_free_netdev(struct net_device *dev)
> +static void slc_dealloc(struct slcan *sl)
>  {
> -	int i = dev->base_addr;
> +	int i = sl->dev->base_addr;
>  
> -	slcan_devs[i] = NULL;
> +	free_candev(sl->dev);
> +	if (slcan_devs)

Why have you added this check?

regards,
Marc

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

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

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

* Re: [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U
  2022-06-12 21:39 ` [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U Dario Binacchi
@ 2022-06-13  7:10   ` Marc Kleine-Budde
  2022-06-13 20:44     ` Dario Binacchi
  0 siblings, 1 reply; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-13  7:10 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vincent Mailhol, Wolfgang Grandegger, linux-can, netdev

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

On 12.06.2022 23:39:19, Dario Binacchi wrote:
> Adding Netlink support to the slcan driver made it necessary to set the
> bitrate to a fake value (-1U) to prevent open_candev() from failing. In
> this case the command `ip --details -s -s link show' would print
> 4294967295 as the bitrate value. The patch change this value in 0.
> 
> Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> ---
> 
> (no changes since v1)
> 
>  drivers/net/can/dev/netlink.c | 12 +++++++++---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
> index 7633d98e3912..788a6752fcc7 100644
> --- a/drivers/net/can/dev/netlink.c
> +++ b/drivers/net/can/dev/netlink.c
> @@ -505,11 +505,16 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
>  	struct can_ctrlmode cm = {.flags = priv->ctrlmode};
>  	struct can_berr_counter bec = { };
>  	enum can_state state = priv->state;
> +	__u32 bitrate = priv->bittiming.bitrate;
> +	int ret = 0;
>  
>  	if (priv->do_get_state)
>  		priv->do_get_state(dev, &state);
>  
> -	if ((priv->bittiming.bitrate &&

What about changing this line to:

        if ((priv->bittiming.bitrate && priv->bittiming.bitrate != -1 &&

This would make the code a lot cleaner. Can you think of a nice macro
name for the -1?

0 could be CAN_BITRATE_UNCONFIGURED or _UNSET. For -1 I cannot find a
catchy name, something like CAN_BITRATE_CONFIGURED_UNKOWN or
SET_UNKNOWN.

The macros can be added to bittiming.h and be part of this patch. Ofq
course the above code (and slcan.c) would make use of the macros instead
of using 0 and -1.

Marc

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

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

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

* Re: [PATCH v3 07/13] can: slcan: set bitrate by CAN device driver API
  2022-06-12 21:39 ` [PATCH v3 07/13] can: slcan: set bitrate by CAN device driver API Dario Binacchi
@ 2022-06-13  7:17   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-13  7:17 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Wolfgang Grandegger, linux-can, netdev

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

On 12.06.2022 23:39:21, Dario Binacchi wrote:
> It allows to set the bitrate via ip tool, as it happens for the other
> CAN device drivers. It still remains possible to set the bitrate via
> slcand or slcan_attach utilities. In case the ip tool is used, the
> driver will send the serial command to the adapter.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> 
> ---
> 
> Changes in v3:
> - Remove the slc_do_set_bittiming().
> - Set the bitrate in the ndo_open().
> - Replace -1UL with -1U in setting a fake value for the bitrate.
> 
> Changes in v2:
> - Use the CAN framework support for setting fixed bit rates.
> 
>  drivers/net/can/slcan.c | 39 ++++++++++++++++++++++++++++++++++++---
>  1 file changed, 36 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
> index 4639a63c3af8..be3f7e5c685b 100644
> --- a/drivers/net/can/slcan.c
> +++ b/drivers/net/can/slcan.c
> @@ -105,6 +105,11 @@ struct slcan {
>  static struct net_device **slcan_devs;
>  static DEFINE_SPINLOCK(slcan_lock);
>  
> +static const u32 slcan_bitrate_const[] = {
> +	10000, 20000, 50000, 100000, 125000,
> +	250000, 500000, 800000, 1000000
> +};
> +
>   /************************************************************************
>    *			SLCAN ENCAPSULATION FORMAT			 *
>    ************************************************************************/
> @@ -440,6 +445,7 @@ static int slc_close(struct net_device *dev)
>  	netif_stop_queue(dev);
>  	close_candev(dev);
>  	sl->can.state = CAN_STATE_STOPPED;
> +	sl->can.bittiming.bitrate = 0;

If the bitrate is configured, please keep that value.

Marc

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

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

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

* Re: [PATCH v3 09/13] can: slcan: send the close command to the adapter
  2022-06-12 21:39 ` [PATCH v3 09/13] can: slcan: send the close " Dario Binacchi
@ 2022-06-13  7:22   ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-13  7:22 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Wolfgang Grandegger, linux-can, netdev

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

On 12.06.2022 23:39:23, Dario Binacchi wrote:
> In case the bitrate has been set via ip tool, this patch changes the
> driver to send the close command ("C\r") to the adapter.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>

Nitpick: Please squash the open and close patches.

Marc

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

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

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

* Re: [PATCH v3 12/13] can: slcan: extend the protocol with error info
  2022-06-12 21:39 ` [PATCH v3 12/13] can: slcan: extend the protocol with error info Dario Binacchi
@ 2022-06-13  7:32   ` Marc Kleine-Budde
  2022-06-13 21:04     ` Dario Binacchi
  0 siblings, 1 reply; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-13  7:32 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

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

On 12.06.2022 23:39:26, Dario Binacchi wrote:
> It extends the protocol to receive the adapter CAN communication errors
> and forward them to the netdev upper levels.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> 
> ---
> 
> (no changes since v2)
> 
> Changes in v2:
> - Protect decoding against the case the len value is longer than the
>   received data.

Where is that check?

> - Continue error handling even if no skb can be allocated.
> 
>  drivers/net/can/slcan/slcan-core.c | 130 ++++++++++++++++++++++++++++-
>  1 file changed, 129 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
> index 3df35ae8f040..48077edb9497 100644
> --- a/drivers/net/can/slcan/slcan-core.c
> +++ b/drivers/net/can/slcan/slcan-core.c
> @@ -175,8 +175,118 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
>    *			STANDARD SLCAN DECAPSULATION			 *
>    ************************************************************************/
>  
> +static void slc_bump_err(struct slcan *sl)
> +{
> +	struct net_device *dev = sl->dev;
> +	struct sk_buff *skb;
> +	struct can_frame *cf;
> +	char *cmd = sl->rbuff;
> +	bool rx_errors = false, tx_errors = false;
> +	int i, len;
> +
> +	if (*cmd != 'e')
> +		return;

This has already been checked in the caller, right?

> +
> +	cmd += SLC_CMD_LEN;
> +	/* get len from sanitized ASCII value */
> +	len = *cmd++;
> +	if (len >= '0' && len < '9')
> +		len -= '0';
> +	else
> +		return;
> +
> +	skb = alloc_can_err_skb(dev, &cf);
> +
> +	if (skb)
> +		cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> +
> +	for (i = 0; i < len; i++, cmd++) {
> +		switch (*cmd) {
> +		case 'a':
> +			netdev_dbg(dev, "ACK error\n");
> +			tx_errors = true;

Nitpick:
Please decide if you want to set tx/tx_errors here and increment at the
end of the function....or.....

> +			if (skb) {
> +				cf->can_id |= CAN_ERR_ACK;
> +				cf->data[3] = CAN_ERR_PROT_LOC_ACK;
> +			}
> +
> +			break;
> +		case 'b':
> +			netdev_dbg(dev, "Bit0 error\n");
> +			tx_errors = true;
> +			if (skb)
> +				cf->data[2] |= CAN_ERR_PROT_BIT0;
> +
> +			break;
> +		case 'B':
> +			netdev_dbg(dev, "Bit1 error\n");
> +			tx_errors = true;
> +			if (skb)
> +				cf->data[2] |= CAN_ERR_PROT_BIT1;
> +
> +			break;
> +		case 'c':
> +			netdev_dbg(dev, "CRC error\n");
> +			rx_errors = true;
> +			if (skb) {
> +				cf->data[2] |= CAN_ERR_PROT_BIT;
> +				cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
> +			}
> +
> +			break;
> +		case 'f':
> +			netdev_dbg(dev, "Form Error\n");
> +			rx_errors = true;
> +			if (skb)
> +				cf->data[2] |= CAN_ERR_PROT_FORM;
> +
> +			break;
> +		case 'o':
> +			netdev_dbg(dev, "Rx overrun error\n");
> +			dev->stats.rx_over_errors++;
> +			dev->stats.rx_errors++;

....if you want to increment in the case.

> +			if (skb) {
> +				cf->can_id |= CAN_ERR_CRTL;
> +				cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> +			}
> +
> +			break;
> +		case 'O':
> +			netdev_dbg(dev, "Tx overrun error\n");
> +			dev->stats.tx_errors++;
> +			if (skb) {
> +				cf->can_id |= CAN_ERR_CRTL;
> +				cf->data[1] = CAN_ERR_CRTL_TX_OVERFLOW;
> +			}
> +
> +			break;
> +		case 's':
> +			netdev_dbg(dev, "Stuff error\n");
> +			rx_errors = true;
> +			if (skb)
> +				cf->data[2] |= CAN_ERR_PROT_STUFF;
> +
> +			break;
> +		default:
> +			if (skb)
> +				dev_kfree_skb(skb);
> +
> +			return;
> +		}
> +	}
> +
> +	if (rx_errors)
> +		dev->stats.rx_errors++;
> +
> +	if (tx_errors)
> +		dev->stats.tx_errors++;
> +
> +	if (skb)
> +		netif_rx(skb);
> +}
> +
>  /* Send one completely decapsulated can_frame to the network layer */
> -static void slc_bump(struct slcan *sl)
> +static void slc_bump_frame(struct slcan *sl)
>  {
>  	struct sk_buff *skb;
>  	struct can_frame *cf;
> @@ -255,6 +365,24 @@ static void slc_bump(struct slcan *sl)
>  	dev_kfree_skb(skb);
>  }
>  
> +static void slc_bump(struct slcan *sl)
> +{
> +	switch (sl->rbuff[0]) {
> +	case 'r':
> +		fallthrough;
> +	case 't':
> +		fallthrough;
> +	case 'R':
> +		fallthrough;
> +	case 'T':
> +		return slc_bump_frame(sl);
> +	case 'e':
> +		return slc_bump_err(sl);
> +	default:
> +		return;
> +	}
> +}
> +
>  /* parse tty input stream */
>  static void slcan_unesc(struct slcan *sl, unsigned char s)
>  {
> -- 
> 2.32.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: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info
  2022-06-12 21:39 ` [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info Dario Binacchi
@ 2022-06-13  7:37   ` Marc Kleine-Budde
  2022-06-14  6:29     ` Dario Binacchi
  0 siblings, 1 reply; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-13  7:37 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

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

On 12.06.2022 23:39:27, Dario Binacchi wrote:
> It extends the protocol to receive the adapter CAN state changes
> (warning, busoff, etc.) and forward them to the netdev upper levels.
> 
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> 
> ---
> 
> Changes in v3:
> - Drop the patch "can: slcan: simplify the device de-allocation".
> - Add the patch "can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U".
> 
> Changes in v2:
> - Continue error handling even if no skb can be allocated.
> 
>  drivers/net/can/slcan/slcan-core.c | 66 ++++++++++++++++++++++++++++++
>  1 file changed, 66 insertions(+)
> 
> diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
> index 48077edb9497..5ba1c141f942 100644
> --- a/drivers/net/can/slcan/slcan-core.c
> +++ b/drivers/net/can/slcan/slcan-core.c
> @@ -78,6 +78,9 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
>  #define SLC_CMD_LEN 1
>  #define SLC_SFF_ID_LEN 3
>  #define SLC_EFF_ID_LEN 8
> +#define SLC_STATE_LEN 1
> +#define SLC_STATE_BE_RXCNT_LEN 3
> +#define SLC_STATE_BE_TXCNT_LEN 3
>  
>  struct slcan {
>  	struct can_priv         can;
> @@ -175,6 +178,67 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
>    *			STANDARD SLCAN DECAPSULATION			 *
>    ************************************************************************/
>  
> +static void slc_bump_state(struct slcan *sl)
> +{
> +	struct net_device *dev = sl->dev;
> +	struct sk_buff *skb;
> +	struct can_frame *cf;
> +	char *cmd = sl->rbuff;
> +	u32 rxerr, txerr;
> +	enum can_state state, rx_state, tx_state;
> +
> +	if (*cmd != 's')
> +		return;

Checked by the caller?

> +
> +	cmd += SLC_CMD_LEN;
> +	switch (*cmd) {
> +	case 'a':
> +		state = CAN_STATE_ERROR_ACTIVE;
> +		break;
> +	case 'w':
> +		state = CAN_STATE_ERROR_WARNING;
> +		break;
> +	case 'p':
> +		state = CAN_STATE_ERROR_PASSIVE;
> +		break;
> +	case 'f':
> +		state = CAN_STATE_BUS_OFF;
> +		break;
> +	default:
> +		return;
> +	}
> +
> +	if (state == sl->can.state)
> +		return;
> +
> +	cmd += SLC_STATE_BE_RXCNT_LEN + 1;

Have you checked that you have received that much data?

> +	cmd[SLC_STATE_BE_TXCNT_LEN] = 0;
> +	if (kstrtou32(cmd, 10, &txerr))
> +		return;
> +
> +	*cmd = 0;
> +	cmd -= SLC_STATE_BE_RXCNT_LEN;
> +	if (kstrtou32(cmd, 10, &rxerr))
> +		return;

Why do you parse TX first and then RX?

> +
> +	skb = alloc_can_err_skb(dev, &cf);
> +
> +	if (skb) {
> +		cf->data[6] = txerr;
> +		cf->data[7] = rxerr;
> +	}
> +
> +	tx_state = txerr >= rxerr ? state : 0;
> +	rx_state = txerr <= rxerr ? state : 0;
> +	can_change_state(dev, skb ? cf : NULL, tx_state, rx_state);

alloc_can_err_skb() set cf to NULL if no skb can be allocated.

> +
> +	if (state == CAN_STATE_BUS_OFF)
> +		can_bus_off(dev);
> +
> +	if (skb)
> +		netif_rx(skb);
> +}
> +
>  static void slc_bump_err(struct slcan *sl)
>  {
>  	struct net_device *dev = sl->dev;
> @@ -378,6 +442,8 @@ static void slc_bump(struct slcan *sl)
>  		return slc_bump_frame(sl);
>  	case 'e':
>  		return slc_bump_err(sl);
> +	case 's':
> +		return slc_bump_state(sl);
>  	default:
>  		return;
>  	}
> -- 
> 2.32.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: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U
  2022-06-13  7:10   ` Marc Kleine-Budde
@ 2022-06-13 20:44     ` Dario Binacchi
  2022-06-14  7:24       ` Marc Kleine-Budde
  0 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-13 20:44 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vincent Mailhol, Wolfgang Grandegger, linux-can, netdev

On Mon, Jun 13, 2022 at 9:11 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 12.06.2022 23:39:19, Dario Binacchi wrote:
> > Adding Netlink support to the slcan driver made it necessary to set the
> > bitrate to a fake value (-1U) to prevent open_candev() from failing. In
> > this case the command `ip --details -s -s link show' would print
> > 4294967295 as the bitrate value. The patch change this value in 0.
> >
> > Suggested-by: Marc Kleine-Budde <mkl@pengutronix.de>
> > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> > ---
> >
> > (no changes since v1)
> >
> >  drivers/net/can/dev/netlink.c | 12 +++++++++---
> >  1 file changed, 9 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c
> > index 7633d98e3912..788a6752fcc7 100644
> > --- a/drivers/net/can/dev/netlink.c
> > +++ b/drivers/net/can/dev/netlink.c
> > @@ -505,11 +505,16 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev)
> >       struct can_ctrlmode cm = {.flags = priv->ctrlmode};
> >       struct can_berr_counter bec = { };
> >       enum can_state state = priv->state;
> > +     __u32 bitrate = priv->bittiming.bitrate;
> > +     int ret = 0;
> >
> >       if (priv->do_get_state)
> >               priv->do_get_state(dev, &state);
> >
> > -     if ((priv->bittiming.bitrate &&
>
> What about changing this line to:
>
>         if ((priv->bittiming.bitrate && priv->bittiming.bitrate != -1 &&

That you are right. The code becomes much cleaner.

>
> This would make the code a lot cleaner. Can you think of a nice macro
> name for the -1?
>
> 0 could be CAN_BITRATE_UNCONFIGURED or _UNSET. For -1 I cannot find a
> catchy name, something like CAN_BITRATE_CONFIGURED_UNKOWN or
> SET_UNKNOWN.
>

Personally I would use CAN_BITRATE_UNSET (0) and CAN_BITRATE_UNKNOWN (-1).
Let me know what your ultimate preference is.

Thanks and regards,
Dario

> The macros can be added to bittiming.h and be part of this patch. Ofq
> course the above code (and slcan.c) would make use of the macros instead
> of using 0 and -1.
>
> 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 |



-- 

Dario Binacchi

Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

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

* Re: [PATCH v3 12/13] can: slcan: extend the protocol with error info
  2022-06-13  7:32   ` Marc Kleine-Budde
@ 2022-06-13 21:04     ` Dario Binacchi
  0 siblings, 0 replies; 25+ messages in thread
From: Dario Binacchi @ 2022-06-13 21:04 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

On Mon, Jun 13, 2022 at 9:32 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 12.06.2022 23:39:26, Dario Binacchi wrote:
> > It extends the protocol to receive the adapter CAN communication errors
> > and forward them to the netdev upper levels.
> >
> > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> >
> > ---
> >
> > (no changes since v2)
> >
> > Changes in v2:
> > - Protect decoding against the case the len value is longer than the
> >   received data.
>
> Where is that check?

I added the default case in the switch statement. Each line that is
processed by slc_bump_err()
is terminated by a '\r' or '\a' character. If len value is longer than
the received characters, it will
enter the default case for the eol character and the function will return.
But I realize now that I am wrong, the terminator is not placed in the
buffer passed to slc_bump_err() !!!!!! :)
I will add the right check in v4.

Thanks and regards,
Dario

>
> > - Continue error handling even if no skb can be allocated.
> >
> >  drivers/net/can/slcan/slcan-core.c | 130 ++++++++++++++++++++++++++++-
> >  1 file changed, 129 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
> > index 3df35ae8f040..48077edb9497 100644
> > --- a/drivers/net/can/slcan/slcan-core.c
> > +++ b/drivers/net/can/slcan/slcan-core.c
> > @@ -175,8 +175,118 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
> >    *                  STANDARD SLCAN DECAPSULATION                     *
> >    ************************************************************************/
> >
> > +static void slc_bump_err(struct slcan *sl)
> > +{
> > +     struct net_device *dev = sl->dev;
> > +     struct sk_buff *skb;
> > +     struct can_frame *cf;
> > +     char *cmd = sl->rbuff;
> > +     bool rx_errors = false, tx_errors = false;
> > +     int i, len;
> > +
> > +     if (*cmd != 'e')
> > +             return;
>
> This has already been checked in the caller, right?
>
> > +
> > +     cmd += SLC_CMD_LEN;
> > +     /* get len from sanitized ASCII value */
> > +     len = *cmd++;
> > +     if (len >= '0' && len < '9')
> > +             len -= '0';
> > +     else
> > +             return;
> > +
> > +     skb = alloc_can_err_skb(dev, &cf);
> > +
> > +     if (skb)
> > +             cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> > +
> > +     for (i = 0; i < len; i++, cmd++) {
> > +             switch (*cmd) {
> > +             case 'a':
> > +                     netdev_dbg(dev, "ACK error\n");
> > +                     tx_errors = true;
>
> Nitpick:
> Please decide if you want to set tx/tx_errors here and increment at the
> end of the function....or.....
>
> > +                     if (skb) {
> > +                             cf->can_id |= CAN_ERR_ACK;
> > +                             cf->data[3] = CAN_ERR_PROT_LOC_ACK;
> > +                     }
> > +
> > +                     break;
> > +             case 'b':
> > +                     netdev_dbg(dev, "Bit0 error\n");
> > +                     tx_errors = true;
> > +                     if (skb)
> > +                             cf->data[2] |= CAN_ERR_PROT_BIT0;
> > +
> > +                     break;
> > +             case 'B':
> > +                     netdev_dbg(dev, "Bit1 error\n");
> > +                     tx_errors = true;
> > +                     if (skb)
> > +                             cf->data[2] |= CAN_ERR_PROT_BIT1;
> > +
> > +                     break;
> > +             case 'c':
> > +                     netdev_dbg(dev, "CRC error\n");
> > +                     rx_errors = true;
> > +                     if (skb) {
> > +                             cf->data[2] |= CAN_ERR_PROT_BIT;
> > +                             cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
> > +                     }
> > +
> > +                     break;
> > +             case 'f':
> > +                     netdev_dbg(dev, "Form Error\n");
> > +                     rx_errors = true;
> > +                     if (skb)
> > +                             cf->data[2] |= CAN_ERR_PROT_FORM;
> > +
> > +                     break;
> > +             case 'o':
> > +                     netdev_dbg(dev, "Rx overrun error\n");
> > +                     dev->stats.rx_over_errors++;
> > +                     dev->stats.rx_errors++;
>
> ....if you want to increment in the case.
>
> > +                     if (skb) {
> > +                             cf->can_id |= CAN_ERR_CRTL;
> > +                             cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
> > +                     }
> > +
> > +                     break;
> > +             case 'O':
> > +                     netdev_dbg(dev, "Tx overrun error\n");
> > +                     dev->stats.tx_errors++;
> > +                     if (skb) {
> > +                             cf->can_id |= CAN_ERR_CRTL;
> > +                             cf->data[1] = CAN_ERR_CRTL_TX_OVERFLOW;
> > +                     }
> > +
> > +                     break;
> > +             case 's':
> > +                     netdev_dbg(dev, "Stuff error\n");
> > +                     rx_errors = true;
> > +                     if (skb)
> > +                             cf->data[2] |= CAN_ERR_PROT_STUFF;
> > +
> > +                     break;
> > +             default:
> > +                     if (skb)
> > +                             dev_kfree_skb(skb);
> > +
> > +                     return;
> > +             }
> > +     }
> > +
> > +     if (rx_errors)
> > +             dev->stats.rx_errors++;
> > +
> > +     if (tx_errors)
> > +             dev->stats.tx_errors++;
> > +
> > +     if (skb)
> > +             netif_rx(skb);
> > +}
> > +
> >  /* Send one completely decapsulated can_frame to the network layer */
> > -static void slc_bump(struct slcan *sl)
> > +static void slc_bump_frame(struct slcan *sl)
> >  {
> >       struct sk_buff *skb;
> >       struct can_frame *cf;
> > @@ -255,6 +365,24 @@ static void slc_bump(struct slcan *sl)
> >       dev_kfree_skb(skb);
> >  }
> >
> > +static void slc_bump(struct slcan *sl)
> > +{
> > +     switch (sl->rbuff[0]) {
> > +     case 'r':
> > +             fallthrough;
> > +     case 't':
> > +             fallthrough;
> > +     case 'R':
> > +             fallthrough;
> > +     case 'T':
> > +             return slc_bump_frame(sl);
> > +     case 'e':
> > +             return slc_bump_err(sl);
> > +     default:
> > +             return;
> > +     }
> > +}
> > +
> >  /* parse tty input stream */
> >  static void slcan_unesc(struct slcan *sl, unsigned char s)
> >  {
> > --
> > 2.32.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 |



-- 

Dario Binacchi

Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

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

* Re: [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info
  2022-06-13  7:37   ` Marc Kleine-Budde
@ 2022-06-14  6:29     ` Dario Binacchi
  2022-06-14  7:22       ` Marc Kleine-Budde
  0 siblings, 1 reply; 25+ messages in thread
From: Dario Binacchi @ 2022-06-14  6:29 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

On Mon, Jun 13, 2022 at 9:37 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> On 12.06.2022 23:39:27, Dario Binacchi wrote:
> > It extends the protocol to receive the adapter CAN state changes
> > (warning, busoff, etc.) and forward them to the netdev upper levels.
> >
> > Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> >
> > ---
> >
> > Changes in v3:
> > - Drop the patch "can: slcan: simplify the device de-allocation".
> > - Add the patch "can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U".
> >
> > Changes in v2:
> > - Continue error handling even if no skb can be allocated.
> >
> >  drivers/net/can/slcan/slcan-core.c | 66 ++++++++++++++++++++++++++++++
> >  1 file changed, 66 insertions(+)
> >
> > diff --git a/drivers/net/can/slcan/slcan-core.c b/drivers/net/can/slcan/slcan-core.c
> > index 48077edb9497..5ba1c141f942 100644
> > --- a/drivers/net/can/slcan/slcan-core.c
> > +++ b/drivers/net/can/slcan/slcan-core.c
> > @@ -78,6 +78,9 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
> >  #define SLC_CMD_LEN 1
> >  #define SLC_SFF_ID_LEN 3
> >  #define SLC_EFF_ID_LEN 8
> > +#define SLC_STATE_LEN 1
> > +#define SLC_STATE_BE_RXCNT_LEN 3
> > +#define SLC_STATE_BE_TXCNT_LEN 3
> >
> >  struct slcan {
> >       struct can_priv         can;
> > @@ -175,6 +178,67 @@ int slcan_enable_err_rst_on_open(struct net_device *ndev, bool on)
> >    *                  STANDARD SLCAN DECAPSULATION                     *
> >    ************************************************************************/
> >
> > +static void slc_bump_state(struct slcan *sl)
> > +{
> > +     struct net_device *dev = sl->dev;
> > +     struct sk_buff *skb;
> > +     struct can_frame *cf;
> > +     char *cmd = sl->rbuff;
> > +     u32 rxerr, txerr;
> > +     enum can_state state, rx_state, tx_state;
> > +
> > +     if (*cmd != 's')
> > +             return;
>
> Checked by the caller?
>
> > +
> > +     cmd += SLC_CMD_LEN;
> > +     switch (*cmd) {
> > +     case 'a':
> > +             state = CAN_STATE_ERROR_ACTIVE;
> > +             break;
> > +     case 'w':
> > +             state = CAN_STATE_ERROR_WARNING;
> > +             break;
> > +     case 'p':
> > +             state = CAN_STATE_ERROR_PASSIVE;
> > +             break;
> > +     case 'f':
> > +             state = CAN_STATE_BUS_OFF;
> > +             break;
> > +     default:
> > +             return;
> > +     }
> > +
> > +     if (state == sl->can.state)
> > +             return;
> > +
> > +     cmd += SLC_STATE_BE_RXCNT_LEN + 1;
>
> Have you checked that you have received that much data?
>
> > +     cmd[SLC_STATE_BE_TXCNT_LEN] = 0;
> > +     if (kstrtou32(cmd, 10, &txerr))
> > +             return;
> > +
> > +     *cmd = 0;
> > +     cmd -= SLC_STATE_BE_RXCNT_LEN;
> > +     if (kstrtou32(cmd, 10, &rxerr))
> > +             return;
>
> Why do you parse TX first and then RX?

Since adding the end-of-string character to the counter to be decoded
invalidates the next one.
If I had started from the rx counter, I would have found the
transmission counter always at 0.

Thanks and regards,
Dario

>
> > +
> > +     skb = alloc_can_err_skb(dev, &cf);
> > +
> > +     if (skb) {
> > +             cf->data[6] = txerr;
> > +             cf->data[7] = rxerr;
> > +     }
> > +
> > +     tx_state = txerr >= rxerr ? state : 0;
> > +     rx_state = txerr <= rxerr ? state : 0;
> > +     can_change_state(dev, skb ? cf : NULL, tx_state, rx_state);
>
> alloc_can_err_skb() set cf to NULL if no skb can be allocated.
>
> > +
> > +     if (state == CAN_STATE_BUS_OFF)
> > +             can_bus_off(dev);
> > +
> > +     if (skb)
> > +             netif_rx(skb);
> > +}
> > +
> >  static void slc_bump_err(struct slcan *sl)
> >  {
> >       struct net_device *dev = sl->dev;
> > @@ -378,6 +442,8 @@ static void slc_bump(struct slcan *sl)
> >               return slc_bump_frame(sl);
> >       case 'e':
> >               return slc_bump_err(sl);
> > +     case 's':
> > +             return slc_bump_state(sl);
> >       default:
> >               return;
> >       }
> > --
> > 2.32.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 |



-- 

Dario Binacchi

Embedded Linux Developer

dario.binacchi@amarulasolutions.com

__________________________________


Amarula Solutions SRL

Via Le Canevare 30, 31100 Treviso, Veneto, IT

T. +39 042 243 5310
info@amarulasolutions.com

www.amarulasolutions.com

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

* Re: [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info
  2022-06-14  6:29     ` Dario Binacchi
@ 2022-06-14  7:22       ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-14  7:22 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Greg Kroah-Hartman,
	Jakub Kicinski, Jiri Slaby, Paolo Abeni,
	Sebastian Andrzej Siewior, Vincent Mailhol, Wolfgang Grandegger,
	linux-can, netdev

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

On 14.06.2022 08:29:57, Dario Binacchi wrote:
> > > +     cmd[SLC_STATE_BE_TXCNT_LEN] = 0;
> > > +     if (kstrtou32(cmd, 10, &txerr))
> > > +             return;
> > > +
> > > +     *cmd = 0;
> > > +     cmd -= SLC_STATE_BE_RXCNT_LEN;
> > > +     if (kstrtou32(cmd, 10, &rxerr))
> > > +             return;
> >
> > Why do you parse TX first and then RX?
> 
> Since adding the end-of-string character to the counter to be decoded
> invalidates the next one.
> If I had started from the rx counter, I would have found the
> transmission counter always at 0.

Thanks for the explanation.

regards,
Marc

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

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

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

* Re: [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U
  2022-06-13 20:44     ` Dario Binacchi
@ 2022-06-14  7:24       ` Marc Kleine-Budde
  0 siblings, 0 replies; 25+ messages in thread
From: Marc Kleine-Budde @ 2022-06-14  7:24 UTC (permalink / raw)
  To: Dario Binacchi
  Cc: linux-kernel, michael, Amarula patchwork, Oliver Hartkopp,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Vincent Mailhol, Wolfgang Grandegger, linux-can, netdev

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

On 13.06.2022 22:44:12, Dario Binacchi wrote:
> On Mon, Jun 13, 2022 at 9:11 AM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
> > This would make the code a lot cleaner. Can you think of a nice macro
> > name for the -1?
> >
> > 0 could be CAN_BITRATE_UNCONFIGURED or _UNSET. For -1 I cannot find a
> > catchy name, something like CAN_BITRATE_CONFIGURED_UNKOWN or
> > SET_UNKNOWN.
> >
> 
> Personally I would use CAN_BITRATE_UNSET (0) and CAN_BITRATE_UNKNOWN (-1).
> Let me know what your ultimate preference is.

Looks good.

Marc

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

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

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

end of thread, other threads:[~2022-06-14  7:24 UTC | newest]

Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-12 21:39 [PATCH v3 00/13] can: slcan: extend supported features Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 01/13] can: slcan: use the BIT() helper Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 02/13] can: slcan: use netdev helpers to print out messages Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 03/13] can: slcan: use the alloc_can_skb() helper Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 04/13] can: slcan: use CAN network device driver API Dario Binacchi
2022-06-13  7:01   ` Marc Kleine-Budde
2022-06-12 21:39 ` [PATCH v3 05/13] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U Dario Binacchi
2022-06-13  7:10   ` Marc Kleine-Budde
2022-06-13 20:44     ` Dario Binacchi
2022-06-14  7:24       ` Marc Kleine-Budde
2022-06-12 21:39 ` [PATCH v3 06/13] can: slcan: allow to send commands to the adapter Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 07/13] can: slcan: set bitrate by CAN device driver API Dario Binacchi
2022-06-13  7:17   ` Marc Kleine-Budde
2022-06-12 21:39 ` [PATCH v3 08/13] can: slcan: send the open command to the adapter Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 09/13] can: slcan: send the close " Dario Binacchi
2022-06-13  7:22   ` Marc Kleine-Budde
2022-06-12 21:39 ` [PATCH v3 10/13] can: slcan: move driver into separate sub directory Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 11/13] can: slcan: add ethtool support to reset adapter errors Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 12/13] can: slcan: extend the protocol with error info Dario Binacchi
2022-06-13  7:32   ` Marc Kleine-Budde
2022-06-13 21:04     ` Dario Binacchi
2022-06-12 21:39 ` [PATCH v3 13/13] can: slcan: extend the protocol with CAN state info Dario Binacchi
2022-06-13  7:37   ` Marc Kleine-Budde
2022-06-14  6:29     ` Dario Binacchi
2022-06-14  7:22       ` 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.