aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/rionet.c
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2013-07-03 18:08:52 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:08:04 -0400
commite6161d64263ee7a903acdde1a8ab7d4221d5512f (patch)
tree8d48426e618e3735db9fbe59795e57a618629831 /drivers/net/rionet.c
parent2ec3ba69faf301fb599e3651515e808e8efa533e (diff)
rapidio/rionet: rework driver initialization and removal
Rework probe/remove routines to prevent rionet driver from monopolizing target RapidIO devices. Fix conflict with modular RapidIO switch drivers. Using one of RapidIO messaging channels rionet driver provides a service layer common to all endpoint devices in a system's RapidIO network. These devices may also require their own specific device driver which will be blocked from attaching to the target device by rionet (or block rionet if loaded earlier). To avoid conflict with device-specific drivers, the rionet driver is reworked to be registered as a subsystem interface on the RapidIO bus. The reworked rio_remove_dev() and rionet_exit() routines also include handling of individual rionet peer device removal which was not supported before. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Cc: Kumar Gala <galak@kernel.crashing.org> Cc: "David S. Miller" <davem@davemloft.net> Cc: Andre van Herk <andre.van.herk@Prodrive.nl> Cc: Micha Nelissen <micha.nelissen@Prodrive.nl> Cc: Stef van Os <stef.van.os@Prodrive.nl> Cc: Jean Delvare <jdelvare@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/net/rionet.c')
-rw-r--r--drivers/net/rionet.c103
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
388static void rionet_remove(struct rio_dev *rdev) 399static 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
408static void rionet_get_drvinfo(struct net_device *ndev, 423static 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
504static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1]; 519static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1];
505 520
506static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) 521static 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 586out:
564 out:
565 return rc; 587 return rc;
566} 588}
567 589
590#ifdef MODULE
568static struct rio_device_id rionet_id_table[] = { 591static 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
572static struct rio_driver rionet_driver = { 596MODULE_DEVICE_TABLE(rapidio, rionet_id_table);
573 .name = "rionet", 597#endif
574 .id_table = rionet_id_table, 598
575 .probe = rionet_probe, 599static 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
579static int __init rionet_init(void) 606static 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
584static void __exit rionet_exit(void) 611static 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
589late_initcall(rionet_init); 642late_initcall(rionet_init);