linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] PHY fixed driver: rework release path and update phy_id notation
@ 2007-06-09 16:21 Vitaly Bordug
  2007-06-11 19:24 ` Andrew Morton
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Vitaly Bordug @ 2007-06-09 16:21 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linuxppc-dev, linux-kernel, netdev


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:  
  [<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 <vitb@kernel.crashing.org>

---

 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,
-				"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_<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

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] PHY fixed driver: rework release path and update phy_id notation
  2007-06-09 16:21 Vitaly Bordug
@ 2007-06-11 19:24 ` Andrew Morton
  2007-06-13 16:06 ` Joakim Tjernlund
  2007-07-10 17:01 ` Jeff Garzik
  2 siblings, 0 replies; 6+ messages in thread
From: Andrew Morton @ 2007-06-11 19:24 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, linux-kernel, Jeff Garzik, netdev

On Sat, 09 Jun 2007 20:21:18 +0400
Vitaly Bordug <vitb@kernel.crashing.org> wrote:

> 
> 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:  
>   [<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"
> 
>  
>  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;
> + 	}

This is pretty fragile code.  It would be better to consolidate all the
cleanup in a single spot at the end of fixed_mdio_register_device() and to
then employ the usual `goto err_foo;' technique.

Generally, embedding multiple return points into a large function like this
is a thing we prefer to avoid: it increases the risk that later changes will
introduce resource leaks, locking errors, etc.


Also, the

	if (NULL == some_ptr)

thing does look rather weird.  It is normally done to force a compile error
if someone uses "=" instead of "==", but gcc will warn about that anyway,
so it isn't really needed.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] PHY fixed driver: rework release path and update phy_id notation
  2007-06-09 16:21 Vitaly Bordug
  2007-06-11 19:24 ` Andrew Morton
@ 2007-06-13 16:06 ` Joakim Tjernlund
  2007-07-10 17:01 ` Jeff Garzik
  2 siblings, 0 replies; 6+ messages in thread
From: Joakim Tjernlund @ 2007-06-13 16:06 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, linux-kernel, Jeff Garzik, netdev

On Sat, 2007-06-09 at 20:21 +0400, Vitaly Bordug wrote:
> 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:  
>   [<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 <vitb@kernel.crashing.org>

Hi Vitaly

I am about to test this but I am having trouble figuring out how to
make ucc_geth find this PHY. Need some hints/template what to write
in the dts or board init code.

Also, I need several fixed PHYs, maybe you should export
fixed_mdio_register_device() ?

 Jocke

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] PHY fixed driver: rework release path and update phy_id notation
  2007-06-09 16:21 Vitaly Bordug
  2007-06-11 19:24 ` Andrew Morton
  2007-06-13 16:06 ` Joakim Tjernlund
@ 2007-07-10 17:01 ` Jeff Garzik
  2 siblings, 0 replies; 6+ messages in thread
From: Jeff Garzik @ 2007-07-10 17:01 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, linux-kernel, netdev

Vitaly Bordug wrote:
> 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:  
>   [<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 <vitb@kernel.crashing.org>
> 
> ---
> 
>  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,
> -				"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;
> -	}

use the standard 'goto' style found in the kernel, rather than repeating 
all these kfree's.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH] PHY fixed driver: rework release path and update phy_id notation
@ 2007-07-17  0:07 Vitaly Bordug
  2007-07-18 22:35 ` Jeff Garzik
  0 siblings, 1 reply; 6+ messages in thread
