diff options
author | Lennert Buytenhek <buytenh@marvell.com> | 2008-10-08 19:33:40 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-10-08 19:33:40 -0400 |
commit | 46abc02175b3c246dd5141d878f565a8725060c9 (patch) | |
tree | a777a25a6613b1187244c3bd5a22e451028fccbe | |
parent | 298cf9beb9679522de995e249eccbd82f7c51999 (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.c | 75 | ||||
-rw-r--r-- | include/linux/phy.h | 8 |
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 | */ |
44 | struct mii_bus *mdiobus_alloc(void) | 44 | struct 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 | } |
48 | EXPORT_SYMBOL(mdiobus_alloc); | 54 | EXPORT_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 | */ | ||
62 | static 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 | |||
69 | static 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 | */ |
108 | void mdiobus_free(struct mii_bus *bus) | 154 | void 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 | } |
112 | EXPORT_SYMBOL(mdiobus_free); | 169 | EXPORT_SYMBOL(mdiobus_free); |
113 | 170 | ||
@@ -205,10 +262,20 @@ EXPORT_SYMBOL(mdio_bus_type); | |||
205 | 262 | ||
206 | int __init mdio_bus_init(void) | 263 | int __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 | ||
211 | void mdio_bus_exit(void) | 277 | void 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 |