diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2007-05-31 11:38:06 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2007-05-31 11:38:12 -0400 |
commit | 59a8a6e227cf0bc42e5be741ebfea97c222ab9ef (patch) | |
tree | 01ea59ed41a878ee4f780221aa439ca573c870a4 /drivers/s390 | |
parent | ea1f4eece943968940a399c72c1ca675d51e466e (diff) |
[S390] cio: Use device_schedule_callback() for removing disconnected devices.
We can't deregister disconnected and orphaned devices directly from
the online attribute's store method, but must take a detour.
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/cio/device.c | 49 |
1 files changed, 38 insertions, 11 deletions
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a8b373f69cf0..6b264bdb5bfb 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -296,30 +296,57 @@ static void ccw_device_unregister(struct ccw_device *cdev) | |||
296 | device_del(&cdev->dev); | 296 | device_del(&cdev->dev); |
297 | } | 297 | } |
298 | 298 | ||
299 | static void ccw_device_remove_orphan_cb(struct device *dev) | ||
300 | { | ||
301 | struct ccw_device *cdev = to_ccwdev(dev); | ||
302 | |||
303 | ccw_device_unregister(cdev); | ||
304 | put_device(&cdev->dev); | ||
305 | } | ||
306 | |||
307 | static void ccw_device_remove_sch_cb(struct device *dev) | ||
308 | { | ||
309 | struct subchannel *sch; | ||
310 | |||
311 | sch = to_subchannel(dev); | ||
312 | css_sch_device_unregister(sch); | ||
313 | /* Reset intparm to zeroes. */ | ||
314 | sch->schib.pmcw.intparm = 0; | ||
315 | cio_modify(sch); | ||
316 | put_device(&sch->dev); | ||
317 | } | ||
318 | |||
299 | static void | 319 | static void |
300 | ccw_device_remove_disconnected(struct ccw_device *cdev) | 320 | ccw_device_remove_disconnected(struct ccw_device *cdev) |
301 | { | 321 | { |
302 | struct subchannel *sch; | ||
303 | unsigned long flags; | 322 | unsigned long flags; |
323 | int rc; | ||
324 | |||
304 | /* | 325 | /* |
305 | * Forced offline in disconnected state means | 326 | * Forced offline in disconnected state means |
306 | * 'throw away device'. | 327 | * 'throw away device'. |
307 | */ | 328 | */ |
308 | if (ccw_device_is_orphan(cdev)) { | 329 | if (ccw_device_is_orphan(cdev)) { |
309 | /* Deregister ccw device. */ | 330 | /* |
331 | * Deregister ccw device. | ||
332 | * Unfortunately, we cannot do this directly from the | ||
333 | * attribute method. | ||
334 | */ | ||
310 | spin_lock_irqsave(cdev->ccwlock, flags); | 335 | spin_lock_irqsave(cdev->ccwlock, flags); |
311 | cdev->private->state = DEV_STATE_NOT_OPER; | 336 | cdev->private->state = DEV_STATE_NOT_OPER; |
312 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 337 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
313 | ccw_device_unregister(cdev); | 338 | rc = device_schedule_callback(&cdev->dev, |
314 | put_device(&cdev->dev); | 339 | ccw_device_remove_orphan_cb); |
315 | return ; | 340 | if (rc) |
341 | dev_info(&cdev->dev, "Couldn't unregister orphan\n"); | ||
342 | return; | ||
316 | } | 343 | } |
317 | sch = to_subchannel(cdev->dev.parent); | 344 | /* Deregister subchannel, which will kill the ccw device. */ |
318 | css_sch_device_unregister(sch); | 345 | rc = device_schedule_callback(cdev->dev.parent, |
319 | /* Reset intparm to zeroes. */ | 346 | ccw_device_remove_sch_cb); |
320 | sch->schib.pmcw.intparm = 0; | 347 | if (rc) |
321 | cio_modify(sch); | 348 | dev_info(&cdev->dev, |
322 | put_device(&sch->dev); | 349 | "Couldn't unregister disconnected device\n"); |
323 | } | 350 | } |
324 | 351 | ||
325 | int | 352 | int |