[PATCH] s390: fix I/O termination race in cio
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>
Fri, 28 Apr 2006 01:40:02 +0000 (18:40 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 28 Apr 2006 15:33:47 +0000 (08:33 -0700)
Fix a race condition in the I/O termination logic.  The race can cause I/O to
a dasd device to fail with no retry left after turning one channel path to the
device off and on multiple times.

Signed-off-by: Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
drivers/s390/cio/chsc.c

index 6412b2c3edd33d7fe67d0662e5cb05c948fbfcfa..daedb00a43464b4981a2c5830d9051c40870e78c 100644 (file)
@@ -242,28 +242,10 @@ s390_subchannel_remove_chpid(struct device *dev, void *data)
        if (sch->vpm == mask)
                goto out_unreg;
 
-       if ((sch->schib.scsw.actl & (SCSW_ACTL_CLEAR_PEND |
-                                    SCSW_ACTL_HALT_PEND |
-                                    SCSW_ACTL_START_PEND |
-                                    SCSW_ACTL_RESUME_PEND)) &&
-           (sch->schib.pmcw.lpum == mask)) {
-               int cc = cio_cancel(sch);
-               
-               if (cc == -ENODEV)
-                       goto out_unreg;
-
-               if (cc == -EINVAL) {
-                       cc = cio_clear(sch);
-                       if (cc == -ENODEV)
-                               goto out_unreg;
-                       /* Call handler. */
-                       if (sch->driver && sch->driver->termination)
-                               sch->driver->termination(&sch->dev);
-                       goto out_unlock;
-               }
-       } else if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
-                  (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
-                  (sch->schib.pmcw.lpum == mask)) {
+       if ((sch->schib.scsw.actl & SCSW_ACTL_DEVACT) &&
+           (sch->schib.scsw.actl & SCSW_ACTL_SCHACT) &&
+           (sch->schib.pmcw.lpum == mask) &&
+           (sch->vpm == 0)) {
                int cc;
 
                cc = cio_clear(sch);