From: Vitaly Bordug @ 2007-07-17  0:07 UTC (permalink / raw)
  To: Jeff Garzik; +Cc: linuxppc-dev, linux-kernel, netdev


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:   
  [<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" and cleaned up 
the whitespace issues.
 
Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>

---

 drivers/net/phy/Kconfig |   14 ++
 drivers/net/phy/fixed.c |  310 ++++++++++++++++++++++++-----------------------
 2 files changed, 169 insertions(+), 155 deletions(-)

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index dd09011..432c210 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -76,4 +76,18 @@ 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
+
+config FIXED_MII_AMNT
+        int "Number of emulated PHYs to allocate "
+        depends on FIXED_PHY
+        default "1"
+        ---help---
+        Sometimes it is required to have several independent emulated
+        PHYs on the bus (in case of multi-eth but phy-less HW for instance).
+        This control will have specified number allocated for each fixed
+        PHY type enabled.
+
 endif # PHYLIB
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index bb96691..5619182 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -30,53 +30,31 @@
 #include <linux/mii.h>
 #include <linux/ethtool.h>
 #include <linux/phy.h>
+#include <linux/phy_fixed.h>
 
 #include <asm/io.h>
 #include <asm/irq.h>
 #include <asm/uaccess.h>
 
-#define MII_REGS_NUM	7
-
-/*
-    The idea is to emulate normal phy behavior by responding with
-    pre-defined values to mii BMCR read, so that read_status hook could
-    take all the needed info.
-*/
-
-struct fixed_phy_status {
-	u8 	link;
-	u16	speed;
-	u8 	duplex;
-};
-
-/*-----------------------------------------------------------------------------
- *  Private information hoder for mii_bus
- *-----------------------------------------------------------------------------*/
-struct fixed_info {
-	u16 *regs;
-	u8 regs_num;
-	struct fixed_phy_status phy_status;
-	struct phy_device *phydev; /* pointer to the container */
-	/* link & speed cb */
-	int(*link_update)(struct net_device*, struct fixed_phy_status*);
-
-};
+/* we need to track the allocated pointers in order to free them on exit */
+static struct fixed_info *fixed_phy_ptrs[CONFIG_FIXED_MII_AMNT*MAX_PHY_AMNT];
 
 /*-----------------------------------------------------------------------------
  *  If something weird is required to be done with link/speed,
  * network driver is able to assign a function to implement this.
  * May be useful for PHY's that need to be software-driven.
  *-----------------------------------------------------------------------------*/
-int fixed_mdio_set_link_update(struct phy_device* phydev,
-		int(*link_update)(struct net_device*, struct fixed_phy_status*))
+int fixed_mdio_set_link_update(struct phy_device *phydev,
+			       int (*link_update) (struct net_device *,
+						   struct fixed_phy_status *))
 {
 	struct fixed_info *fixed;
 
-	if(link_update == NULL)
+	if (link_update == NULL)
 		return -EINVAL;
 
-	if(phydev) {
-		if(phydev->bus)	{
+	if (phydev) {
+		if (phydev->bus) {
 			fixed = phydev->bus->priv;
 			fixed->link_update = link_update;
 			return 0;
@@ -84,54 +62,64 @@ int fixed_mdio_set_link_update(struct phy_device* phydev,
 	}
 	return -EINVAL;
 }
+
 EXPORT_SYMBOL(fixed_mdio_set_link_update);
 
+struct fixed_info *fixed_mdio_get_phydev (int phydev_ind)
+{
+	if (phydev_ind >= MAX_PHY_AMNT)
+		return NULL;
+	return fixed_phy_ptrs[phydev_ind];
+}
+
+EXPORT_SYMBOL(fixed_mdio_get_phydev);
+
 /*-----------------------------------------------------------------------------
  *  This is used for updating internal mii regs from the status
  *-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
 static int fixed_mdio_update_regs(struct fixed_info *fixed)
 {
 	u16 *regs = fixed->regs;
 	u16 bmsr = 0;
 	u16 bmcr = 0;
 
-	if(!regs) {
+	if (!regs) {
 		printk(KERN_ERR "%s: regs not set up", __FUNCTION__);
 		return -EINVAL;
 	}
 
-	if(fixed->phy_status.link)
+	if (fixed->phy_status.link)
 		bmsr |= BMSR_LSTATUS;
 
-	if(fixed->phy_status.duplex) {
+	if (fixed->phy_status.duplex) {
 		bmcr |= BMCR_FULLDPLX;
 
-		switch ( fixed->phy_status.speed ) {
+		switch (fixed->phy_status.speed) {
 		case 100:
 			bmsr |= BMSR_100FULL;
 			bmcr |= BMCR_SPEED100;
-		break;
+			break;
 
 		case 10:
 			bmsr |= BMSR_10FULL;
-		break;
+			break;
 		}
 	} else {
-		switch ( fixed->phy_status.speed ) {
+		switch (fixed->phy_status.speed) {
 		case 100:
 			bmsr |= BMSR_100HALF;
 			bmcr |= BMCR_SPEED100;
-		break;
+			break;
 
 		case 10:
 			bmsr |= BMSR_100HALF;
-		break;
+			break;
 		}
 	}
 
-	regs[MII_BMCR] =  bmcr;
-	regs[MII_BMSR] =  bmsr | 0x800; /*we are always capable of 10 hdx*/
+	regs[MII_BMCR] = bmcr;
+	regs[MII_BMSR] = bmsr | 0x800;	/*we are always capable of 10 hdx */
 
 	return 0;
 }
@@ -141,29 +129,30 @@ static int fixed_mii_read(struct mii_bus *bus, int phy_id, int location)
 	struct fixed_info *fixed = bus->priv;
 
 	/* if user has registered link update callback, use it */
-	if(fixed->phydev)
-		if(fixed->phydev->attached_dev) {
-			if(fixed->link_update) {
+	if (fixed->phydev)
+		if (fixed->phydev->attached_dev) {
+			if (fixed->link_update) {
 				fixed->link_update(fixed->phydev->attached_dev,
-						&fixed->phy_status);
+						   &fixed->phy_status);
 				fixed_mdio_update_regs(fixed);
 			}
-	}
+		}
 
 	if ((unsigned int)location >= fixed->regs_num)
 		return -1;
 	return fixed->regs[location];
 }
 
-static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location, u16 val)
+static int fixed_mii_write(struct mii_bus *bus, int phy_id, int location,
+			   u16 val)
 {
-	/* do nothing for now*/
+	/* do nothing for now */
 	return 0;
 }
 
 static int fixed_mii_reset(struct mii_bus *bus)
 {
-	/*nothing here - no way/need to reset it*/
+	/*nothing here - no way/need to reset it */
 	return 0;
 }
 #endif
@@ -171,8 +160,8 @@ static int fixed_mii_reset(struct mii_bus *bus)
 static int fixed_config_aneg(struct phy_device *phydev)
 {
 	/* :TODO:03/13/2006 09:45:37 PM::
-	 The full autoneg funcionality can be emulated,
-	 but no need to have anything here for now
+	   The full autoneg funcionality can be emulated,
+	   but no need to have anything here for now
 	 */
 	return 0;
 }
@@ -182,59 +171,79 @@ static int fixed_config_aneg(struct phy_device *phydev)
  * match will never return true...
  *-----------------------------------------------------------------------------*/
 static struct phy_driver fixed_mdio_driver = {
-	.name		= "Fixed PHY",
-	.features	= PHY_BASIC_FEATURES,
-	.config_aneg	= fixed_config_aneg,
-	.read_status	= genphy_read_status,
-	.driver 	= { .owner = THIS_MODULE,},
+	.name = "Fixed PHY",
+#ifdef CONFIG_FIXED_MII_1000_FDX
+	.features = PHY_GBIT_FEATURES,
+#else
+	.features = PHY_BASIC_FEATURES,
+#endif
+	.config_aneg = fixed_config_aneg,
+	.read_status = genphy_read_status,
+	.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.
  *-----------------------------------------------------------------------------*/
-#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX)
-static int fixed_mdio_register_device(int number, int speed, int duplex)
+#if defined(CONFIG_FIXED_MII_100_FDX) || defined(CONFIG_FIXED_MII_10_FDX) || defined(CONFIG_FIXED_MII_1000_FDX)
+struct fixed_info *fixed_mdio_register_device(
+	int bus_id, int speed, int duplex, u8 phy_id)
 {
 	struct mii_bus *new_bus;
 	struct fixed_info *fixed;
 	struct phy_device *phydev;
-	int err = 0;
+	int err;
 
-	struct device* dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+	struct device *dev = kzalloc(sizeof(struct device), GFP_KERNEL);
 
-	if (NULL == dev)
-		return -ENOMEM;
+	if (dev == NULL)
+		goto err_dev_alloc;
 
 	new_bus = kzalloc(sizeof(struct mii_bus), GFP_KERNEL);
 
-	if (NULL == new_bus) {
-		kfree(dev);
-		return -ENOMEM;
-	}
+	if (new_bus == NULL)
+		goto err_bus_alloc;
+
 	fixed = kzalloc(sizeof(struct fixed_info), GFP_KERNEL);
 
-	if (NULL == fixed) {
-		kfree(dev);
-		kfree(new_bus);
-		return -ENOMEM;
-	}
+	if (fixed == NULL)
+		goto err_fixed_alloc;
+
+	fixed->regs = kzalloc(MII_REGS_NUM * sizeof(int), GFP_KERNEL);
+	if (NULL == fixed->regs)
+		goto err_fixed_regs_alloc;
 
-	fixed->regs = kzalloc(MII_REGS_NUM*sizeof(int), GFP_KERNEL);
 	fixed->regs_num = MII_REGS_NUM;
 	fixed->phy_status.speed = speed;
 	fixed->phy_status.duplex = duplex;
 	fixed->phy_status.link = 1;
 
-	new_bus->name = "Fixed MII Bus",
-	new_bus->read = &fixed_mii_read,
-	new_bus->write = &fixed_mii_write,
-	new_bus->reset = &fixed_mii_reset,
-
-	/*set up workspace*/
+	new_bus->name = "Fixed MII Bus";
+	new_bus->read = &fixed_mii_read;
+	new_bus->write = &fixed_mii_write;
+	new_bus->reset = &fixed_mii_reset;
+	/*set up workspace */
 	fixed_mdio_update_regs(fixed);
 	new_bus->priv = fixed;
 
@@ -243,119 +252,110 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)
 
 	/* create phy_device and register it on the mdio bus */
 	phydev = phy_device_create(new_bus, 0, 0);
+	if (phydev == NULL)
+		goto err_phy_dev_create;
 
 	/*
-	 Put the phydev pointer into the fixed pack so that bus read/write code could
-	 be able to access for instance attached netdev. Well it doesn't have to do
-	 so, only in case of utilizing user-specified link-update...
+	 * Put the phydev pointer into the fixed pack so that bus read/write
+	 * code could be able to access for instance attached netdev. Well it
+	 * doesn't have to do so, only in case of utilizing user-specified
+	 * link-update...
 	 */
-	fixed->phydev = phydev;
 
-	if(NULL == phydev) {
-		err = -ENOMEM;
-		goto device_create_fail;
-	}
+	fixed->phydev = phydev;
+	phydev->speed = speed;
+	phydev->duplex = duplex;
 
 	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);
-	phydev->bus = new_bus;
+	snprintf(phydev->dev.bus_id, BUS_ID_SIZE,
+		 PHY_ID_FMT, bus_id, phy_id);
 
-	err = device_register(&phydev->dev);
-	if(err) {
-		printk(KERN_ERR "Phy %s failed to register\n",
-				phydev->dev.bus_id);
-		goto bus_register_fail;
-	}
+	phydev->bus = new_bus;
 
-	/*
-	   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;
-
+	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);
-		goto probe_fail;
+	if (err < 0) {
+		printk(KERN_ERR "Phy %s: problems with fixed driver\n",
+		       phydev->dev.bus_id);
+		goto err_out;
 	}
+	err = device_register(&phydev->dev);
+	if (err) {
+		printk(KERN_ERR "Phy %s failed to register\n",
+		       phydev->dev.bus_id);
+		goto err_out;
+	}
+	//phydev->state = PHY_RUNNING; /* make phy go up quick, but in 10Mbit/HDX
+	return fixed;
 
-	err = device_bind_driver(&phydev->dev);
-	if (err)
-		goto probe_fail;
-
-	return 0;
-
-probe_fail:
-	device_unregister(&phydev->dev);
-bus_register_fail:
+err_out:
 	kfree(phydev);
-device_create_fail:
-	kfree(dev);
-	kfree(new_bus);
+err_phy_dev_create:
+	kfree(fixed->regs);
+err_fixed_regs_alloc:
 	kfree(fixed);
+err_fixed_alloc:
+	kfree(new_bus);
+err_bus_alloc:
+	kfree(dev);
+err_dev_alloc:
+
+	return NULL;
 
-	return err;
 }
 #endif
 
-
 MODULE_DESCRIPTION("Fixed PHY device & driver for PAL");
 MODULE_AUTHOR("Vitaly Bordug");
 MODULE_LICENSE("GPL");
 
 static int __init fixed_init(void)
 {
-#if 0
-	int ret;
-	int duplex = 0;
-#endif
-
-	/* register on the bus... Not expected to be matched with anything there... */
+	int cnt = 0;
+	int i;
+/* register on the bus... Not expected to be matched
+ * with anything there...
+ *
+ */
 	phy_driver_register(&fixed_mdio_driver);
 
-	/* So let the fun begin...
-	   We will create several mdio devices here, and will bound the upper
-	   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
-	   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
-	   driver-specific link control callback, if for instance PHY is completely
-	   SW-driven.
-
-	*/
-
-#ifdef CONFIG_FIXED_MII_DUPLEX
-#if 0
-	duplex = 1;
-#endif
+/* We will create several mdio devices here, and will bound the upper
+ * driver to them.
+ *
+ * Then the external software can lookup the phy bus by searching
+ * for 0:101, to be connected to the virtual 100M Fdx phy.
+ *
+ * In case several virtual PHYs required, the bus_id will be in form
+ * [num]:[duplex]+[speed], which make it able even to define
+ * driver-specific link control callback, if for instance PHY is
+ * completely SW-driven.
+ */
+	for (i=1; i <= CONFIG_FIXED_MII_AMNT; i++) {
+#ifdef CONFIG_FIXED_MII_1000_FDX
+		fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(0, 1000, 1, i);
 #endif
-
 #ifdef CONFIG_FIXED_MII_100_FDX
-	fixed_mdio_register_device(0, 100, 1);
+		fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(1, 100, 1, i);
 #endif
-
 #ifdef CONFIG_FIXED_MII_10_FDX
-	fixed_mdio_register_device(0, 10, 1);
+		fixed_phy_ptrs[cnt++] = fixed_mdio_register_device(2, 10, 1, i);
 #endif
+	}
+
 	return 0;
 }
 
 static void __exit fixed_exit(void)
 {
+	int i;
+
 	phy_driver_unregister(&fixed_mdio_driver);
-	/* :WARNING:02/18/2006 04:32:40 AM:: Cleanup all the created stuff */
+	for (i=0; i < MAX_PHY_AMNT; i++)
+		if ( fixed_phy_ptrs[i] )
+			device_unregister(&fixed_phy_ptrs[i]->phydev->dev);
 }
 
 module_init(fixed_init);

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] PHY fixed driver: rework release path and update phy_id notation
  2007-07-17  0:07 [PATCH] PHY fixed driver: rework release path and update phy_id notation Vitaly Bordug
