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.c237
1 files changed, 163 insertions, 74 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index aaccc8ecfa8f..fdb2e7c14506 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -24,7 +24,6 @@
24#include <asm/ccwdev.h> 24#include <asm/ccwdev.h>
25#include <asm/ebcdic.h> 25#include <asm/ebcdic.h>
26#include <asm/idals.h> 26#include <asm/idals.h>
27#include <asm/todclk.h>
28#include <asm/itcw.h> 27#include <asm/itcw.h>
29 28
30/* This is ugly... */ 29/* This is ugly... */
@@ -64,6 +63,7 @@ static void do_restore_device(struct work_struct *);
64static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); 63static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
65static void dasd_device_timeout(unsigned long); 64static void dasd_device_timeout(unsigned long);
66static void dasd_block_timeout(unsigned long); 65static void dasd_block_timeout(unsigned long);
66static void __dasd_process_erp(struct dasd_device *, struct dasd_ccw_req *);
67 67
68/* 68/*
69 * SECTION: Operations on the device structure. 69 * SECTION: Operations on the device structure.
@@ -960,7 +960,7 @@ static void dasd_device_timeout(unsigned long ptr)
960 device = (struct dasd_device *) ptr; 960 device = (struct dasd_device *) ptr;
961 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); 961 spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags);
962 /* re-activate request queue */ 962 /* re-activate request queue */
963 device->stopped &= ~DASD_STOPPED_PENDING; 963 dasd_device_remove_stop_bits(device, DASD_STOPPED_PENDING);
964 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); 964 spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags);
965 dasd_schedule_device_bh(device); 965 dasd_schedule_device_bh(device);
966} 966}
@@ -994,10 +994,9 @@ static void dasd_handle_killed_request(struct ccw_device *cdev,
994 return; 994 return;
995 cqr = (struct dasd_ccw_req *) intparm; 995 cqr = (struct dasd_ccw_req *) intparm;
996 if (cqr->status != DASD_CQR_IN_IO) { 996 if (cqr->status != DASD_CQR_IN_IO) {
997 DBF_EVENT(DBF_DEBUG, 997 DBF_EVENT_DEVID(DBF_DEBUG, cdev,
998 "invalid status in handle_killed_request: " 998 "invalid status in handle_killed_request: "
999 "bus_id %s, status %02x", 999 "%02x", cqr->status);
1000 dev_name(&cdev->dev), cqr->status);
1001 return; 1000 return;
1002 } 1001 }
1003 1002
@@ -1023,7 +1022,7 @@ void dasd_generic_handle_state_change(struct dasd_device *device)
1023 /* First of all start sense subsystem status request. */ 1022 /* First of all start sense subsystem status request. */
1024 dasd_eer_snss(device); 1023 dasd_eer_snss(device);
1025 1024
1026 device->stopped &= ~DASD_STOPPED_PENDING; 1025 dasd_device_remove_stop_bits(device, DASD_STOPPED_PENDING);
1027 dasd_schedule_device_bh(device); 1026 dasd_schedule_device_bh(device);
1028 if (device->block) 1027 if (device->block)
1029 dasd_schedule_block_bh(device->block); 1028 dasd_schedule_block_bh(device->block);
@@ -1045,12 +1044,13 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm,
1045 case -EIO: 1044 case -EIO:
1046 break; 1045 break;
1047 case -ETIMEDOUT: 1046 case -ETIMEDOUT:
1048 DBF_EVENT(DBF_WARNING, "%s(%s): request timed out\n", 1047 DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: "
1049 __func__, dev_name(&cdev->dev)); 1048 "request timed out\n", __func__);
1050 break; 1049 break;
1051 default: 1050 default:
1052 DBF_EVENT(DBF_WARNING, "%s(%s): unknown error %ld\n", 1051 DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s: "
1053 __func__, dev_name(&cdev->dev), PTR_ERR(irb)); 1052 "unknown error %ld\n", __func__,
1053 PTR_ERR(irb));
1054 } 1054 }
1055 dasd_handle_killed_request(cdev, intparm); 1055 dasd_handle_killed_request(cdev, intparm);
1056 return; 1056 return;
@@ -1405,6 +1405,20 @@ void dasd_schedule_device_bh(struct dasd_device *device)
1405 tasklet_hi_schedule(&device->tasklet); 1405 tasklet_hi_schedule(&device->tasklet);
1406} 1406}
1407 1407
1408void dasd_device_set_stop_bits(struct dasd_device *device, int bits)
1409{
1410 device->stopped |= bits;
1411}
1412EXPORT_SYMBOL_GPL(dasd_device_set_stop_bits);
1413
1414void dasd_device_remove_stop_bits(struct dasd_device *device, int bits)
1415{
1416 device->stopped &= ~bits;
1417 if (!device->stopped)
1418 wake_up(&generic_waitq);
1419}
1420EXPORT_SYMBOL_GPL(dasd_device_remove_stop_bits);
1421
1408/* 1422/*
1409 * Queue a request to the head of the device ccw_queue. 1423 * Queue a request to the head of the device ccw_queue.
1410 * Start the I/O if possible. 1424 * Start the I/O if possible.
@@ -1465,58 +1479,135 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr)
1465} 1479}
1466 1480
1467/* 1481/*
1468 * Queue a request to the tail of the device ccw_queue and wait for 1482 * checks if error recovery is necessary, returns 1 if yes, 0 otherwise.
1469 * it's completion.
1470 */ 1483 */
1471int dasd_sleep_on(struct dasd_ccw_req *cqr) 1484static int __dasd_sleep_on_erp(struct dasd_ccw_req *cqr)
1472{ 1485{
1473 struct dasd_device *device; 1486 struct dasd_device *device;
1474 int rc; 1487 dasd_erp_fn_t erp_fn;
1475 1488
1489 if (cqr->status == DASD_CQR_FILLED)
1490 return 0;
1476 device = cqr->startdev; 1491 device = cqr->startdev;
1492 if (test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) {
1493 if (cqr->status == DASD_CQR_TERMINATED) {
1494 device->discipline->handle_terminated_request(cqr);
1495 return 1;
1496 }
1497 if (cqr->status == DASD_CQR_NEED_ERP) {
1498 erp_fn = device->discipline->erp_action(cqr);
1499 erp_fn(cqr);
1500 return 1;
1501 }
1502 if (cqr->status == DASD_CQR_FAILED)
1503 dasd_log_sense(cqr, &cqr->irb);
1504 if (cqr->refers) {
1505 __dasd_process_erp(device, cqr);
1506 return 1;
1507 }
1508 }
1509 return 0;
1510}
1477 1511
1478 cqr->callback = dasd_wakeup_cb; 1512static int __dasd_sleep_on_loop_condition(struct dasd_ccw_req *cqr)
1479 cqr->callback_data = (void *) &generic_waitq; 1513{
1480 dasd_add_request_tail(cqr); 1514 if (test_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags)) {
1481 wait_event(generic_waitq, _wait_for_wakeup(cqr)); 1515 if (cqr->refers) /* erp is not done yet */
1516 return 1;
1517 return ((cqr->status != DASD_CQR_DONE) &&
1518 (cqr->status != DASD_CQR_FAILED));
1519 } else
1520 return (cqr->status == DASD_CQR_FILLED);
1521}
1482 1522
1483 if (cqr->status == DASD_CQR_DONE) 1523static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
1524{
1525 struct dasd_device *device;
1526 int rc;
1527 struct list_head ccw_queue;
1528 struct dasd_ccw_req *cqr;
1529
1530 INIT_LIST_HEAD(&ccw_queue);
1531 maincqr->status = DASD_CQR_FILLED;
1532 device = maincqr->startdev;
1533 list_add(&maincqr->blocklist, &ccw_queue);
1534 for (cqr = maincqr; __dasd_sleep_on_loop_condition(cqr);
1535 cqr = list_first_entry(&ccw_queue,
1536 struct dasd_ccw_req, blocklist)) {
1537
1538 if (__dasd_sleep_on_erp(cqr))
1539 continue;
1540 if (cqr->status != DASD_CQR_FILLED) /* could be failed */
1541 continue;
1542
1543 /* Non-temporary stop condition will trigger fail fast */
1544 if (device->stopped & ~DASD_STOPPED_PENDING &&
1545 test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
1546 (!dasd_eer_enabled(device))) {
1547 cqr->status = DASD_CQR_FAILED;
1548 continue;
1549 }
1550
1551 /* Don't try to start requests if device is stopped */
1552 if (interruptible) {
1553 rc = wait_event_interruptible(
1554 generic_waitq, !(device->stopped));
1555 if (rc == -ERESTARTSYS) {
1556 cqr->status = DASD_CQR_FAILED;
1557 maincqr->intrc = rc;
1558 continue;
1559 }
1560 } else
1561 wait_event(generic_waitq, !(device->stopped));
1562
1563 cqr->callback = dasd_wakeup_cb;
1564 cqr->callback_data = (void *) &generic_waitq;
1565 dasd_add_request_tail(cqr);
1566 if (interruptible) {
1567 rc = wait_event_interruptible(
1568 generic_waitq, _wait_for_wakeup(cqr));
1569 if (rc == -ERESTARTSYS) {
1570 dasd_cancel_req(cqr);
1571 /* wait (non-interruptible) for final status */
1572 wait_event(generic_waitq,
1573 _wait_for_wakeup(cqr));
1574 cqr->status = DASD_CQR_FAILED;
1575 maincqr->intrc = rc;
1576 continue;
1577 }
1578 } else
1579 wait_event(generic_waitq, _wait_for_wakeup(cqr));
1580 }
1581
1582 maincqr->endclk = get_clock();
1583 if ((maincqr->status != DASD_CQR_DONE) &&
1584 (maincqr->intrc != -ERESTARTSYS))
1585 dasd_log_sense(maincqr, &maincqr->irb);
1586 if (maincqr->status == DASD_CQR_DONE)
1484 rc = 0; 1587 rc = 0;
1485 else if (cqr->intrc) 1588 else if (maincqr->intrc)
1486 rc = cqr->intrc; 1589 rc = maincqr->intrc;
1487 else 1590 else
1488 rc = -EIO; 1591 rc = -EIO;
1489 return rc; 1592 return rc;
1490} 1593}
1491 1594
1492/* 1595/*
1596 * Queue a request to the tail of the device ccw_queue and wait for
1597 * it's completion.
1598 */
1599int dasd_sleep_on(struct dasd_ccw_req *cqr)
1600{
1601 return _dasd_sleep_on(cqr, 0);
1602}
1603
1604/*
1493 * Queue a request to the tail of the device ccw_queue and wait 1605 * Queue a request to the tail of the device ccw_queue and wait
1494 * interruptible for it's completion. 1606 * interruptible for it's completion.
1495 */ 1607 */
1496int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr) 1608int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
1497{ 1609{
1498 struct dasd_device *device; 1610 return _dasd_sleep_on(cqr, 1);
1499 int rc;
1500
1501 device = cqr->startdev;
1502 cqr->callback = dasd_wakeup_cb;
1503 cqr->callback_data = (void *) &generic_waitq;
1504 dasd_add_request_tail(cqr);
1505 rc = wait_event_interruptible(generic_waitq, _wait_for_wakeup(cqr));
1506 if (rc == -ERESTARTSYS) {
1507 dasd_cancel_req(cqr);
1508 /* wait (non-interruptible) for final status */
1509 wait_event(generic_waitq, _wait_for_wakeup(cqr));
1510 cqr->intrc = rc;
1511 }
1512
1513 if (cqr->status == DASD_CQR_DONE)
1514 rc = 0;
1515 else if (cqr->intrc)
1516 rc = cqr->intrc;
1517 else
1518 rc = -EIO;
1519 return rc;
1520} 1611}
1521 1612
1522/* 1613/*
@@ -1630,7 +1721,7 @@ static void dasd_block_timeout(unsigned long ptr)
1630 block = (struct dasd_block *) ptr; 1721 block = (struct dasd_block *) ptr;
1631 spin_lock_irqsave(get_ccwdev_lock(block->base->cdev), flags); 1722 spin_lock_irqsave(get_ccwdev_lock(block->base->cdev), flags);
1632 /* re-activate request queue */ 1723 /* re-activate request queue */
1633 block->base->stopped &= ~DASD_STOPPED_PENDING; 1724 dasd_device_remove_stop_bits(block->base, DASD_STOPPED_PENDING);
1634 spin_unlock_irqrestore(get_ccwdev_lock(block->base->cdev), flags); 1725 spin_unlock_irqrestore(get_ccwdev_lock(block->base->cdev), flags);
1635 dasd_schedule_block_bh(block); 1726 dasd_schedule_block_bh(block);
1636} 1727}
@@ -1657,11 +1748,10 @@ void dasd_block_clear_timer(struct dasd_block *block)
1657/* 1748/*
1658 * Process finished error recovery ccw. 1749 * Process finished error recovery ccw.
1659 */ 1750 */
1660static inline void __dasd_block_process_erp(struct dasd_block *block, 1751static void __dasd_process_erp(struct dasd_device *device,
1661 struct dasd_ccw_req *cqr) 1752 struct dasd_ccw_req *cqr)
1662{ 1753{
1663 dasd_erp_fn_t erp_fn; 1754 dasd_erp_fn_t erp_fn;
1664 struct dasd_device *device = block->base;
1665 1755
1666 if (cqr->status == DASD_CQR_DONE) 1756 if (cqr->status == DASD_CQR_DONE)
1667 DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful"); 1757 DBF_DEV_EVENT(DBF_NOTICE, device, "%s", "ERP successful");
@@ -1725,9 +1815,12 @@ static void __dasd_process_request_queue(struct dasd_block *block)
1725 */ 1815 */
1726 if (!list_empty(&block->ccw_queue)) 1816 if (!list_empty(&block->ccw_queue))
1727 break; 1817 break;
1728 spin_lock_irqsave(get_ccwdev_lock(basedev->cdev), flags); 1818 spin_lock_irqsave(
1729 basedev->stopped |= DASD_STOPPED_PENDING; 1819 get_ccwdev_lock(basedev->cdev), flags);
1730 spin_unlock_irqrestore(get_ccwdev_lock(basedev->cdev), flags); 1820 dasd_device_set_stop_bits(basedev,
1821 DASD_STOPPED_PENDING);
1822 spin_unlock_irqrestore(
1823 get_ccwdev_lock(basedev->cdev), flags);
1731 dasd_block_set_timer(block, HZ/2); 1824 dasd_block_set_timer(block, HZ/2);
1732 break; 1825 break;
1733 } 1826 }
@@ -1813,7 +1906,7 @@ restart:
1813 cqr->status = DASD_CQR_FILLED; 1906 cqr->status = DASD_CQR_FILLED;
1814 cqr->retries = 255; 1907 cqr->retries = 255;
1815 spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); 1908 spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags);
1816 base->stopped |= DASD_STOPPED_QUIESCE; 1909 dasd_device_set_stop_bits(base, DASD_STOPPED_QUIESCE);
1817 spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), 1910 spin_unlock_irqrestore(get_ccwdev_lock(base->cdev),
1818 flags); 1911 flags);
1819 goto restart; 1912 goto restart;
@@ -1821,7 +1914,7 @@ restart:
1821 1914
1822 /* Process finished ERP request. */ 1915 /* Process finished ERP request. */
1823 if (cqr->refers) { 1916 if (cqr->refers) {
1824 __dasd_block_process_erp(block, cqr); 1917 __dasd_process_erp(base, cqr);
1825 goto restart; 1918 goto restart;
1826 } 1919 }
1827 1920
@@ -1952,7 +2045,7 @@ restart_cb:
1952 /* Process finished ERP request. */ 2045 /* Process finished ERP request. */
1953 if (cqr->refers) { 2046 if (cqr->refers) {
1954 spin_lock_bh(&block->queue_lock); 2047 spin_lock_bh(&block->queue_lock);
1955 __dasd_block_process_erp(block, cqr); 2048 __dasd_process_erp(block->base, cqr);
1956 spin_unlock_bh(&block->queue_lock); 2049 spin_unlock_bh(&block->queue_lock);
1957 /* restart list_for_xx loop since dasd_process_erp 2050 /* restart list_for_xx loop since dasd_process_erp
1958 * might remove multiple elements */ 2051 * might remove multiple elements */
@@ -2208,18 +2301,11 @@ int dasd_generic_probe(struct ccw_device *cdev,
2208{ 2301{
2209 int ret; 2302 int ret;
2210 2303
2211 ret = ccw_device_set_options(cdev, CCWDEV_DO_PATHGROUP);
2212 if (ret) {
2213 DBF_EVENT(DBF_WARNING,
2214 "dasd_generic_probe: could not set ccw-device options "
2215 "for %s\n", dev_name(&cdev->dev));
2216 return ret;
2217 }
2218 ret = dasd_add_sysfs_files(cdev); 2304 ret = dasd_add_sysfs_files(cdev);
2219 if (ret) { 2305 if (ret) {
2220 DBF_EVENT(DBF_WARNING, 2306 DBF_EVENT_DEVID(DBF_WARNING, cdev, "%s",
2221 "dasd_generic_probe: could not add sysfs entries " 2307 "dasd_generic_probe: could not add "
2222 "for %s\n", dev_name(&cdev->dev)); 2308 "sysfs entries");
2223 return ret; 2309 return ret;
2224 } 2310 }
2225 cdev->handler = &dasd_int_handler; 2311 cdev->handler = &dasd_int_handler;
@@ -2418,16 +2504,16 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
2418 cqr->status = DASD_CQR_QUEUED; 2504 cqr->status = DASD_CQR_QUEUED;
2419 cqr->retries++; 2505 cqr->retries++;
2420 } 2506 }
2421 device->stopped |= DASD_STOPPED_DC_WAIT; 2507 dasd_device_set_stop_bits(device, DASD_STOPPED_DC_WAIT);
2422 dasd_device_clear_timer(device); 2508 dasd_device_clear_timer(device);
2423 dasd_schedule_device_bh(device); 2509 dasd_schedule_device_bh(device);
2424 ret = 1; 2510 ret = 1;
2425 break; 2511 break;
2426 case CIO_OPER: 2512 case CIO_OPER:
2427 /* FIXME: add a sanity check. */ 2513 /* FIXME: add a sanity check. */
2428 device->stopped &= ~DASD_STOPPED_DC_WAIT; 2514 dasd_device_remove_stop_bits(device, DASD_STOPPED_DC_WAIT);
2429 if (device->stopped & DASD_UNRESUMED_PM) { 2515 if (device->stopped & DASD_UNRESUMED_PM) {
2430 device->stopped &= ~DASD_UNRESUMED_PM; 2516 dasd_device_remove_stop_bits(device, DASD_UNRESUMED_PM);
2431 dasd_restore_device(device); 2517 dasd_restore_device(device);
2432 ret = 1; 2518 ret = 1;
2433 break; 2519 break;
@@ -2452,7 +2538,7 @@ int dasd_generic_pm_freeze(struct ccw_device *cdev)
2452 if (IS_ERR(device)) 2538 if (IS_ERR(device))
2453 return PTR_ERR(device); 2539 return PTR_ERR(device);
2454 /* disallow new I/O */ 2540 /* disallow new I/O */
2455 device->stopped |= DASD_STOPPED_PM; 2541 dasd_device_set_stop_bits(device, DASD_STOPPED_PM);
2456 /* clear active requests */ 2542 /* clear active requests */
2457 INIT_LIST_HEAD(&freeze_queue); 2543 INIT_LIST_HEAD(&freeze_queue);
2458 spin_lock_irq(get_ccwdev_lock(cdev)); 2544 spin_lock_irq(get_ccwdev_lock(cdev));
@@ -2504,14 +2590,18 @@ int dasd_generic_restore_device(struct ccw_device *cdev)
2504 return PTR_ERR(device); 2590 return PTR_ERR(device);
2505 2591
2506 /* allow new IO again */ 2592 /* allow new IO again */
2507 device->stopped &= ~DASD_STOPPED_PM; 2593 dasd_device_remove_stop_bits(device,
2508 device->stopped &= ~DASD_UNRESUMED_PM; 2594 (DASD_STOPPED_PM | DASD_UNRESUMED_PM));
2509 2595
2510 dasd_schedule_device_bh(device); 2596 dasd_schedule_device_bh(device);
2511 2597
2512 if (device->discipline->restore) 2598 /*
2599 * call discipline restore function
2600 * if device is stopped do nothing e.g. for disconnected devices
2601 */
2602 if (device->discipline->restore && !(device->stopped))
2513 rc = device->discipline->restore(device); 2603 rc = device->discipline->restore(device);
2514 if (rc) 2604 if (rc || device->stopped)
2515 /* 2605 /*
2516 * if the resume failed for the DASD we put it in 2606 * if the resume failed for the DASD we put it in
2517 * an UNRESUMED stop state 2607 * an UNRESUMED stop state
@@ -2561,8 +2651,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
2561 cqr->startdev = device; 2651 cqr->startdev = device;
2562 cqr->memdev = device; 2652 cqr->memdev = device;
2563 cqr->expires = 10*HZ; 2653 cqr->expires = 10*HZ;
2564 clear_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); 2654 cqr->retries = 256;
2565 cqr->retries = 2;
2566 cqr->buildclk = get_clock(); 2655 cqr->buildclk = get_clock();
2567 cqr->status = DASD_CQR_FILLED; 2656 cqr->status = DASD_CQR_FILLED;
2568 return cqr; 2657 return cqr;