[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>
This commit is contained in:
parent
ea1f4eece9
commit
59a8a6e227
|
@ -296,25 +296,19 @@ static void ccw_device_unregister(struct ccw_device *cdev)
|
||||||
device_del(&cdev->dev);
|
device_del(&cdev->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void ccw_device_remove_orphan_cb(struct device *dev)
|
||||||
ccw_device_remove_disconnected(struct ccw_device *cdev)
|
{
|
||||||
|
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;
|
struct subchannel *sch;
|
||||||
unsigned long flags;
|
|
||||||
/*
|
sch = to_subchannel(dev);
|
||||||
* Forced offline in disconnected state means
|
|
||||||
* 'throw away device'.
|
|
||||||
*/
|
|
||||||
if (ccw_device_is_orphan(cdev)) {
|
|
||||||
/* Deregister ccw device. */
|
|
||||||
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 ;
|
|
||||||
}
|
|
||||||
sch = to_subchannel(cdev->dev.parent);
|
|
||||||
css_sch_device_unregister(sch);
|
css_sch_device_unregister(sch);
|
||||||
/* Reset intparm to zeroes. */
|
/* Reset intparm to zeroes. */
|
||||||
sch->schib.pmcw.intparm = 0;
|
sch->schib.pmcw.intparm = 0;
|
||||||
|
@ -322,6 +316,39 @@ ccw_device_remove_disconnected(struct ccw_device *cdev)
|
||||||
put_device(&sch->dev);
|
put_device(&sch->dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ccw_device_remove_disconnected(struct ccw_device *cdev)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Forced offline in disconnected state means
|
||||||
|
* 'throw away device'.
|
||||||
|
*/
|
||||||
|
if (ccw_device_is_orphan(cdev)) {
|
||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
rc = device_schedule_callback(&cdev->dev,
|
||||||
|
ccw_device_remove_orphan_cb);
|
||||||
|
if (rc)
|
||||||
|
dev_info(&cdev->dev, "Couldn't unregister orphan\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* 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
|
int
|
||||||
ccw_device_set_offline(struct ccw_device *cdev)
|
ccw_device_set_offline(struct ccw_device *cdev)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue