Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Alexandre Bounine and committed by
Linus Torvalds
e6161d64 2ec3ba69

+78 -25
+78 -25
drivers/net/rionet.c
··· 208 208 if (nets[rnet->mport->id].active[destid]) 209 209 rionet_queue_tx_msg(skb, ndev, 210 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 224 spin_unlock_irqrestore(&rnet->tx_lock, flags); ··· 396 385 return 0; 397 386 } 398 387 399 - static void rionet_remove(struct rio_dev *rdev) 388 + static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif) 400 389 { 401 - struct net_device *ndev = rio_get_drvdata(rdev); 390 + struct rio_dev *rdev = to_rio_dev(dev); 402 391 unsigned char netid = rdev->net->hport->id; 403 392 struct rionet_peer *peer, *tmp; 404 393 405 - unregister_netdev(ndev); 394 + if (dev_rionet_capable(rdev)) { 395 + list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { 396 + if (peer->rdev == rdev) { 397 + if (nets[netid].active[rdev->destid]) { 398 + nets[netid].active[rdev->destid] = NULL; 399 + nets[netid].nact--; 400 + } 406 401 407 - free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) * 408 - RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size))); 409 - nets[netid].active = NULL; 410 - 411 - list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) { 412 - list_del(&peer->node); 413 - kfree(peer); 402 + list_del(&peer->node); 403 + kfree(peer); 404 + break; 405 + } 406 + } 414 407 } 415 408 416 - free_netdev(ndev); 409 + return 0; 417 410 } 418 411 419 412 static void rionet_get_drvinfo(struct net_device *ndev, ··· 518 503 519 504 static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1]; 520 505 521 - static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id) 506 + static int rionet_add_dev(struct device *dev, struct subsys_interface *sif) 522 507 { 523 508 int rc = -ENODEV; 524 509 u32 lsrc_ops, ldst_ops; 525 510 struct rionet_peer *peer; 526 511 struct net_device *ndev = NULL; 512 + struct rio_dev *rdev = to_rio_dev(dev); 527 513 unsigned char netid = rdev->net->hport->id; 528 514 int oldnet; 529 515 ··· 534 518 oldnet = test_and_set_bit(netid, net_table); 535 519 536 520 /* 537 - * First time through, make sure local device is rionet 538 - * capable, setup netdev (will be skipped on later probes) 521 + * If first time through this net, make sure local device is rionet 522 + * capable and setup netdev (this step will be skipped in later probes 523 + * on the same net). 539 524 */ 540 525 if (!oldnet) { 541 526 rio_local_read_config_32(rdev->net->hport, RIO_SRC_OPS_CAR, ··· 558 541 } 559 542 nets[netid].ndev = ndev; 560 543 rc = rionet_setup_netdev(rdev->net->hport, ndev); 544 + if (rc) { 545 + printk(KERN_ERR "%s: failed to setup netdev (rc=%d)\n", 546 + DRV_NAME, rc); 547 + goto out; 548 + } 549 + 561 550 INIT_LIST_HEAD(&nets[netid].peers); 562 551 nets[netid].nact = 0; 563 552 } else if (nets[netid].ndev == NULL) ··· 582 559 list_add_tail(&peer->node, &nets[netid].peers); 583 560 } 584 561 585 - rio_set_drvdata(rdev, nets[netid].ndev); 586 - 587 - out: 562 + return 0; 563 + out: 588 564 return rc; 589 565 } 590 566 567 + #ifdef MODULE 591 568 static struct rio_device_id rionet_id_table[] = { 592 - {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)} 569 + {RIO_DEVICE(RIO_ANY_ID, RIO_ANY_ID)}, 570 + { 0, } /* terminate list */ 593 571 }; 594 572 595 - static struct rio_driver rionet_driver = { 596 - .name = "rionet", 597 - .id_table = rionet_id_table, 598 - .probe = rionet_probe, 599 - .remove = rionet_remove, 573 + MODULE_DEVICE_TABLE(rapidio, rionet_id_table); 574 + #endif 575 + 576 + static struct subsys_interface rionet_interface = { 577 + .name = "rionet", 578 + .subsys = &rio_bus_type, 579 + .add_dev = rionet_add_dev, 580 + .remove_dev = rionet_remove_dev, 600 581 }; 601 582 602 583 static int __init rionet_init(void) 603 584 { 604 - return rio_register_driver(&rionet_driver); 585 + return subsys_interface_register(&rionet_interface); 605 586 } 606 587 607 588 static void __exit rionet_exit(void) 608 589 { 609 - rio_unregister_driver(&rionet_driver); 590 + struct rionet_private *rnet; 591 + struct net_device *ndev; 592 + struct rionet_peer *peer, *tmp; 593 + int i; 594 + 595 + for (i = 0; i < RIONET_MAX_NETS; i++) { 596 + if (nets[i].ndev != NULL) { 597 + ndev = nets[i].ndev; 598 + rnet = netdev_priv(ndev); 599 + unregister_netdev(ndev); 600 + 601 + list_for_each_entry_safe(peer, 602 + tmp, &nets[i].peers, node) { 603 + list_del(&peer->node); 604 + kfree(peer); 605 + } 606 + 607 + free_pages((unsigned long)nets[i].active, 608 + get_order(sizeof(void *) * 609 + RIO_MAX_ROUTE_ENTRIES(rnet->mport->sys_size))); 610 + nets[i].active = NULL; 611 + 612 + free_netdev(ndev); 613 + } 614 + } 615 + 616 + subsys_interface_unregister(&rionet_interface); 610 617 } 611 618 612 619 late_initcall(rionet_init);