diff options
Diffstat (limited to 'drivers/base/sys.c')
-rw-r--r-- | drivers/base/sys.c | 71 |
1 files changed, 14 insertions, 57 deletions
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 7ad893167823..ac7ff6d0c6e5 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -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) |