diff options
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r-- | drivers/s390/block/dasd.c | 46 |
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 | } |