]> git.baikalelectronics.ru Git - kernel.git/commitdiff
can: slcan: use the alloc_can_skb() helper
authorDario Binacchi <dario.binacchi@amarulasolutions.com>
Tue, 28 Jun 2022 16:31:27 +0000 (18:31 +0200)
committerMarc Kleine-Budde <mkl@pengutronix.de>
Sun, 3 Jul 2022 09:34:21 +0000 (11:34 +0200)
It is used successfully by most (if not all) CAN device drivers. It
allows to remove replicated code.

Link: https://lore.kernel.org/all/20220628163137.413025-4-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/slcan.c

index 6162a9c21672cb97b89cb6510e4b16a4e1d818ff..c39580b142e0fc361d243722f37f5076d8286f8e 100644 (file)
@@ -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 */