Patchwork [UBUNTU] drivers/net/fec: Convert to a platform bus driver

login
register
mail settings
Submitter Jeremy Kerr
Date Oct. 8, 2009, 12:16 p.m.
Message ID <1255004186.869445.430235980982.1.gpush@pororo>
Download mbox | patch
Permalink /patch/35433/
State Accepted
Headers show

Comments

Jeremy Kerr - Oct. 8, 2009, 12:16 p.m.
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@canonical.com>

---
 drivers/net/fec.c |   90 ++++++++++++++++++++++++++++++++++++----------
 1 file changed, 72 insertions(+), 18 deletions(-)
Tim Gardner - Oct. 8, 2009, 3:01 p.m.
Jeremy Kerr wrote:
> 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@canonical.com>
> 
> ---
>  drivers/net/fec.c |   90 ++++++++++++++++++++++++++++++++++++----------
>  1 file changed, 72 insertions(+), 18 deletions(-)

applied - Have you dropped this one on the Freescale folks? I changed
the commit label to 'UBUNTU: SAUCE:' until they get it in their tree, or
it gets upstream.
Jeremy Kerr - Oct. 9, 2009, 1:26 a.m.
Tim,

> applied - Have you dropped this one on the Freescale folks? I changed
> the commit label to 'UBUNTU: SAUCE:' until they get it in their tree, or
> it gets upstream.

I've heard that freescale have an updated FEC driver, and will get in touch to 
see if I can grab the new version. Once that happens, we will probably want to 
update to the new driver.

So, this patch should only be required as a workaround for NM issues while 
we're on this older version. I don't think there's any need to upstream it.

Cheers,


Jeremy

Patch

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);