diff options
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r-- | drivers/s390/block/dasd.c | 237 |
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 *); | |||
64 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); | 63 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); |
65 | static void dasd_device_timeout(unsigned long); | 64 | static void dasd_device_timeout(unsigned long); |
66 | static void dasd_block_timeout(unsigned long); | 65 | static void dasd_block_timeout(unsigned long); |
66 | static 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 | ||
1408 | void dasd_device_set_stop_bits(struct dasd_device *device, int bits) | ||
1409 | { | ||
1410 | device->stopped |= bits; | ||
1411 | } | ||
1412 | EXPORT_SYMBOL_GPL(dasd_device_set_stop_bits); | ||
1413 | |||
1414 | void 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 | } | ||
1420 | EXPORT_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 | */ |
1471 | int dasd_sleep_on(struct dasd_ccw_req *cqr) | 1484 | static 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; | 1512 | static 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) | 1523 | static 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 | */ | ||
1599 | int 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 | */ |
1496 | int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr) | 1608 | int 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 | */ |
1660 | static inline void __dasd_block_process_erp(struct dasd_block *block, | 1751 | static 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; |