Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756551AbXFIQVk (ORCPT ); Sat, 9 Jun 2007 12:21:40 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755912AbXFIQVa (ORCPT ); Sat, 9 Jun 2007 12:21:30 -0400 Received: from rtsoft2.corbina.net ([85.21.88.2]:56211 "EHLO aca800fc.ipt.aol.com" rhost-flags-OK-FAIL-OK-FAIL) by vger.kernel.org with ESMTP id S1755803AbXFIQV3 (ORCPT ); Sat, 9 Jun 2007 12:21:29 -0400 To: Jeff Garzik Cc: linuxppc-dev@ozlabs.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: linuxppc-dev@ozlabs.org From: Vitaly Bordug Subject: [PATCH] PHY fixed driver: rework release path and update phy_id notation Date: Sat, 09 Jun 2007 20:21:18 +0400 Message-ID: <20070609162118.2680.99019.stgit@ACA800FC.ipt.aol.com> User-Agent: StGIT/0.12 MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6296 Lines: 209 device_bind_driver() error code returning has been fixed. release() function has been written, so that to free resources in correct way; the release path is now clean. Before the rework, it used to cause Device 'fixed@100:1' does not have a release() function, it is broken and must be fixed. BUG: at drivers/base/core.c:104 device_release() Call Trace: [] kobject_cleanup+0x53/0x7e [] kobject_release+0x0/0x9 [] kref_put+0x74/0x81 [] fixed_mdio_register_device+0x230/0x265 [] fixed_init+0x1f/0x35 [] init+0x147/0x2fb [] schedule_tail+0x36/0x92 [] child_rip+0xa/0x12 [] acpi_ds_init_one_object+0x0/0x83 [] init+0x0/0x2fb [] child_rip+0x0/0x12 Also changed the notation of the fixed phy definition on mdio bus to the form of + to make it able to be used by gianfar and ucc_geth that define phy_id strictly as "%d:%d" Signed-off-by: Vitaly Bordug --- drivers/net/phy/Kconfig | 4 ++ drivers/net/phy/fixed.c | 93 +++++++++++++++++++++++++++-------------------- 2 files changed, 57 insertions(+), 40 deletions(-) diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 09b6f25..a938c48 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -71,4 +71,8 @@ config FIXED_MII_100_FDX bool "Emulation for 100M Fdx fixed PHY behavior" depends on FIXED_PHY +config FIXED_MII_1000_FDX + bool "Emulation for 1000M Fdx fixed PHY behavior" + depends on FIXED_PHY + endif # PHYLIB diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c index 68c99b4..34b9111 100644 --- a/drivers/net/phy/fixed.c +++ b/drivers/net/phy/fixed.c @@ -187,12 +187,29 @@ static struct phy_driver fixed_mdio_driver = { .driver = { .owner = THIS_MODULE,}, }; +static void fixed_mdio_release (struct device * dev) +{ + struct phy_device *phydev = container_of(dev, struct phy_device, dev); + struct mii_bus *bus = phydev->bus; + struct fixed_info *fixed = bus->priv; + + kfree(phydev); + kfree(bus->dev); + kfree(bus); + kfree(fixed->regs); + kfree(fixed); +} + /*----------------------------------------------------------------------------- * This func is used to create all the necessary stuff, bind * the fixed phy driver and register all it on the mdio_bus_type. - * speed is either 10 or 100, duplex is boolean. + * speed is either 10 or 100 or 1000, duplex is boolean. * number is used to create multiple fixed PHYs, so that several devices can * utilize them simultaneously. + * + * The device on mdio bus will look like :, + * bus_id = number + * phy_id = speed+duplex. *-----------------------------------------------------------------------------*/ static int fixed_mdio_register_device(int number, int speed, int duplex) { @@ -221,6 +238,12 @@ static int fixed_mdio_register_device(int number, int speed, int duplex) } fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL); + if (NULL == fixed->regs) { + kfree(dev); + kfree(new_bus); + kfree(fixed); + return -ENOMEM; + } fixed->regs_num = MII_REGS_NUM; fixed->phy_status.speed = speed; fixed->phy_status.duplex = duplex; @@ -249,57 +272,43 @@ static int fixed_mdio_register_device(int number, int speed, int duplex) fixed->phydev = phydev; if(NULL == phydev) { - err = -ENOMEM; - goto device_create_fail; + kfree(dev); + kfree(new_bus); + kfree(fixed->regs); + kfree(fixed); + return -ENOMEM; } phydev->irq = PHY_IGNORE_INTERRUPT; phydev->dev.bus = &mdio_bus_type; - if(number) - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, - "fixed_%d@%d:%d", number, speed, duplex); - else - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, - "fixed@%d:%d", speed, duplex); + snprintf(phydev->dev.bus_id, BUS_ID_SIZE, + "%d:%d", number, speed + duplex); + phydev->bus = new_bus; + phydev->dev.driver = &fixed_mdio_driver.driver; + phydev->dev.release = fixed_mdio_release; + + err = phydev->dev.driver->probe(&phydev->dev); + if(err < 0) { + printk(KERN_ERR "Phy %s: problems with fixed driver\n", + phydev->dev.bus_id); + kfree(phydev); + kfree(dev); + kfree(new_bus); + kfree(fixed->regs); + kfree(fixed); + return err; + } + err = device_register(&phydev->dev); if(err) { printk(KERN_ERR "Phy %s failed to register\n", phydev->dev.bus_id); - goto bus_register_fail; - } - - /* - the mdio bus has phy_id match... In order not to do it - artificially, we are binding the driver here by hand; - it will be the same for all the fixed phys anyway. - */ - phydev->dev.driver = &fixed_mdio_driver.driver; - - err = phydev->dev.driver->probe(&phydev->dev); - if(err < 0) { - printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id); - goto probe_fail; } - err = device_bind_driver(&phydev->dev); - if (err) - goto probe_fail; - return 0; - -probe_fail: - device_unregister(&phydev->dev); -bus_register_fail: - kfree(phydev); -device_create_fail: - kfree(dev); - kfree(new_bus); - kfree(fixed); - - return err; } @@ -322,11 +331,11 @@ static int __init fixed_init(void) driver to them. Then the external software can lookup the phy bus by searching - fixed@speed:duplex, e.g. fixed@100:1, to be connected to the + 0:speed+duplex, e.g. 0:101, to be connected to the virtual 100M Fdx phy. In case several virtual PHYs required, the bus_id will be in form - fixed_@:, which make it able even to define + :+, which make it able even to define driver-specific link control callback, if for instance PHY is completely SW-driven. @@ -338,6 +347,10 @@ static int __init fixed_init(void) #endif #endif +#ifdef CONFIG_FIXED_MII_1000_FDX + fixed_mdio_register_device(0, 1000, 1); +#endif + #ifdef CONFIG_FIXED_MII_100_FDX fixed_mdio_register_device(0, 100, 1); #endif - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/