From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
To: Marc Kleine-Budde <mkl@pengutronix.de>
Cc: netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org,
linux-can@vger.kernel.org, kernel@pengutronix.de,
Jeroen Hofstee <jhofstee@victronenergy.com>
Subject: Re: [PATCH net-next 08/15] can: slcan: use CAN network device driver API
Date: Sun, 10 Jul 2022 17:38:40 +0200 [thread overview]
Message-ID: <CABGWkvpcHhicFGs96+czuTeVuxbXoKXx_XPvQPGt98GEvqr6aw@mail.gmail.com> (raw)
In-Reply-To: <20220703101430.1306048-9-mkl@pengutronix.de>
Hi Marc,
On Sun, Jul 3, 2022 at 12:26 PM Marc Kleine-Budde <mkl@pengutronix.de> wrote:
>
> From: Dario Binacchi <dario.binacchi@amarulasolutions.com>
>
> 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.
>
> Using the rtnl_lock()/rtnl_unlock() functions has become a bit more
> tricky as the register_candev() function indirectly calls rtnl_lock()
> via register_netdev(). To avoid a deadlock it is therefore necessary to
> call rtnl_unlock() before calling register_candev(). The same goes for
> the unregister_candev() function.
>
> [1] commit 39549eef3587f ("can: CAN Network device driver and Netlink interface")
>
> Link: https://lore.kernel.org/all/20220628163137.413025-6-dario.binacchi@amarulasolutions.com
> Signed-off-by: Dario Binacchi <dario.binacchi@amarulasolutions.com>
> Tested-by: Jeroen Hofstee <jhofstee@victronenergy.com>
> Signed-off-by: Marc Kleine-Budde <mkl@pengutronix.de>
> ---
> drivers/net/can/Kconfig | 40 ++++++++++----------
> drivers/net/can/slcan.c | 82 ++++++++++++++++++++---------------------
> 2 files changed, 60 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 4078d0775572..3048ad77edb3 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -49,26 +49,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_NETLINK
> bool "CAN device drivers with Netlink support"
> default y
> @@ -172,6 +152,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..bf84698f1a81 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. */
> @@ -394,6 +394,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);
Maybe better to move the spin_unlock_bh() before calling close_candev()?
Thanks and regards,
Dario
> @@ -405,20 +407,34 @@ 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 CAN_BITRATE_UNSET (0), causing
> + * open_candev() to fail. So let's set to a fake value.
> + */
> + sl->can.bittiming.bitrate = CAN_BITRATE_UNKNOWN;
> + 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;
>
> + free_candev(sl->dev);
> slcan_devs[i] = NULL;
> }
>
> @@ -434,24 +450,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 +512,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 +526,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;
> @@ -605,26 +598,28 @@ static int slcan_open(struct tty_struct *tty)
>
> set_bit(SLF_INUSE, &sl->flags);
>
> - err = register_netdevice(sl->dev);
> - if (err)
> + rtnl_unlock();
> + err = register_candev(sl->dev);
> + if (err) {
> + pr_err("slcan: can't register candev\n");
> goto err_free_chan;
> + }
> + } else {
> + rtnl_unlock();
> }
>
> - /* Done. We have linked the TTY line to a channel. */
> - rtnl_unlock();
> tty->receive_room = 65536; /* We don't flow control */
>
> /* TTY layer expects 0 on success */
> return 0;
>
> err_free_chan:
> + rtnl_lock();
> 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 */
> + slc_dealloc(sl);
> rtnl_unlock();
> - free_netdev(sl->dev);
> return err;
>
> err_exit:
> @@ -658,9 +653,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);
> + rtnl_lock();
> + slc_dealloc(sl);
> + rtnl_unlock();
> }
>
> static void slcan_hangup(struct tty_struct *tty)
> @@ -768,14 +765,15 @@ 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");
> }
>
> - unregister_netdev(dev);
> + slc_close(dev);
> + unregister_candev(dev);
> + slc_dealloc(sl);
> }
>
> kfree(slcan_devs);
> --
> 2.35.1
>
>
--
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
next prev parent reply other threads:[~2022-07-10 15:38 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-07-03 10:14 [PATCH net-next 0/15] pull-request: can-next 2022-07-03 Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 01/15] tty: Add N_CAN327 line discipline ID for ELM327 based CAN driver Marc Kleine-Budde
2022-07-03 11:40 ` patchwork-bot+netdevbpf
2022-07-03 10:14 ` [PATCH net-next 02/15] can: can327: CAN/ldisc driver for ELM327 based OBD-II adapters Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 03/15] can: ctucanfd: ctucan_interrupt(): fix typo Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 04/15] can: slcan: use the BIT() helper Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 05/15] can: slcan: use netdev helpers to print out messages Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 06/15] can: slcan: use the alloc_can_skb() helper Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 07/15] can: netlink: dump bitrate 0 if can_priv::bittiming.bitrate is -1U Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 08/15] can: slcan: use CAN network device driver API Marc Kleine-Budde
2022-07-10 15:38 ` Dario Binacchi [this message]
2022-07-03 10:14 ` [PATCH net-next 09/15] can: slcan: allow to send commands to the adapter Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 10/15] can: slcan: set bitrate by CAN device driver API Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 11/15] can: slcan: send the open/close commands to the adapter Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 12/15] can: slcan: move driver into separate sub directory Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 13/15] can: slcan: add ethtool support to reset adapter errors Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 14/15] can: slcan: extend the protocol with error info Marc Kleine-Budde
2022-07-03 10:14 ` [PATCH net-next 15/15] can: slcan: extend the protocol with CAN state info Marc Kleine-Budde
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=CABGWkvpcHhicFGs96+czuTeVuxbXoKXx_XPvQPGt98GEvqr6aw@mail.gmail.com \
--to=dario.binacchi@amarulasolutions.com \
--cc=davem@davemloft.net \
--cc=jhofstee@victronenergy.com \
--cc=kernel@pengutronix.de \
--cc=kuba@kernel.org \
--cc=linux-can@vger.kernel.org \
--cc=mkl@pengutronix.de \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).