* [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).