Skip to content

Commit 7b6856a

Browse files
grandwolfdavem330
authored andcommitted
can: provide library functions for skb allocation
This patch makes the private functions alloc_can_skb() and alloc_can_err_skb() of the at91_can driver public and adapts all drivers to use these. While making the patch I realized, that the skb's are *not* setup consistently. It's now done as shown below: skb->protocol = htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; skb->ip_summed = CHECKSUM_UNNECESSARY; *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); memset(*cf, 0, sizeof(struct can_frame)); The frame is zeroed out to avoid uninitialized data to be passed to user space. Some drivers or library code did not set "pkt_type" or "ip_summed". Also, "__constant_htons()" should not be used for runtime invocations, as pointed out by David Miller. Signed-off-by: Wolfgang Grandegger <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0eae750 commit 7b6856a

File tree

6 files changed

+47
-76
lines changed

6 files changed

+47
-76
lines changed

drivers/net/can/at91_can.c

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -221,38 +221,6 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
221221
set_mb_mode_prio(priv, mb, mode, 0);
222222
}
223223

224-
static struct sk_buff *alloc_can_skb(struct net_device *dev,
225-
struct can_frame **cf)
226-
{
227-
struct sk_buff *skb;
228-
229-
skb = netdev_alloc_skb(dev, sizeof(struct can_frame));
230-
if (unlikely(!skb))
231-
return NULL;
232-
233-
skb->protocol = htons(ETH_P_CAN);
234-
skb->ip_summed = CHECKSUM_UNNECESSARY;
235-
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
236-
237-
return skb;
238-
}
239-
240-
static struct sk_buff *alloc_can_err_skb(struct net_device *dev,
241-
struct can_frame **cf)
242-
{
243-
struct sk_buff *skb;
244-
245-
skb = alloc_can_skb(dev, cf);
246-
if (unlikely(!skb))
247-
return NULL;
248-
249-
memset(*cf, 0, sizeof(struct can_frame));
250-
(*cf)->can_id = CAN_ERR_FLAG;
251-
(*cf)->can_dlc = CAN_ERR_DLC;
252-
253-
return skb;
254-
}
255-
256224
/*
257225
* Swtich transceiver on or off
258226
*/

drivers/net/can/dev.c

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -366,17 +366,12 @@ void can_restart(unsigned long data)
366366
can_flush_echo_skb(dev);
367367

368368
/* send restart message upstream */
369-
skb = dev_alloc_skb(sizeof(struct can_frame));
369+
skb = alloc_can_err_skb(dev, &cf);
370370
if (skb == NULL) {
371371
err = -ENOMEM;
372372
goto restart;
373373
}
374-
skb->dev = dev;
375-
skb->protocol = htons(ETH_P_CAN);
376-
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
377-
memset(cf, 0, sizeof(struct can_frame));
378-
cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;
379-
cf->can_dlc = CAN_ERR_DLC;
374+
cf->can_id |= CAN_ERR_RESTARTED;
380375

381376
netif_rx(skb);
382377

@@ -449,6 +444,39 @@ static void can_setup(struct net_device *dev)
449444
dev->features = NETIF_F_NO_CSUM;
450445
}
451446

447+
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf)
448+
{
449+
struct sk_buff *skb;
450+
451+
skb = netdev_alloc_skb(dev, sizeof(struct can_frame));
452+
if (unlikely(!skb))
453+
return NULL;
454+
455+
skb->protocol = htons(ETH_P_CAN);
456+
skb->pkt_type = PACKET_BROADCAST;
457+
skb->ip_summed = CHECKSUM_UNNECESSARY;
458+
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
459+
memset(*cf, 0, sizeof(struct can_frame));
460+
461+
return skb;
462+
}
463+
EXPORT_SYMBOL_GPL(alloc_can_skb);
464+
465+
struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf)
466+
{
467+
struct sk_buff *skb;
468+
469+
skb = alloc_can_skb(dev, cf);
470+
if (unlikely(!skb))
471+
return NULL;
472+
473+
(*cf)->can_id = CAN_ERR_FLAG;
474+
(*cf)->can_dlc = CAN_ERR_DLC;
475+
476+
return skb;
477+
}
478+
EXPORT_SYMBOL_GPL(alloc_can_err_skb);
479+
452480
/*
453481
* Allocate and setup space for the CAN network device
454482
*/

drivers/net/can/sja1000/sja1000.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,9 @@ static void sja1000_rx(struct net_device *dev)
296296
uint8_t dlc;
297297
int i;
298298

299-
skb = dev_alloc_skb(sizeof(struct can_frame));
299+
skb = alloc_can_skb(dev, &cf);
300300
if (skb == NULL)
301301
return;
302-
skb->dev = dev;
303-
skb->protocol = htons(ETH_P_CAN);
304302

