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 '[EMAIL PROTECTED]: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: [<ffffffff802ec380>] kobject_cleanup+0x53/0x7e [<ffffffff802ec3ab>] kobject_release+0x0/0x9 [<ffffffff802ecf3f>] kref_put+0x74/0x81 [<ffffffff8035493b>] fixed_mdio_register_device+0x230/0x265 [<ffffffff80564d31>] fixed_init+0x1f/0x35 [<ffffffff802071a4>] init+0x147/0x2fb [<ffffffff80223b6e>] schedule_tail+0x36/0x92 [<ffffffff8020a678>] child_rip+0xa/0x12 [<ffffffff80311714>] acpi_ds_init_one_object+0x0/0x83 [<ffffffff8020705d>] init+0x0/0x2fb [<ffffffff8020a66e>] child_rip+0x0/0x12 Also changed the notation of the fixed phy definition on mdio bus to the form of <speed>+<duplex> 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 <[EMAIL PROTECTED]> --- 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>:<phy_id>, + * 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, - "[EMAIL PROTECTED]:%d", number, speed, duplex); - else - snprintf(phydev->dev.bus_id, BUS_ID_SIZE, - "[EMAIL PROTECTED]:%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 - [EMAIL PROTECTED]:duplex, e.g. [EMAIL PROTECTED]: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_<num>@<speed>:<duplex>, which make it able even to define + <num>:<duplex>+<speed>, 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 [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/