Skip to content

Commit

Permalink
can: slcan: use the alloc_can_skb() helper
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dario Binacchi authored and Marc Kleine-Budde committed Jul 3, 2022
1 parent da6788e commit 92a3178
Showing 1 changed file with 33 additions and 37 deletions.
70 changes: 33 additions & 37 deletions drivers/net/can/slcan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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 */
Expand Down

0 comments on commit 92a3178

Please sign in to comment.