aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c46
1 files changed, 33 insertions, 13 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index ef4c687e7c01..abdf1ee633e7 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -7,7 +7,6 @@
7 * Bugreports.to..: <Linux390@de.ibm.com> 7 * Bugreports.to..: <Linux390@de.ibm.com>
8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001 8 * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
9 * 9 *
10 * $Revision: 1.172 $
11 */ 10 */
12 11
13#include <linux/config.h> 12#include <linux/config.h>
@@ -675,11 +674,8 @@ dasd_term_IO(struct dasd_ccw_req * cqr)
675 rc = ccw_device_clear(device->cdev, (long) cqr); 674 rc = ccw_device_clear(device->cdev, (long) cqr);
676 switch (rc) { 675 switch (rc) {
677 case 0: /* termination successful */ 676 case 0: /* termination successful */
678 if (cqr->retries > 0) { 677 cqr->retries--;
679 cqr->retries--; 678 cqr->status = DASD_CQR_CLEAR;
680 cqr->status = DASD_CQR_CLEAR;
681 } else
682 cqr->status = DASD_CQR_FAILED;
683 cqr->stopclk = get_clock(); 679 cqr->stopclk = get_clock();
684 DBF_DEV_EVENT(DBF_DEBUG, device, 680 DBF_DEV_EVENT(DBF_DEBUG, device,
685 "terminate cqr %p successful", 681 "terminate cqr %p successful",
@@ -1308,7 +1304,7 @@ dasd_tasklet(struct dasd_device * device)
1308 /* Now call the callback function of requests with final status */ 1304 /* Now call the callback function of requests with final status */
1309 list_for_each_safe(l, n, &final_queue) { 1305 list_for_each_safe(l, n, &final_queue) {
1310 cqr = list_entry(l, struct dasd_ccw_req, list); 1306 cqr = list_entry(l, struct dasd_ccw_req, list);
1311 list_del(&cqr->list); 1307 list_del_init(&cqr->list);
1312 if (cqr->callback != NULL) 1308 if (cqr->callback != NULL)
1313 (cqr->callback)(cqr, cqr->callback_data); 1309 (cqr->callback)(cqr, cqr->callback_data);
1314 } 1310 }
@@ -1393,7 +1389,9 @@ _wait_for_wakeup(struct dasd_ccw_req *cqr)
1393 1389
1394 device = cqr->device; 1390 device = cqr->device;
1395 spin_lock_irq(get_ccwdev_lock(device->cdev)); 1391 spin_lock_irq(get_ccwdev_lock(device->cdev));
1396 rc = cqr->status == DASD_CQR_DONE || cqr->status == DASD_CQR_FAILED; 1392 rc = ((cqr->status == DASD_CQR_DONE ||
1393 cqr->status == DASD_CQR_FAILED) &&
1394 list_empty(&cqr->list));
1397 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 1395 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1398 return rc; 1396 return rc;
1399} 1397}
@@ -1457,15 +1455,37 @@ dasd_sleep_on_interruptible(struct dasd_ccw_req * cqr)
1457 while (!finished) { 1455 while (!finished) {
1458 rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr)); 1456 rc = wait_event_interruptible(wait_q, _wait_for_wakeup(cqr));
1459 if (rc != -ERESTARTSYS) { 1457 if (rc != -ERESTARTSYS) {
1460 /* Request status is either done or failed. */ 1458 /* Request is final (done or failed) */
1461 rc = (cqr->status == DASD_CQR_FAILED) ? -EIO : 0; 1459 rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
1462 break; 1460 break;
1463 } 1461 }
1464 spin_lock_irq(get_ccwdev_lock(device->cdev)); 1462 spin_lock_irq(get_ccwdev_lock(device->cdev));
1465 if (cqr->status == DASD_CQR_IN_IO && 1463 switch (cqr->status) {
1466 device->discipline->term_IO(cqr) == 0) { 1464 case DASD_CQR_IN_IO:
1467 list_del(&cqr->list); 1465 /* terminate runnig cqr */
1466 if (device->discipline->term_IO) {
1467 cqr->retries = -1;
1468 device->discipline->term_IO(cqr);
1469 /*nished =
1470 * wait (non-interruptible) for final status
1471 * because signal ist still pending
1472 */
1473 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1474 wait_event(wait_q, _wait_for_wakeup(cqr));
1475 spin_lock_irq(get_ccwdev_lock(device->cdev));
1476 rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO;
1477 finished = 1;
1478 }
1479 break;
1480 case DASD_CQR_QUEUED:
1481 /* request */
1482 list_del_init(&cqr->list);
1483 rc = -EIO;
1468 finished = 1; 1484 finished = 1;
1485 break;
1486 default:
1487 /* cqr with 'non-interruptable' status - just wait */
1488 break;
1469 } 1489 }
1470 spin_unlock_irq(get_ccwdev_lock(device->cdev)); 1490 spin_unlock_irq(get_ccwdev_lock(device->cdev));
1471 } 1491 }