diff options
author | Sebastian Ott <sebott@linux.vnet.ibm.com> | 2009-12-07 12:51:35 +0100 |
---|---|---|
committer | Martin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com> | 2009-12-07 12:51:32 +0100 |
commit | 56e6b796fe9b99287648fc5686aae00106b37bab (patch) | |
tree | f0c75986905f3ff01ec1c801843f94923509af06 /drivers/s390/cio/device_fsm.c | |
parent | 24a1872d6411c7cce82c0888a4fbea23e993e051 (diff) | |
download | blackbird-op-linux-56e6b796fe9b99287648fc5686aae00106b37bab.tar.gz blackbird-op-linux-56e6b796fe9b99287648fc5686aae00106b37bab.zip |
[S390] cio: fix quiesce state
DEV_STATE_QUIESCE is used to stop all IO on a busy subchannel.
This patch fixes the following problems related to the QUIESCE
state:
* Fix a potential race condition which could occur when the
resulting state was DEV_STATE_OFFLINE.
* Add missing locking around cio_disable_subchannel,
ccw_device_cancel_halt_clear and the cdev's handler.
* Loop until we know for sure that the subchannel is disabled.
Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/cio/device_fsm.c')
-rw-r--r-- | drivers/s390/cio/device_fsm.c | 17 |
1 files changed, 4 insertions, 13 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 7d42417bc2c7..862b89ef3ee6 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -911,10 +911,7 @@ static void ccw_device_quiesce_done(struct ccw_device *cdev, enum dev_event dev_event) { ccw_device_set_timeout(cdev, 0); - if (dev_event == DEV_EVENT_NOTOPER) - cdev->private->state = DEV_STATE_NOT_OPER; - else - cdev->private->state = DEV_STATE_OFFLINE; + cdev->private->state = DEV_STATE_NOT_OPER; wake_up(&cdev->private->wait_q); } @@ -924,17 +921,11 @@ ccw_device_quiesce_timeout(struct ccw_device *cdev, enum dev_event dev_event) int ret; ret = ccw_device_cancel_halt_clear(cdev); - switch (ret) { - case 0: - cdev->private->state = DEV_STATE_OFFLINE; - wake_up(&cdev->private->wait_q); - break; - case -ENODEV: + if (ret == -EBUSY) { + ccw_device_set_timeout(cdev, HZ/10); + } else { cdev->private->state = DEV_STATE_NOT_OPER; wake_up(&cdev->private->wait_q); - break; - default: - ccw_device_set_timeout(cdev, HZ/10); } } |