[S390] cio: Try harder to disable subchannel.
authorCornelia Huck <cornelia.huck@de.ibm.com>
Thu, 26 Mar 2009 14:24:06 +0000 (15:24 +0100)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Thu, 26 Mar 2009 14:24:12 +0000 (15:24 +0100)
Acting upon the assumption that cio_disable_subchannel()
is only called when we really want to disable the subchannel
(a) remove the check for activity (it is already done in
    ccw_device_offline(), which is the place where it matters)
(b) collect pending status via tsch() and ignore it (it
    can't matter anymore since the subchannel will be disabled).

Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/cio/cio.c
drivers/s390/cio/device_fsm.c

index 73135c5..2aebb98 100644 (file)
@@ -472,6 +472,7 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel);
 int cio_disable_subchannel(struct subchannel *sch)
 {
        char dbf_txt[15];
+       int retry;
        int ret;
 
        CIO_TRACE_EVENT (2, "dissch");
@@ -482,16 +483,17 @@ int cio_disable_subchannel(struct subchannel *sch)
        if (cio_update_schib(sch))
                return -ENODEV;
 
-       if (scsw_actl(&sch->schib.scsw) != 0)
-               /*
-                * the disable function must not be called while there are
-                *  requests pending for completion !
-                */
-               return -EBUSY;
-
        sch->config.ena = 0;
-       ret = cio_commit_config(sch);
 
+       for (retry = 0; retry < 3; retry++) {
+               ret = cio_commit_config(sch);
+               if (ret == -EBUSY) {
+                       struct irb irb;
+                       if (tsch(sch->schid, &irb) != 0)
+                               break;
+               } else
+                       break;
+       }
        sprintf (dbf_txt, "ret:%d", ret);
        CIO_TRACE_EVENT (2, dbf_txt);
        return ret;
index 95f2f35..301d27b 100644 (file)
@@ -1052,7 +1052,7 @@ ccw_device_offline_irq(struct ccw_device *cdev, enum dev_event dev_event)
        sch = to_subchannel(cdev->dev.parent);
        /*
         * An interrupt in state offline means a previous disable was not
-        * successful. Try again.
+        * successful - should not happen, but we try to disable again.
         */
        cio_disable_subchannel(sch);
 }