@ 2007-07-18 22:35 ` Jeff Garzik
  0 siblings, 0 replies; 6+ messages in thread
From: Jeff Garzik @ 2007-07-18 22:35 UTC (permalink / raw)
  To: Vitaly Bordug; +Cc: linuxppc-dev, linux-kernel, netdev

Vitaly Bordug wrote:
> 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:   
>   [<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" and cleaned up 
> the whitespace issues.
>  
> Signed-off-by: Vitaly Bordug <vitb@kernel.crashing.org>
> 
> ---
> 
>  drivers/net/phy/Kconfig |   14 ++
>  drivers/net/phy/fixed.c |  310 ++++++++++++++++++++++++-----------------------
>  2 files changed, 169 insertions(+), 155 deletions(-)
> 
> diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
> index dd09011..432c210 100644
> --- a/drivers/net/phy/Kconfig
> +++ b/drivers/net/phy/Kconfig
> @@ -76,4 +76,18 @@ 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
> +
> +config FIXED_MII_AMNT
> +        int "Number of emulated PHYs to allocate "
> +        depends on FIXED_PHY
> +        default "1"
> +        ---help---
> +        Sometimes it is required to have several independent emulated
> +        PHYs on the bus (in case of multi-eth but phy-less HW for instance).
> +        This control will have specified number allocated for each fixed
> +        PHY type enabled.

addition of new config options etc. should be in a separate patch from 
the fix, since they are separate logical changes

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2007-07-18 22:35 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-17  0:07 [PATCH] PHY fixed driver: rework release path and update phy_id notation Vitaly Bordug
2007-07-18 22:35 ` Jeff Garzik
  -- strict thread matches above, loose matches on Subject: below --
2007-06-09 16:21 Vitaly Bordug
2007-06-11 19:24 ` Andrew Morton
2007-06-13 16:06 ` Joakim Tjernlund
2007-07-10 17:01 ` Jeff Garzik

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).