summaryrefslogtreecommitdiff
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorPeter Oberparleiter <peter.oberparleiter@de.ibm.com>2006-04-27 18:40:02 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-28 08:33:47 -0700
commit329b785bcee5d001f97a33bdb80de014bb5020b0 (patch)
tree795cbbba999f83c3e61a87135dde088b574c7406 /drivers/s390/cio
parentbcff5cd667da6eb3df9173626497e3e69b004e42 (diff)
[PATCH] s390: fix I/O termination race in cio
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>
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/chsc.c26
1 files changed, 4 insertions, 22 deletions
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 6412b2c3edd..daedb00a434 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -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);