diff options
Diffstat (limited to 'drivers/net/sunlance.c')
| -rw-r--r-- | drivers/net/sunlance.c | 173 |
1 files changed, 97 insertions, 76 deletions
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 6381243d8d00..2c239ab63a80 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c | |||
| @@ -266,7 +266,6 @@ struct lance_private { | |||
| 266 | char *name; | 266 | char *name; |
| 267 | dma_addr_t init_block_dvma; | 267 | dma_addr_t init_block_dvma; |
| 268 | struct net_device *dev; /* Backpointer */ | 268 | struct net_device *dev; /* Backpointer */ |
| 269 | struct lance_private *next_module; | ||
| 270 | struct sbus_dev *sdev; | 269 | struct sbus_dev *sdev; |
| 271 | struct timer_list multicast_timer; | 270 | struct timer_list multicast_timer; |
| 272 | }; | 271 | }; |
| @@ -298,8 +297,6 @@ int sparc_lance_debug = 2; | |||
| 298 | 297 | ||
| 299 | #define LANCE_ADDR(x) ((long)(x) & ~0xff000000) | 298 | #define LANCE_ADDR(x) ((long)(x) & ~0xff000000) |
| 300 | 299 | ||
| 301 | static struct lance_private *root_lance_dev; | ||
| 302 | |||
| 303 | /* Load the CSR registers */ | 300 | /* Load the CSR registers */ |
| 304 | static void load_csrs(struct lance_private *lp) | 301 | static void load_csrs(struct lance_private *lp) |
| 305 | { | 302 | { |
| @@ -1327,9 +1324,9 @@ static struct ethtool_ops sparc_lance_ethtool_ops = { | |||
| 1327 | .get_link = sparc_lance_get_link, | 1324 | .get_link = sparc_lance_get_link, |
| 1328 | }; | 1325 | }; |
| 1329 | 1326 | ||
| 1330 | static int __init sparc_lance_init(struct sbus_dev *sdev, | 1327 | static int __init sparc_lance_probe_one(struct sbus_dev *sdev, |
| 1331 | struct sbus_dma *ledma, | 1328 | struct sbus_dma *ledma, |
| 1332 | struct sbus_dev *lebuffer) | 1329 | struct sbus_dev *lebuffer) |
| 1333 | { | 1330 | { |
| 1334 | static unsigned version_printed; | 1331 | static unsigned version_printed; |
| 1335 | struct net_device *dev; | 1332 | struct net_device *dev; |
| @@ -1473,6 +1470,7 @@ no_link_test: | |||
| 1473 | 1470 | ||
| 1474 | lp->dev = dev; | 1471 | lp->dev = dev; |
| 1475 | SET_MODULE_OWNER(dev); | 1472 | SET_MODULE_OWNER(dev); |
| 1473 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | ||
| 1476 | dev->open = &lance_open; | 1474 | dev->open = &lance_open; |
| 1477 | dev->stop = &lance_close; | 1475 | dev->stop = &lance_close; |
| 1478 | dev->hard_start_xmit = &lance_start_xmit; | 1476 | dev->hard_start_xmit = &lance_start_xmit; |
| @@ -1500,8 +1498,7 @@ no_link_test: | |||
| 1500 | goto fail; | 1498 | goto fail; |
| 1501 | } | 1499 | } |
| 1502 | 1500 | ||
| 1503 | lp->next_module = root_lance_dev; | 1501 | dev_set_drvdata(&sdev->ofdev.dev, lp); |
| 1504 | root_lance_dev = lp; | ||
| 1505 | 1502 | ||
| 1506 | printk(KERN_INFO "%s: LANCE ", dev->name); | 1503 | printk(KERN_INFO "%s: LANCE ", dev->name); |
| 1507 | 1504 | ||
| @@ -1536,88 +1533,112 @@ static inline struct sbus_dma *find_ledma(struct sbus_dev *sdev) | |||
| 1536 | #include <asm/machines.h> | 1533 | #include <asm/machines.h> |
| 1537 | 1534 | ||
| 1538 | /* Find all the lance cards on the system and initialize them */ | 1535 | /* Find all the lance cards on the system and initialize them */ |
| 1539 | static int __init sparc_lance_probe(void) | 1536 | static struct sbus_dev sun4_sdev; |
| 1537 | static int __init sparc_lance_init(void) | ||
| 1540 | { | 1538 | { |
| 1541 | static struct sbus_dev sdev; | ||
| 1542 | static int called; | ||
| 1543 | |||
| 1544 | root_lance_dev = NULL; | ||
| 1545 | |||
| 1546 | if (called) | ||
| 1547 | return -ENODEV; | ||
| 1548 | called++; | ||
| 1549 | |||
| 1550 | if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || | 1539 | if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || |
| 1551 | (idprom->id_machtype == (SM_SUN4|SM_4_470))) { | 1540 | (idprom->id_machtype == (SM_SUN4|SM_4_470))) { |
| 1552 | memset(&sdev, 0, sizeof(sdev)); | 1541 | memset(&sun4_sdev, 0, sizeof(sdev)); |
| 1553 | sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; | 1542 | sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; |
| 1554 | sdev.irqs[0] = 6; | 1543 | sun4_sdev.irqs[0] = 6; |
| 1555 | return sparc_lance_init(&sdev, NULL, NULL); | 1544 | return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); |
| 1556 | } | 1545 | } |
| 1557 | return -ENODEV; | 1546 | return -ENODEV; |
| 1558 | } | 1547 | } |
| 1559 | 1548 | ||
| 1560 | #else /* !CONFIG_SUN4 */ | 1549 | static int __exit sunlance_sun4_remove(void) |
| 1561 | |||
| 1562 | /* Find all the lance cards on the system and initialize them */ | ||
| 1563 | static int __init sparc_lance_probe(void) | ||
| 1564 | { | 1550 | { |
| 1565 | struct sbus_bus *bus; | 1551 | struct lance_private *lp = dev_get_drvdata(&sun4_sdev->dev); |
| 1566 | struct sbus_dev *sdev = NULL; | 1552 | struct net_device *net_dev = lp->dev; |
| 1567 | struct sbus_dma *ledma = NULL; | 1553 | |
| 1568 | static int called; | 1554 | unregister_netdevice(net_dev); |
| 1569 | int cards = 0, v; | 1555 | |
| 1570 | 1556 | lance_free_hwresources(root_lance_dev); | |
| 1571 | root_lance_dev = NULL; | 1557 | |
| 1572 | 1558 | free_netdev(net_dev); | |
| 1573 | if (called) | 1559 | |
| 1574 | return -ENODEV; | 1560 | dev_set_drvdata(&sun4_sdev->dev, NULL); |
| 1575 | called++; | 1561 | |
| 1576 | |||
| 1577 | for_each_sbus (bus) { | ||
| 1578 | for_each_sbusdev (sdev, bus) { | ||
| 1579 | if (strcmp(sdev->prom_name, "le") == 0) { | ||
| 1580 | cards++; | ||
| 1581 | if ((v = sparc_lance_init(sdev, NULL, NULL))) | ||
| 1582 | return v; | ||
| 1583 | continue; | ||
| 1584 | } | ||
| 1585 | if (strcmp(sdev->prom_name, "ledma") == 0) { | ||
| 1586 | cards++; | ||
| 1587 | ledma = find_ledma(sdev); | ||
| 1588 | if ((v = sparc_lance_init(sdev->child, | ||
| 1589 | ledma, NULL))) | ||
| 1590 | return v; | ||
| 1591 | continue; | ||
| 1592 | } | ||
| 1593 | if (strcmp(sdev->prom_name, "lebuffer") == 0){ | ||
| 1594 | cards++; | ||
| 1595 | if ((v = sparc_lance_init(sdev->child, | ||
| 1596 | NULL, sdev))) | ||
| 1597 | return v; | ||
| 1598 | continue; | ||
| 1599 | } | ||
| 1600 | } /* for each sbusdev */ | ||
| 1601 | } /* for each sbus */ | ||
| 1602 | if (!cards) | ||
| 1603 | return -ENODEV; | ||
| 1604 | return 0; | 1562 | return 0; |
| 1605 | } | 1563 | } |
| 1606 | #endif /* !CONFIG_SUN4 */ | ||
| 1607 | 1564 | ||
| 1608 | static void __exit sparc_lance_cleanup(void) | 1565 | #else /* !CONFIG_SUN4 */ |
| 1566 | |||
| 1567 | static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
| 1609 | { | 1568 | { |
| 1610 | struct lance_private *lp; | 1569 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
| 1570 | struct device_node *dp = dev->node; | ||
| 1571 | int err; | ||
| 1572 | |||
| 1573 | if (!strcmp(dp->name, "le")) { | ||
| 1574 | err = sparc_lance_probe_one(sdev, NULL, NULL); | ||
| 1575 | } else if (!strcmp(dp->name, "ledma")) { | ||
| 1576 | struct sbus_dma *ledma = find_ledma(sdev); | ||
| 1611 | 1577 | ||
| 1612 | while (root_lance_dev) { | 1578 | err = sparc_lance_probe_one(sdev->child, ledma, NULL); |
| 1613 | lp = root_lance_dev->next_module; | 1579 | } else { |
| 1580 | BUG_ON(strcmp(dp->name, "lebuffer")); | ||
| 1614 | 1581 | ||
| 1615 | unregister_netdev(root_lance_dev->dev); | 1582 | err = sparc_lance_probe_one(sdev->child, NULL, sdev); |
| 1616 | lance_free_hwresources(root_lance_dev); | ||
| 1617 | free_netdev(root_lance_dev->dev); | ||
| 1618 | root_lance_dev = lp; | ||
| 1619 | } | 1583 | } |
| 1584 | |||
| 1585 | return err; | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | static int __devexit sunlance_sbus_remove(struct of_device *dev) | ||
| 1589 | { | ||
| 1590 | struct lance_private *lp = dev_get_drvdata(&dev->dev); | ||
| 1591 | struct net_device *net_dev = lp->dev; | ||
| 1592 | |||
| 1593 | unregister_netdevice(net_dev); | ||
| 1594 | |||
| 1595 | lance_free_hwresources(lp); | ||
| 1596 | |||
| 1597 | free_netdev(net_dev); | ||
| 1598 | |||
| 1599 | dev_set_drvdata(&dev->dev, NULL); | ||
| 1600 | |||
| 1601 | return 0; | ||
| 1602 | } | ||
| 1603 | |||
| 1604 | static struct of_device_id sunlance_sbus_match[] = { | ||
| 1605 | { | ||
| 1606 | .name = "le", | ||
| 1607 | }, | ||
| 1608 | { | ||
| 1609 | .name = "ledma", | ||
| 1610 | }, | ||
| 1611 | { | ||
| 1612 | .name = "lebuffer", | ||
| 1613 | }, | ||
| 1614 | {}, | ||
| 1615 | }; | ||
| 1616 | |||
| 1617 | MODULE_DEVICE_TABLE(of, sunlance_sbus_match); | ||
| 1618 | |||
| 1619 | static struct of_platform_driver sunlance_sbus_driver = { | ||
| 1620 | .name = "sunlance", | ||
| 1621 | .match_table = sunlance_sbus_match, | ||
| 1622 | .probe = sunlance_sbus_probe, | ||
| 1623 | .remove = __devexit_p(sunlance_sbus_remove), | ||
| 1624 | }; | ||
| 1625 | |||
| 1626 | |||
| 1627 | /* Find all the lance cards on the system and initialize them */ | ||
| 1628 | static int __init sparc_lance_init(void) | ||
| 1629 | { | ||
| 1630 | return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type); | ||
| 1631 | } | ||
| 1632 | #endif /* !CONFIG_SUN4 */ | ||
| 1633 | |||
| 1634 | static void __exit sparc_lance_exit(void) | ||
| 1635 | { | ||
| 1636 | #ifdef CONFIG_SUN4 | ||
| 1637 | sunlance_sun4_remove(); | ||
| 1638 | #else | ||
| 1639 | of_unregister_driver(&sunlance_sbus_driver); | ||
| 1640 | #endif | ||
| 1620 | } | 1641 | } |
| 1621 | 1642 | ||
| 1622 | module_init(sparc_lance_probe); | 1643 | module_init(sparc_lance_init); |
| 1623 | module_exit(sparc_lance_cleanup); | 1644 | module_exit(sparc_lance_exit); |
