aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennert Buytenhek <buytenh@marvell.com>2008-10-08 19:33:40 -0400
committerDavid S. Miller <davem@davemloft.net>2008-10-08 19:33:40 -0400
commit46abc02175b3c246dd5141d878f565a8725060c9 (patch)
treea777a25a6613b1187244c3bd5a22e451028fccbe
parent298cf9beb9679522de995e249eccbd82f7c51999 (diff)
phylib: give mdio buses a device tree presence
Introduce the mdio_bus class, and give each 'struct mii_bus' its own 'struct device', so that mii_bus objects are represented in the device tree and can be found by querying the device tree. Signed-off-by: Lennert Buytenhek <buytenh@marvell.com> Acked-by: Andy Fleming <afleming@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/mdio_bus.c75
-rw-r--r--include/linux/phy.h8
2 files changed, 79 insertions, 4 deletions
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index d206691f15d8..fb4c0965b152 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -43,11 +43,35 @@
43 */ 43 */
44struct mii_bus *mdiobus_alloc(void) 44struct mii_bus *mdiobus_alloc(void)
45{ 45{
46 return kzalloc(sizeof(struct mii_bus), GFP_KERNEL); 46 struct mii_bus *bus;
47
48 bus = kzalloc(sizeof(*bus), GFP_KERNEL);
49 if (bus != NULL)
50 bus->state = MDIOBUS_ALLOCATED;
51
52 return bus;
47} 53}
48EXPORT_SYMBOL(mdiobus_alloc); 54EXPORT_SYMBOL(mdiobus_alloc);
49 55
50/** 56/**
57 * mdiobus_release - mii_bus device release callback
58 *
59 * Description: called when the last reference to an mii_bus is
60 * dropped, to free the underlying memory.
61 */
62static void mdiobus_release(struct device *d)
63{
64 struct mii_bus *bus = to_mii_bus(d);
65 BUG_ON(bus->state != MDIOBUS_RELEASED);
66 kfree(bus);
67}
68
69static struct class mdio_bus_class = {
70 .name = "mdio_bus",
71 .dev_release = mdiobus_release,
72};
73
74/**
51 * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus 75 * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus
52 * @bus: target mii_bus 76 * @bus: target mii_bus
53 * 77 *
@@ -66,6 +90,22 @@ int mdiobus_register(struct mii_bus *bus)
66 NULL == bus->write) 90 NULL == bus->write)
67 return -EINVAL; 91 return -EINVAL;
68 92
93 BUG_ON(bus->state != MDIOBUS_ALLOCATED &&
94 bus->state != MDIOBUS_UNREGISTERED);
95
96 bus->dev.parent = bus->parent;
97 bus->dev.class = &mdio_bus_class;
98 bus->dev.groups = NULL;
99 memcpy(bus->dev.bus_id, bus->id, MII_BUS_ID_SIZE);
100
101 err = device_register(&bus->dev);
102 if (err) {
103 printk(KERN_ERR "mii_bus %s failed to register\n", bus->id);
104 return -EINVAL;
105 }
106
107 bus->state = MDIOBUS_REGISTERED;
108
69 mutex_init(&bus->mdio_lock); 109 mutex_init(&bus->mdio_lock);
70 110
71 if (bus->reset) 111 if (bus->reset)
@@ -92,6 +132,10 @@ void mdiobus_unregister(struct mii_bus *bus)
92{ 132{
93 int i; 133 int i;
94 134
135 BUG_ON(bus->state != MDIOBUS_REGISTERED);
136 bus->state = MDIOBUS_UNREGISTERED;
137
138 device_unregister(&bus->dev);
95 for (i = 0; i < PHY_MAX_ADDR; i++) { 139 for (i = 0; i < PHY_MAX_ADDR; i++) {
96 if (bus->phy_map[i]) 140 if (bus->phy_map[i])
97 device_unregister(&bus->phy_map[i]->dev); 141 device_unregister(&bus->phy_map[i]->dev);
@@ -103,11 +147,24 @@ EXPORT_SYMBOL(mdiobus_unregister);
103 * mdiobus_free - free a struct mii_bus 147 * mdiobus_free - free a struct mii_bus
104 * @bus: mii_bus to free 148 * @bus: mii_bus to free
105 * 149 *
106 * This function frees the mii_bus. 150 * This function releases the reference to the underlying device
151 * object in the mii_bus. If this is the last reference, the mii_bus
152 * will be freed.
107 */ 153 */
108void mdiobus_free(struct mii_bus *bus) 154void mdiobus_free(struct mii_bus *bus)
109{ 155{
110 kfree(bus); 156 /*
157 * For compatibility with error handling in drivers.
158 */
159 if (bus->state == MDIOBUS_ALLOCATED) {
160 kfree(bus);
161 return;
162 }
163
164 BUG_ON(bus->state != MDIOBUS_UNREGISTERED);
165 bus->state = MDIOBUS_RELEASED;
166
167 put_device(&bus->dev);
111} 168}
112EXPORT_SYMBOL(mdiobus_free); 169EXPORT_SYMBOL(mdiobus_free);
113 170
@@ -205,10 +262,20 @@ EXPORT_SYMBOL(mdio_bus_type);
205 262
206int __init mdio_bus_init(void) 263int __init mdio_bus_init(void)
207{ 264{
208 return bus_register(&mdio_bus_type); 265 int ret;
266
267 ret = class_register(&mdio_bus_class);
268 if (!ret) {
269 ret = bus_register(&mdio_bus_type);
270 if (ret)
271 class_unregister(&mdio_bus_class);
272 }
273
274 return ret;
209} 275}
210 276
211void mdio_bus_exit(void) 277void mdio_bus_exit(void)
212{ 278{
279 class_unregister(&mdio_bus_class);
213 bus_unregister(&mdio_bus_type); 280 bus_unregister(&mdio_bus_type);
214} 281}
diff --git a/include/linux/phy.h b/include/linux/phy.h
index ca4a83c4c537..891f27f9137e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -100,6 +100,13 @@ struct mii_bus {
100 struct mutex mdio_lock; 100 struct mutex mdio_lock;
101 101
102 struct device *parent; 102 struct device *parent;
103 enum {
104 MDIOBUS_ALLOCATED = 1,
105 MDIOBUS_REGISTERED,
106 MDIOBUS_UNREGISTERED,
107 MDIOBUS_RELEASED,
108 } state;
109 struct device dev;
103 110
104 /* list of all PHYs on bus */ 111 /* list of all PHYs on bus */
105 struct phy_device *phy_map[PHY_MAX_ADDR]; 112 struct phy_device *phy_map[PHY_MAX_ADDR];
@@ -113,6 +120,7 @@ struct mii_bus {
113 */ 120 */
114 int *irq; 121 int *irq;
115}; 122};
123#define to_mii_bus(d) container_of(d, struct mii_bus, dev)
116 124
117#define PHY_INTERRUPT_DISABLED 0x0 125#define PHY_INTERRUPT_DISABLED 0x0
118#define PHY_INTERRUPT_ENABLED 0x80000000 126#define PHY_INTERRUPT_ENABLED 0x80000000