summaryrefslogtreecommitdiff
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
authorStefan Weinhuber <wein@de.ibm.com>2010-10-25 18:10:47 +0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-10-25 18:10:20 +0400
commita5a0061fb3a22bbd9b108af8382142fd0f41ebee (patch)
tree03e643e12b634b201201cddb162de46aa744595b /drivers/s390/block/dasd.c
parent26cffecf84c8cb33787dd13a72bd2124d107d413 (diff)
downloadlinux-a5a0061fb3a22bbd9b108af8382142fd0f41ebee.tar.xz
[S390] dasd: fix unsolicited interrupt recognition
The dasd interrupt handler needs to distinguish solicited from unsolicited interrupts, as unsolicited interrupts may require special handling (e.g. summary unit checks) and solicited interrupts require proper error recovery for the failed I/O request. The interrupt handler needs to check several bit fields in the interrupt response block (irb) to make this distinction. So far our check of the status control bits has not been specific enough, which may lead to a failed request getting just retried instead of the necessary error recovery. Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index aa95f1001761..80e45de096a9 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -1099,11 +1099,20 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
cqr = (struct dasd_ccw_req *) intparm;
if (!cqr || ((scsw_cc(&irb->scsw) == 1) &&
(scsw_fctl(&irb->scsw) & SCSW_FCTL_START_FUNC) &&
- (scsw_stctl(&irb->scsw) & SCSW_STCTL_STATUS_PEND))) {
+ ((scsw_stctl(&irb->scsw) == SCSW_STCTL_STATUS_PEND) ||
+ (scsw_stctl(&irb->scsw) == (SCSW_STCTL_STATUS_PEND |
+ SCSW_STCTL_ALERT_STATUS))))) {
if (cqr && cqr->status == DASD_CQR_IN_IO)
cqr->status = DASD_CQR_QUEUED;
+ if (cqr)
+ memcpy(&cqr->irb, irb, sizeof(*irb));
device = dasd_device_from_cdev_locked(cdev);
if (!IS_ERR(device)) {
+ device->discipline->dump_sense_dbf(device, irb,
+ "unsolicited");
+ if ((device->features & DASD_FEATURE_ERPLOG))
+ device->discipline->dump_sense(device, cqr,
+ irb);
dasd_device_clear_timer(device);
device->discipline->handle_unsolicited_interrupt(device,
irb);