aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@evo.osdl.org>2005-09-06 03:32:12 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-06 03:32:12 -0400
commitf65e77693aa5a1cf688fc378bc6913a56f9ff7b7 (patch)
tree5d5b6ee3e3f9da241a583bf49ab648637ac4c1a9 /drivers/base
parent8566cfc9fe0934f52ddedc12b083176116c13978 (diff)
parentd856f1e337782326c638c70c0b4df2b909350dec (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/bus.c8
-rw-r--r--drivers/base/class.c39
-rw-r--r--drivers/base/core.c2
-rw-r--r--drivers/base/dd.c2
-rw-r--r--drivers/base/sys.c110
5 files changed, 125 insertions, 36 deletions
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index ab53832d57e5..17e96698410e 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -156,7 +156,9 @@ static ssize_t driver_unbind(struct device_driver *drv,
156 device_release_driver(dev); 156 device_release_driver(dev);
157 err = count; 157 err = count;
158 } 158 }
159 return err; 159 if (err)
160 return err;
161 return count;
160} 162}
161static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind); 163static DRIVER_ATTR(unbind, S_IWUSR, NULL, driver_unbind);
162 164
@@ -358,7 +360,7 @@ int bus_add_device(struct device * dev)
358 if (bus) { 360 if (bus) {
359 pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id); 361 pr_debug("bus %s: add device %s\n", bus->name, dev->bus_id);
360 device_attach(dev); 362 device_attach(dev);
361 klist_add_tail(&bus->klist_devices, &dev->knode_bus); 363 klist_add_tail(&dev->knode_bus, &bus->klist_devices);
362 error = device_add_attrs(bus, dev); 364 error = device_add_attrs(bus, dev);
363 if (!error) { 365 if (!error) {
364 sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id); 366 sysfs_create_link(&bus->devices.kobj, &dev->kobj, dev->bus_id);
@@ -446,7 +448,7 @@ int bus_add_driver(struct device_driver * drv)
446 } 448 }
447 449
448 driver_attach(drv); 450 driver_attach(drv);
449 klist_add_tail(&bus->klist_drivers, &drv->knode_bus); 451 klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
450 module_add_driver(drv->owner, drv); 452 module_add_driver(drv->owner, drv);
451 453
452 driver_add_attrs(bus, drv); 454 driver_add_attrs(bus, drv);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index 0154a1623b21..d164c32a97ad 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -299,10 +299,8 @@ static void class_dev_release(struct kobject * kobj)
299 299
300 pr_debug("device class '%s': release.\n", cd->class_id); 300 pr_debug("device class '%s': release.\n", cd->class_id);
301 301
302 if (cd->devt_attr) { 302 kfree(cd->devt_attr);
303 kfree(cd->devt_attr); 303 cd->devt_attr = NULL;
304 cd->devt_attr = NULL;
305 }
306 304
307 if (cls->release) 305 if (cls->release)
308 cls->release(cd); 306 cls->release(cd);
@@ -452,10 +450,29 @@ void class_device_initialize(struct class_device *class_dev)
452 INIT_LIST_HEAD(&class_dev->node); 450 INIT_LIST_HEAD(&class_dev->node);
453} 451}
454 452
453static char *make_class_name(struct class_device *class_dev)
454{
455 char *name;
456 int size;
457
458 size = strlen(class_dev->class->name) +
459 strlen(kobject_name(&class_dev->kobj)) + 2;
460
461 name = kmalloc(size, GFP_KERNEL);
462 if (!name)
463 return ERR_PTR(-ENOMEM);
464
465 strcpy(name, class_dev->class->name);
466 strcat(name, ":");
467 strcat(name, kobject_name(&class_dev->kobj));
468 return name;
469}
470
455int class_device_add(struct class_device *class_dev) 471int class_device_add(struct class_device *class_dev)
456{ 472{
457 struct class * parent = NULL; 473 struct class * parent = NULL;
458 struct class_interface * class_intf; 474 struct class_interface * class_intf;
475 char *class_name = NULL;
459 int error; 476 int error;
460 477
461 class_dev = class_device_get(class_dev); 478 class_dev = class_device_get(class_dev);
@@ -500,9 +517,13 @@ int class_device_add(struct class_device *class_dev)
500 } 517 }
501 518
502 class_device_add_attrs(class_dev); 519 class_device_add_attrs(class_dev);
503 if (class_dev->dev) 520 if (class_dev->dev) {
521 class_name = make_class_name(class_dev);
504 sysfs_create_link(&class_dev->kobj, 522 sysfs_create_link(&class_dev->kobj,
505 &class_dev->dev->kobj, "device"); 523 &class_dev->dev->kobj, "device");
524 sysfs_create_link(&class_dev->dev->kobj, &class_dev->kobj,
525 class_name);
526 }
506 527
507 /* notify any interfaces this device is now here */ 528 /* notify any interfaces this device is now here */
508 if (parent) { 529 if (parent) {
@@ -519,6 +540,7 @@ int class_device_add(struct class_device *class_dev)
519 if (error && parent) 540 if (error && parent)
520 class_put(parent); 541 class_put(parent);
521 class_device_put(class_dev); 542 class_device_put(class_dev);
543 kfree(class_name);
522 return error; 544 return error;
523} 545}
524 546
@@ -584,6 +606,7 @@ void class_device_del(struct class_device *class_dev)
584{ 606{
585 struct class * parent = class_dev->class; 607 struct class * parent = class_dev->class;
586 struct class_interface * class_intf; 608 struct class_interface * class_intf;
609 char *class_name = NULL;
587 610
588 if (parent) { 611 if (parent) {
589 down(&parent->sem); 612 down(&parent->sem);
@@ -594,8 +617,11 @@ void class_device_del(struct class_device *class_dev)
594 up(&parent->sem); 617 up(&parent->sem);
595 } 618 }
596 619
597 if (class_dev->dev) 620 if (class_dev->dev) {
621 class_name = make_class_name(class_dev);
598 sysfs_remove_link(&class_dev->kobj, "device"); 622 sysfs_remove_link(&class_dev->kobj, "device");
623 sysfs_remove_link(&class_dev->dev->kobj, class_name);
624 }
599 if (class_dev->devt_attr) 625 if (class_dev->devt_attr)
600 class_device_remove_file(class_dev, class_dev->devt_attr); 626 class_device_remove_file(class_dev, class_dev->devt_attr);
601 class_device_remove_attrs(class_dev); 627 class_device_remove_attrs(class_dev);
@@ -605,6 +631,7 @@ void class_device_del(struct class_device *class_dev)
605 631
606 if (parent) 632 if (parent)
607 class_put(parent); 633 class_put(parent);
634 kfree(class_name);
608} 635}
609 636
610void class_device_unregister(struct class_device *class_dev) 637void class_device_unregister(struct class_device *class_dev)
diff --git a/drivers/base/core.c b/drivers/base/core.c
index efe03a024a5b..c8a33df00761 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -249,7 +249,7 @@ int device_add(struct device *dev)
249 if ((error = bus_add_device(dev))) 249 if ((error = bus_add_device(dev)))
250 goto BusError; 250 goto BusError;
251 if (parent) 251 if (parent)
252 klist_add_tail(&parent->klist_children, &dev->knode_parent); 252 klist_add_tail(&dev->knode_parent, &parent->klist_children);
253 253
254 /* notify platform of device entry */ 254 /* notify platform of device entry */
255 if (platform_notify) 255 if (platform_notify)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 16323f9cbff0..d5bbce38282f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -42,7 +42,7 @@ void device_bind_driver(struct device * dev)
42{ 42{
43 pr_debug("bound device '%s' to driver '%s'\n", 43 pr_debug("bound device '%s' to driver '%s'\n",
44 dev->bus_id, dev->driver->name); 44 dev->bus_id, dev->driver->name);
45 klist_add_tail(&dev->driver->klist_devices, &dev->knode_driver); 45 klist_add_tail(&dev->knode_driver, &dev->driver->klist_devices);
46 sysfs_create_link(&dev->driver->kobj, &dev->kobj, 46 sysfs_create_link(&dev->driver->kobj, &dev->kobj,
47 kobject_name(&dev->kobj)); 47 kobject_name(&dev->kobj));
48 sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver"); 48 sysfs_create_link(&dev->kobj, &dev->driver->kobj, "driver");
diff --git a/drivers/base/sys.c b/drivers/base/sys.c
index 214b96435409..3431eb6004c3 100644
--- a/drivers/base/sys.c
+++ b/drivers/base/sys.c
@@ -288,6 +288,27 @@ void sysdev_shutdown(void)
288 up(&sysdev_drivers_lock); 288 up(&sysdev_drivers_lock);
289} 289}
290 290
291static void __sysdev_resume(struct sys_device *dev)
292{
293 struct sysdev_class *cls = dev->cls;
294 struct sysdev_driver *drv;
295
296 /* First, call the class-specific one */
297 if (cls->resume)
298 cls->resume(dev);
299
300 /* Call auxillary drivers next. */
301 list_for_each_entry(drv, &cls->drivers, entry) {
302 if (drv->resume)
303 drv->resume(dev);
304 }
305
306 /* Call global drivers. */
307 list_for_each_entry(drv, &sysdev_drivers, entry) {
308 if (drv->resume)
309 drv->resume(dev);
310 }
311}
291 312
292/** 313/**
293 * sysdev_suspend - Suspend all system devices. 314 * sysdev_suspend - Suspend all system devices.
@@ -305,38 +326,93 @@ void sysdev_shutdown(void)
305int sysdev_suspend(pm_message_t state) 326int sysdev_suspend(pm_message_t state)
306{ 327{
307 struct sysdev_class * cls; 328 struct sysdev_class * cls;
329 struct sys_device *sysdev, *err_dev;
330 struct sysdev_driver *drv, *err_drv;
331 int ret;
308 332
309 pr_debug("Suspending System Devices\n"); 333 pr_debug("Suspending System Devices\n");
310 334
311 list_for_each_entry_reverse(cls, &system_subsys.kset.list, 335 list_for_each_entry_reverse(cls, &system_subsys.kset.list,
312 kset.kobj.entry) { 336 kset.kobj.entry) {
313 struct sys_device * sysdev;
314 337
315 pr_debug("Suspending type '%s':\n", 338 pr_debug("Suspending type '%s':\n",
316 kobject_name(&cls->kset.kobj)); 339 kobject_name(&cls->kset.kobj));
317 340
318 list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { 341 list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
319 struct sysdev_driver * drv;
320 pr_debug(" %s\n", kobject_name(&sysdev->kobj)); 342 pr_debug(" %s\n", kobject_name(&sysdev->kobj));
321 343
322 /* Call global drivers first. */ 344 /* Call global drivers first. */
323 list_for_each_entry(drv, &sysdev_drivers, entry) { 345 list_for_each_entry(drv, &sysdev_drivers, entry) {
324 if (drv->suspend) 346 if (drv->suspend) {
325 drv->suspend(sysdev, state); 347 ret = drv->suspend(sysdev, state);
348 if (ret)
349 goto gbl_driver;
350 }
326 } 351 }
327 352
328 /* Call auxillary drivers next. */ 353 /* Call auxillary drivers next. */
329 list_for_each_entry(drv, &cls->drivers, entry) { 354 list_for_each_entry(drv, &cls->drivers, entry) {
330 if (drv->suspend) 355 if (drv->suspend) {
331 drv->suspend(sysdev, state); 356 ret = drv->suspend(sysdev, state);
357 if (ret)
358 goto aux_driver;
359 }
332 } 360 }
333 361
334 /* Now call the generic one */ 362 /* Now call the generic one */
335 if (cls->suspend) 363 if (cls->suspend) {
336 cls->suspend(sysdev, state); 364 ret = cls->suspend(sysdev, state);
365 if (ret)
366 goto cls_driver;
367 }
337 } 368 }
338 } 369 }
339 return 0; 370 return 0;
371 /* resume current sysdev */
372cls_driver:
373 drv = NULL;
374 printk(KERN_ERR "Class suspend failed for %s\n",
375 kobject_name(&sysdev->kobj));
376
377aux_driver:
378 if (drv)
379 printk(KERN_ERR "Class driver suspend failed for %s\n",
380 kobject_name(&sysdev->kobj));
381 list_for_each_entry(err_drv, &cls->drivers, entry) {
382 if (err_drv == drv)
383 break;
384 if (err_drv->resume)
385 err_drv->resume(sysdev);
386 }
387 drv = NULL;
388
389gbl_driver:
390 if (drv)
391 printk(KERN_ERR "sysdev driver suspend failed for %s\n",
392 kobject_name(&sysdev->kobj));
393 list_for_each_entry(err_drv, &sysdev_drivers, entry) {
394 if (err_drv == drv)
395 break;
396 if (err_drv->resume)
397 err_drv->resume(sysdev);
398 }
399 /* resume other sysdevs in current class */
400 list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
401 if (err_dev == sysdev)
402 break;
403 pr_debug(" %s\n", kobject_name(&err_dev->kobj));
404 __sysdev_resume(err_dev);
405 }
406
407 /* resume other classes */
408 list_for_each_entry_continue(cls, &system_subsys.kset.list,
409 kset.kobj.entry) {
410 list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) {
411 pr_debug(" %s\n", kobject_name(&err_dev->kobj));
412 __sysdev_resume(err_dev);
413 }
414 }
415 return ret;
340} 416}
341 417
342 418
@@ -362,25 +438,9 @@ int sysdev_resume(void)
362 kobject_name(&cls->kset.kobj)); 438 kobject_name(&cls->kset.kobj));
363 439
364 list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { 440 list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
365 struct sysdev_driver * drv;
366 pr_debug(" %s\n", kobject_name(&sysdev->kobj)); 441 pr_debug(" %s\n", kobject_name(&sysdev->kobj));
367 442
368 /* First, call the class-specific one */ 443 __sysdev_resume(sysdev);
369 if (cls->resume)
370 cls->resume(sysdev);
371
372 /* Call auxillary drivers next. */
373 list_for_each_entry(drv, &cls->drivers, entry) {
374 if (drv->resume)
375 drv->resume(sysdev);
376 }
377
378 /* Call global drivers. */
379 list_for_each_entry(drv, &sysdev_drivers, entry) {
380 if (drv->resume)
381 drv->resume(sysdev);
382 }
383
384 } 444 }
385 } 445 }
386 return 0; 446 return 0;