diff options
author | Stefan Weinhuber <wein@de.ibm.com> | 2009-06-12 04:26:39 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-12 04:27:36 -0400 |
commit | 6cc7f168954fe8b3d8988a90b2478a9c11c5ebcb (patch) | |
tree | de3ee836f75f4cd1010a78c49d42393198b6f955 /drivers/s390 | |
parent | 736e6ea0bf97ec79521f88704ce8506e5d60d078 (diff) |
[S390] dasd: forward internal errors to dasd_sleep_on caller
If a DASD requests is started with dasd_sleep_on and fails, then the
calling function may need to know the reason for the failure.
In cases of hardware errors it can inspect the sense data in the irb,
but when the reason is internal (e.g. start_IO failed) then it needs
a meaningfull return code.
Signed-off-by: Stefan Weinhuber <wein@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r-- | drivers/s390/block/dasd.c | 30 | ||||
-rw-r--r-- | drivers/s390/block/dasd_diag.c | 1 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 8 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 1 |
4 files changed, 31 insertions, 9 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 35f43bea5d07..442bb98a2821 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -851,8 +851,10 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
851 | 851 | ||
852 | /* Check the cqr */ | 852 | /* Check the cqr */ |
853 | rc = dasd_check_cqr(cqr); | 853 | rc = dasd_check_cqr(cqr); |
854 | if (rc) | 854 | if (rc) { |
855 | cqr->intrc = rc; | ||
855 | return rc; | 856 | return rc; |
857 | } | ||
856 | device = (struct dasd_device *) cqr->startdev; | 858 | device = (struct dasd_device *) cqr->startdev; |
857 | if (cqr->retries < 0) { | 859 | if (cqr->retries < 0) { |
858 | /* internal error 14 - start_IO run out of retries */ | 860 | /* internal error 14 - start_IO run out of retries */ |
@@ -915,6 +917,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
915 | BUG(); | 917 | BUG(); |
916 | break; | 918 | break; |
917 | } | 919 | } |
920 | cqr->intrc = rc; | ||
918 | return rc; | 921 | return rc; |
919 | } | 922 | } |
920 | 923 | ||
@@ -1454,8 +1457,12 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr) | |||
1454 | dasd_add_request_tail(cqr); | 1457 | dasd_add_request_tail(cqr); |
1455 | wait_event(generic_waitq, _wait_for_wakeup(cqr)); | 1458 | wait_event(generic_waitq, _wait_for_wakeup(cqr)); |
1456 | 1459 | ||
1457 | /* Request status is either done or failed. */ | 1460 | if (cqr->status == DASD_CQR_DONE) |
1458 | rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; | 1461 | rc = 0; |
1462 | else if (cqr->intrc) | ||
1463 | rc = cqr->intrc; | ||
1464 | else | ||
1465 | rc = -EIO; | ||
1459 | return rc; | 1466 | return rc; |
1460 | } | 1467 | } |
1461 | 1468 | ||
@@ -1477,8 +1484,15 @@ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr) | |||
1477 | dasd_cancel_req(cqr); | 1484 | dasd_cancel_req(cqr); |
1478 | /* wait (non-interruptible) for final status */ | 1485 | /* wait (non-interruptible) for final status */ |
1479 | wait_event(generic_waitq, _wait_for_wakeup(cqr)); | 1486 | wait_event(generic_waitq, _wait_for_wakeup(cqr)); |
1487 | cqr->intrc = rc; | ||
1480 | } | 1488 | } |
1481 | rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; | 1489 | |
1490 | if (cqr->status == DASD_CQR_DONE) | ||
1491 | rc = 0; | ||
1492 | else if (cqr->intrc) | ||
1493 | rc = cqr->intrc; | ||
1494 | else | ||
1495 | rc = -EIO; | ||
1482 | return rc; | 1496 | return rc; |
1483 | } | 1497 | } |
1484 | 1498 | ||
@@ -1523,8 +1537,12 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) | |||
1523 | 1537 | ||
1524 | wait_event(generic_waitq, _wait_for_wakeup(cqr)); | 1538 | wait_event(generic_waitq, _wait_for_wakeup(cqr)); |
1525 | 1539 | ||
1526 | /* Request status is either done or failed. */ | 1540 | if (cqr->status == DASD_CQR_DONE) |
1527 | rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; | 1541 | rc = 0; |
1542 | else if (cqr->intrc) | ||
1543 | rc = cqr->intrc; | ||
1544 | else | ||
1545 | rc = -EIO; | ||
1528 | return rc; | 1546 | return rc; |
1529 | } | 1547 | } |
1530 | 1548 | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 2efaddfae560..644086ba2ede 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -202,6 +202,7 @@ dasd_start_diag(struct dasd_ccw_req * cqr) | |||
202 | rc = -EIO; | 202 | rc = -EIO; |
203 | break; | 203 | break; |
204 | } | 204 | } |
205 | cqr->intrc = rc; | ||
205 | return rc; | 206 | return rc; |
206 | } | 207 | } |
207 | 208 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 216c09bcd222..cf0cfdba1244 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -3017,8 +3017,9 @@ static void dasd_eckd_dump_sense_ccw(struct dasd_device *device, | |||
3017 | " I/O status report for device %s:\n", | 3017 | " I/O status report for device %s:\n", |
3018 | dev_name(&device->cdev->dev)); | 3018 | dev_name(&device->cdev->dev)); |
3019 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3019 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3020 | " in req: %p CS: 0x%02X DS: 0x%02X\n", req, | 3020 | " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d\n", |
3021 | scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw)); | 3021 | req, scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), |
3022 | scsw_cc(&irb->scsw), req->intrc); | ||
3022 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3023 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3023 | " device %s: Failing CCW: %p\n", | 3024 | " device %s: Failing CCW: %p\n", |
3024 | dev_name(&device->cdev->dev), | 3025 | dev_name(&device->cdev->dev), |
@@ -3119,9 +3120,10 @@ static void dasd_eckd_dump_sense_tcw(struct dasd_device *device, | |||
3119 | " I/O status report for device %s:\n", | 3120 | " I/O status report for device %s:\n", |
3120 | dev_name(&device->cdev->dev)); | 3121 | dev_name(&device->cdev->dev)); |
3121 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3122 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3122 | " in req: %p CS: 0x%02X DS: 0x%02X " | 3123 | " in req: %p CS: 0x%02X DS: 0x%02X CC: 0x%02X RC: %d " |
3123 | "fcxs: 0x%02X schxs: 0x%02X\n", req, | 3124 | "fcxs: 0x%02X schxs: 0x%02X\n", req, |
3124 | scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), | 3125 | scsw_cstat(&irb->scsw), scsw_dstat(&irb->scsw), |
3126 | scsw_cc(&irb->scsw), req->intrc, | ||
3125 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs); | 3127 | irb->scsw.tm.fcxs, irb->scsw.tm.schxs); |
3126 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER | 3128 | len += sprintf(page + len, KERN_ERR PRINTK_HEADER |
3127 | " device %s: Failing TCW: %p\n", | 3129 | " device %s: Failing TCW: %p\n", |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 3ab69b5a41f6..f97ceb795078 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -173,6 +173,7 @@ struct dasd_ccw_req { | |||
173 | void *data; /* pointer to data area */ | 173 | void *data; /* pointer to data area */ |
174 | 174 | ||
175 | /* these are important for recovering erroneous requests */ | 175 | /* these are important for recovering erroneous requests */ |
176 | int intrc; /* internal error, e.g. from start_IO */ | ||
176 | struct irb irb; /* device status in case of an error */ | 177 | struct irb irb; /* device status in case of an error */ |
177 | struct dasd_ccw_req *refers; /* ERP-chain queueing. */ | 178 | struct dasd_ccw_req *refers; /* ERP-chain queueing. */ |
178 | void *function; /* originating ERP action */ | 179 | void *function; /* originating ERP action */ |