aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Ott2017-09-05 14:22:48 +0200
committerMartin Schwidefsky2017-09-28 07:29:41 +0200
commitadc69b4d76ee8a7065c7c637584b39ace265ffab (patch)
treea100bac8bd2063c347148beab68365c804e09def
parentb08e19defc10befc50af09771ff0b086f2a72138 (diff)
s390/cmf: set_schib_wait add timeout
When enabling channel measurement fails with a busy condition we wait for the next interrupt to arrive before we retry the operation. For devices which usually don't create interrupts we wait forever. Although the waiting is done interruptible that behavior is not expected and confused some users. Abort the operation after a 10s timeout. Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--drivers/s390/cio/cmf.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c
index 220491d27ef4..be0b010ff136 100644
--- a/drivers/s390/cio/cmf.c
+++ b/drivers/s390/cio/cmf.c
@@ -227,6 +227,7 @@ static void cmf_set_schib_release(struct kref *kref)
}
#define CMF_PENDING 1
+#define SET_SCHIB_TIMEOUT (10 * HZ)
static int set_schib_wait(struct ccw_device *cdev, u32 mme,
int mbfc, unsigned long address)
@@ -263,19 +264,19 @@ static int set_schib_wait(struct ccw_device *cdev, u32 mme,
cdev->private->state = DEV_STATE_CMFCHANGE;
set_data->ret = CMF_PENDING;
cdev->private->cmb_wait = set_data;
-
spin_unlock_irq(cdev->ccwlock);
- if (wait_event_interruptible(set_data->wait,
- set_data->ret != CMF_PENDING)) {
- spin_lock_irq(cdev->ccwlock);
+
+ ret = wait_event_interruptible_timeout(set_data->wait,
+ set_data->ret != CMF_PENDING,
+ SET_SCHIB_TIMEOUT);
+ spin_lock_irq(cdev->ccwlock);
+ if (ret <= 0) {
if (set_data->ret == CMF_PENDING) {
- set_data->ret = -ERESTARTSYS;
+ set_data->ret = (ret == 0) ? -ETIME : ret;
if (cdev->private->state == DEV_STATE_CMFCHANGE)
cdev->private->state = DEV_STATE_ONLINE;
}
- spin_unlock_irq(cdev->ccwlock);
}
- spin_lock_irq(cdev->ccwlock);
cdev->private->cmb_wait = NULL;
ret = set_data->ret;
out_put: