diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2006-06-29 14:56:52 +0200 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-06-29 14:56:52 +0200 |
commit | 887ab5992925736ab23985c35f8149739e9de354 (patch) | |
tree | 5979c930c1ba34341e04e541f98b0584c58ac62b | |
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>
-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 bdfee7fbaa2..c7319a07ba3 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -404,21 +404,24 @@ ccwgroup_driver_register (struct ccwgroup_driver *cdriver) } static int -__ccwgroup_driver_unregister_device(struct device *dev, void *data) +__ccwgroup_match_all(struct device *dev, void *data) { - __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); - device_unregister(dev); - put_device(dev); - return 0; + return 1; } void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) { + struct device *dev; + /* We don't want ccwgroup devices to live longer than their driver. */ get_driver(&cdriver->driver); - driver_for_each_device(&cdriver->driver, NULL, NULL, - __ccwgroup_driver_unregister_device); + while ((dev = driver_find_device(&cdriver->driver, NULL, NULL, + __ccwgroup_match_all))) { + __ccwgroup_remove_symlinks(to_ccwgroupdev(dev)); + device_unregister(dev); + put_device(dev); + } put_driver(&cdriver->driver); driver_unregister(&cdriver->driver); } |