diff options
-rw-r--r-- | drivers/net/rionet.c | 103 |
1 files changed, 78 insertions, 25 deletions
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index f433b594388e..6d1f6ed3113f 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c | |||
@@ -208,6 +208,17 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
208 | if (nets[rnet->mport->id].active[destid]) | 208 | if (nets[rnet->mport->id].active[destid]) |
209 | rionet_queue_tx_msg(skb, ndev, | 209 | rionet_queue_tx_msg(skb, ndev, |
210 | nets[rnet->mport->id].active[destid]); | 210 | nets[rnet->mport->id].active[destid]); |
211 | else { | ||
212 | /* | ||
213 | * If the target device was removed from the list of | ||
214 | * active peers but we still have TX packets targeting | ||
215 | * it just report sending a packet to the target | ||
216 | * (without actual packet transfer). | ||
217 | */ | ||
218 | dev_kfree_skb_any(skb); | ||
219 | ndev->stats.tx_packets++; | ||
220 | ndev->stats.tx_bytes += skb->len; | ||
221 | } | ||
211 | } | 222 | } |
212 | 223 | ||
213 | spin_unlock_irqrestore(&rnet->tx_lock, flags); | 224 | spin_unlock_irqrestore(&rnet->tx_lock, flags); |
@@ -385,24 +396,28 @@ static int rionet_close(struct net_device *ndev) | |||
385 | return 0; | 396 | return 0; |
386 | } | 397 | } |
387 | 398 | ||
388 | static void rionet_remove(struct rio_dev *rdev) | 399 | static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif) |
389 | { | 400 | { |
390 | struct net_device *ndev = rio_get_drvdata(rdev); | 401 | struct rio_dev *rdev = to_rio_dev(dev); |
391 | unsigned char netid = rdev->net->hport->id; | 402 | unsigned char netid = rdev->net->hport->id; |
392 | struct rionet_peer *peer, *tmp; | 403 | struct rionet_peer *peer, *tmp; |
393 | 404 | ||
394 | unregister_netdev(ndev); | 405 | if (dev_rionet_capable(rdev)) { |
395 | 406 | list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { | |
396 | free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) * | 407 | if (peer->rdev == rdev) { |
397 | RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size))); | 408 | if (nets[netid].active[rdev->destid]) { |
398 | nets[netid].active = NULL; | 409 | nets[netid].active[rdev->destid] = NULL; |
410 | nets[netid].nact--; | ||
411 | } | ||
399 | 412 | ||
400 | list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { | 413 | list_del(&peer->node); |
401 | list_del(&peer->node); | 414 | kfree(peer); |
402 | kfree(peer); | 415 | break; |
416 | } | ||
417 | } | ||
403 | } | 418 | } |
404 | 419 | ||
405 | free_netdev(ndev); | 420 | return 0; |
406 | } | 421 | } |
407 | 422 | ||
408 | static void rionet_get_drvinfo(struct net_device *ndev, | 423 | static void rionet_get_drvinfo(struct net_device *ndev, |
@@ -503,12 +518,13 @@ static int rionet_setup_netdev(struct rio_mport *mport, struct net_device *ndev) | |||
503 | 518 | ||
504 | static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1]; | 519 | static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1]; |
505 | 520 | ||
506 | static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | 521 | static int rionet_add_dev(struct device *dev, struct subsys_interface *sif) |
507 | { | 522 | { |
508 | int rc = -ENODEV; | 523 | int rc = -ENODEV; |
509 | u32 lsrc_ops, ldst_ops; | 524 | u32 lsrc_ops, ldst_ops; |
510 | struct rionet_peer *peer; | 525 | struct rionet_peer *peer; |
511 | struct net_device *ndev = NULL; | 526 | struct net_device *ndev = NULL; |
527 | struct rio_dev *rdev = to_rio_dev(dev); | ||
512 | unsigned char netid = rdev->net->hport->id; | 528 | unsigned char netid = rdev->net->hport->id; |
513 | int oldnet; | 529 | int oldnet; |
514 | 530 | ||
@@ -518,8 +534,9 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
518 | oldnet = test_and_set_bit(netid, net_table); | 534 | oldnet = test_and_set_bit(netid, net_table); |
519 | 535 | ||
520 | /* | 536 | /* |
521 | * First time through, make sure local device is rionet | 537 | * If first time through this net, make sure local device is rionet |
522 | * capable, setup netdev (will be skipped on later probes) | 538 | * capable and setup netdev (this step will be skipped in later probes |
539 | * on the same net). | ||
523 | */ | 540 | */ |
524 | if (!oldnet) { | 541 | if (!oldnet) { |
525 | rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, | 542 | rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, |
@@ -541,6 +558,12 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
541 | } | 558 | } |
542 | nets[netid].ndev = ndev; | 559 | nets[netid].ndev = ndev; |
543 | rc = rionet_setup_netdev(rdev->net->hport, ndev); | 560 | rc = rionet_setup_netdev(rdev->net->hport, ndev); |
561 | if (rc) { | ||
562 | printk(KERN_ERR "%s: failed to setup netdev (rc=%d)\n", | ||
563 | DRV_NAME, rc); | ||
564 | goto out; | ||
565 | } | ||
566 | |||
544 | INIT_LIST_HEAD(&nets[netid].peers); | 567 | INIT_LIST_HEAD(&nets[netid].peers); |
545 | nets[netid].nact = 0; | 568 | nets[netid].nact = 0; |
546 | } else if (nets[netid].ndev == NULL) | 569 | } else if (nets[netid].ndev == NULL) |
@@ -559,31 +582,61 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) | |||
559 | list_add_tail(&peer->node, &nets[netid].peers); | 582 | list_add_tail(&peer->node, &nets[netid].peers); |
560 | } | 583 | } |
561 | 584 | ||
562 | rio_set_drvdata(rdev, nets[netid].ndev); | 585 | return 0; |
563 | 586 | out: | |
564 | out: | ||
565 | return rc; | 587 | return rc; |
566 | } | 588 | } |
567 | 589 | ||
590 | #ifdef MODULE | ||
568 | static struct rio_device_id rionet_id_table[] = { | 591 | static struct rio_device_id rionet_id_table[] = { |
569 | {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)} | 592 | {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}, |
593 | { 0, } /* terminate list */ | ||
570 | }; | 594 | }; |
571 | 595 | ||
572 | static struct rio_driver rionet_driver = { | 596 | MODULE_DEVICE_TABLE(rapidio, rionet_id_table); |
573 | .name = "rionet", | 597 | #endif |
574 | .id_table = rionet_id_table, | 598 | |
575 | .probe = rionet_probe, | 599 | static struct subsys_interface rionet_interface = { |
576 | .remove = rionet_remove, | 600 | .name = "rionet", |
601 | .subsys = &rio_bus_type, | ||
602 | .add_dev = rionet_add_dev, | ||
603 | .remove_dev = rionet_remove_dev, | ||
577 | }; | 604 | }; |
578 | 605 | ||
579 | static int __init rionet_init(void) | 606 | static int __init rionet_init(void) |
580 | { | 607 | { |
581 | return rio_register_driver(&rionet_driver); | 608 | return subsys_interface_register(&rionet_interface); |
582 | } | 609 | } |
583 | 610 | ||
584 | static void __exit rionet_exit(void) | 611 | static void __exit rionet_exit(void) |
585 | { | 612 | { |
586 | rio_unregister_driver(&rionet_driver); | 613 | struct rionet_private *rnet; |
614 | struct net_device *ndev; | ||
615 | struct rionet_peer *peer, *tmp; | ||
616 | int i; | ||
617 | |||
618 | for (i = 0; i < RIONET_MAX_NETS; i++) { | ||
619 | if (nets[i].ndev != NULL) { | ||
620 | ndev = nets[i].ndev; | ||
621 | rnet = netdev_priv(ndev); | ||
622 | unregister_netdev(ndev); | ||
623 | |||
624 | list_for_each_entry_safe(peer, | ||
625 | tmp, &nets[i].peers, node) { | ||
626 | list_del(&peer->node); | ||
627 | kfree(peer); | ||
628 | } | ||
629 | |||
630 | free_pages((unsigned long)nets[i].active, | ||
631 | get_order(sizeof(void *) * | ||
632 | RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size))); | ||
633 | nets[i].active = NULL; | ||
634 | |||
635 | free_netdev(ndev); | ||
636 | } | ||
637 | } | ||
638 | |||
639 | subsys_interface_unregister(&rionet_interface); | ||
587 | } | 640 | } |
588 | 641 | ||
589 | late_initcall(rionet_init); | 642 | late_initcall(rionet_init); |