From: Marc Kleine-Budde <mkl@pengutronix.de>
To: Alexander Stein <alexander.stein@systec-electronic.com>,
Wolfgang Grandegger <wg@grandegger.com>
Cc: linux-can@vger.kernel.org
Subject: Re: [PATCH 2/5] can: slcan: Convert to can_dev interface
Date: Thu, 17 Apr 2014 21:10:35 +0200 [thread overview]
Message-ID: <5350272B.70703@pengutronix.de> (raw)
In-Reply-To: <1397573468-7619-3-git-send-email-alexander.stein@systec-electronic.com>
[-- Attachment #1: Type: text/plain, Size: 10981 bytes --]
On 04/15/2014 04:51 PM, Alexander Stein wrote:
> No actual feature change despite the interface name. This is just a
> preparation for additional CAN related features.
>
> Signed-off-by: Alexander Stein <alexander.stein@systec-electronic.com>
> ---
> drivers/net/can/Kconfig | 40 +++++++++----------
> drivers/net/can/slcan.c | 104 +++++++++++++++++++++---------------------------
> 2 files changed, 65 insertions(+), 79 deletions(-)
>
> diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
> index 9e7d95d..daea043 100644
> --- a/drivers/net/can/Kconfig
> +++ b/drivers/net/can/Kconfig
> @@ -9,26 +9,6 @@ config CAN_VCAN
> This driver can also be built as a module. If so, the module
> will be called vcan.
>
> -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 SocketCAN SVN, see
> - http://developer.berlios.de/projects/socketcan 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
> @@ -125,6 +105,26 @@ config CAN_GRCAN
> endian syntheses of the cores would need some modifications on
> the hardware level to work.
>
> +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 SocketCAN SVN, see
> + http://developer.berlios.de/projects/socketcan 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.
> +
> source "drivers/net/can/mscan/Kconfig"
>
> source "drivers/net/can/sja1000/Kconfig"
> diff --git a/drivers/net/can/slcan.c b/drivers/net/can/slcan.c
> index 2577c1e..337e6e3 100644
> --- a/drivers/net/can/slcan.c
> +++ b/drivers/net/can/slcan.c
> @@ -53,6 +53,7 @@
> #include <linux/init.h>
> #include <linux/kernel.h>
> #include <linux/can.h>
> +#include <linux/can/dev.h>
> #include <linux/can/skb.h>
>
> static __initconst const char banner[] =
> @@ -79,6 +80,7 @@ MODULE_PARM_DESC(maxdev, "Maximum number of slcan interfaces");
> #define SLC_EFF_ID_LEN 8
>
> struct slcan {
> + struct can_priv can; /* must be the first member */
> int magic;
>
> /* Various fields. */
> @@ -99,6 +101,7 @@ struct slcan {
> };
>
> static struct net_device **slcan_devs;
> +static DEFINE_MUTEX(slcan_mutex);
>
> /************************************************************************
> * SLCAN ENCAPSULATION FORMAT *
> @@ -143,31 +146,33 @@ 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;
> + canid_t can_id;
> + u8 can_dlc;
> int i, tmp;
> u32 tmpid;
> char *cmd = sl->rbuff;
>
> - cf.can_id = 0;
> + can_id = 0;
>
> switch (*cmd) {
> case 'r':
> - cf.can_id = CAN_RTR_FLAG;
> + can_id = CAN_RTR_FLAG;
> /* fallthrough */
> case 't':
> /* store dlc ASCII value and terminate SFF CAN ID string */
> - cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_SFF_ID_LEN];
> + can_dlc = 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;
> + can_id = CAN_RTR_FLAG;
> /* fallthrough */
> case 'T':
> - cf.can_id |= CAN_EFF_FLAG;
> + can_id |= CAN_EFF_FLAG;
> /* store dlc ASCII value and terminate EFF CAN ID string */
> - cf.can_dlc = sl->rbuff[SLC_CMD_LEN + SLC_EFF_ID_LEN];
> + can_dlc = 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;
> @@ -179,49 +184,39 @@ static void slc_bump(struct slcan *sl)
> if (kstrtou32(sl->rbuff + SLC_CMD_LEN, 16, &tmpid))
> return;
>
> - cf.can_id |= tmpid;
> + can_id |= tmpid;
>
> /* get can_dlc from sanitized ASCII value */
> - if (cf.can_dlc >= '0' && cf.can_dlc < '9')
> - cf.can_dlc -= '0';
> + if (can_dlc >= '0' && can_dlc < '9')
> + can_dlc -= '0';
> else
> return;
>
> - *(u64 *) (&cf.data) = 0; /* clear payload */
> + skb = alloc_can_skb(sl->dev, &cf);
> + if (!skb)
> + return;
> + cf->can_id = can_id;
> + cf->can_dlc = can_dlc;
>
> /* 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.can_dlc; i++) {
> + if (!(cf->can_id & CAN_RTR_FLAG)) {
> + for (i = 0; i < cf->can_dlc; i++) {
> tmp = hex_to_bin(*cmd++);
> if (tmp < 0)
> return;
> - cf.data[i] = (tmp << 4);
> + cf->data[i] = (tmp << 4);
> tmp = hex_to_bin(*cmd++);
> if (tmp < 0)
> return;
> - cf.data[i] |= tmp;
> + cf->data[i] |= tmp;
> }
> }
> -
> - skb = dev_alloc_skb(sizeof(struct can_frame) +
> - sizeof(struct can_skb_priv));
> - if (!skb)
> - return;
> -
> skb->dev = sl->dev;
I think this is not needed anymore, as alloc_can_skb() sets this already.
> - 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;
>
> - memcpy(skb_put(skb, sizeof(struct can_frame)),
> - &cf, sizeof(struct can_frame));
> netif_rx_ni(skb);
>
> sl->dev->stats.rx_packets++;
> - sl->dev->stats.rx_bytes += cf.can_dlc;
> + sl->dev->stats.rx_bytes += cf->can_dlc;
Please don't touch the skb (and this cf) after netif_rx_ni
> }
>
> /* parse tty input stream */
> @@ -385,6 +380,10 @@ static int slc_close(struct net_device *dev)
> netif_stop_queue(dev);
> sl->rcount = 0;
> sl->xleft = 0;
> + sl->can.state = CAN_STATE_STOPPED;
> +
> + close_candev(dev);
> +
> spin_unlock_bh(&sl->lock);
>
> return 0;
> @@ -394,12 +393,19 @@ 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;
>
> + err = open_candev(dev);
> + if (err)
> + return err;
> +
> + sl->can.state = CAN_STATE_ERROR_ACTIVE;
> sl->flags &= (1 << SLF_INUSE);
> netif_start_queue(dev);
> +
> return 0;
> }
>
> @@ -407,7 +413,7 @@ static int slc_open(struct net_device *dev)
> static void slc_free_netdev(struct net_device *dev)
> {
> int i = dev->base_addr;
> - free_netdev(dev);
> + free_candev(dev);
> slcan_devs[i] = NULL;
> }
>
> @@ -417,23 +423,6 @@ static const struct net_device_ops slc_netdev_ops = {
> .ndo_start_xmit = slc_xmit,
> };
>
> -static void slc_setup(struct net_device *dev)
> -{
> - dev->netdev_ops = &slc_netdev_ops;
> - dev->destructor = slc_free_netdev;
> -
> - dev->hard_header_len = 0;
> - dev->addr_len = 0;
> - dev->tx_queue_len = 10;
> -
> - dev->mtu = sizeof(struct can_frame);
> - dev->type = ARPHRD_CAN;
> -
> - /* New-style flags. */
> - dev->flags = IFF_NOARP;
> - dev->features = NETIF_F_HW_CSUM;
> -}
> -
> /******************************************
> Routines looking at TTY side.
> ******************************************/
> @@ -495,7 +484,6 @@ static void slc_sync(void)
> static struct slcan *slc_alloc(dev_t line)
> {
> int i;
> - char name[IFNAMSIZ];
> struct net_device *dev = NULL;
> struct slcan *sl;
>
> @@ -510,12 +498,13 @@ static struct slcan *slc_alloc(dev_t line)
> if (i >= maxdev)
> return NULL;
>
> - sprintf(name, "slcan%d", i);
> - dev = alloc_netdev(sizeof(*sl), name, slc_setup);
> + dev = alloc_candev(sizeof(*sl), 1);
> if (!dev)
> return NULL;
>
> dev->base_addr = i;
> + dev->netdev_ops = &slc_netdev_ops;
> + dev->destructor = slc_free_netdev;
> sl = netdev_priv(dev);
>
> /* Initialize channel control data */
> @@ -548,11 +537,8 @@ 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();
> + /* Serialize concurrent opens of slcan channels. */
> + mutex_lock(&slcan_mutex);
>
> /* Collect hanged up channels. */
> slc_sync();
> @@ -580,13 +566,13 @@ static int slcan_open(struct tty_struct *tty)
>
> set_bit(SLF_INUSE, &sl->flags);
>
> - err = register_netdevice(sl->dev);
> + err = register_candev(sl->dev);
> if (err)
> goto err_free_chan;
> }
>
> /* Done. We have linked the TTY line to a channel. */
> - rtnl_unlock();
> + mutex_unlock(&slcan_mutex);
> tty->receive_room = 65536; /* We don't flow control */
>
> /* TTY layer expects 0 on success */
> @@ -598,7 +584,7 @@ err_free_chan:
> clear_bit(SLF_INUSE, &sl->flags);
>
> err_exit:
> - rtnl_unlock();
> + mutex_unlock(&slcan_mutex);
>
> /* Count references from TTY module */
> return err;
>
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Industrial Linux Solutions | Phone: +49-231-2826-924 |
Vertretung West/Dortmund | Fax: +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de |
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 242 bytes --]
next prev parent reply other threads:[~2014-04-17 19:10 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-15 14:51 Bitrate and CAN status support for slcan Alexander Stein
2014-04-15 14:51 ` [PATCH 1/5] can: slcan: Fix spinlock variant Alexander Stein
2014-04-22 19:58 ` Oliver Hartkopp
2014-04-24 20:32 ` Marc Kleine-Budde
2014-04-15 14:51 ` [PATCH 2/5] can: slcan: Convert to can_dev interface Alexander Stein
2014-04-17 19:10 ` Marc Kleine-Budde [this message]
2014-04-15 14:51 ` [PATCH 3/5] can: slcan: Send open/close command upon interface up/down Alexander Stein
2014-04-15 14:51 ` [PATCH 4/5] can: slcan: Add bitrate change support Alexander Stein
2014-04-17 19:13 ` Marc Kleine-Budde
2014-04-15 14:51 ` [PATCH 5/5] can: slcan: Add CAN status flag support Alexander Stein
2014-04-17 19:22 ` Marc Kleine-Budde
2014-04-19 20:38 ` Oliver Hartkopp
2014-04-19 19:24 ` Bitrate and CAN status support for slcan Oliver Hartkopp
2014-04-22 7:08 ` Alexander Stein
2014-04-22 19:50 ` Oliver Hartkopp
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=5350272B.70703@pengutronix.de \
--to=mkl@pengutronix.de \
--cc=alexander.stein@systec-electronic.com \
--cc=linux-can@vger.kernel.org \
--cc=wg@grandegger.com \
/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).