From: wolf Date: Wed, 7 Oct 2009 17:37:57 +0000 (+0000) Subject: can: provide library functions for skb allocation X-Git-Url: http://rtime.felk.cvut.cz/gitweb/socketcan-devel.git/commitdiff_plain/14c99752aa69ff13c8aa0f3115733073e33370bd?ds=sidebyside 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. The skb's are now setup as shown: skb->protocol = __constant_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 used "htons(ETH_P_CAN)" or did not set "pkt_type" or "ip_summed" or did not zero the fame. Signed-off-by: Wolfgang Grandegger Acked-by: Oliver Hartkopp git-svn-id: svn://svn.berlios.de//socketcan/trunk@1068 030b6a49-0b11-0410-94ab-b0dab22257f2 --- diff --git a/kernel/2.6/drivers/net/can/at91_can.c b/kernel/2.6/drivers/net/can/at91_can.c index 28b65d7..9269640 100644 --- a/kernel/2.6/drivers/net/can/at91_can.c +++ b/kernel/2.6/drivers/net/can/at91_can.c @@ -221,38 +221,6 @@ static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb, set_mb_mode_prio(priv, mb, mode, 0); } -static struct sk_buff *alloc_can_skb(struct net_device *dev, - struct can_frame **cf) -{ - struct sk_buff *skb; - - skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); - if (unlikely(!skb)) - return NULL; - - skb->protocol = htons(ETH_P_CAN); - skb->ip_summed = CHECKSUM_UNNECESSARY; - *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - - return skb; -} - -static struct sk_buff *alloc_can_err_skb(struct net_device *dev, - struct can_frame **cf) -{ - struct sk_buff *skb; - - skb = alloc_can_skb(dev, cf); - if (unlikely(!skb)) - return NULL; - - memset(*cf, 0, sizeof(struct can_frame)); - (*cf)->can_id = CAN_ERR_FLAG; - (*cf)->can_dlc = CAN_ERR_DLC; - - return skb; -} - /* * Swtich transceiver on or off */ diff --git a/kernel/2.6/drivers/net/can/cc770/cc770.c b/kernel/2.6/drivers/net/can/cc770/cc770.c index 02c033e..c7a3240 100644 --- a/kernel/2.6/drivers/net/can/cc770/cc770.c +++ b/kernel/2.6/drivers/net/can/cc770/cc770.c @@ -517,13 +517,10 @@ static void cc770_rx(struct net_device *dev, unsigned int mo, u8 ctrl1) u32 id; int i; - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_skb(dev, &cf); if (skb == NULL) return; - skb->dev = dev; - skb->protocol = htons(ETH_P_CAN); - cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); config = cc770_read_reg(priv, msgobj[mo].config); if (ctrl1 & RMTPND_SET) { @@ -582,15 +579,9 @@ static int cc770_err(struct net_device *dev, u8 status) dev_dbg(ND2D(dev), "status interrupt (%#x)\n", status); - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) return -ENOMEM; - skb->dev = dev; - skb->protocol = htons(ETH_P_CAN); - cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - memset(cf, 0, sizeof(struct can_frame)); - cf->can_id = CAN_ERR_FLAG; - cf->can_dlc = CAN_ERR_DLC; if (status & STAT_BOFF) { /* Disable interrupts */ diff --git a/kernel/2.6/drivers/net/can/dev.c b/kernel/2.6/drivers/net/can/dev.c index 111e7a9..3be767f 100644 --- a/kernel/2.6/drivers/net/can/dev.c +++ b/kernel/2.6/drivers/net/can/dev.c @@ -318,7 +318,7 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, skb->sk = srcsk; /* make settings for echo to reduce code in irq context */ - skb->protocol = htons(ETH_P_CAN); + skb->protocol = __constant_htons(ETH_P_CAN); skb->pkt_type = PACKET_BROADCAST; skb->ip_summed = CHECKSUM_UNNECESSARY; skb->dev = dev; @@ -397,17 +397,12 @@ void can_restart(unsigned long data) can_flush_echo_skb(dev); /* send restart message upstream */ - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) { err = -ENOMEM; goto restart; } - skb->dev = dev; - skb->protocol = htons(ETH_P_CAN); - cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - memset(cf, 0, sizeof(struct can_frame)); - cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; - cf->can_dlc = CAN_ERR_DLC; + cf->can_id |= CAN_ERR_RESTARTED; netif_rx(skb); @@ -496,6 +491,39 @@ static void can_setup(struct net_device *dev) #endif } +struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) +{ + struct sk_buff *skb; + + skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); + if (unlikely(!skb)) + return NULL; + + skb->protocol = __constant_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)); + + return skb; +} +EXPORT_SYMBOL_GPL(alloc_can_skb); + +struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf) +{ + struct sk_buff *skb; + + skb = alloc_can_skb(dev, cf); + if (unlikely(!skb)) + return NULL; + + (*cf)->can_id = CAN_ERR_FLAG; + (*cf)->can_dlc = CAN_ERR_DLC; + + return skb; +} +EXPORT_SYMBOL_GPL(alloc_can_err_skb); + /* * Allocate and setup space for the CAN network device */ diff --git a/kernel/2.6/drivers/net/can/esd_pci331.c b/kernel/2.6/drivers/net/can/esd_pci331.c index d19578c..534c762 100644 --- a/kernel/2.6/drivers/net/can/esd_pci331.c +++ b/kernel/2.6/drivers/net/can/esd_pci331.c @@ -439,7 +439,7 @@ static int esd331_create_err_frame(struct net_device *dev, canid_t idflags, struct can_frame *cf; struct sk_buff *skb; - skb = dev_alloc_skb(sizeof(*cf)); + skb = alloc_can_err_skb(dev, &cf); if (unlikely(skb == NULL)) return -ENOMEM; @@ -449,13 +449,7 @@ static int esd331_create_err_frame(struct net_device *dev, canid_t idflags, stats = &dev->stats; #endif - skb->dev = dev; - skb->protocol = htons(ETH_P_CAN); - cf = (struct can_frame *)skb_put(skb, sizeof(*cf)); - memset(cf, 0, sizeof(*cf)); - - cf->can_id = CAN_ERR_FLAG | idflags; - cf->can_dlc = CAN_ERR_DLC; + cf->can_id |= idflags; cf->data[1] = d1; netif_rx(skb); @@ -481,15 +475,11 @@ static void esd331_irq_rx(struct net_device *dev, struct esd331_can_msg *msg, struct sk_buff *skb; int i; - skb = netdev_alloc_skb(dev, sizeof(*cfrm)); + skb = alloc_can_skb(dev, &cfrm); if (unlikely(skb == NULL)) { stats->rx_dropped++; return; } - skb->protocol = htons(ETH_P_CAN); - - cfrm = (struct can_frame *)skb_put(skb, sizeof(*cfrm)); - memset(cfrm, 0, sizeof(*cfrm)); if (eff) { cfrm->can_id = (msg->id << 16); diff --git a/kernel/2.6/drivers/net/can/mcp251x.c b/kernel/2.6/drivers/net/can/mcp251x.c index 3f92d17..5fa74be 100644 --- a/kernel/2.6/drivers/net/can/mcp251x.c +++ b/kernel/2.6/drivers/net/can/mcp251x.c @@ -357,15 +357,13 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) struct sk_buff *skb; struct can_frame *frame; - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_skb(priv->net, &frame); if (!skb) { dev_err(&spi->dev, "%s: out of memory for Rx'd frame\n", __func__); priv->net->stats.rx_dropped++; return; } - skb->dev = priv->net; - frame = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); if (pdata->model == CAN_MCP251X_MCP2510) { int i; @@ -457,9 +455,6 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) priv->net->stats.rx_packets++; priv->net->stats.rx_bytes += frame->can_dlc; - skb->protocol = __constant_htons(ETH_P_CAN); - skb->pkt_type = PACKET_BROADCAST; - skb->ip_summed = CHECKSUM_UNNECESSARY; netif_rx(skb); } @@ -808,19 +803,8 @@ static void mcp251x_irq_work_handler(struct work_struct *ws) u8 eflag = mcp251x_read_reg(spi, EFLG); /* create error frame */ - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_err_skb(net, &frame); if (skb) { - frame = (struct can_frame *) - skb_put(skb, sizeof(struct can_frame)); - *(unsigned long long *)&frame->data = 0ULL; - frame->can_id = CAN_ERR_FLAG; - frame->can_dlc = CAN_ERR_DLC; - - skb->dev = net; - skb->protocol = __constant_htons(ETH_P_CAN); - skb->pkt_type = PACKET_BROADCAST; - skb->ip_summed = CHECKSUM_UNNECESSARY; - /* Set error frame flags based on bus state */ if (eflag & EFLG_TXBO) { frame->can_id |= CAN_ERR_BUSOFF; diff --git a/kernel/2.6/drivers/net/can/mscan/mscan.c b/kernel/2.6/drivers/net/can/mscan/mscan.c index 38fe340..e5d5004 100644 --- a/kernel/2.6/drivers/net/can/mscan/mscan.c +++ b/kernel/2.6/drivers/net/can/mscan/mscan.c @@ -364,7 +364,7 @@ static int mscan_rx_poll(struct net_device *dev, int *budget) while (npackets < quota && ((canrflg = in_8(®s->canrflg)) & (MSCAN_RXF | MSCAN_ERR_IF))) { - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_skb(dev, &frame); if (!skb) { if (printk_ratelimit()) dev_notice(ND2D(dev), "packet dropped\n"); @@ -373,9 +373,6 @@ static int mscan_rx_poll(struct net_device *dev, int *budget) continue; } - frame = (struct can_frame *)skb_put(skb, sizeof(*frame)); - memset(frame, 0, sizeof(*frame)); - if (canrflg & MSCAN_RXF) { can_id = in_be16(®s->rx.idr1_0); if (can_id & (1 << 3)) { @@ -459,9 +456,6 @@ static int mscan_rx_poll(struct net_device *dev, int *budget) } npackets++; - skb->dev = dev; - skb->protocol = __constant_htons(ETH_P_CAN); - skb->ip_summed = CHECKSUM_UNNECESSARY; netif_receive_skb(skb); } diff --git a/kernel/2.6/drivers/net/can/sja1000/sja1000.c b/kernel/2.6/drivers/net/can/sja1000/sja1000.c index 84838d4..03c9b9a 100644 --- a/kernel/2.6/drivers/net/can/sja1000/sja1000.c +++ b/kernel/2.6/drivers/net/can/sja1000/sja1000.c @@ -308,11 +308,9 @@ static void sja1000_rx(struct net_device *dev) uint8_t dlc; int i; - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_skb(dev, &cf); if (skb == NULL) return; - skb->dev = dev; - skb->protocol = htons(ETH_P_CAN); fi = priv->read_reg(priv, REG_FI); dlc = fi & 0x0F; @@ -370,15 +368,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) enum can_state state = priv->can.state; uint8_t ecc, alc; - skb = dev_alloc_skb(sizeof(struct can_frame)); + skb = alloc_can_err_skb(dev, &cf); if (skb == NULL) return -ENOMEM; - skb->dev = dev; - skb->protocol = htons(ETH_P_CAN); - cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - memset(cf, 0, sizeof(struct can_frame)); - cf->can_id = CAN_ERR_FLAG; - cf->can_dlc = CAN_ERR_DLC; if (isrc & IRQ_DOI) { /* data overrun interrupt */ diff --git a/kernel/2.6/drivers/net/can/softing/softing_main.c b/kernel/2.6/drivers/net/can/softing/softing_main.c index 8d80734..043ff56 100644 --- a/kernel/2.6/drivers/net/can/softing/softing_main.c +++ b/kernel/2.6/drivers/net/can/softing/softing_main.c @@ -143,16 +143,14 @@ int softing_rx(struct net_device *netdev, const struct can_frame *msg, ktime_t ktime) { struct sk_buff *skb; + struct can_frame *cf; int ret; struct net_device_stats *stats; - skb = dev_alloc_skb(sizeof(msg)); + skb = alloc_can_skb(netdev, &cf); if (!skb) return -ENOMEM; - skb->dev = netdev; - skb->protocol = htons(ETH_P_CAN); - skb->ip_summed = CHECKSUM_UNNECESSARY; - memcpy(skb_put(skb, sizeof(*msg)), msg, sizeof(*msg)); + memcpy(cf, msg, sizeof(*msg)); skb->tstamp = ktime; ret = netif_rx(skb); if (ret == NET_RX_DROP) { diff --git a/kernel/2.6/drivers/net/can/usb/ems_usb.c b/kernel/2.6/drivers/net/can/usb/ems_usb.c index 17df9d7..62d0e04 100644 --- a/kernel/2.6/drivers/net/can/usb/ems_usb.c +++ b/kernel/2.6/drivers/net/can/usb/ems_usb.c @@ -311,14 +311,10 @@ static void ems_usb_rx_can_msg(struct ems_usb *dev, struct ems_cpc_msg *msg) int i; struct net_device_stats *stats = &dev->netdev->stats; - skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame)); + skb = alloc_can_skb(dev->netdev, &cf); if (skb == NULL) return; - skb->protocol = htons(ETH_P_CAN); - - cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - cf->can_id = msg->msg.can_msg.id; cf->can_dlc = min_t(u8, msg->msg.can_msg.length, 8); @@ -349,18 +345,10 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg) struct sk_buff *skb; struct net_device_stats *stats = &dev->netdev->stats; - skb = netdev_alloc_skb(dev->netdev, sizeof(struct can_frame)); + skb = alloc_can_err_skb(dev->netdev, &cf); if (skb == NULL) return; - skb->protocol = htons(ETH_P_CAN); - - cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); - memset(cf, 0, sizeof(struct can_frame)); - - cf->can_id = CAN_ERR_FLAG; - cf->can_dlc = CAN_ERR_DLC; - if (msg->type == CPC_MSG_TYPE_CAN_STATE) { u8 state = msg->msg.can_state; diff --git a/kernel/2.6/include/socketcan/can/dev.h b/kernel/2.6/include/socketcan/can/dev.h index 617037c..9cac237 100644 --- a/kernel/2.6/include/socketcan/can/dev.h +++ b/kernel/2.6/include/socketcan/can/dev.h @@ -88,4 +88,8 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, void can_get_echo_skb(struct net_device *dev, unsigned int idx); void can_free_echo_skb(struct net_device *dev, unsigned int idx); +struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf); +struct sk_buff *alloc_can_err_skb(struct net_device *dev, + struct can_frame **cf); + #endif /* CAN_DEV_H */