305303
fi = priv->read_reg(priv, REG_FI);
306304
dlc = fi & 0x0F;
@@ -351,15 +349,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
351349
enum can_state state = priv->can.state;
352350
uint8_t ecc, alc;
353351

354-
skb = dev_alloc_skb(sizeof(struct can_frame));
352+
skb = alloc_can_err_skb(dev, &cf);
355353
if (skb == NULL)
356354
return -ENOMEM;
357-
skb->dev = dev;
358-
skb->protocol = htons(ETH_P_CAN);
359-
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
360-
memset(cf, 0, sizeof(struct can_frame));
361-
cf->can_id = CAN_ERR_FLAG;
362-
cf->can_dlc = CAN_ERR_DLC;
363355

364356
if (isrc & IRQ_DOI) {
365357
/* data overrun interrupt */

drivers/net/can/ti_hecc.c

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -535,18 +535,15 @@ static int ti_hecc_rx_pkt(struct ti_hecc_priv *priv, int mbxno)
535535
u32 data, mbx_mask;
536536
unsigned long flags;
537537

538-
skb = netdev_alloc_skb(priv->ndev, sizeof(struct can_frame));
538+
skb = alloc_can_skb(priv->ndev, &cf);
539539
if (!skb) {
540540
if (printk_ratelimit())
541541
dev_err(priv->ndev->dev.parent,
542-
"ti_hecc_rx_pkt: netdev_alloc_skb() failed\n");
542+
"ti_hecc_rx_pkt: alloc_can_skb() failed\n");
543543
return -ENOMEM;
544544
}
545-
skb->protocol = __constant_htons(ETH_P_CAN);
546-
skb->ip_summed = CHECKSUM_UNNECESSARY;
547545

548546
mbx_mask = BIT(mbxno);
549-
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
550547
data = hecc_read_mbx(priv, mbxno, HECC_CANMID);
551548
if (data & HECC_CANMID_IDE)
552549
cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG;
@@ -656,19 +653,13 @@ static int ti_hecc_error(struct net_device *ndev, int int_status,
656653
struct sk_buff *skb;
657654

658655
/* propogate the error condition to the can stack */
659-
skb = netdev_alloc_skb(ndev, sizeof(struct can_frame));
656+
skb = alloc_can_err_skb(ndev, &cf);
660657
if (!skb) {
661658
if (printk_ratelimit())
662659
dev_err(priv->ndev->dev.parent,
663-
"ti_hecc_error: netdev_alloc_skb() failed\n");
660+
"ti_hecc_error: alloc_can_err_skb() failed\n");
664661
return -ENOMEM;
665662
}
666-
skb->protocol = __constant_htons(ETH_P_CAN);
667-
skb->ip_summed = CHECKSUM_UNNECESSARY;
668-
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
669-
memset(cf, 0, sizeof(struct can_frame));
670-
cf->can_id = CAN_ERR_FLAG;
671-
cf->can_dlc = CAN_ERR_DLC;
672663

673664
if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
674665
if ((int_status & HECC_CANGIF_BOIF) == 0) {

drivers/net/can/usb/ems_usb.c

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -311,14 +311,10 @@ static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg)
311311
int i;
312312
struct net_device_stats *stats = &dev->netdev->stats;
313313

314-
skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
314+
skb = alloc_can_skb(dev->netdev, &cf);
315315
if (skb == NULL)
316316
return;
317317

318-
skb->protocol = htons(ETH_P_CAN);
319-
320-
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
321-
322318
cf->can_id = msg->msg.can_msg.id;
323319
cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8);
324320

@@ -346,18 +342,10 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
346342
struct sk_buff *skb;
347343
struct net_device_stats *stats = &dev->netdev->stats;
348344

349-
skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame));
345+
skb = alloc_can_err_skb(dev->netdev, &cf);
350346
if (skb == NULL)
351347
return;
352348

353-
skb->protocol = htons(ETH_P_CAN);
354-
355-
cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
356-
memset(cf, 0, sizeof(struct can_frame));
357-
358-
cf->can_id = CAN_ERR_FLAG;
359-
cf->can_dlc = CAN_ERR_DLC;
360-
361349
if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
362350
u8 state = msg->msg.can_state;
363351

include/linux/can/dev.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,8 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
6868
void can_get_echo_skb(struct net_device *dev, unsigned int idx);
6969
void can_free_echo_skb(struct net_device *dev, unsigned int idx);
7070

71+
struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf);
72+
struct sk_buff *alloc_can_err_skb(struct net_device *dev,
73+
struct can_frame **cf);
74+
7175
#endif /* CAN_DEV_H */

0 commit comments

Comments
 (0)