X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fsunlance.c;h=b7d87d4690b489c6cf8c32f90a145127de4f1a78;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=ec0413609f36fd6b4bc8175f64e06bd330bb4157;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index ec0413609..b7d87d469 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c @@ -71,6 +71,7 @@ static char lancestr[] = "LANCE"; +#include #include #include #include @@ -265,6 +266,7 @@ struct lance_private { char *name; dma_addr_t init_block_dvma; struct net_device *dev; /* Backpointer */ + struct lance_private *next_module; struct sbus_dev *sdev; struct timer_list multicast_timer; }; @@ -296,6 +298,8 @@ int sparc_lance_debug = 2; #define LANCE_ADDR(x) ((long)(x) & ~0xff000000) +static struct lance_private *root_lance_dev; + /* Load the CSR registers */ static void load_csrs(struct lance_private *lp) { @@ -930,9 +934,9 @@ static int lance_open(struct net_device *dev) STOP_LANCE(lp); - if (request_irq(dev->irq, &lance_interrupt, IRQF_SHARED, + if (request_irq(dev->irq, &lance_interrupt, SA_SHIRQ, lancestr, (void *) dev)) { - printk(KERN_ERR "Lance: Can't get irq %d\n", dev->irq); + printk(KERN_ERR "Lance: Can't get irq %s\n", __irq_itoa(dev->irq)); return -EAGAIN; } @@ -1323,9 +1327,9 @@ static struct ethtool_ops sparc_lance_ethtool_ops = { .get_link = sparc_lance_get_link, }; -static int __init sparc_lance_probe_one(struct sbus_dev *sdev, - struct sbus_dma *ledma, - struct sbus_dev *lebuffer) +static int __init sparc_lance_init(struct sbus_dev *sdev, + struct sbus_dma *ledma, + struct sbus_dev *lebuffer) { static unsigned version_printed; struct net_device *dev; @@ -1469,7 +1473,6 @@ no_link_test: lp->dev = dev; SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &sdev->ofdev.dev); dev->open = &lance_open; dev->stop = &lance_close; dev->hard_start_xmit = &lance_start_xmit; @@ -1497,7 +1500,8 @@ no_link_test: goto fail; } - dev_set_drvdata(&sdev->ofdev.dev, lp); + lp->next_module = root_lance_dev; + root_lance_dev = lp; printk(KERN_INFO "%s: LANCE ", dev->name); @@ -1532,107 +1536,88 @@ static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev) #include /* Find all the lance cards on the system and initialize them */ -static struct sbus_dev sun4_sdev; -static int __init sparc_lance_init(void) +static int __init sparc_lance_probe(void) { + static struct sbus_dev sdev; + static int called; + + root_lance_dev = NULL; + + if (called) + return -ENODEV; + called++; + if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || (idprom->id_machtype == (SM_SUN4|SM_4_470))) { - memset(&sun4_sdev, 0, sizeof(struct sbus_dev)); - sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; - sun4_sdev.irqs[0] = 6; - return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); + memset(&sdev, 0, sizeof(sdev)); + sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; + sdev.irqs[0] = 6; + return sparc_lance_init(&sdev, NULL, NULL); } return -ENODEV; } -static int __exit sunlance_sun4_remove(void) -{ - struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev); - struct net_device *net_dev = lp->dev; - - unregister_netdevice(net_dev); - - lance_free_hwresources(lp); - - free_netdev(net_dev); - - dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL); - - return 0; -} - #else /* !CONFIG_SUN4 */ -static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct sbus_dev *sdev = to_sbus_device(&dev->dev); - int err; - - if (sdev->parent) { - struct of_device *parent = &sdev->parent->ofdev; - - if (!strcmp(parent->node->name, "ledma")) { - struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev)); - - err = sparc_lance_probe_one(sdev, ledma, NULL); - } else if (!strcmp(parent->node->name, "lebuffer")) { - err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev)); - } else - err = sparc_lance_probe_one(sdev, NULL, NULL); - } else - err = sparc_lance_probe_one(sdev, NULL, NULL); - - return err; -} - -static int __devexit sunlance_sbus_remove(struct of_device *dev) -{ - struct lance_private *lp = dev_get_drvdata(&dev->dev); - struct net_device *net_dev = lp->dev; - - unregister_netdevice(net_dev); - - lance_free_hwresources(lp); - - free_netdev(net_dev); - - dev_set_drvdata(&dev->dev, NULL); - - return 0; -} - -static struct of_device_id sunlance_sbus_match[] = { - { - .name = "le", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, sunlance_sbus_match); - -static struct of_platform_driver sunlance_sbus_driver = { - .name = "sunlance", - .match_table = sunlance_sbus_match, - .probe = sunlance_sbus_probe, - .remove = __devexit_p(sunlance_sbus_remove), -}; - - /* Find all the lance cards on the system and initialize them */ -static int __init sparc_lance_init(void) +static int __init sparc_lance_probe(void) { - return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type); + struct sbus_bus *bus; + struct sbus_dev *sdev = NULL; + struct sbus_dma *ledma = NULL; + static int called; + int cards = 0, v; + + root_lance_dev = NULL; + + if (called) + return -ENODEV; + called++; + + for_each_sbus (bus) { + for_each_sbusdev (sdev, bus) { + if (strcmp(sdev->prom_name, "le") == 0) { + cards++; + if ((v = sparc_lance_init(sdev, NULL, NULL))) + return v; + continue; + } + if (strcmp(sdev->prom_name, "ledma") == 0) { + cards++; + ledma = find_ledma(sdev); + if ((v = sparc_lance_init(sdev->child, + ledma, NULL))) + return v; + continue; + } + if (strcmp(sdev->prom_name, "lebuffer") == 0){ + cards++; + if ((v = sparc_lance_init(sdev->child, + NULL, sdev))) + return v; + continue; + } + } /* for each sbusdev */ + } /* for each sbus */ + if (!cards) + return -ENODEV; + return 0; } #endif /* !CONFIG_SUN4 */ -static void __exit sparc_lance_exit(void) +static void __exit sparc_lance_cleanup(void) { -#ifdef CONFIG_SUN4 - sunlance_sun4_remove(); -#else - of_unregister_driver(&sunlance_sbus_driver); -#endif + struct lance_private *lp; + + while (root_lance_dev) { + lp = root_lance_dev->next_module; + + unregister_netdev(root_lance_dev->dev); + lance_free_hwresources(root_lance_dev); + free_netdev(root_lance_dev->dev); + root_lance_dev = lp; + } } -module_init(sparc_lance_init); -module_exit(sparc_lance_exit); +module_init(sparc_lance_probe); +module_exit(sparc_lance_cleanup);