diff options
Diffstat (limited to 'drivers/net/can/dev.c')
| -rw-r--r-- | drivers/net/can/dev.c | 76 |
1 files changed, 62 insertions, 14 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 2868fe842a41..c1bb29f0322b 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
| @@ -245,7 +245,7 @@ static void can_flush_echo_skb(struct net_device *dev) | |||
| 245 | struct net_device_stats *stats = &dev->stats; | 245 | struct net_device_stats *stats = &dev->stats; |
| 246 | int i; | 246 | int i; |
| 247 | 247 | ||
| 248 | for (i = 0; i < CAN_ECHO_SKB_MAX; i++) { | 248 | for (i = 0; i < priv->echo_skb_max; i++) { |
| 249 | if (priv->echo_skb[i]) { | 249 | if (priv->echo_skb[i]) { |
| 250 | kfree_skb(priv->echo_skb[i]); | 250 | kfree_skb(priv->echo_skb[i]); |
| 251 | priv->echo_skb[i] = NULL; | 251 | priv->echo_skb[i] = NULL; |
| @@ -262,10 +262,13 @@ static void can_flush_echo_skb(struct net_device *dev) | |||
| 262 | * of the device driver. The driver must protect access to | 262 | * of the device driver. The driver must protect access to |
| 263 | * priv->echo_skb, if necessary. | 263 | * priv->echo_skb, if necessary. |
| 264 | */ | 264 | */ |
| 265 | void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx) | 265 | void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, |
| 266 | unsigned int idx) | ||
| 266 | { | 267 | { |
| 267 | struct can_priv *priv = netdev_priv(dev); | 268 | struct can_priv *priv = netdev_priv(dev); |
| 268 | 269 | ||
| 270 | BUG_ON(idx >= priv->echo_skb_max); | ||
| 271 | |||
| 269 | /* check flag whether this packet has to be looped back */ | 272 | /* check flag whether this packet has to be looped back */ |
| 270 | if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) { | 273 | if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) { |
| 271 | kfree_skb(skb); | 274 | kfree_skb(skb); |
| @@ -311,10 +314,12 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb); | |||
| 311 | * is handled in the device driver. The driver must protect | 314 | * is handled in the device driver. The driver must protect |
| 312 | * access to priv->echo_skb, if necessary. | 315 | * access to priv->echo_skb, if necessary. |
| 313 | */ | 316 | */ |
| 314 | void can_get_echo_skb(struct net_device *dev, int idx) | 317 | void can_get_echo_skb(struct net_device *dev, unsigned int idx) |
| 315 | { | 318 | { |
| 316 | struct can_priv *priv = netdev_priv(dev); | 319 | struct can_priv *priv = netdev_priv(dev); |
| 317 | 320 | ||
| 321 | BUG_ON(idx >= priv->echo_skb_max); | ||
| 322 | |||
| 318 | if (priv->echo_skb[idx]) { | 323 | if (priv->echo_skb[idx]) { |
| 319 | netif_rx(priv->echo_skb[idx]); | 324 | netif_rx(priv->echo_skb[idx]); |
| 320 | priv->echo_skb[idx] = NULL; | 325 | priv->echo_skb[idx] = NULL; |
| @@ -327,10 +332,12 @@ EXPORT_SYMBOL_GPL(can_get_echo_skb); | |||
| 327 | * | 332 | * |
| 328 | * The function is typically called when TX failed. | 333 | * The function is typically called when TX failed. |
| 329 | */ | 334 | */ |
| 330 | void can_free_echo_skb(struct net_device *dev, int idx) | 335 | void can_free_echo_skb(struct net_device *dev, unsigned int idx) |
| 331 | { | 336 | { |
| 332 | struct can_priv *priv = netdev_priv(dev); | 337 | struct can_priv *priv = netdev_priv(dev); |
| 333 | 338 | ||
| 339 | BUG_ON(idx >= priv->echo_skb_max); | ||
| 340 | |||
| 334 | if (priv->echo_skb[idx]) { | 341 | if (priv->echo_skb[idx]) { |
| 335 | kfree_skb(priv->echo_skb[idx]); | 342 | kfree_skb(priv->echo_skb[idx]); |
| 336 | priv->echo_skb[idx] = NULL; | 343 | priv->echo_skb[idx] = NULL; |
| @@ -359,17 +366,12 @@ void can_restart(unsigned long data) | |||
| 359 | can_flush_echo_skb(dev); | 366 | can_flush_echo_skb(dev); |
| 360 | 367 | ||
| 361 | /* send restart message upstream */ | 368 | /* send restart message upstream */ |
| 362 | skb = dev_alloc_skb(sizeof(struct can_frame)); | 369 | skb = alloc_can_err_skb(dev, &cf); |
| 363 | if (skb == NULL) { | 370 | if (skb == NULL) { |
| 364 | err = -ENOMEM; | 371 | err = -ENOMEM; |
| 365 | goto restart; | 372 | goto restart; |
| 366 | } | 373 | } |
| 367 | skb->dev = dev; | 374 | cf->can_id |= CAN_ERR_RESTARTED; |
| 368 | skb->protocol = htons(ETH_P_CAN); | ||
| 369 | cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
| 370 | memset(cf, 0, sizeof(struct can_frame)); | ||
| 371 | cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; | ||
| 372 | cf->can_dlc = CAN_ERR_DLC; | ||
| 373 | 375 | ||
| 374 | netif_rx(skb); | 376 | netif_rx(skb); |
| 375 | 377 | ||
| @@ -442,20 +444,66 @@ static void can_setup(struct net_device *dev) | |||
| 442 | dev->features = NETIF_F_NO_CSUM; | 444 | dev->features = NETIF_F_NO_CSUM; |
| 443 | } | 445 | } |
| 444 | 446 | ||
| 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 | |||
| 445 | /* | 480 | /* |
| 446 | * Allocate and setup space for the CAN network device | 481 | * Allocate and setup space for the CAN network device |
| 447 | */ | 482 | */ |
| 448 | struct net_device *alloc_candev(int sizeof_priv) | 483 | struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) |
| 449 | { | 484 | { |
| 450 | struct net_device *dev; | 485 | struct net_device *dev; |
| 451 | struct can_priv *priv; | 486 | struct can_priv *priv; |
| 487 | int size; | ||
| 452 | 488 | ||
| 453 | dev = alloc_netdev(sizeof_priv, "can%d", can_setup); | 489 | if (echo_skb_max) |
| 490 | size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) + | ||
| 491 | echo_skb_max * sizeof(struct sk_buff *); | ||
| 492 | else | ||
| 493 | size = sizeof_priv; | ||
| 494 | |||
| 495 | dev = alloc_netdev(size, "can%d", can_setup); | ||
| 454 | if (!dev) | 496 | if (!dev) |
| 455 | return NULL; | 497 | return NULL; |
| 456 | 498 | ||
| 457 | priv = netdev_priv(dev); | 499 | priv = netdev_priv(dev); |
| 458 | 500 | ||
| 501 | if (echo_skb_max) { | ||
| 502 | priv->echo_skb_max = echo_skb_max; | ||
| 503 | priv->echo_skb = (void *)priv + | ||
| 504 | ALIGN(sizeof_priv, sizeof(struct sk_buff *)); | ||
| 505 | } | ||
| 506 | |||
| 459 | priv->state = CAN_STATE_STOPPED; | 507 | priv->state = CAN_STATE_STOPPED; |
| 460 | 508 | ||
| 461 | init_timer(&priv->restart_timer); | 509 | init_timer(&priv->restart_timer); |
| @@ -647,7 +695,7 @@ nla_put_failure: | |||
| 647 | return -EMSGSIZE; | 695 | return -EMSGSIZE; |
| 648 | } | 696 | } |
| 649 | 697 | ||
| 650 | static int can_newlink(struct net_device *dev, | 698 | static int can_newlink(struct net *src_net, struct net_device *dev, |
| 651 | struct nlattr *tb[], struct nlattr *data[]) | 699 | struct nlattr *tb[], struct nlattr *data[]) |
| 652 | { | 700 | { |
| 653 | return -EOPNOTSUPP; | 701 | return -EOPNOTSUPP; |
