[PATCH UBUNTU] drivers/net/fec: Convert to a platform bus driver
Jeremy Kerr
jeremy.kerr at canonical.com
Thu Oct 8 12:16:26 UTC 2009
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 <jeremy.kerr at canonical.com>
---
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 <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/clk.h>
+#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/uaccess.h>
@@ -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);
More information about the kernel-team
mailing list