diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Makefile | 4 | ||||
-rw-r--r-- | drivers/base/base.h | 2 | ||||
-rw-r--r-- | drivers/base/bus.c | 297 | ||||
-rw-r--r-- | drivers/base/class.c | 194 | ||||
-rw-r--r-- | drivers/base/class_simple.c | 199 | ||||
-rw-r--r-- | drivers/base/core.c | 69 | ||||
-rw-r--r-- | drivers/base/cpu.c | 11 | ||||
-rw-r--r-- | drivers/base/dd.c | 248 | ||||
-rw-r--r-- | drivers/base/dmapool.c | 2 | ||||
-rw-r--r-- | drivers/base/driver.c | 39 | ||||
-rw-r--r-- | drivers/base/interface.c | 51 | ||||
-rw-r--r-- | drivers/base/node.c | 22 | ||||
-rw-r--r-- | drivers/base/power/power.h | 11 | ||||
-rw-r--r-- | drivers/base/power/resume.c | 19 | ||||
-rw-r--r-- | drivers/base/power/shutdown.c | 23 | ||||
-rw-r--r-- | drivers/base/power/suspend.c | 33 | ||||
-rw-r--r-- | drivers/base/power/sysfs.c | 4 | ||||
-rw-r--r-- | drivers/base/sys.c | 4 |
18 files changed, 626 insertions, 606 deletions
diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 6662b545e0a9..66d9c4643fc1 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile | |||
@@ -1,7 +1,7 @@ | |||
1 | # Makefile for the Linux device tree | 1 | # Makefile for the Linux device tree |
2 | 2 | ||
3 | obj-y := core.o sys.o interface.o bus.o \ | 3 | obj-y := core.o sys.o bus.o dd.o \ |
4 | driver.o class.o class_simple.o platform.o \ | 4 | driver.o class.o platform.o \ |
5 | cpu.o firmware.o init.o map.o dmapool.o \ | 5 | cpu.o firmware.o init.o map.o dmapool.o \ |
6 | attribute_container.o transport_class.o | 6 | attribute_container.o transport_class.o |
7 | obj-y += power/ | 7 | obj-y += power/ |
diff --git a/drivers/base/base.h b/drivers/base/base.h index 8d1e8bd48632..645f62692920 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -4,6 +4,8 @@ extern void bus_remove_device(struct device * dev); | |||
4 | extern int bus_add_driver(struct device_driver *); | 4 | extern int bus_add_driver(struct device_driver *); |
5 | extern void bus_remove_driver(struct device_driver *); | 5 | extern void bus_remove_driver(struct device_driver *); |
6 | 6 | ||
7 | extern void driver_detach(struct device_driver * drv); | ||
8 | |||
7 | static inline struct class_device *to_class_dev(struct kobject *obj) | 9 | static inline struct class_device *to_class_dev(struct kobject *obj) |
8 | { | 10 | { |
9 | return container_of(obj, struct class_device, kobj); | 11 | return container_of(obj, struct class_device, kobj); |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 2b3902c867da..c3fac7fd555e 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
@@ -17,9 +17,6 @@ | |||
17 | #include "base.h" | 17 | #include "base.h" |
18 | #include "power/power.h" | 18 | #include "power/power.h" |
19 | 19 | ||
20 | #define to_dev(node) container_of(node, struct device, bus_list) | ||
21 | #define to_drv(node) container_of(node, struct device_driver, kobj.entry) | ||
22 | |||
23 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) | 20 | #define to_bus_attr(_attr) container_of(_attr, struct bus_attribute, attr) |
24 | #define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj) | 21 | #define to_bus(obj) container_of(obj, struct bus_type, subsys.kset.kobj) |
25 | 22 | ||
@@ -36,7 +33,7 @@ drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | |||
36 | { | 33 | { |
37 | struct driver_attribute * drv_attr = to_drv_attr(attr); | 34 | struct driver_attribute * drv_attr = to_drv_attr(attr); |
38 | struct device_driver * drv = to_driver(kobj); | 35 | struct device_driver * drv = to_driver(kobj); |
39 | ssize_t ret = 0; | 36 | ssize_t ret = -EIO; |
40 | 37 | ||
41 | if (drv_attr->show) | 38 | if (drv_attr->show) |
42 | ret = drv_attr->show(drv, buf); | 39 | ret = drv_attr->show(drv, buf); |
@@ -49,7 +46,7 @@ drv_attr_store(struct kobject * kobj, struct attribute * attr, | |||
49 | { | 46 | { |
50 | struct driver_attribute * drv_attr = to_drv_attr(attr); | 47 | struct driver_attribute * drv_attr = to_drv_attr(attr); |
51 | struct device_driver * drv = to_driver(kobj); | 48 | struct device_driver * drv = to_driver(kobj); |
52 | ssize_t ret = 0; | 49 | ssize_t ret = -EIO; |
53 | 50 | ||
54 | if (drv_attr->store) | 51 | if (drv_attr->store) |
55 | ret = drv_attr->store(drv, buf, count); | 52 | ret = drv_attr->store(drv, buf, count); |
@@ -135,50 +132,11 @@ static struct kobj_type ktype_bus = { | |||
135 | 132 | ||
136 | decl_subsys(bus, &ktype_bus, NULL); | 133 | decl_subsys(bus, &ktype_bus, NULL); |
137 | 134 | ||
138 | static int __bus_for_each_dev(struct bus_type *bus, struct device *start, | ||
139 | void *data, int (*fn)(struct device *, void *)) | ||
140 | { | ||
141 | struct list_head *head; | ||
142 | struct device *dev; | ||
143 | int error = 0; | ||
144 | |||
145 | if (!(bus = get_bus(bus))) | ||
146 | return -EINVAL; | ||
147 | |||
148 | head = &bus->devices.list; | ||
149 | dev = list_prepare_entry(start, head, bus_list); | ||
150 | list_for_each_entry_continue(dev, head, bus_list) { | ||
151 | get_device(dev); | ||
152 | error = fn(dev, data); | ||
153 | put_device(dev); | ||
154 | if (error) | ||
155 | break; | ||
156 | } | ||
157 | put_bus(bus); | ||
158 | return error; | ||
159 | } | ||
160 | 135 | ||
161 | static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | 136 | static struct device * next_device(struct klist_iter * i) |
162 | void * data, int (*fn)(struct device_driver *, void *)) | ||
163 | { | 137 | { |
164 | struct list_head *head; | 138 | struct klist_node * n = klist_next(i); |
165 | struct device_driver *drv; | 139 | return n ? container_of(n, struct device, knode_bus) : NULL; |
166 | int error = 0; | ||
167 | |||
168 | if (!(bus = get_bus(bus))) | ||
169 | return -EINVAL; | ||
170 | |||
171 | head = &bus->drivers.list; | ||
172 | drv = list_prepare_entry(start, head, kobj.entry); | ||
173 | list_for_each_entry_continue(drv, head, kobj.entry) { | ||
174 | get_driver(drv); | ||
175 | error = fn(drv, data); | ||
176 | put_driver(drv); | ||
177 | if (error) | ||
178 | break; | ||
179 | } | ||
180 | put_bus(bus); | ||
181 | return error; | ||
182 | } | 140 | } |
183 | 141 | ||
184 | /** | 142 | /** |
@@ -204,12 +162,27 @@ static int __bus_for_each_drv(struct bus_type *bus, struct device_driver *start, | |||
204 | int bus_for_each_dev(struct bus_type * bus, struct device * start, | 162 | int bus_for_each_dev(struct bus_type * bus, struct device * start, |
205 | void * data, int (*fn)(struct device *, void *)) | 163 | void * data, int (*fn)(struct device *, void *)) |
206 | { | 164 | { |
207 | int ret; | 165 | struct klist_iter i; |
166 | struct device * dev; | ||
167 | int error = 0; | ||
208 | 168 | ||
209 | down_read(&bus->subsys.rwsem); | 169 | if (!bus) |
210 | ret = __bus_for_each_dev(bus, start, data, fn); | 170 | return -EINVAL; |
211 | up_read(&bus->subsys.rwsem); | 171 | |
212 | return ret; | 172 | klist_iter_init_node(&bus->klist_devices, &i, |
173 | (start ? &start->knode_bus : NULL)); | ||
174 | while ((dev = next_device(&i)) && !error) | ||
175 | error = fn(dev, data); | ||
176 | klist_iter_exit(&i); | ||
177 | return error; | ||
178 | } | ||
179 | |||
180 | |||
181 | |||
182 | static struct device_driver * next_driver(struct klist_iter * i) | ||
183 | { | ||
184 | struct klist_node * n = klist_next(i); | ||
185 | return n ? container_of(n, struct device_driver, knode_bus) : NULL; | ||
213 | } | 186 | } |
214 | 187 | ||
215 | /** | 188 | /** |
@@ -235,180 +208,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, | |||
235 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, | 208 | int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, |
236 | void * data, int (*fn)(struct device_driver *, void *)) | 209 | void * data, int (*fn)(struct device_driver *, void *)) |
237 | { | 210 | { |
238 | int ret; | 211 | struct klist_iter i; |
239 | 212 | struct device_driver * drv; | |
240 | down_read(&bus->subsys.rwsem); | 213 | int error = 0; |
241 | ret = __bus_for_each_drv(bus, start, data, fn); | ||
242 | up_read(&bus->subsys.rwsem); | ||
243 | return ret; | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * device_bind_driver - bind a driver to one device. | ||
248 | * @dev: device. | ||
249 | * | ||
250 | * Allow manual attachment of a driver to a device. | ||
251 | * Caller must have already set @dev->driver. | ||
252 | * | ||
253 | * Note that this does not modify the bus reference count | ||
254 | * nor take the bus's rwsem. Please verify those are accounted | ||
255 | * for before calling this. (It is ok to call with no other effort | ||
256 | * from a driver's probe() method.) | ||
257 | */ | ||
258 | |||
259 | void device_bind_driver(struct device * dev) | ||
260 | { | ||
261 | pr_debug("bound device '%s' to driver '%s'\n", | ||
262 | dev->bus_id, dev->driver->name); | ||
263 | list_add_tail(&dev->driver_list, &dev->driver->devices); | ||
264 | sysfs_create_link(&dev->driver->kobj, &dev->kobj, | ||
265 | kobject_name(&dev->kobj)); | ||
266 | sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver"); | ||
267 | } | ||
268 | |||
269 | |||
270 | /** | ||
271 | * driver_probe_device - attempt to bind device & driver. | ||
272 | * @drv: driver. | ||
273 | * @dev: device. | ||
274 | * | ||
275 | * First, we call the bus's match function, if one present, which | ||
276 | * should compare the device IDs the driver supports with the | ||
277 | * device IDs of the device. Note we don't do this ourselves | ||
278 | * because we don't know the format of the ID structures, nor what | ||
279 | * is to be considered a match and what is not. | ||
280 | * | ||
281 | * If we find a match, we call @drv->probe(@dev) if it exists, and | ||
282 | * call device_bind_driver() above. | ||
283 | */ | ||
284 | int driver_probe_device(struct device_driver * drv, struct device * dev) | ||
285 | { | ||
286 | if (drv->bus->match && !drv->bus->match(dev, drv)) | ||
287 | return -ENODEV; | ||
288 | |||
289 | dev->driver = drv; | ||
290 | if (drv->probe) { | ||
291 | int error = drv->probe(dev); | ||
292 | if (error) { | ||
293 | dev->driver = NULL; | ||
294 | return error; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | device_bind_driver(dev); | ||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | |||
303 | /** | ||
304 | * device_attach - try to attach device to a driver. | ||
305 | * @dev: device. | ||
306 | * | ||
307 | * Walk the list of drivers that the bus has and call | ||
308 | * driver_probe_device() for each pair. If a compatible | ||
309 | * pair is found, break out and return. | ||
310 | */ | ||
311 | int device_attach(struct device * dev) | ||
312 | { | ||
313 | struct bus_type * bus = dev->bus; | ||
314 | struct list_head * entry; | ||
315 | int error; | ||
316 | |||
317 | if (dev->driver) { | ||
318 | device_bind_driver(dev); | ||
319 | return 1; | ||
320 | } | ||
321 | |||
322 | if (bus->match) { | ||
323 | list_for_each(entry, &bus->drivers.list) { | ||
324 | struct device_driver * drv = to_drv(entry); | ||
325 | error = driver_probe_device(drv, dev); | ||
326 | if (!error) | ||
327 | /* success, driver matched */ | ||
328 | return 1; | ||
329 | if (error != -ENODEV && error != -ENXIO) | ||
330 | /* driver matched but the probe failed */ | ||
331 | printk(KERN_WARNING | ||
332 | "%s: probe of %s failed with error %d\n", | ||
333 | drv->name, dev->bus_id, error); | ||
334 | } | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | |||
341 | /** | ||
342 | * driver_attach - try to bind driver to devices. | ||
343 | * @drv: driver. | ||
344 | * | ||
345 | * Walk the list of devices that the bus has on it and try to | ||
346 | * match the driver with each one. If driver_probe_device() | ||
347 | * returns 0 and the @dev->driver is set, we've found a | ||
348 | * compatible pair. | ||
349 | * | ||
350 | * Note that we ignore the -ENODEV error from driver_probe_device(), | ||
351 | * since it's perfectly valid for a driver not to bind to any devices. | ||
352 | */ | ||
353 | void driver_attach(struct device_driver * drv) | ||
354 | { | ||
355 | struct bus_type * bus = drv->bus; | ||
356 | struct list_head * entry; | ||
357 | int error; | ||
358 | |||
359 | if (!bus->match) | ||
360 | return; | ||
361 | |||
362 | list_for_each(entry, &bus->devices.list) { | ||
363 | struct device * dev = container_of(entry, struct device, bus_list); | ||
364 | if (!dev->driver) { | ||
365 | error = driver_probe_device(drv, dev); | ||
366 | if (error && (error != -ENODEV)) | ||
367 | /* driver matched but the probe failed */ | ||
368 | printk(KERN_WARNING | ||
369 | "%s: probe of %s failed with error %d\n", | ||
370 | drv->name, dev->bus_id, error); | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | |||
376 | /** | ||
377 | * device_release_driver - manually detach device from driver. | ||
378 | * @dev: device. | ||
379 | * | ||
380 | * Manually detach device from driver. | ||
381 | * Note that this is called without incrementing the bus | ||
382 | * reference count nor taking the bus's rwsem. Be sure that | ||
383 | * those are accounted for before calling this function. | ||
384 | */ | ||
385 | |||
386 | void device_release_driver(struct device * dev) | ||
387 | { | ||
388 | struct device_driver * drv = dev->driver; | ||
389 | if (drv) { | ||
390 | sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); | ||
391 | sysfs_remove_link(&dev->kobj, "driver"); | ||
392 | list_del_init(&dev->driver_list); | ||
393 | device_detach_shutdown(dev); | ||
394 | if (drv->remove) | ||
395 | drv->remove(dev); | ||
396 | dev->driver = NULL; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | 214 | ||
401 | /** | 215 | if (!bus) |
402 | * driver_detach - detach driver from all devices it controls. | 216 | return -EINVAL; |
403 | * @drv: driver. | ||
404 | */ | ||
405 | 217 | ||
406 | static void driver_detach(struct device_driver * drv) | 218 | klist_iter_init_node(&bus->klist_drivers, &i, |
407 | { | 219 | start ? &start->knode_bus : NULL); |
408 | while (!list_empty(&drv->devices)) { | 220 | while ((drv = next_driver(&i)) && !error) |
409 | struct device * dev = container_of(drv->devices.next, struct device, driver_list); | 221 | error = fn(drv, data); |
410 | device_release_driver(dev); | 222 | klist_iter_exit(&i); |
411 | } | 223 | return error; |
412 | } | 224 | } |
413 | 225 | ||
414 | static int device_add_attrs(struct bus_type * bus, struct device * dev) | 226 | static int device_add_attrs(struct bus_type * bus, struct device * dev) |
@@ -457,14 +269,14 @@ int bus_add_device(struct device * dev) | |||
457 | int error = 0; | 269 | int error = 0; |
458 | 270 | ||
459 | if (bus) { | 271 | if (bus) { |
460 | down_write(&dev->bus->subsys.rwsem); | ||
461 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); | 272 | pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); |
462 | list_add_tail(&dev->bus_list, &dev->bus->devices.list); | ||
463 | device_attach(dev); | 273 | device_attach(dev); |
464 | up_write(&dev->bus->subsys.rwsem); | 274 | klist_add_tail(&bus->klist_devices, &dev->knode_bus); |
465 | device_add_attrs(bus, dev); | 275 | error = device_add_attrs(bus, dev); |
466 | sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); | 276 | if (!error) { |
467 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); | 277 | sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); |
278 | sysfs_create_link(&dev->kobj, &dev->bus->subsys.kset.kobj, "bus"); | ||
279 | } | ||
468 | } | 280 | } |
469 | return error; | 281 | return error; |
470 | } | 282 | } |
@@ -484,11 +296,9 @@ void bus_remove_device(struct device * dev) | |||
484 | sysfs_remove_link(&dev->kobj, "bus"); | 296 | sysfs_remove_link(&dev->kobj, "bus"); |
485 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); | 297 | sysfs_remove_link(&dev->bus->devices.kobj, dev->bus_id); |
486 | device_remove_attrs(dev->bus, dev); | 298 | device_remove_attrs(dev->bus, dev); |
487 | down_write(&dev->bus->subsys.rwsem); | 299 | klist_remove(&dev->knode_bus); |
488 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); | 300 | pr_debug("bus %s: remove device %s\n", dev->bus->name, dev->bus_id); |
489 | device_release_driver(dev); | 301 | device_release_driver(dev); |
490 | list_del_init(&dev->bus_list); | ||
491 | up_write(&dev->bus->subsys.rwsem); | ||
492 | put_bus(dev->bus); | 302 | put_bus(dev->bus); |
493 | } | 303 | } |
494 | } | 304 | } |
@@ -548,9 +358,8 @@ int bus_add_driver(struct device_driver * drv) | |||
548 | return error; | 358 | return error; |
549 | } | 359 | } |
550 | 360 | ||
551 | down_write(&bus->subsys.rwsem); | ||
552 | driver_attach(drv); | 361 | driver_attach(drv); |
553 | up_write(&bus->subsys.rwsem); | 362 | klist_add_tail(&bus->klist_drivers, &drv->knode_bus); |
554 | module_add_driver(drv->owner, drv); | 363 | module_add_driver(drv->owner, drv); |
555 | 364 | ||
556 | driver_add_attrs(bus, drv); | 365 | driver_add_attrs(bus, drv); |
@@ -572,10 +381,9 @@ void bus_remove_driver(struct device_driver * drv) | |||
572 | { | 381 | { |
573 | if (drv->bus) { | 382 | if (drv->bus) { |
574 | driver_remove_attrs(drv->bus, drv); | 383 | driver_remove_attrs(drv->bus, drv); |
575 | down_write(&drv->bus->subsys.rwsem); | 384 | klist_remove(&drv->knode_bus); |
576 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); | 385 | pr_debug("bus %s: remove driver %s\n", drv->bus->name, drv->name); |
577 | driver_detach(drv); | 386 | driver_detach(drv); |
578 | up_write(&drv->bus->subsys.rwsem); | ||
579 | module_remove_driver(drv); | 387 | module_remove_driver(drv); |
580 | kobject_unregister(&drv->kobj); | 388 | kobject_unregister(&drv->kobj); |
581 | put_bus(drv->bus); | 389 | put_bus(drv->bus); |
@@ -588,7 +396,7 @@ static int bus_rescan_devices_helper(struct device *dev, void *data) | |||
588 | { | 396 | { |
589 | int *count = data; | 397 | int *count = data; |
590 | 398 | ||
591 | if (!dev->driver && device_attach(dev)) | 399 | if (!dev->driver && (device_attach(dev) > 0)) |
592 | (*count)++; | 400 | (*count)++; |
593 | 401 | ||
594 | return 0; | 402 | return 0; |
@@ -608,9 +416,7 @@ int bus_rescan_devices(struct bus_type * bus) | |||
608 | { | 416 | { |
609 | int count = 0; | 417 | int count = 0; |
610 | 418 | ||
611 | down_write(&bus->subsys.rwsem); | 419 | bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); |
612 | __bus_for_each_dev(bus, NULL, &count, bus_rescan_devices_helper); | ||
613 | up_write(&bus->subsys.rwsem); | ||
614 | 420 | ||
615 | return count; | 421 | return count; |
616 | } | 422 | } |
@@ -711,6 +517,9 @@ int bus_register(struct bus_type * bus) | |||
711 | retval = kset_register(&bus->drivers); | 517 | retval = kset_register(&bus->drivers); |
712 | if (retval) | 518 | if (retval) |
713 | goto bus_drivers_fail; | 519 | goto bus_drivers_fail; |
520 | |||
521 | klist_init(&bus->klist_devices); | ||
522 | klist_init(&bus->klist_drivers); | ||
714 | bus_add_attrs(bus); | 523 | bus_add_attrs(bus); |
715 | 524 | ||
716 | pr_debug("bus type '%s' registered\n", bus->name); | 525 | pr_debug("bus type '%s' registered\n", bus->name); |
@@ -750,12 +559,6 @@ int __init buses_init(void) | |||
750 | EXPORT_SYMBOL_GPL(bus_for_each_dev); | 559 | EXPORT_SYMBOL_GPL(bus_for_each_dev); |
751 | EXPORT_SYMBOL_GPL(bus_for_each_drv); | 560 | EXPORT_SYMBOL_GPL(bus_for_each_drv); |
752 | 561 | ||
753 | EXPORT_SYMBOL_GPL(driver_probe_device); | ||
754 | EXPORT_SYMBOL_GPL(device_bind_driver); | ||
755 | EXPORT_SYMBOL_GPL(device_release_driver); | ||
756 | EXPORT_SYMBOL_GPL(device_attach); | ||
757 | EXPORT_SYMBOL_GPL(driver_attach); | ||
758 | |||
759 | EXPORT_SYMBOL_GPL(bus_add_device); | 562 | EXPORT_SYMBOL_GPL(bus_add_device); |
760 | EXPORT_SYMBOL_GPL(bus_remove_device); | 563 | EXPORT_SYMBOL_GPL(bus_remove_device); |
761 | EXPORT_SYMBOL_GPL(bus_register); | 564 | EXPORT_SYMBOL_GPL(bus_register); |
diff --git a/drivers/base/class.c b/drivers/base/class.c index d2a2f8f2b4ed..479c12570881 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include <linux/kdev_t.h> | 18 | #include <linux/kdev_t.h> |
19 | #include <linux/err.h> | ||
19 | #include "base.h" | 20 | #include "base.h" |
20 | 21 | ||
21 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) | 22 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) |
@@ -26,7 +27,7 @@ class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | |||
26 | { | 27 | { |
27 | struct class_attribute * class_attr = to_class_attr(attr); | 28 | struct class_attribute * class_attr = to_class_attr(attr); |
28 | struct class * dc = to_class(kobj); | 29 | struct class * dc = to_class(kobj); |
29 | ssize_t ret = 0; | 30 | ssize_t ret = -EIO; |
30 | 31 | ||
31 | if (class_attr->show) | 32 | if (class_attr->show) |
32 | ret = class_attr->show(dc, buf); | 33 | ret = class_attr->show(dc, buf); |
@@ -39,7 +40,7 @@ class_attr_store(struct kobject * kobj, struct attribute * attr, | |||
39 | { | 40 | { |
40 | struct class_attribute * class_attr = to_class_attr(attr); | 41 | struct class_attribute * class_attr = to_class_attr(attr); |
41 | struct class * dc = to_class(kobj); | 42 | struct class * dc = to_class(kobj); |
42 | ssize_t ret = 0; | 43 | ssize_t ret = -EIO; |
43 | 44 | ||
44 | if (class_attr->store) | 45 | if (class_attr->store) |
45 | ret = class_attr->store(dc, buf, count); | 46 | ret = class_attr->store(dc, buf, count); |
@@ -162,6 +163,69 @@ void class_unregister(struct class * cls) | |||
162 | subsystem_unregister(&cls->subsys); | 163 | subsystem_unregister(&cls->subsys); |
163 | } | 164 | } |
164 | 165 | ||
166 | static void class_create_release(struct class *cls) | ||
167 | { | ||
168 | kfree(cls); | ||
169 | } | ||
170 | |||
171 | static void class_device_create_release(struct class_device *class_dev) | ||
172 | { | ||
173 | kfree(class_dev); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * class_create - create a struct class structure | ||
178 | * @owner: pointer to the module that is to "own" this struct class | ||
179 | * @name: pointer to a string for the name of this class. | ||
180 | * | ||
181 | * This is used to create a struct class pointer that can then be used | ||
182 | * in calls to class_device_create(). | ||
183 | * | ||
184 | * Note, the pointer created here is to be destroyed when finished by | ||
185 | * making a call to class_destroy(). | ||
186 | */ | ||
187 | struct class *class_create(struct module *owner, char *name) | ||
188 | { | ||
189 | struct class *cls; | ||
190 | int retval; | ||
191 | |||
192 | cls = kmalloc(sizeof(struct class), GFP_KERNEL); | ||
193 | if (!cls) { | ||
194 | retval = -ENOMEM; | ||
195 | goto error; | ||
196 | } | ||
197 | memset(cls, 0x00, sizeof(struct class)); | ||
198 | |||
199 | cls->name = name; | ||
200 | cls->owner = owner; | ||
201 | cls->class_release = class_create_release; | ||
202 | cls->release = class_device_create_release; | ||
203 | |||
204 | retval = class_register(cls); | ||
205 | if (retval) | ||
206 | goto error; | ||
207 | |||
208 | return cls; | ||
209 | |||
210 | error: | ||
211 | kfree(cls); | ||
212 | return ERR_PTR(retval); | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * class_destroy - destroys a struct class structure | ||
217 | * @cs: pointer to the struct class that is to be destroyed | ||
218 | * | ||
219 | * Note, the pointer to be destroyed must have been created with a call | ||
220 | * to class_create(). | ||
221 | */ | ||
222 | void class_destroy(struct class *cls) | ||
223 | { | ||
224 | if ((cls == NULL) || (IS_ERR(cls))) | ||
225 | return; | ||
226 | |||
227 | class_unregister(cls); | ||
228 | } | ||
165 | 229 | ||
166 | /* Class Device Stuff */ | 230 | /* Class Device Stuff */ |
167 | 231 | ||
@@ -262,7 +326,7 @@ static int class_hotplug_filter(struct kset *kset, struct kobject *kobj) | |||
262 | return 0; | 326 | return 0; |
263 | } | 327 | } |
264 | 328 | ||
265 | static char *class_hotplug_name(struct kset *kset, struct kobject *kobj) | 329 | static const char *class_hotplug_name(struct kset *kset, struct kobject *kobj) |
266 | { | 330 | { |
267 | struct class_device *class_dev = to_class_dev(kobj); | 331 | struct class_device *class_dev = to_class_dev(kobj); |
268 | 332 | ||
@@ -375,7 +439,6 @@ static ssize_t show_dev(struct class_device *class_dev, char *buf) | |||
375 | { | 439 | { |
376 | return print_dev_t(buf, class_dev->devt); | 440 | return print_dev_t(buf, class_dev->devt); |
377 | } | 441 | } |
378 | static CLASS_DEVICE_ATTR(dev, S_IRUGO, show_dev, NULL); | ||
379 | 442 | ||
380 | void class_device_initialize(struct class_device *class_dev) | 443 | void class_device_initialize(struct class_device *class_dev) |
381 | { | 444 | { |
@@ -412,7 +475,31 @@ int class_device_add(struct class_device *class_dev) | |||
412 | if ((error = kobject_add(&class_dev->kobj))) | 475 | if ((error = kobject_add(&class_dev->kobj))) |
413 | goto register_done; | 476 | goto register_done; |
414 | 477 | ||
415 | /* now take care of our own registration */ | 478 | /* add the needed attributes to this device */ |
479 | if (MAJOR(class_dev->devt)) { | ||
480 | struct class_device_attribute *attr; | ||
481 | attr = kmalloc(sizeof(*attr), GFP_KERNEL); | ||
482 | if (!attr) { | ||
483 | error = -ENOMEM; | ||
484 | kobject_del(&class_dev->kobj); | ||
485 | goto register_done; | ||
486 | } | ||
487 | memset(attr, sizeof(*attr), 0x00); | ||
488 | attr->attr.name = "dev"; | ||
489 | attr->attr.mode = S_IRUGO; | ||
490 | attr->attr.owner = parent->owner; | ||
491 | attr->show = show_dev; | ||
492 | attr->store = NULL; | ||
493 | class_device_create_file(class_dev, attr); | ||
494 | class_dev->devt_attr = attr; | ||
495 | } | ||
496 | |||
497 | class_device_add_attrs(class_dev); | ||
498 | if (class_dev->dev) | ||
499 | sysfs_create_link(&class_dev->kobj, | ||
500 | &class_dev->dev->kobj, "device"); | ||
501 | |||
502 | /* notify any interfaces this device is now here */ | ||
416 | if (parent) { | 503 | if (parent) { |
417 | down(&parent->sem); | 504 | down(&parent->sem); |
418 | list_add_tail(&class_dev->node, &parent->children); | 505 | list_add_tail(&class_dev->node, &parent->children); |
@@ -421,16 +508,8 @@ int class_device_add(struct class_device *class_dev) | |||
421 | class_intf->add(class_dev); | 508 | class_intf->add(class_dev); |
422 | up(&parent->sem); | 509 | up(&parent->sem); |
423 | } | 510 | } |
424 | |||
425 | if (MAJOR(class_dev->devt)) | ||
426 | class_device_create_file(class_dev, &class_device_attr_dev); | ||
427 | |||
428 | class_device_add_attrs(class_dev); | ||
429 | if (class_dev->dev) | ||
430 | sysfs_create_link(&class_dev->kobj, | ||
431 | &class_dev->dev->kobj, "device"); | ||
432 | |||
433 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); | 511 | kobject_hotplug(&class_dev->kobj, KOBJ_ADD); |
512 | |||
434 | register_done: | 513 | register_done: |
435 | if (error && parent) | 514 | if (error && parent) |
436 | class_put(parent); | 515 | class_put(parent); |
@@ -444,6 +523,58 @@ int class_device_register(struct class_device *class_dev) | |||
444 | return class_device_add(class_dev); | 523 | return class_device_add(class_dev); |
445 | } | 524 | } |
446 | 525 | ||
526 | /** | ||
527 | * class_device_create - creates a class device and registers it with sysfs | ||
528 | * @cs: pointer to the struct class that this device should be registered to. | ||
529 | * @dev: the dev_t for the char device to be added. | ||
530 | * @device: a pointer to a struct device that is assiociated with this class device. | ||
531 | * @fmt: string for the class device's name | ||
532 | * | ||
533 | * This function can be used by char device classes. A struct | ||
534 | * class_device will be created in sysfs, registered to the specified | ||
535 | * class. A "dev" file will be created, showing the dev_t for the | ||
536 | * device. The pointer to the struct class_device will be returned from | ||
537 | * the call. Any further sysfs files that might be required can be | ||
538 | * created using this pointer. | ||
539 | * | ||
540 | * Note: the struct class passed to this function must have previously | ||
541 | * been created with a call to class_create(). | ||
542 | */ | ||
543 | struct class_device *class_device_create(struct class *cls, dev_t devt, | ||
544 | struct device *device, char *fmt, ...) | ||
545 | { | ||
546 | va_list args; | ||
547 | struct class_device *class_dev = NULL; | ||
548 | int retval = -ENODEV; | ||
549 | |||
550 | if (cls == NULL || IS_ERR(cls)) | ||
551 | goto error; | ||
552 | |||
553 | class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL); | ||
554 | if (!class_dev) { | ||
555 | retval = -ENOMEM; | ||
556 | goto error; | ||
557 | } | ||
558 | memset(class_dev, 0x00, sizeof(struct class_device)); | ||
559 | |||
560 | class_dev->devt = devt; | ||
561 | class_dev->dev = device; | ||
562 | class_dev->class = cls; | ||
563 | |||
564 | va_start(args, fmt); | ||
565 | vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args); | ||
566 | va_end(args); | ||
567 | retval = class_device_register(class_dev); | ||
568 | if (retval) | ||
569 | goto error; | ||
570 | |||
571 | return class_dev; | ||
572 | |||
573 | error: | ||
574 | kfree(class_dev); | ||
575 | return ERR_PTR(retval); | ||
576 | } | ||
577 | |||
447 | void class_device_del(struct class_device *class_dev) | 578 | void class_device_del(struct class_device *class_dev) |
448 | { | 579 | { |
449 | struct class * parent = class_dev->class; | 580 | struct class * parent = class_dev->class; |
@@ -460,6 +591,11 @@ void class_device_del(struct class_device *class_dev) | |||
460 | 591 | ||
461 | if (class_dev->dev) | 592 | if (class_dev->dev) |
462 | sysfs_remove_link(&class_dev->kobj, "device"); | 593 | sysfs_remove_link(&class_dev->kobj, "device"); |
594 | if (class_dev->devt_attr) { | ||
595 | class_device_remove_file(class_dev, class_dev->devt_attr); | ||
596 | kfree(class_dev->devt_attr); | ||
597 | class_dev->devt_attr = NULL; | ||
598 | } | ||
463 | class_device_remove_attrs(class_dev); | 599 | class_device_remove_attrs(class_dev); |
464 | 600 | ||
465 | kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); | 601 | kobject_hotplug(&class_dev->kobj, KOBJ_REMOVE); |
@@ -477,6 +613,32 @@ void class_device_unregister(struct class_device *class_dev) | |||
477 | class_device_put(class_dev); | 613 | class_device_put(class_dev); |
478 | } | 614 | } |
479 | 615 | ||
616 | /** | ||
617 | * class_device_destroy - removes a class device that was created with class_device_create() | ||
618 | * @cls: the pointer to the struct class that this device was registered * with. | ||
619 | * @dev: the dev_t of the device that was previously registered. | ||
620 | * | ||
621 | * This call unregisters and cleans up a class device that was created with a | ||
622 | * call to class_device_create() | ||
623 | */ | ||
624 | void class_device_destroy(struct class *cls, dev_t devt) | ||
625 | { | ||
626 | struct class_device *class_dev = NULL; | ||
627 | struct class_device *class_dev_tmp; | ||
628 | |||
629 | down(&cls->sem); | ||
630 | list_for_each_entry(class_dev_tmp, &cls->children, node) { | ||
631 | if (class_dev_tmp->devt == devt) { | ||
632 | class_dev = class_dev_tmp; | ||
633 | break; | ||
634 | } | ||
635 | } | ||
636 | up(&cls->sem); | ||
637 | |||
638 | if (class_dev) | ||
639 | class_device_unregister(class_dev); | ||
640 | } | ||
641 | |||
480 | int class_device_rename(struct class_device *class_dev, char *new_name) | 642 | int class_device_rename(struct class_device *class_dev, char *new_name) |
481 | { | 643 | { |
482 | int error = 0; | 644 | int error = 0; |
@@ -576,6 +738,8 @@ EXPORT_SYMBOL_GPL(class_register); | |||
576 | EXPORT_SYMBOL_GPL(class_unregister); | 738 | EXPORT_SYMBOL_GPL(class_unregister); |
577 | EXPORT_SYMBOL_GPL(class_get); | 739 | EXPORT_SYMBOL_GPL(class_get); |
578 | EXPORT_SYMBOL_GPL(class_put); | 740 | EXPORT_SYMBOL_GPL(class_put); |
741 | EXPORT_SYMBOL_GPL(class_create); | ||
742 | EXPORT_SYMBOL_GPL(class_destroy); | ||
579 | 743 | ||
580 | EXPORT_SYMBOL_GPL(class_device_register); | 744 | EXPORT_SYMBOL_GPL(class_device_register); |
581 | EXPORT_SYMBOL_GPL(class_device_unregister); | 745 | EXPORT_SYMBOL_GPL(class_device_unregister); |
@@ -584,6 +748,8 @@ EXPORT_SYMBOL_GPL(class_device_add); | |||
584 | EXPORT_SYMBOL_GPL(class_device_del); | 748 | EXPORT_SYMBOL_GPL(class_device_del); |
585 | EXPORT_SYMBOL_GPL(class_device_get); | 749 | EXPORT_SYMBOL_GPL(class_device_get); |
586 | EXPORT_SYMBOL_GPL(class_device_put); | 750 | EXPORT_SYMBOL_GPL(class_device_put); |
751 | EXPORT_SYMBOL_GPL(class_device_create); | ||
752 | EXPORT_SYMBOL_GPL(class_device_destroy); | ||
587 | EXPORT_SYMBOL_GPL(class_device_create_file); | 753 | EXPORT_SYMBOL_GPL(class_device_create_file); |
588 | EXPORT_SYMBOL_GPL(class_device_remove_file); | 754 | EXPORT_SYMBOL_GPL(class_device_remove_file); |
589 | EXPORT_SYMBOL_GPL(class_device_create_bin_file); | 755 | EXPORT_SYMBOL_GPL(class_device_create_bin_file); |
diff --git a/drivers/base/class_simple.c b/drivers/base/class_simple.c deleted file mode 100644 index 27699eb20a37..000000000000 --- a/drivers/base/class_simple.c +++ /dev/null | |||
@@ -1,199 +0,0 @@ | |||
1 | /* | ||
2 | * class_simple.c - a "simple" interface for classes for simple char devices. | ||
3 | * | ||
4 | * Copyright (c) 2003-2004 Greg Kroah-Hartman <greg@kroah.com> | ||
5 | * Copyright (c) 2003-2004 IBM Corp. | ||
6 | * | ||
7 | * This file is released under the GPLv2 | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/config.h> | ||
12 | #include <linux/device.h> | ||
13 | #include <linux/err.h> | ||
14 | |||
15 | struct class_simple { | ||
16 | struct class class; | ||
17 | }; | ||
18 | #define to_class_simple(d) container_of(d, struct class_simple, class) | ||
19 | |||
20 | struct simple_dev { | ||
21 | struct list_head node; | ||
22 | struct class_device class_dev; | ||
23 | }; | ||
24 | #define to_simple_dev(d) container_of(d, struct simple_dev, class_dev) | ||
25 | |||
26 | static LIST_HEAD(simple_dev_list); | ||
27 | static DEFINE_SPINLOCK(simple_dev_list_lock); | ||
28 | |||
29 | static void release_simple_dev(struct class_device *class_dev) | ||
30 | { | ||
31 | struct simple_dev *s_dev = to_simple_dev(class_dev); | ||
32 | kfree(s_dev); | ||
33 | } | ||
34 | |||
35 | static void class_simple_release(struct class *class) | ||
36 | { | ||
37 | struct class_simple *cs = to_class_simple(class); | ||
38 | kfree(cs); | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * class_simple_create - create a struct class_simple structure | ||
43 | * @owner: pointer to the module that is to "own" this struct class_simple | ||
44 | * @name: pointer to a string for the name of this class. | ||
45 | * | ||
46 | * This is used to create a struct class_simple pointer that can then be used | ||
47 | * in calls to class_simple_device_add(). This is used when you do not wish to | ||
48 | * create a full blown class support for a type of char devices. | ||
49 | * | ||
50 | * Note, the pointer created here is to be destroyed when finished by making a | ||
51 | * call to class_simple_destroy(). | ||
52 | */ | ||
53 | struct class_simple *class_simple_create(struct module *owner, char *name) | ||
54 | { | ||
55 | struct class_simple *cs; | ||
56 | int retval; | ||
57 | |||
58 | cs = kmalloc(sizeof(*cs), GFP_KERNEL); | ||
59 | if (!cs) { | ||
60 | retval = -ENOMEM; | ||
61 | goto error; | ||
62 | } | ||
63 | memset(cs, 0x00, sizeof(*cs)); | ||
64 | |||
65 | cs->class.name = name; | ||
66 | cs->class.class_release = class_simple_release; | ||
67 | cs->class.release = release_simple_dev; | ||
68 | |||
69 | retval = class_register(&cs->class); | ||
70 | if (retval) | ||
71 | goto error; | ||
72 | |||
73 | return cs; | ||
74 | |||
75 | error: | ||
76 | kfree(cs); | ||
77 | return ERR_PTR(retval); | ||
78 | } | ||
79 | EXPORT_SYMBOL(class_simple_create); | ||
80 | |||
81 | /** | ||
82 | * class_simple_destroy - destroys a struct class_simple structure | ||
83 | * @cs: pointer to the struct class_simple that is to be destroyed | ||
84 | * | ||
85 | * Note, the pointer to be destroyed must have been created with a call to | ||
86 | * class_simple_create(). | ||
87 | */ | ||
88 | void class_simple_destroy(struct class_simple *cs) | ||
89 | { | ||
90 | if ((cs == NULL) || (IS_ERR(cs))) | ||
91 | return; | ||
92 | |||
93 | class_unregister(&cs->class); | ||
94 | } | ||
95 | EXPORT_SYMBOL(class_simple_destroy); | ||
96 | |||
97 | /** | ||
98 | * class_simple_device_add - adds a class device to sysfs for a character driver | ||
99 | * @cs: pointer to the struct class_simple that this device should be registered to. | ||
100 | * @dev: the dev_t for the device to be added. | ||
101 | * @device: a pointer to a struct device that is assiociated with this class device. | ||
102 | * @fmt: string for the class device's name | ||
103 | * | ||
104 | * This function can be used by simple char device classes that do not | ||
105 | * implement their own class device registration. A struct class_device will | ||
106 | * be created in sysfs, registered to the specified class. A "dev" file will | ||
107 | * be created, showing the dev_t for the device. The pointer to the struct | ||
108 | * class_device will be returned from the call. Any further sysfs files that | ||
109 | * might be required can be created using this pointer. | ||
110 | * Note: the struct class_simple passed to this function must have previously been | ||
111 | * created with a call to class_simple_create(). | ||
112 | */ | ||
113 | struct class_device *class_simple_device_add(struct class_simple *cs, dev_t dev, struct device *device, const char *fmt, ...) | ||
114 | { | ||
115 | va_list args; | ||
116 | struct simple_dev *s_dev = NULL; | ||
117 | int retval; | ||
118 | |||
119 | if ((cs == NULL) || (IS_ERR(cs))) { | ||
120 | retval = -ENODEV; | ||
121 | goto error; | ||
122 | } | ||
123 | |||
124 | s_dev = kmalloc(sizeof(*s_dev), GFP_KERNEL); | ||
125 | if (!s_dev) { | ||
126 | retval = -ENOMEM; | ||
127 | goto error; | ||
128 | } | ||
129 | memset(s_dev, 0x00, sizeof(*s_dev)); | ||
130 | |||
131 | s_dev->class_dev.devt = dev; | ||
132 | s_dev->class_dev.dev = device; | ||
133 | s_dev->class_dev.class = &cs->class; | ||
134 | |||
135 | va_start(args, fmt); | ||
136 | vsnprintf(s_dev->class_dev.class_id, BUS_ID_SIZE, fmt, args); | ||
137 | va_end(args); | ||
138 | retval = class_device_register(&s_dev->class_dev); | ||
139 | if (retval) | ||
140 | goto error; | ||
141 | |||
142 | spin_lock(&simple_dev_list_lock); | ||
143 | list_add(&s_dev->node, &simple_dev_list); | ||
144 | spin_unlock(&simple_dev_list_lock); | ||
145 | |||
146 | return &s_dev->class_dev; | ||
147 | |||
148 | error: | ||
149 | kfree(s_dev); | ||
150 | return ERR_PTR(retval); | ||
151 | } | ||
152 | EXPORT_SYMBOL(class_simple_device_add); | ||
153 | |||
154 | /** | ||
155 | * class_simple_set_hotplug - set the hotplug callback in the embedded struct class | ||
156 | * @cs: pointer to the struct class_simple to hold the pointer | ||
157 | * @hotplug: function pointer to the hotplug function | ||
158 | * | ||
159 | * Implement and set a hotplug function to add environment variables specific to this | ||
160 | * class on the hotplug event. | ||
161 | */ | ||
162 | int class_simple_set_hotplug(struct class_simple *cs, | ||
163 | int (*hotplug)(struct class_device *dev, char **envp, int num_envp, char *buffer, int buffer_size)) | ||
164 | { | ||
165 | if ((cs == NULL) || (IS_ERR(cs))) | ||
166 | return -ENODEV; | ||
167 | cs->class.hotplug = hotplug; | ||
168 | return 0; | ||
169 | } | ||
170 | EXPORT_SYMBOL(class_simple_set_hotplug); | ||
171 | |||
172 | /** | ||
173 | * class_simple_device_remove - removes a class device that was created with class_simple_device_add() | ||
174 | * @dev: the dev_t of the device that was previously registered. | ||
175 | * | ||
176 | * This call unregisters and cleans up a class device that was created with a | ||
177 | * call to class_device_simple_add() | ||
178 | */ | ||
179 | void class_simple_device_remove(dev_t dev) | ||
180 | { | ||
181 | struct simple_dev *s_dev = NULL; | ||
182 | int found = 0; | ||
183 | |||
184 | spin_lock(&simple_dev_list_lock); | ||
185 | list_for_each_entry(s_dev, &simple_dev_list, node) { | ||
186 | if (s_dev->class_dev.devt == dev) { | ||
187 | found = 1; | ||
188 | break; | ||
189 | } | ||
190 | } | ||
191 | if (found) { | ||
192 | list_del(&s_dev->node); | ||
193 | spin_unlock(&simple_dev_list_lock); | ||
194 | class_device_unregister(&s_dev->class_dev); | ||
195 | } else { | ||
196 | spin_unlock(&simple_dev_list_lock); | ||
197 | } | ||
198 | } | ||
199 | EXPORT_SYMBOL(class_simple_device_remove); | ||
diff --git a/drivers/base/core.c b/drivers/base/core.c index 268a9c8d168b..86d79755fbfb 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -31,17 +31,15 @@ int (*platform_notify_remove)(struct device * dev) = NULL; | |||
31 | #define to_dev(obj) container_of(obj, struct device, kobj) | 31 | #define to_dev(obj) container_of(obj, struct device, kobj) |
32 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) | 32 | #define to_dev_attr(_attr) container_of(_attr, struct device_attribute, attr) |
33 | 33 | ||
34 | extern struct attribute * dev_default_attrs[]; | ||
35 | |||
36 | static ssize_t | 34 | static ssize_t |
37 | dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) | 35 | dev_attr_show(struct kobject * kobj, struct attribute * attr, char * buf) |
38 | { | 36 | { |
39 | struct device_attribute * dev_attr = to_dev_attr(attr); | 37 | struct device_attribute * dev_attr = to_dev_attr(attr); |
40 | struct device * dev = to_dev(kobj); | 38 | struct device * dev = to_dev(kobj); |
41 | ssize_t ret = 0; | 39 | ssize_t ret = -EIO; |
42 | 40 | ||
43 | if (dev_attr->show) | 41 | if (dev_attr->show) |
44 | ret = dev_attr->show(dev, buf); | 42 | ret = dev_attr->show(dev, dev_attr, buf); |
45 | return ret; | 43 | return ret; |
46 | } | 44 | } |
47 | 45 | ||
@@ -51,10 +49,10 @@ dev_attr_store(struct kobject * kobj, struct attribute * attr, | |||
51 | { | 49 | { |
52 | struct device_attribute * dev_attr = to_dev_attr(attr); | 50 | struct device_attribute * dev_attr = to_dev_attr(attr); |
53 | struct device * dev = to_dev(kobj); | 51 | struct device * dev = to_dev(kobj); |
54 | ssize_t ret = 0; | 52 | ssize_t ret = -EIO; |
55 | 53 | ||
56 | if (dev_attr->store) | 54 | if (dev_attr->store) |
57 | ret = dev_attr->store(dev, buf, count); | 55 | ret = dev_attr->store(dev, dev_attr, buf, count); |
58 | return ret; | 56 | return ret; |
59 | } | 57 | } |
60 | 58 | ||
@@ -89,7 +87,6 @@ static void device_release(struct kobject * kobj) | |||
89 | static struct kobj_type ktype_device = { | 87 | static struct kobj_type ktype_device = { |
90 | .release = device_release, | 88 | .release = device_release, |
91 | .sysfs_ops = &dev_sysfs_ops, | 89 | .sysfs_ops = &dev_sysfs_ops, |
92 | .default_attrs = dev_default_attrs, | ||
93 | }; | 90 | }; |
94 | 91 | ||
95 | 92 | ||
@@ -105,7 +102,7 @@ static int dev_hotplug_filter(struct kset *kset, struct kobject *kobj) | |||
105 | return 0; | 102 | return 0; |
106 | } | 103 | } |
107 | 104 | ||
108 | static char *dev_hotplug_name(struct kset *kset, struct kobject *kobj) | 105 | static const char *dev_hotplug_name(struct kset *kset, struct kobject *kobj) |
109 | { | 106 | { |
110 | struct device *dev = to_dev(kobj); | 107 | struct device *dev = to_dev(kobj); |
111 | 108 | ||
@@ -210,11 +207,9 @@ void device_initialize(struct device *dev) | |||
210 | { | 207 | { |
211 | kobj_set_kset_s(dev, devices_subsys); | 208 | kobj_set_kset_s(dev, devices_subsys); |
212 | kobject_init(&dev->kobj); | 209 | kobject_init(&dev->kobj); |
213 | INIT_LIST_HEAD(&dev->node); | 210 | klist_init(&dev->klist_children); |
214 | INIT_LIST_HEAD(&dev->children); | ||
215 | INIT_LIST_HEAD(&dev->driver_list); | ||
216 | INIT_LIST_HEAD(&dev->bus_list); | ||
217 | INIT_LIST_HEAD(&dev->dma_pools); | 211 | INIT_LIST_HEAD(&dev->dma_pools); |
212 | init_MUTEX(&dev->sem); | ||
218 | } | 213 | } |
219 | 214 | ||
220 | /** | 215 | /** |
@@ -248,26 +243,24 @@ int device_add(struct device *dev) | |||
248 | 243 | ||
249 | if ((error = kobject_add(&dev->kobj))) | 244 | if ((error = kobject_add(&dev->kobj))) |
250 | goto Error; | 245 | goto Error; |
246 | kobject_hotplug(&dev->kobj, KOBJ_ADD); | ||
251 | if ((error = device_pm_add(dev))) | 247 | if ((error = device_pm_add(dev))) |
252 | goto PMError; | 248 | goto PMError; |
253 | if ((error = bus_add_device(dev))) | 249 | if ((error = bus_add_device(dev))) |
254 | goto BusError; | 250 | goto BusError; |
255 | down_write(&devices_subsys.rwsem); | ||
256 | if (parent) | 251 | if (parent) |
257 | list_add_tail(&dev->node, &parent->children); | 252 | klist_add_tail(&parent->klist_children, &dev->knode_parent); |
258 | up_write(&devices_subsys.rwsem); | ||
259 | 253 | ||
260 | /* notify platform of device entry */ | 254 | /* notify platform of device entry */ |
261 | if (platform_notify) | 255 | if (platform_notify) |
262 | platform_notify(dev); | 256 | platform_notify(dev); |
263 | |||
264 | kobject_hotplug(&dev->kobj, KOBJ_ADD); | ||
265 | Done: | 257 | Done: |
266 | put_device(dev); | 258 | put_device(dev); |
267 | return error; | 259 | return error; |
268 | BusError: | 260 | BusError: |
269 | device_pm_remove(dev); | 261 | device_pm_remove(dev); |
270 | PMError: | 262 | PMError: |
263 | kobject_hotplug(&dev->kobj, KOBJ_REMOVE); | ||
271 | kobject_del(&dev->kobj); | 264 | kobject_del(&dev->kobj); |
272 | Error: | 265 | Error: |
273 | if (parent) | 266 | if (parent) |
@@ -339,10 +332,8 @@ void device_del(struct device * dev) | |||
339 | { | 332 | { |
340 | struct device * parent = dev->parent; | 333 | struct device * parent = dev->parent; |
341 | 334 | ||
342 | down_write(&devices_subsys.rwsem); | ||
343 | if (parent) | 335 | if (parent) |
344 | list_del_init(&dev->node); | 336 | klist_remove(&dev->knode_parent); |
345 | up_write(&devices_subsys.rwsem); | ||
346 | 337 | ||
347 | /* Notify the platform of the removal, in case they | 338 | /* Notify the platform of the removal, in case they |
348 | * need to do anything... | 339 | * need to do anything... |
@@ -376,6 +367,12 @@ void device_unregister(struct device * dev) | |||
376 | } | 367 | } |
377 | 368 | ||
378 | 369 | ||
370 | static struct device * next_device(struct klist_iter * i) | ||
371 | { | ||
372 | struct klist_node * n = klist_next(i); | ||
373 | return n ? container_of(n, struct device, knode_parent) : NULL; | ||
374 | } | ||
375 | |||
379 | /** | 376 | /** |
380 | * device_for_each_child - device child iterator. | 377 | * device_for_each_child - device child iterator. |
381 | * @dev: parent struct device. | 378 | * @dev: parent struct device. |
@@ -388,39 +385,20 @@ void device_unregister(struct device * dev) | |||
388 | * We check the return of @fn each time. If it returns anything | 385 | * We check the return of @fn each time. If it returns anything |
389 | * other than 0, we break out and return that value. | 386 | * other than 0, we break out and return that value. |
390 | */ | 387 | */ |
391 | int device_for_each_child(struct device * dev, void * data, | 388 | int device_for_each_child(struct device * parent, void * data, |
392 | int (*fn)(struct device *, void *)) | 389 | int (*fn)(struct device *, void *)) |
393 | { | 390 | { |
391 | struct klist_iter i; | ||
394 | struct device * child; | 392 | struct device * child; |
395 | int error = 0; | 393 | int error = 0; |
396 | 394 | ||
397 | down_read(&devices_subsys.rwsem); | 395 | klist_iter_init(&parent->klist_children, &i); |
398 | list_for_each_entry(child, &dev->children, node) { | 396 | while ((child = next_device(&i)) && !error) |
399 | if((error = fn(child, data))) | 397 | error = fn(child, data); |
400 | break; | 398 | klist_iter_exit(&i); |
401 | } | ||
402 | up_read(&devices_subsys.rwsem); | ||
403 | return error; | 399 | return error; |
404 | } | 400 | } |
405 | 401 | ||
406 | /** | ||
407 | * device_find - locate device on a bus by name. | ||
408 | * @name: name of the device. | ||
409 | * @bus: bus to scan for the device. | ||
410 | * | ||
411 | * Call kset_find_obj() to iterate over list of devices on | ||
412 | * a bus to find device by name. Return device if found. | ||
413 | * | ||
414 | * Note that kset_find_obj increments device's reference count. | ||
415 | */ | ||
416 | struct device *device_find(const char *name, struct bus_type *bus) | ||
417 | { | ||
418 | struct kobject *k = kset_find_obj(&bus->devices, name); | ||
419 | if (k) | ||
420 | return to_dev(k); | ||
421 | return NULL; | ||
422 | } | ||
423 | |||
424 | int __init devices_init(void) | 402 | int __init devices_init(void) |
425 | { | 403 | { |
426 | return subsystem_register(&devices_subsys); | 404 | return subsystem_register(&devices_subsys); |
@@ -436,7 +414,6 @@ EXPORT_SYMBOL_GPL(device_del); | |||
436 | EXPORT_SYMBOL_GPL(device_unregister); | 414 | EXPORT_SYMBOL_GPL(device_unregister); |
437 | EXPORT_SYMBOL_GPL(get_device); | 415 | EXPORT_SYMBOL_GPL(get_device); |
438 | EXPORT_SYMBOL_GPL(put_device); | 416 | EXPORT_SYMBOL_GPL(put_device); |
439 | EXPORT_SYMBOL_GPL(device_find); | ||
440 | 417 | ||
441 | EXPORT_SYMBOL_GPL(device_create_file); | 418 | EXPORT_SYMBOL_GPL(device_create_file); |
442 | EXPORT_SYMBOL_GPL(device_remove_file); | 419 | EXPORT_SYMBOL_GPL(device_remove_file); |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 6ef3069b5710..b79badd0f158 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -16,6 +16,11 @@ struct sysdev_class cpu_sysdev_class = { | |||
16 | EXPORT_SYMBOL(cpu_sysdev_class); | 16 | EXPORT_SYMBOL(cpu_sysdev_class); |
17 | 17 | ||
18 | #ifdef CONFIG_HOTPLUG_CPU | 18 | #ifdef CONFIG_HOTPLUG_CPU |
19 | int __attribute__((weak)) smp_prepare_cpu (int cpu) | ||
20 | { | ||
21 | return 0; | ||
22 | } | ||
23 | |||
19 | static ssize_t show_online(struct sys_device *dev, char *buf) | 24 | static ssize_t show_online(struct sys_device *dev, char *buf) |
20 | { | 25 | { |
21 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 26 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
@@ -36,7 +41,11 @@ static ssize_t store_online(struct sys_device *dev, const char *buf, | |||
36 | kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); | 41 | kobject_hotplug(&dev->kobj, KOBJ_OFFLINE); |
37 | break; | 42 | break; |
38 | case '1': | 43 | case '1': |
39 | ret = cpu_up(cpu->sysdev.id); | 44 | ret = smp_prepare_cpu(cpu->sysdev.id); |
45 | if (!ret) | ||
46 | ret = cpu_up(cpu->sysdev.id); | ||
47 | if (!ret) | ||
48 | kobject_hotplug(&dev->kobj, KOBJ_ONLINE); | ||
40 | break; | 49 | break; |
41 | default: | 50 | default: |
42 | ret = -EINVAL; | 51 | ret = -EINVAL; |
diff --git a/drivers/base/dd.c b/drivers/base/dd.c new file mode 100644 index 000000000000..6db3a789c54f --- /dev/null +++ b/drivers/base/dd.c | |||
@@ -0,0 +1,248 @@ | |||
1 | /* | ||
2 | * drivers/base/dd.c - The core device/driver interactions. | ||
3 | * | ||
4 | * This file contains the (sometimes tricky) code that controls the | ||
5 | * interactions between devices and drivers, which primarily includes | ||
6 | * driver binding and unbinding. | ||
7 | * | ||
8 | * All of this code used to exist in drivers/base/bus.c, but was | ||
9 | * relocated to here in the name of compartmentalization (since it wasn't | ||
10 | * strictly code just for the 'struct bus_type'. | ||
11 | * | ||
12 | * Copyright (c) 2002-5 Patrick Mochel | ||
13 | * Copyright (c) 2002-3 Open Source Development Labs | ||
14 | * | ||
15 | * This file is released under the GPLv2 | ||
16 | */ | ||
17 | |||
18 | #include <linux/device.h> | ||
19 | #include <linux/module.h> | ||
20 | |||
21 | #include "base.h" | ||
22 | #include "power/power.h" | ||
23 | |||
24 | #define to_drv(node) container_of(node, struct device_driver, kobj.entry) | ||
25 | |||
26 | |||
27 | /** | ||
28 | * device_bind_driver - bind a driver to one device. | ||
29 | * @dev: device. | ||
30 | * | ||
31 | * Allow manual attachment of a driver to a device. | ||
32 | * Caller must have already set @dev->driver. | ||
33 | * | ||
34 | * Note that this does not modify the bus reference count | ||
35 | * nor take the bus's rwsem. Please verify those are accounted | ||
36 | * for before calling this. (It is ok to call with no other effort | ||
37 | * from a driver's probe() method.) | ||
38 | * | ||
39 | * This function must be called with @dev->sem held. | ||
40 | */ | ||
41 | void device_bind_driver(struct device * dev) | ||
42 | { | ||
43 | pr_debug("bound device '%s' to driver '%s'\n", | ||
44 | dev->bus_id, dev->driver->name); | ||
45 | klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver); | ||
46 | sysfs_create_link(&dev->driver->kobj, &dev->kobj, | ||
47 | kobject_name(&dev->kobj)); | ||
48 | sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver"); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * driver_probe_device - attempt to bind device & driver. | ||
53 | * @drv: driver. | ||
54 | * @dev: device. | ||
55 | * | ||
56 | * First, we call the bus's match function, if one present, which | ||
57 | * should compare the device IDs the driver supports with the | ||
58 | * device IDs of the device. Note we don't do this ourselves | ||
59 | * because we don't know the format of the ID structures, nor what | ||
60 | * is to be considered a match and what is not. | ||
61 | * | ||
62 | * | ||
63 | * This function returns 1 if a match is found, an error if one | ||
64 | * occurs (that is not -ENODEV or -ENXIO), and 0 otherwise. | ||
65 | * | ||
66 | * This function must be called with @dev->sem held. | ||
67 | */ | ||
68 | static int driver_probe_device(struct device_driver * drv, struct device * dev) | ||
69 | { | ||
70 | int ret = 0; | ||
71 | |||
72 | if (drv->bus->match && !drv->bus->match(dev, drv)) | ||
73 | goto Done; | ||
74 | |||
75 | pr_debug("%s: Matched Device %s with Driver %s\n", | ||
76 | drv->bus->name, dev->bus_id, drv->name); | ||
77 | dev->driver = drv; | ||
78 | if (drv->probe) { | ||
79 | ret = drv->probe(dev); | ||
80 | if (ret) { | ||
81 | dev->driver = NULL; | ||
82 | goto ProbeFailed; | ||
83 | } | ||
84 | } | ||
85 | device_bind_driver(dev); | ||
86 | ret = 1; | ||
87 | pr_debug("%s: Bound Device %s to Driver %s\n", | ||
88 | drv->bus->name, dev->bus_id, drv->name); | ||
89 | goto Done; | ||
90 | |||
91 | ProbeFailed: | ||
92 | if (ret == -ENODEV || ret == -ENXIO) { | ||
93 | /* Driver matched, but didn't support device | ||
94 | * or device not found. | ||
95 | * Not an error; keep going. | ||
96 | */ | ||
97 | ret = 0; | ||
98 | } else { | ||
99 | /* driver matched but the probe failed */ | ||
100 | printk(KERN_WARNING | ||
101 | "%s: probe of %s failed with error %d\n", | ||
102 | drv->name, dev->bus_id, ret); | ||
103 | } | ||
104 | Done: | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | static int __device_attach(struct device_driver * drv, void * data) | ||
109 | { | ||
110 | struct device * dev = data; | ||
111 | return driver_probe_device(drv, dev); | ||
112 | } | ||
113 | |||
114 | /** | ||
115 | * device_attach - try to attach device to a driver. | ||
116 | * @dev: device. | ||
117 | * | ||
118 | * Walk the list of drivers that the bus has and call | ||
119 | * driver_probe_device() for each pair. If a compatible | ||
120 | * pair is found, break out and return. | ||
121 | * | ||
122 | * Returns 1 if the device was bound to a driver; | ||
123 | * 0 if no matching device was found; error code otherwise. | ||
124 | */ | ||
125 | int device_attach(struct device * dev) | ||
126 | { | ||
127 | int ret = 0; | ||
128 | |||
129 | down(&dev->sem); | ||
130 | if (dev->driver) { | ||
131 | device_bind_driver(dev); | ||
132 | ret = 1; | ||
133 | } else | ||
134 | ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach); | ||
135 | up(&dev->sem); | ||
136 | return ret; | ||
137 | } | ||
138 | |||
139 | static int __driver_attach(struct device * dev, void * data) | ||
140 | { | ||
141 | struct device_driver * drv = data; | ||
142 | |||
143 | /* | ||
144 | * Lock device and try to bind to it. We drop the error | ||
145 | * here and always return 0, because we need to keep trying | ||
146 | * to bind to devices and some drivers will return an error | ||
147 | * simply if it didn't support the device. | ||
148 | * | ||
149 | * driver_probe_device() will spit a warning if there | ||
150 | * is an error. | ||
151 | */ | ||
152 | |||
153 | down(&dev->sem); | ||
154 | if (!dev->driver) | ||
155 | driver_probe_device(drv, dev); | ||
156 | up(&dev->sem); | ||
157 | |||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * driver_attach - try to bind driver to devices. | ||
164 | * @drv: driver. | ||
165 | * | ||
166 | * Walk the list of devices that the bus has on it and try to | ||
167 | * match the driver with each one. If driver_probe_device() | ||
168 | * returns 0 and the @dev->driver is set, we've found a | ||
169 | * compatible pair. | ||
170 | */ | ||
171 | void driver_attach(struct device_driver * drv) | ||
172 | { | ||
173 | bus_for_each_dev(drv->bus, NULL, drv, __driver_attach); | ||
174 | } | ||
175 | |||
176 | /** | ||
177 | * device_release_driver - manually detach device from driver. | ||
178 | * @dev: device. | ||
179 | * | ||
180 | * Manually detach device from driver. | ||
181 | * | ||
182 | * __device_release_driver() must be called with @dev->sem held. | ||
183 | */ | ||
184 | |||
185 | static void __device_release_driver(struct device * dev) | ||
186 | { | ||
187 | struct device_driver * drv; | ||
188 | |||
189 | drv = dev->driver; | ||
190 | if (drv) { | ||
191 | get_driver(drv); | ||
192 | sysfs_remove_link(&drv->kobj, kobject_name(&dev->kobj)); | ||
193 | sysfs_remove_link(&dev->kobj, "driver"); | ||
194 | klist_remove(&dev->knode_driver); | ||
195 | |||
196 | if (drv->remove) | ||
197 | drv->remove(dev); | ||
198 | dev->driver = NULL; | ||
199 | put_driver(drv); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | void device_release_driver(struct device * dev) | ||
204 | { | ||
205 | /* | ||
206 | * If anyone calls device_release_driver() recursively from | ||
207 | * within their ->remove callback for the same device, they | ||
208 | * will deadlock right here. | ||
209 | */ | ||
210 | down(&dev->sem); | ||
211 | __device_release_driver(dev); | ||
212 | up(&dev->sem); | ||
213 | } | ||
214 | |||
215 | |||
216 | /** | ||
217 | * driver_detach - detach driver from all devices it controls. | ||
218 | * @drv: driver. | ||
219 | */ | ||
220 | void driver_detach(struct device_driver * drv) | ||
221 | { | ||
222 | struct device * dev; | ||
223 | |||
224 | for (;;) { | ||
225 | spin_lock_irq(&drv->klist_devices.k_lock); | ||
226 | if (list_empty(&drv->klist_devices.k_list)) { | ||
227 | spin_unlock_irq(&drv->klist_devices.k_lock); | ||
228 | break; | ||
229 | } | ||
230 | dev = list_entry(drv->klist_devices.k_list.prev, | ||
231 | struct device, knode_driver.n_node); | ||
232 | get_device(dev); | ||
233 | spin_unlock_irq(&drv->klist_devices.k_lock); | ||
234 | |||
235 | down(&dev->sem); | ||
236 | if (dev->driver == drv) | ||
237 | __device_release_driver(dev); | ||
238 | up(&dev->sem); | ||
239 | put_device(dev); | ||
240 | } | ||
241 | } | ||
242 | |||
243 | |||
244 | EXPORT_SYMBOL_GPL(device_bind_driver); | ||
245 | EXPORT_SYMBOL_GPL(device_release_driver); | ||
246 | EXPORT_SYMBOL_GPL(device_attach); | ||
247 | EXPORT_SYMBOL_GPL(driver_attach); | ||
248 | |||
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c index f48833df61a2..c4aebf2f522d 100644 --- a/drivers/base/dmapool.c +++ b/drivers/base/dmapool.c | |||
@@ -41,7 +41,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */ | |||
41 | static DECLARE_MUTEX (pools_lock); | 41 | static DECLARE_MUTEX (pools_lock); |
42 | 42 | ||
43 | static ssize_t | 43 | static ssize_t |
44 | show_pools (struct device *dev, char *buf) | 44 | show_pools (struct device *dev, struct device_attribute *attr, char *buf) |
45 | { | 45 | { |
46 | unsigned temp; | 46 | unsigned temp; |
47 | unsigned size; | 47 | unsigned size; |
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 3b269f7e5213..1b645886e9eb 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
@@ -18,6 +18,43 @@ | |||
18 | #define to_dev(node) container_of(node, struct device, driver_list) | 18 | #define to_dev(node) container_of(node, struct device, driver_list) |
19 | #define to_drv(obj) container_of(obj, struct device_driver, kobj) | 19 | #define to_drv(obj) container_of(obj, struct device_driver, kobj) |
20 | 20 | ||
21 | |||
22 | static struct device * next_device(struct klist_iter * i) | ||
23 | { | ||
24 | struct klist_node * n = klist_next(i); | ||
25 | return n ? container_of(n, struct device, knode_driver) : NULL; | ||
26 | } | ||
27 | |||
28 | /** | ||
29 | * driver_for_each_device - Iterator for devices bound to a driver. | ||
30 | * @drv: Driver we're iterating. | ||
31 | * @data: Data to pass to the callback. | ||
32 | * @fn: Function to call for each device. | ||
33 | * | ||
34 | * Iterate over the @drv's list of devices calling @fn for each one. | ||
35 | */ | ||
36 | |||
37 | int driver_for_each_device(struct device_driver * drv, struct device * start, | ||
38 | void * data, int (*fn)(struct device *, void *)) | ||
39 | { | ||
40 | struct klist_iter i; | ||
41 | struct device * dev; | ||
42 | int error = 0; | ||
43 | |||
44 | if (!drv) | ||
45 | return -EINVAL; | ||
46 | |||
47 | klist_iter_init_node(&drv->klist_devices, &i, | ||
48 | start ? &start->knode_driver : NULL); | ||
49 | while ((dev = next_device(&i)) && !error) | ||
50 | error = fn(dev, data); | ||
51 | klist_iter_exit(&i); | ||
52 | return error; | ||
53 | } | ||
54 | |||
55 | EXPORT_SYMBOL_GPL(driver_for_each_device); | ||
56 | |||
57 | |||
21 | /** | 58 | /** |
22 | * driver_create_file - create sysfs file for driver. | 59 | * driver_create_file - create sysfs file for driver. |
23 | * @drv: driver. | 60 | * @drv: driver. |
@@ -85,7 +122,7 @@ void put_driver(struct device_driver * drv) | |||
85 | */ | 122 | */ |
86 | int driver_register(struct device_driver * drv) | 123 | int driver_register(struct device_driver * drv) |
87 | { | 124 | { |
88 | INIT_LIST_HEAD(&drv->devices); | 125 | klist_init(&drv->klist_devices); |
89 | init_completion(&drv->unloaded); | 126 | init_completion(&drv->unloaded); |
90 | return bus_add_driver(drv); | 127 | return bus_add_driver(drv); |
91 | } | 128 | } |
diff --git a/drivers/base/interface.c b/drivers/base/interface.c deleted file mode 100644 index bd515843a0cb..000000000000 --- a/drivers/base/interface.c +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/base/interface.c - common driverfs interface that's exported to | ||
3 | * the world for all devices. | ||
4 | * | ||
5 | * Copyright (c) 2002-3 Patrick Mochel | ||
6 | * Copyright (c) 2002-3 Open Source Development Labs | ||
7 | * | ||
8 | * This file is released under the GPLv2 | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/device.h> | ||
13 | #include <linux/err.h> | ||
14 | #include <linux/stat.h> | ||
15 | #include <linux/string.h> | ||
16 | |||
17 | /** | ||
18 | * detach_state - control the default power state for the device. | ||
19 | * | ||
20 | * This is the state the device enters when it's driver module is | ||
21 | * unloaded. The value is an unsigned integer, in the range of 0-4. | ||
22 | * '0' indicates 'On', so no action will be taken when the driver is | ||
23 | * unloaded. This is the default behavior. | ||
24 | * '4' indicates 'Off', meaning the driver core will call the driver's | ||
25 | * shutdown method to quiesce the device. | ||
26 | * 1-3 indicate a low-power state for the device to enter via the | ||
27 | * driver's suspend method. | ||
28 | */ | ||
29 | |||
30 | static ssize_t detach_show(struct device * dev, char * buf) | ||
31 | { | ||
32 | return sprintf(buf, "%u\n", dev->detach_state); | ||
33 | } | ||
34 | |||
35 | static ssize_t detach_store(struct device * dev, const char * buf, size_t n) | ||
36 | { | ||
37 | u32 state; | ||
38 | state = simple_strtoul(buf, NULL, 10); | ||
39 | if (state > 4) | ||
40 | return -EINVAL; | ||
41 | dev->detach_state = state; | ||
42 | return n; | ||
43 | } | ||
44 | |||
45 | static DEVICE_ATTR(detach_state, 0644, detach_show, detach_store); | ||
46 | |||
47 | |||
48 | struct attribute * dev_default_attrs[] = { | ||
49 | &dev_attr_detach_state.attr, | ||
50 | NULL, | ||
51 | }; | ||
diff --git a/drivers/base/node.c b/drivers/base/node.c index 583d57ec49a8..904b27caf697 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -87,7 +87,7 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | |||
87 | for (i = 0; i < MAX_NR_ZONES; i++) { | 87 | for (i = 0; i < MAX_NR_ZONES; i++) { |
88 | struct zone *z = &pg->node_zones[i]; | 88 | struct zone *z = &pg->node_zones[i]; |
89 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | 89 | for (cpu = 0; cpu < NR_CPUS; cpu++) { |
90 | struct per_cpu_pageset *ps = &z->pageset[cpu]; | 90 | struct per_cpu_pageset *ps = zone_pcp(z,cpu); |
91 | numa_hit += ps->numa_hit; | 91 | numa_hit += ps->numa_hit; |
92 | numa_miss += ps->numa_miss; | 92 | numa_miss += ps->numa_miss; |
93 | numa_foreign += ps->numa_foreign; | 93 | numa_foreign += ps->numa_foreign; |
@@ -136,7 +136,7 @@ static SYSDEV_ATTR(distance, S_IRUGO, node_read_distance, NULL); | |||
136 | * | 136 | * |
137 | * Initialize and register the node device. | 137 | * Initialize and register the node device. |
138 | */ | 138 | */ |
139 | int __init register_node(struct node *node, int num, struct node *parent) | 139 | int register_node(struct node *node, int num, struct node *parent) |
140 | { | 140 | { |
141 | int error; | 141 | int error; |
142 | 142 | ||
@@ -153,8 +153,24 @@ int __init register_node(struct node *node, int num, struct node *parent) | |||
153 | return error; | 153 | return error; |
154 | } | 154 | } |
155 | 155 | ||
156 | /** | ||
157 | * unregister_node - unregister a node device | ||
158 | * @node: node going away | ||
159 | * | ||
160 | * Unregisters a node device @node. All the devices on the node must be | ||
161 | * unregistered before calling this function. | ||
162 | */ | ||
163 | void unregister_node(struct node *node) | ||
164 | { | ||
165 | sysdev_remove_file(&node->sysdev, &attr_cpumap); | ||
166 | sysdev_remove_file(&node->sysdev, &attr_meminfo); | ||
167 | sysdev_remove_file(&node->sysdev, &attr_numastat); | ||
168 | sysdev_remove_file(&node->sysdev, &attr_distance); | ||
169 | |||
170 | sysdev_unregister(&node->sysdev); | ||
171 | } | ||
156 | 172 | ||
157 | int __init register_node_type(void) | 173 | static int __init register_node_type(void) |
158 | { | 174 | { |
159 | return sysdev_class_register(&node_class); | 175 | return sysdev_class_register(&node_class); |
160 | } | 176 | } |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index e5eda746f2a6..2e700d795cf1 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -1,18 +1,7 @@ | |||
1 | |||
2 | |||
3 | enum { | ||
4 | DEVICE_PM_ON, | ||
5 | DEVICE_PM1, | ||
6 | DEVICE_PM2, | ||
7 | DEVICE_PM3, | ||
8 | DEVICE_PM_OFF, | ||
9 | }; | ||
10 | |||
11 | /* | 1 | /* |
12 | * shutdown.c | 2 | * shutdown.c |
13 | */ | 3 | */ |
14 | 4 | ||
15 | extern int device_detach_shutdown(struct device *); | ||
16 | extern void device_shutdown(void); | 5 | extern void device_shutdown(void); |
17 | 6 | ||
18 | 7 | ||
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c index f8f5055754d6..bdd96b03b885 100644 --- a/drivers/base/power/resume.c +++ b/drivers/base/power/resume.c | |||
@@ -22,9 +22,22 @@ extern int sysdev_resume(void); | |||
22 | 22 | ||
23 | int resume_device(struct device * dev) | 23 | int resume_device(struct device * dev) |
24 | { | 24 | { |
25 | if (dev->bus && dev->bus->resume) | 25 | int error = 0; |
26 | return dev->bus->resume(dev); | 26 | |
27 | return 0; | 27 | down(&dev->sem); |
28 | if (dev->power.pm_parent | ||
29 | && dev->power.pm_parent->power.power_state) { | ||
30 | dev_err(dev, "PM: resume from %d, parent %s still %d\n", | ||
31 | dev->power.power_state, | ||
32 | dev->power.pm_parent->bus_id, | ||
33 | dev->power.pm_parent->power.power_state); | ||
34 | } | ||
35 | if (dev->bus && dev->bus->resume) { | ||
36 | dev_dbg(dev,"resuming\n"); | ||
37 | error = dev->bus->resume(dev); | ||
38 | } | ||
39 | up(&dev->sem); | ||
40 | return error; | ||
28 | } | 41 | } |
29 | 42 | ||
30 | 43 | ||
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c index d1e023fbe169..f50a08be424b 100644 --- a/drivers/base/power/shutdown.c +++ b/drivers/base/power/shutdown.c | |||
@@ -19,20 +19,6 @@ | |||
19 | extern struct subsystem devices_subsys; | 19 | extern struct subsystem devices_subsys; |
20 | 20 | ||
21 | 21 | ||
22 | int device_detach_shutdown(struct device * dev) | ||
23 | { | ||
24 | if (!dev->detach_state) | ||
25 | return 0; | ||
26 | |||
27 | if (dev->detach_state == DEVICE_PM_OFF) { | ||
28 | if (dev->driver && dev->driver->shutdown) | ||
29 | dev->driver->shutdown(dev); | ||
30 | return 0; | ||
31 | } | ||
32 | return dpm_runtime_suspend(dev, dev->detach_state); | ||
33 | } | ||
34 | |||
35 | |||
36 | /** | 22 | /** |
37 | * We handle system devices differently - we suspend and shut them | 23 | * We handle system devices differently - we suspend and shut them |
38 | * down last and resume them first. That way, we don't do anything stupid like | 24 | * down last and resume them first. That way, we don't do anything stupid like |
@@ -52,13 +38,12 @@ void device_shutdown(void) | |||
52 | struct device * dev; | 38 | struct device * dev; |
53 | 39 | ||
54 | down_write(&devices_subsys.rwsem); | 40 | down_write(&devices_subsys.rwsem); |
55 | list_for_each_entry_reverse(dev, &devices_subsys.kset.list, kobj.entry) { | 41 | list_for_each_entry_reverse(dev, &devices_subsys.kset.list, |
56 | pr_debug("shutting down %s: ", dev->bus_id); | 42 | kobj.entry) { |
57 | if (dev->driver && dev->driver->shutdown) { | 43 | if (dev->driver && dev->driver->shutdown) { |
58 | pr_debug("Ok\n"); | 44 | dev_dbg(dev, "shutdown\n"); |
59 | dev->driver->shutdown(dev); | 45 | dev->driver->shutdown(dev); |
60 | } else | 46 | } |
61 | pr_debug("Ignored.\n"); | ||
62 | } | 47 | } |
63 | up_write(&devices_subsys.rwsem); | 48 | up_write(&devices_subsys.rwsem); |
64 | 49 | ||
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c index a0b5cf689e63..2ccee3763acf 100644 --- a/drivers/base/power/suspend.c +++ b/drivers/base/power/suspend.c | |||
@@ -39,13 +39,27 @@ int suspend_device(struct device * dev, pm_message_t state) | |||
39 | { | 39 | { |
40 | int error = 0; | 40 | int error = 0; |
41 | 41 | ||
42 | dev_dbg(dev, "suspending\n"); | 42 | down(&dev->sem); |
43 | if (dev->power.power_state) { | ||
44 | dev_dbg(dev, "PM: suspend %d-->%d\n", | ||
45 | dev->power.power_state, state); | ||
46 | } | ||
47 | if (dev->power.pm_parent | ||
48 | && dev->power.pm_parent->power.power_state) { | ||
49 | dev_err(dev, | ||
50 | "PM: suspend %d->%d, parent %s already %d\n", | ||
51 | dev->power.power_state, state, | ||
52 | dev->power.pm_parent->bus_id, | ||
53 | dev->power.pm_parent->power.power_state); | ||
54 | } | ||
43 | 55 | ||
44 | dev->power.prev_state = dev->power.power_state; | 56 | dev->power.prev_state = dev->power.power_state; |
45 | 57 | ||
46 | if (dev->bus && dev->bus->suspend && !dev->power.power_state) | 58 | if (dev->bus && dev->bus->suspend && !dev->power.power_state) { |
59 | dev_dbg(dev, "suspending\n"); | ||
47 | error = dev->bus->suspend(dev, state); | 60 | error = dev->bus->suspend(dev, state); |
48 | 61 | } | |
62 | up(&dev->sem); | ||
49 | return error; | 63 | return error; |
50 | } | 64 | } |
51 | 65 | ||
@@ -100,8 +114,19 @@ int device_suspend(pm_message_t state) | |||
100 | put_device(dev); | 114 | put_device(dev); |
101 | } | 115 | } |
102 | up(&dpm_list_sem); | 116 | up(&dpm_list_sem); |
103 | if (error) | 117 | if (error) { |
118 | /* we failed... before resuming, bring back devices from | ||
119 | * dpm_off_irq list back to main dpm_off list, we do want | ||
120 | * to call resume() on them, in case they partially suspended | ||
121 | * despite returning -EAGAIN | ||
122 | */ | ||
123 | while (!list_empty(&dpm_off_irq)) { | ||
124 | struct list_head * entry = dpm_off_irq.next; | ||
125 | list_del(entry); | ||
126 | list_add(entry, &dpm_off); | ||
127 | } | ||
104 | dpm_resume(); | 128 | dpm_resume(); |
129 | } | ||
105 | up(&dpm_sem); | 130 | up(&dpm_sem); |
106 | return error; | 131 | return error; |
107 | } | 132 | } |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 6ac96349a8e8..f82b3df9545f 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -24,12 +24,12 @@ | |||
24 | * low-power state. | 24 | * low-power state. |
25 | */ | 25 | */ |
26 | 26 | ||
27 | static ssize_t state_show(struct device * dev, char * buf) | 27 | static ssize_t state_show(struct device * dev, struct device_attribute *attr, char * buf) |
28 | { | 28 | { |
29 | return sprintf(buf, "%u\n", dev->power.power_state); | 29 | return sprintf(buf, "%u\n", dev->power.power_state); |
30 | } | 30 | } |
31 | 31 | ||
32 | static ssize_t state_store(struct device * dev, const char * buf, size_t n) | 32 | static ssize_t state_store(struct device * dev, struct device_attribute *attr, const char * buf, size_t n) |
33 | { | 33 | { |
34 | u32 state; | 34 | u32 state; |
35 | char * rest; | 35 | char * rest; |
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 9102e3756f95..f37a13de804a 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -37,7 +37,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) | |||
37 | 37 | ||
38 | if (sysdev_attr->show) | 38 | if (sysdev_attr->show) |
39 | return sysdev_attr->show(sysdev, buffer); | 39 | return sysdev_attr->show(sysdev, buffer); |
40 | return 0; | 40 | return -EIO; |
41 | } | 41 | } |
42 | 42 | ||
43 | 43 | ||
@@ -50,7 +50,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr, | |||
50 | 50 | ||
51 | if (sysdev_attr->store) | 51 | if (sysdev_attr->store) |
52 | return sysdev_attr->store(sysdev, buffer, count); | 52 | return sysdev_attr->store(sysdev, buffer, count); |
53 | return 0; | 53 | return -EIO; |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct sysfs_ops sysfs_ops = { | 56 | static struct sysfs_ops sysfs_ops = { |