aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/sys.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/base/sys.c')
-rw-r--r--drivers/base/sys.c71
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)
153EXPORT_SYMBOL_GPL(sysdev_class_register); 153EXPORT_SYMBOL_GPL(sysdev_class_register);
154EXPORT_SYMBOL_GPL(sysdev_class_unregister); 154EXPORT_SYMBOL_GPL(sysdev_class_unregister);
155 155
156
157static LIST_HEAD(sysdev_drivers);
158static DEFINE_MUTEX(sysdev_drivers_lock); 156static 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
172int sysdev_driver_register(struct sysdev_class * cls, 168int 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
441gbl_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)