From 59a8a6e227cf0bc42e5be741ebfea97c222ab9ef Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 31 May 2007 17:38:06 +0200 Subject: [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 Signed-off-by: Martin Schwidefsky diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index a8b373f..6b264bd 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) device_del(&cdev->dev); } +static void ccw_device_remove_orphan_cb(struct device *dev) +{ + struct ccw_device *cdev = to_ccwdev(dev); + + ccw_device_unregister(cdev); + put_device(&cdev->dev); +} + +static void ccw_device_remove_sch_cb(struct device *dev) +{ + struct subchannel *sch; + + sch = to_subchannel(dev); + css_sch_device_unregister(sch); + /* Reset intparm to zeroes. */ + sch->schib.pmcw.intparm = 0; + cio_modify(sch); + put_device(&sch->dev); +} + static void ccw_device_remove_disconnected(struct ccw_device *cdev) { - struct subchannel *sch; unsigned long flags; + int rc; + /* * Forced offline in disconnected state means * 'throw away device'. */ if (ccw_device_is_orphan(cdev)) { - /* Deregister ccw device. */ + /* + * Deregister ccw device. + * Unfortunately, we cannot do this directly from the + * attribute method. + */ spin_lock_irqsave(cdev->ccwlock, flags); cdev->private->state = DEV_STATE_NOT_OPER; spin_unlock_irqrestore(cdev->ccwlock, flags); - ccw_device_unregister(cdev); - put_device(&cdev->dev); - return ; + rc = device_schedule_callback(&cdev->dev, + ccw_device_remove_orphan_cb); + if (rc) + dev_info(&cdev->dev, "Couldn't unregister orphan\n"); + return; } - sch = to_subchannel(cdev->dev.parent); - css_sch_device_unregister(sch); - /* Reset intparm to zeroes. */ - sch->schib.pmcw.intparm = 0; - cio_modify(sch); - put_device(&sch->dev); + /* Deregister subchannel, which will kill the ccw device. */ + rc = device_schedule_callback(cdev->dev.parent, + ccw_device_remove_sch_cb); + if (rc) + dev_info(&cdev->dev, + "Couldn't unregister disconnected device\n"); } int -- cgit v0.10.2