From patchwork Thu Oct 8 12:16:26 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: [UBUNTU] drivers/net/fec: Convert to a platform bus driver Date: Thu, 08 Oct 2009 02:16:26 -0000 From: Jeremy Kerr X-Patchwork-Id: 35433 Message-Id: <1255004186.869445.430235980982.1.gpush@pororo> To: kernel-team@lists.ubuntu.com BugLink: https://bugs.launchpad.net/bugs/438687 Currently, the FEC device is placed on the 'virtual' bus, and so has no driver symlink in sysfs. This symlink is required for network manager to handle the device properly, so FEC devices are currently ignored. This change converts the FEC driver to use the platform bus, so we get the proper symlinks set up in sysfs. With this change, NM will bring up the network as expected. We're doing the platform_device_register in the driver itself, rather than in machine-specific code. This is a bit of a hack: the driver will always attempt to initialise a FEC even if one isn't present in the system. However, this is no different from the existing driver. Signed-off-by: Jeremy Kerr --- drivers/net/fec.c | 90 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 72 insertions(+), 18 deletions(-) diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 55727a5..c7bc552 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -3106,34 +3107,87 @@ fec_stop(struct net_device *dev) fecp->fec_mii_speed = fep->phy_speed; } -static int __init fec_enet_module_init(void) +static int __init fec_probe(struct platform_device *pdev) { struct net_device *dev; - int i, err; + int err; DECLARE_MAC_BUF(mac); + dev = alloc_etherdev(sizeof(struct fec_enet_private)); + if (!dev) { + pr_debug("%s: alloc_etherdev failed\n", __func__); + return -ENOMEM; + } + err = fec_enet_init(dev); + if (err) { + pr_debug("%s: fec_enet_init failed (%d)\n", + __func__, err); + free_netdev(dev); + return err; + } + + SET_NETDEV_DEV(dev, &pdev->dev); + err = register_netdev(dev); + if (err) { + /* XXX: missing cleanup here */ + pr_debug("%s: register_netdev failed (%d)\n", + __func__, err); + free_netdev(dev); + return -EIO; + } + + printk("%s: ethernet %s\n", + dev->name, print_mac(mac, dev->dev_addr)); + + return 0; +} + +static struct platform_driver fec_driver = { + .driver = { + .name = "fec", + .owner = THIS_MODULE, + }, + .probe = fec_probe, +}; + +static struct platform_device fec_devices[] = { + { + .name = "fec", + .id = 0, + .num_resources = 0, + }, +#ifdef CONFIG_FEC2 + { + .name = "fec", + .id = 1, + .num_resources = 0, + }, +#endif +}; + +static int __init fec_enet_module_init(void) +{ + int i, rc = 0; + printk("FEC ENET Version 0.2\n"); fec_arch_init(); - for (i = 0; (i < FEC_MAX_PORTS); i++) { - dev = alloc_etherdev(sizeof(struct fec_enet_private)); - if (!dev) - return -ENOMEM; - err = fec_enet_init(dev); - if (err) { - free_netdev(dev); - continue; - } - if (register_netdev(dev) != 0) { - /* XXX: missing cleanup here */ - free_netdev(dev); - return -EIO; + for (i = 0; i < ARRAY_SIZE(fec_devices); i++) { + rc = platform_device_register(&fec_devices[i]); + if (rc) { + printk("%s: error [%d] registering device %d", + __func__, rc, i); + break; } + } - printk("%s: ethernet %s\n", - dev->name, print_mac(mac, dev->dev_addr)); + if (rc) { + for (i--; i >= 0; i--) + platform_device_unregister(&fec_devices[i]); + return rc; } - return 0; + + return platform_driver_probe(&fec_driver, fec_probe); } module_init(fec_enet_module_init);