summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2006-03-24 03:15:12 -0800
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-24 07:33:15 -0800
commit3ba1998e90239ed0d7af918998bc866fa77303eb (patch)
tree6417c281e7121149b86246a26ac136c9973e2b7d
parent3d1712c91df01d2573b934e972e231e8edb102c7 (diff)
downloadlinux-3.10-3ba1998e90239ed0d7af918998bc866fa77303eb.tar.gz
linux-3.10-3ba1998e90239ed0d7af918998bc866fa77303eb.tar.bz2
linux-3.10-3ba1998e90239ed0d7af918998bc866fa77303eb.zip
[PATCH] s390: wrong interrupt delivered for hsch() or csch()
When cio waits for the interrupt for a basic sense, interrupts for hsch() or csch() issued in the meantime are wrongly counted as interrupts for the basic sense and the accumulated irb is passed to the device driver. In ccw_device_w4sense(), check for clear or halt function in the irb and pass the irb for the csch() or hsch() to the device driver. Signed-off-by: Cornelia Huck <cornelia.huck@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>
-rw-r--r--drivers/s390/cio/device_fsm.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index b302779e7cf..180b3bf8b90 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -827,6 +827,17 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
}
return;
}
+ /*
+ * Check if a halt or clear has been issued in the meanwhile. If yes,
+ * only deliver the halt/clear interrupt to the device driver as if it
+ * had killed the original request.
+ */
+ if (irb->scsw.fctl & (SCSW_FCTL_CLEAR_FUNC | SCSW_FCTL_HALT_FUNC)) {
+ cdev->private->flags.dosense = 0;
+ memset(&cdev->private->irb, 0, sizeof(struct irb));
+ ccw_device_accumulate_irb(cdev, irb);
+ goto call_handler;
+ }
/* Add basic sense info to irb. */
ccw_device_accumulate_basic_sense(cdev, irb);
if (cdev->private->flags.dosense) {
@@ -834,6 +845,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
ccw_device_do_sense(cdev, irb);
return;
}
+call_handler:
cdev->private->state = DEV_STATE_ONLINE;
/* Call the handler. */
if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify)