diff options
| author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 18:49:37 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-12 18:49:37 -0400 |
| commit | efefc6eb38d43b8e5daef482f575d767b002004e (patch) | |
| tree | 8a3933db1f8721f9bcc9912c800dc8406f4bdf94 /drivers/base/sys.c | |
| parent | 117494a1b65183f0e3fcc817b07944bc5c465050 (diff) | |
| parent | cd59abfcc441b2abb4cf2cd62c1eb0f02a60e8dd (diff) | |
Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/driver-2.6: (75 commits)
PM: merge device power-management source files
sysfs: add copyrights
kobject: update the copyrights
kset: add some kerneldoc to help describe what these strange things are
Driver core: rename ktype_edd and ktype_efivar
Driver core: rename ktype_driver
Driver core: rename ktype_device
Driver core: rename ktype_class
driver core: remove subsystem_init()
sysfs: move sysfs file poll implementation to sysfs_open_dirent
sysfs: implement sysfs_open_dirent
sysfs: move sysfs_dirent->s_children into sysfs_dirent->s_dir
sysfs: make sysfs_root a regular directory dirent
sysfs: open code sysfs_attach_dentry()
sysfs: make s_elem an anonymous union
sysfs: make bin attr open get active reference of parent too
sysfs: kill unnecessary NULL pointer check in sysfs_release()
sysfs: kill unnecessary sysfs_get() in open paths
sysfs: reposition sysfs_dirent->s_mode.
sysfs: kill sysfs_update_file()
...
Diffstat (limited to 'drivers/base/sys.c')
| -rw-r--r-- | drivers/base/sys.c | 73 |
1 files changed, 15 insertions, 58 deletions
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 18febe26caa1..ac7ff6d0c6e5 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
| @@ -139,7 +139,7 @@ int sysdev_class_register(struct sysdev_class * cls) | |||
| 139 | kobject_name(&cls->kset.kobj)); | 139 | kobject_name(&cls->kset.kobj)); |
| 140 | INIT_LIST_HEAD(&cls->drivers); | 140 | INIT_LIST_HEAD(&cls->drivers); |
| 141 | cls->kset.kobj.parent = &system_subsys.kobj; | 141 | cls->kset.kobj.parent = &system_subsys.kobj; |
| 142 | kset_set_kset_s(cls, system_subsys); | 142 | cls->kset.kobj.kset = &system_subsys; |
| 143 | return kset_register(&cls->kset); | 143 | return kset_register(&cls->kset); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| @@ -153,25 +153,22 @@ void sysdev_class_unregister(struct sysdev_class * cls) | |||
| 153 | EXPORT_SYMBOL_GPL(sysdev_class_register); | 153 | EXPORT_SYMBOL_GPL(sysdev_class_register); |
| 154 | EXPORT_SYMBOL_GPL(sysdev_class_unregister); | 154 | EXPORT_SYMBOL_GPL(sysdev_class_unregister); |
| 155 | 155 | ||
| 156 | |||
| 157 | static LIST_HEAD(sysdev_drivers); | ||
| 158 | static DEFINE_MUTEX(sysdev_drivers_lock); | 156 | static DEFINE_MUTEX(sysdev_drivers_lock); |
| 159 | 157 | ||
| 160 | /** | 158 | /** |
| 161 | * sysdev_driver_register - Register auxillary driver | 159 | * sysdev_driver_register - Register auxillary driver |
| 162 | * @cls: Device class driver belongs to. | 160 | * @cls: Device class driver belongs to. |
| 163 | * @drv: Driver. | 161 | * @drv: Driver. |
| 164 | * | 162 | * |
| 165 | * If @cls is valid, then @drv is inserted into @cls->drivers to be | 163 | * @drv is inserted into @cls->drivers to be |
| 166 | * called on each operation on devices of that class. The refcount | 164 | * called on each operation on devices of that class. The refcount |
| 167 | * of @cls is incremented. | 165 | * of @cls is incremented. |
| 168 | * Otherwise, @drv is inserted into sysdev_drivers, and called for | ||
| 169 | * each device. | ||
| 170 | */ | 166 | */ |
| 171 | 167 | ||
| 172 | int sysdev_driver_register(struct sysdev_class * cls, | 168 | int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) |
| 173 | struct sysdev_driver * drv) | ||
| 174 | { | 169 | { |
| 170 | int err = 0; | ||
| 171 | |||
| 175 | mutex_lock(&sysdev_drivers_lock); | 172 | mutex_lock(&sysdev_drivers_lock); |
| 176 | if (cls && kset_get(&cls->kset)) { | 173 | if (cls && kset_get(&cls->kset)) { |
| 177 | list_add_tail(&drv->entry, &cls->drivers); | 174 | list_add_tail(&drv->entry, &cls->drivers); |
| @@ -182,10 +179,13 @@ int sysdev_driver_register(struct sysdev_class * cls, | |||
| 182 | list_for_each_entry(dev, &cls->kset.list, kobj.entry) | 179 | list_for_each_entry(dev, &cls->kset.list, kobj.entry) |
| 183 | drv->add(dev); | 180 | drv->add(dev); |
| 184 | } | 181 | } |
| 185 | } else | 182 | } else { |
| 186 | list_add_tail(&drv->entry, &sysdev_drivers); | 183 | err = -EINVAL; |
| 184 | printk(KERN_ERR "%s: invalid device class\n", __FUNCTION__); | ||
| 185 | WARN_ON(1); | ||
| 186 | } | ||
| 187 | mutex_unlock(&sysdev_drivers_lock); | 187 | mutex_unlock(&sysdev_drivers_lock); |
| 188 | return 0; | 188 | return err; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | 191 | ||
| @@ -251,12 +251,6 @@ int sysdev_register(struct sys_device * sysdev) | |||
| 251 | * code that should have called us. | 251 | * code that should have called us. |
| 252 | */ | 252 | */ |
| 253 | 253 | ||
| 254 | /* Notify global drivers */ | ||
| 255 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 256 | if (drv->add) | ||
| 257 | drv->add(sysdev); | ||
| 258 | } | ||
| 259 | |||
| 260 | /* Notify class auxillary drivers */ | 254 | /* Notify class auxillary drivers */ |
| 261 | list_for_each_entry(drv, &cls->drivers, entry) { | 255 | list_for_each_entry(drv, &cls->drivers, entry) { |
| 262 | if (drv->add) | 256 | if (drv->add) |
| @@ -272,11 +266,6 @@ void sysdev_unregister(struct sys_device * sysdev) | |||
| 272 | struct sysdev_driver * drv; | 266 | struct sysdev_driver * drv; |
| 273 | 267 | ||
| 274 | mutex_lock(&sysdev_drivers_lock); | 268 | mutex_lock(&sysdev_drivers_lock); |
| 275 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 276 | if (drv->remove) | ||
| 277 | drv->remove(sysdev); | ||
| 278 | } | ||
| 279 | |||
| 280 | list_for_each_entry(drv, &sysdev->cls->drivers, entry) { | 269 | list_for_each_entry(drv, &sysdev->cls->drivers, entry) { |
| 281 | if (drv->remove) | 270 | if (drv->remove) |
| 282 | drv->remove(sysdev); | 271 | drv->remove(sysdev); |
| @@ -293,7 +282,7 @@ void sysdev_unregister(struct sys_device * sysdev) | |||
| 293 | * | 282 | * |
| 294 | * Loop over each class of system devices, and the devices in each | 283 | * Loop over each class of system devices, and the devices in each |
| 295 | * of those classes. For each device, we call the shutdown method for | 284 | * of those classes. For each device, we call the shutdown method for |
| 296 | * each driver registered for the device - the globals, the auxillaries, | 285 | * each driver registered for the device - the auxillaries, |
| 297 | * and the class driver. | 286 | * and the class driver. |
| 298 | * | 287 | * |
| 299 | * Note: The list is iterated in reverse order, so that we shut down | 288 | * Note: The list is iterated in reverse order, so that we shut down |
| @@ -320,13 +309,7 @@ void sysdev_shutdown(void) | |||
| 320 | struct sysdev_driver * drv; | 309 | struct sysdev_driver * drv; |
| 321 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | 310 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); |
| 322 | 311 | ||
| 323 | /* Call global drivers first. */ | 312 | /* Call auxillary drivers first */ |
| 324 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 325 | if (drv->shutdown) | ||
| 326 | drv->shutdown(sysdev); | ||
| 327 | } | ||
| 328 | |||
| 329 | /* Call auxillary drivers next. */ | ||
| 330 | list_for_each_entry(drv, &cls->drivers, entry) { | 313 | list_for_each_entry(drv, &cls->drivers, entry) { |
| 331 | if (drv->shutdown) | 314 | if (drv->shutdown) |
| 332 | drv->shutdown(sysdev); | 315 | drv->shutdown(sysdev); |
| @@ -354,12 +337,6 @@ static void __sysdev_resume(struct sys_device *dev) | |||
| 354 | if (drv->resume) | 337 | if (drv->resume) |
| 355 | drv->resume(dev); | 338 | drv->resume(dev); |
| 356 | } | 339 | } |
| 357 | |||
| 358 | /* Call global drivers. */ | ||
| 359 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 360 | if (drv->resume) | ||
| 361 | drv->resume(dev); | ||
| 362 | } | ||
| 363 | } | 340 | } |
| 364 | 341 | ||
| 365 | /** | 342 | /** |
| @@ -393,16 +370,7 @@ int sysdev_suspend(pm_message_t state) | |||
| 393 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { | 370 | list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { |
| 394 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); | 371 | pr_debug(" %s\n", kobject_name(&sysdev->kobj)); |
| 395 | 372 | ||
| 396 | /* Call global drivers first. */ | 373 | /* Call auxillary drivers first */ |
| 397 | list_for_each_entry(drv, &sysdev_drivers, entry) { | ||
| 398 | if (drv->suspend) { | ||
| 399 | ret = drv->suspend(sysdev, state); | ||
| 400 | if (ret) | ||
| 401 | goto gbl_driver; | ||
| 402 | } | ||
| 403 | } | ||
| 404 | |||
| 405 | /* Call auxillary drivers next. */ | ||
| 406 | list_for_each_entry(drv, &cls->drivers, entry) { | 374 | list_for_each_entry(drv, &cls->drivers, entry) { |
| 407 | if (drv->suspend) { | 375 | if (drv->suspend) { |
| 408 | ret = drv->suspend(sysdev, state); | 376 | ret = drv->suspend(sysdev, state); |
| @@ -436,18 +404,7 @@ aux_driver: | |||
| 436 | if (err_drv->resume) | 404 | if (err_drv->resume) |
| 437 | err_drv->resume(sysdev); | 405 | err_drv->resume(sysdev); |
| 438 | } | 406 | } |
| 439 | drv = NULL; | ||
| 440 | 407 | ||
| 441 | gbl_driver: | ||
| 442 | if (drv) | ||
| 443 | printk(KERN_ERR "sysdev driver suspend failed for %s\n", | ||
| 444 | kobject_name(&sysdev->kobj)); | ||
| 445 | list_for_each_entry(err_drv, &sysdev_drivers, entry) { | ||
| 446 | if (err_drv == drv) | ||
| 447 | break; | ||
| 448 | if (err_drv->resume) | ||
| 449 | err_drv->resume(sysdev); | ||
| 450 | } | ||
| 451 | /* resume other sysdevs in current class */ | 408 | /* resume other sysdevs in current class */ |
| 452 | list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) { | 409 | list_for_each_entry(err_dev, &cls->kset.list, kobj.entry) { |
| 453 | if (err_dev == sysdev) | 410 | if (err_dev == sysdev) |
