Commit d40f7b75 authored by Sebastian Ott's avatar Sebastian Ott Committed by Martin Schwidefsky

[S390] cio: dont unregister a busy device in ccw_device_set_offline

If we detect a busy subchannel after the driver's set_offline
callback returned in ccw_device_set_offline, the current behavior
is to unregister the device, which may lead to undesired
consequences. Change this to just quiesce the subchannel and go on
with the offline processing.

Note: This is no excuse for not fixing these drivers -
after the set_offline callback they should have no running IO!
Signed-off-by: default avatarSebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent de1b0438
...@@ -314,6 +314,8 @@ static void ccw_device_unregister(struct ccw_device *cdev) ...@@ -314,6 +314,8 @@ static void ccw_device_unregister(struct ccw_device *cdev)
} }
} }
static void io_subchannel_quiesce(struct subchannel *);
/** /**
* ccw_device_set_offline() - disable a ccw device for I/O * ccw_device_set_offline() - disable a ccw device for I/O
* @cdev: target ccw device * @cdev: target ccw device
...@@ -327,7 +329,8 @@ static void ccw_device_unregister(struct ccw_device *cdev) ...@@ -327,7 +329,8 @@ static void ccw_device_unregister(struct ccw_device *cdev)
*/ */
int ccw_device_set_offline(struct ccw_device *cdev) int ccw_device_set_offline(struct ccw_device *cdev)
{ {
int ret; struct subchannel *sch;
int ret, state;
if (!cdev) if (!cdev)
return -ENODEV; return -ENODEV;
...@@ -341,6 +344,7 @@ int ccw_device_set_offline(struct ccw_device *cdev) ...@@ -341,6 +344,7 @@ int ccw_device_set_offline(struct ccw_device *cdev)
} }
cdev->online = 0; cdev->online = 0;
spin_lock_irq(cdev->ccwlock); spin_lock_irq(cdev->ccwlock);
sch = to_subchannel(cdev->dev.parent);
/* Wait until a final state or DISCONNECTED is reached */ /* Wait until a final state or DISCONNECTED is reached */
while (!dev_fsm_final_state(cdev) && while (!dev_fsm_final_state(cdev) &&
cdev->private->state != DEV_STATE_DISCONNECTED) { cdev->private->state != DEV_STATE_DISCONNECTED) {
...@@ -349,9 +353,21 @@ int ccw_device_set_offline(struct ccw_device *cdev) ...@@ -349,9 +353,21 @@ int ccw_device_set_offline(struct ccw_device *cdev)
cdev->private->state == DEV_STATE_DISCONNECTED)); cdev->private->state == DEV_STATE_DISCONNECTED));
spin_lock_irq(cdev->ccwlock); spin_lock_irq(cdev->ccwlock);
} }
do {
ret = ccw_device_offline(cdev); ret = ccw_device_offline(cdev);
if (ret) if (!ret)
break;
CIO_MSG_EVENT(0, "ccw_device_offline returned %d, device "
"0.%x.%04x\n", ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
if (ret != -EBUSY)
goto error; goto error;
state = cdev->private->state;
spin_unlock_irq(cdev->ccwlock);
io_subchannel_quiesce(sch);
spin_lock_irq(cdev->ccwlock);
cdev->private->state = state;
} while (ret == -EBUSY);
spin_unlock_irq(cdev->ccwlock); spin_unlock_irq(cdev->ccwlock);
wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) || wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) ||
cdev->private->state == DEV_STATE_DISCONNECTED)); cdev->private->state == DEV_STATE_DISCONNECTED));
...@@ -368,9 +384,6 @@ int ccw_device_set_offline(struct ccw_device *cdev) ...@@ -368,9 +384,6 @@ int ccw_device_set_offline(struct ccw_device *cdev)
return 0; return 0;
error: error:
CIO_MSG_EVENT(0, "ccw_device_offline returned %d, device 0.%x.%04x\n",
ret, cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
cdev->private->state = DEV_STATE_OFFLINE; cdev->private->state = DEV_STATE_OFFLINE;
dev_fsm_event(cdev, DEV_EVENT_NOTOPER); dev_fsm_event(cdev, DEV_EVENT_NOTOPER);
spin_unlock_irq(cdev->ccwlock); spin_unlock_irq(cdev->ccwlock);
...@@ -1059,8 +1072,6 @@ static int io_subchannel_probe(struct subchannel *sch) ...@@ -1059,8 +1072,6 @@ static int io_subchannel_probe(struct subchannel *sch)
return 0; return 0;
} }
static void io_subchannel_quiesce(struct subchannel *);
static int static int
io_subchannel_remove (struct subchannel *sch) io_subchannel_remove (struct subchannel *sch)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment