diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2006-06-29 08:56:52 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-06-29 08:56:52 -0400 |
commit | 887ab5992925736ab23985c35f8149739e9de354 (patch) | |
tree | 5979c930c1ba34341e04e541f98b0584c58ac62b /drivers/s390/cio | |
parent | 231caa1cac555bdd5cb64bf91b554b38e8ddf715 (diff) |
[S390] ccwgroup device unregister.
Work around the problem that a device cannot be unregistered from
driver_for_each_device() because of klist node refcounting: Get device
after device owned by the driver to be unregistered with driver_find_device()
and then unregister it. This works because driver_get_device() gets us out of
the region of the elevated klist node refcount. driver_find_device() will
always get the next device in the list after the found one has been
unregistered.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r-- | drivers/s390/cio/ccwgroup.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index bdfee7fbaa2e..c7319a07ba35 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -404,21 +404,24 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | |||
404 | } | 404 | } |
405 | 405 | ||
406 | static int | 406 | static int |
407 | __ccwgroup_driver_unregister_device(struct device *dev, void *data) | 407 | __ccwgroup_match_all(struct device *dev, void *data) |
408 | { | 408 | { |
409 | __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); | 409 | return 1; |
410 | device_unregister(dev); | ||
411 | put_device(dev); | ||
412 | return 0; | ||
413 | } | 410 | } |
414 | 411 | ||
415 | void | 412 | void |
416 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | 413 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) |
417 | { | 414 | { |
415 | struct device *dev; | ||
416 | |||
418 | /* We don't want ccwgroup devices to live longer than their driver. */ | 417 | /* We don't want ccwgroup devices to live longer than their driver. */ |
419 | get_driver(&cdriver->driver); | 418 | get_driver(&cdriver->driver); |
420 | driver_for_each_device(&cdriver->driver, NULL, NULL, | 419 | while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, |
421 | __ccwgroup_driver_unregister_device); | 420 | __ccwgroup_match_all))) { |
421 | __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); | ||
422 | device_unregister(dev); | ||
423 | put_device(dev); | ||
424 | } | ||
422 | put_driver(&cdriver->driver); | 425 | put_driver(&cdriver->driver); |
423 | driver_unregister(&cdriver->driver); | 426 | driver_unregister(&cdriver->driver); |
424 | } | 427 | } |