]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
s390/cmf: set_schib_wait add timeout
authorSebastian Ott <sebott@linux.vnet.ibm.com>
Tue, 5 Sep 2017 12:22:48 +0000 (14:22 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 28 Sep 2017 05:29:41 +0000 (07:29 +0200)
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>
drivers/s390/cio/cmf.c

index 220491d27ef4791f72ac85a9c921ede2a0370775..be0b010ff1360dad9f24cd62403778a196e99fd6 100644 (file)
@@ -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: