Skip to content

Commit e6161d6

Browse files
Alexandre Bouninetorvalds
authored andcommitted
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>
1 parent 2ec3ba6 commit e6161d6

File tree

1 file changed

+78
-25
lines changed

1 file changed

+78
-25
lines changed

drivers/net/rionet.c

Lines changed: 78 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,17 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
208208
if (nets[rnet->mport->id].active[destid])
209209
rionet_queue_tx_msg(skb, ndev,
210210
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+
}
211222
}
212223

213224
spin_unlock_irqrestore(&rnet->tx_lock, flags);
@@ -385,24 +396,28 @@ static int rionet_close(struct net_device *ndev)
385396
return 0;
386397
}
387398

388-
static void rionet_remove(struct rio_dev *rdev)
399+
static int rionet_remove_dev(struct device *dev, struct subsys_interface *sif)
389400
{
390-
struct net_device *ndev = rio_get_drvdata(rdev);
401+
struct rio_dev *rdev = to_rio_dev(dev);
391402
unsigned char netid = rdev->net->hport->id;
392403
struct rionet_peer *peer, *tmp;
393404

394-
unregister_netdev(ndev);
395-
396-
free_pages((unsigned long)nets[netid].active, get_order(sizeof(void *) *
397-
RIO_MAX_ROUTE_ENTRIES(rdev->net->hport->sys_size)));
398-
nets[netid].active = NULL;
405+
if (dev_rionet_capable(rdev)) {
406+
list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) {
407+
if (peer->rdev == rdev) {
408+
if (nets[netid].active[rdev->destid]) {
409+
nets[netid].active[rdev->destid] = NULL;
410+
nets[netid].nact--;
411+
}
399412

400-
list_for_each_entry_safe(peer, tmp, &nets[netid].peers, node) {
401-
list_del(&peer->node);
402-
kfree(peer);
413+
list_del(&peer->node);
414+
kfree(peer);
415+
break;
416+
}
417+
}
403418
}
404419

405-
free_netdev(ndev);
420+
return 0;
406421
}
407422

408423
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)
503518

504519
static unsigned long net_table[RIONET_MAX_NETS/sizeof(unsigned long) + 1];
505520

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)
507522
{
508523
int rc = -ENODEV;
509524
u32 lsrc_ops, ldst_ops;
510525
struct rionet_peer *peer;
511526
struct net_device *ndev = NULL;
527+
struct rio_dev *rdev = to_rio_dev(dev);
512528
unsigned char netid = rdev->net->hport->id;
513529
int oldnet;
514530

@@ -518,8 +534,9 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
518534
oldnet = test_and_set_bit(netid, net_table);
519535

520536
/*
521-
* First time through, make sure local device is rionet
522-
* capable, setup netdev (will be skipped on later probes)
537+
* If first time through this net, make sure local device is rionet
538+
* capable and setup netdev (this step will be skipped in later probes
539+
* on the same net).
523540
*/
524541
if (!oldnet) {
525542
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)
541558
}
542559
nets[netid].ndev = ndev;
543560
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+
544567
INIT_LIST_HEAD(&nets[netid].peers);
545568
nets[netid].nact = 0;
546569
} else if (nets[netid].ndev == NULL)
@@ -559,31 +582,61 @@ static int rionet_probe(struct rio_dev *rdev, const struct rio_device_id *id)
559582
list_add_tail(&peer->node, &nets[netid].peers);
560583
}
561584

562-
rio_set_drvdata(rdev, nets[netid].ndev);
563-
564-
out:
585+
return 0;
586+
out:
565587
return rc;
566588
}
567589

590+
#ifdef MODULE
568591
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 */
570594
};
571595

572-
static struct rio_driver rionet_driver = {
573-
.name = "rionet",
574-
.id_table = rionet_id_table,
575-
.probe = rionet_probe,
576-
.remove = rionet_remove,
596+
MODULE_DEVICE_TABLE(rapidio, rionet_id_table);
597+
#endif
598+
599+
static struct subsys_interface rionet_interface = {
600+
.name = "rionet",
601+
.subsys = &rio_bus_type,
602+
.add_dev = rionet_add_dev,
603+
.remove_dev = rionet_remove_dev,
577604
};
578605

579606
static int __init rionet_init(void)
580607
{
581-
return rio_register_driver(&rionet_driver);
608+
return subsys_interface_register(&rionet_interface);
582609
}
583610

584611
static void __exit rionet_exit(void)
585612
{
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);
587640
}
588641

589642
late_initcall(rionet_init);

0 commit comments

Comments
 (0)