Commit 92a31782 authored by Dario Binacchi's avatar Dario Binacchi Committed by Marc Kleine-Budde

can: slcan: use the alloc_can_skb() helper

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.comSigned-off-by: default avatarDario Binacchi <dario.binacchi@amarulasolutions.com>
Tested-by: default avatarJeroen Hofstee <jhofstee@victronenergy.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent da6788ea
......@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment