aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block/dasd.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2009-09-08 20:55:21 -0400
committerDan Williams <dan.j.williams@intel.com>2009-09-08 20:55:21 -0400
commitbbb20089a3275a19e475dbc21320c3742e3ca423 (patch)
tree216fdc1cbef450ca688135c5b8969169482d9a48 /drivers/s390/block/dasd.c
parent3e48e656903e9fd8bc805c6a2c4264d7808d315b (diff)
parent657a77fa7284d8ae28dfa48f1dc5d919bf5b2843 (diff)
Merge branch 'dmaengine' into async-tx-next
Conflicts: crypto/async_tx/async_xor.c drivers/dma/ioat/dma_v2.h drivers/dma/ioat/pci.c drivers/md/raid5.c
Diffstat (limited to 'drivers/s390/block/dasd.c')
-rw-r--r--drivers/s390/block/dasd.c198
1 files changed, 159 insertions, 39 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c
index d1815272c435..749836668655 100644
--- a/drivers/s390/block/dasd.c
+++ b/drivers/s390/block/dasd.c
@@ -5,8 +5,7 @@
5 * Carsten Otte <Cotte@de.ibm.com> 5 * Carsten Otte <Cotte@de.ibm.com>
6 * Martin Schwidefsky <schwidefsky@de.ibm.com> 6 * Martin Schwidefsky <schwidefsky@de.ibm.com>
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 * Copyright IBM Corp. 1999, 2009
9 *
10 */ 9 */
11 10
12#define KMSG_COMPONENT "dasd" 11#define KMSG_COMPONENT "dasd"
@@ -61,6 +60,7 @@ static int dasd_flush_block_queue(struct dasd_block *);
61static void dasd_device_tasklet(struct dasd_device *); 60static void dasd_device_tasklet(struct dasd_device *);
62static void dasd_block_tasklet(struct dasd_block *); 61static void dasd_block_tasklet(struct dasd_block *);
63static void do_kick_device(struct work_struct *); 62static void do_kick_device(struct work_struct *);
63static void do_restore_device(struct work_struct *);
64static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); 64static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *);
65static void dasd_device_timeout(unsigned long); 65static void dasd_device_timeout(unsigned long);
66static void dasd_block_timeout(unsigned long); 66static void dasd_block_timeout(unsigned long);
@@ -109,6 +109,7 @@ struct dasd_device *dasd_alloc_device(void)
109 device->timer.function = dasd_device_timeout; 109 device->timer.function = dasd_device_timeout;
110 device->timer.data = (unsigned long) device; 110 device->timer.data = (unsigned long) device;
111 INIT_WORK(&device->kick_work, do_kick_device); 111 INIT_WORK(&device->kick_work, do_kick_device);
112 INIT_WORK(&device->restore_device, do_restore_device);
112 device->state = DASD_STATE_NEW; 113 device->state = DASD_STATE_NEW;
113 device->target = DASD_STATE_NEW; 114 device->target = DASD_STATE_NEW;
114 115
@@ -469,7 +470,7 @@ static int dasd_decrease_state(struct dasd_device *device)
469 */ 470 */
470static void dasd_change_state(struct dasd_device *device) 471static void dasd_change_state(struct dasd_device *device)
471{ 472{
472 int rc; 473 int rc;
473 474
474 if (device->state == device->target) 475 if (device->state == device->target)
475 /* Already where we want to go today... */ 476 /* Already where we want to go today... */
@@ -478,8 +479,10 @@ static void dasd_change_state(struct dasd_device *device)
478 rc = dasd_increase_state(device); 479 rc = dasd_increase_state(device);
479 else 480 else
480 rc = dasd_decrease_state(device); 481 rc = dasd_decrease_state(device);
481 if (rc && rc != -EAGAIN) 482 if (rc == -EAGAIN)
482 device->target = device->state; 483 return;
484 if (rc)
485 device->target = device->state;
483 486
484 if (device->state == device->target) { 487 if (device->state == device->target) {
485 wake_up(&dasd_init_waitq); 488 wake_up(&dasd_init_waitq);
@@ -512,6 +515,25 @@ void dasd_kick_device(struct dasd_device *device)
512} 515}
513 516
514/* 517/*
518 * dasd_restore_device will schedule a call do do_restore_device to the kernel
519 * event daemon.
520 */
521static void do_restore_device(struct work_struct *work)
522{
523 struct dasd_device *device = container_of(work, struct dasd_device,
524 restore_device);
525 device->cdev->drv->restore(device->cdev);
526 dasd_put_device(device);
527}
528
529void dasd_restore_device(struct dasd_device *device)
530{
531 dasd_get_device(device);
532 /* queue call to dasd_restore_device to the kernel event daemon. */
533 schedule_work(&device->restore_device);
534}
535
536/*
515 * Set the target state for a device and starts the state change. 537 * Set the target state for a device and starts the state change.
516 */ 538 */
517void dasd_set_target_state(struct dasd_device *device, int target) 539void dasd_set_target_state(struct dasd_device *device, int target)
@@ -603,7 +625,7 @@ static void dasd_profile_end(struct dasd_block *block,
603 if (dasd_profile_level != DASD_PROFILE_ON) 625 if (dasd_profile_level != DASD_PROFILE_ON)
604 return; 626 return;
605 627
606 sectors = req->nr_sectors; 628 sectors = blk_rq_sectors(req);
607 if (!cqr->buildclk || !cqr->startclk || 629 if (!cqr->buildclk || !cqr->startclk ||
608 !cqr->stopclk || !cqr->endclk || 630 !cqr->stopclk || !cqr->endclk ||
609 !sectors) 631 !sectors)
@@ -851,8 +873,10 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
851 873
852 /* Check the cqr */ 874 /* Check the cqr */
853 rc = dasd_check_cqr(cqr); 875 rc = dasd_check_cqr(cqr);
854 if (rc) 876 if (rc) {
877 cqr->intrc = rc;
855 return rc; 878 return rc;
879 }
856 device = (struct dasd_device *) cqr->startdev; 880 device = (struct dasd_device *) cqr->startdev;
857 if (cqr->retries < 0) { 881 if (cqr->retries < 0) {
858 /* internal error 14 - start_IO run out of retries */ 882 /* internal error 14 - start_IO run out of retries */
@@ -906,6 +930,12 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
906 DBF_DEV_EVENT(DBF_DEBUG, device, "%s", 930 DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
907 "start_IO: -EIO device gone, retry"); 931 "start_IO: -EIO device gone, retry");
908 break; 932 break;
933 case -EINVAL:
934 /* most likely caused in power management context */
935 DBF_DEV_EVENT(DBF_DEBUG, device, "%s",
936 "start_IO: -EINVAL device currently "
937 "not accessible");
938 break;
909 default: 939 default:
910 /* internal error 11 - unknown rc */ 940 /* internal error 11 - unknown rc */
911 snprintf(errorstring, ERRORLENGTH, "11 %d", rc); 941 snprintf(errorstring, ERRORLENGTH, "11 %d", rc);
@@ -915,6 +945,7 @@ int dasd_start_IO(struct dasd_ccw_req *cqr)
915 BUG(); 945 BUG();
916 break; 946 break;
917 } 947 }
948 cqr->intrc = rc;
918 return rc; 949 return rc;
919} 950}
920 951
@@ -1454,8 +1485,12 @@ int dasd_sleep_on(struct dasd_ccw_req *cqr)
1454 dasd_add_request_tail(cqr); 1485 dasd_add_request_tail(cqr);
1455 wait_event(generic_waitq, _wait_for_wakeup(cqr)); 1486 wait_event(generic_waitq, _wait_for_wakeup(cqr));
1456 1487
1457 /* Request status is either done or failed. */ 1488 if (cqr->status == DASD_CQR_DONE)
1458 rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; 1489 rc = 0;
1490 else if (cqr->intrc)
1491 rc = cqr->intrc;
1492 else
1493 rc = -EIO;
1459 return rc; 1494 return rc;
1460} 1495}
1461 1496
@@ -1477,8 +1512,15 @@ int dasd_sleep_on_interruptible(struct dasd_ccw_req *cqr)
1477 dasd_cancel_req(cqr); 1512 dasd_cancel_req(cqr);
1478 /* wait (non-interruptible) for final status */ 1513 /* wait (non-interruptible) for final status */
1479 wait_event(generic_waitq, _wait_for_wakeup(cqr)); 1514 wait_event(generic_waitq, _wait_for_wakeup(cqr));
1515 cqr->intrc = rc;
1480 } 1516 }
1481 rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; 1517
1518 if (cqr->status == DASD_CQR_DONE)
1519 rc = 0;
1520 else if (cqr->intrc)
1521 rc = cqr->intrc;
1522 else
1523 rc = -EIO;
1482 return rc; 1524 return rc;
1483} 1525}
1484 1526
@@ -1523,8 +1565,12 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
1523 1565
1524 wait_event(generic_waitq, _wait_for_wakeup(cqr)); 1566 wait_event(generic_waitq, _wait_for_wakeup(cqr));
1525 1567
1526 /* Request status is either done or failed. */ 1568 if (cqr->status == DASD_CQR_DONE)
1527 rc = (cqr->status == DASD_CQR_DONE) ? 0 : -EIO; 1569 rc = 0;
1570 else if (cqr->intrc)
1571 rc = cqr->intrc;
1572 else
1573 rc = -EIO;
1528 return rc; 1574 return rc;
1529} 1575}
1530 1576
@@ -1614,15 +1660,6 @@ void dasd_block_clear_timer(struct dasd_block *block)
1614} 1660}
1615 1661
1616/* 1662/*
1617 * posts the buffer_cache about a finalized request
1618 */
1619static inline void dasd_end_request(struct request *req, int error)
1620{
1621 if (__blk_end_request(req, error, blk_rq_bytes(req)))
1622 BUG();
1623}
1624
1625/*
1626 * Process finished error recovery ccw. 1663 * Process finished error recovery ccw.
1627 */ 1664 */
1628static inline void __dasd_block_process_erp(struct dasd_block *block, 1665static inline void __dasd_block_process_erp(struct dasd_block *block,
@@ -1665,18 +1702,14 @@ static void __dasd_process_request_queue(struct dasd_block *block)
1665 if (basedev->state < DASD_STATE_READY) 1702 if (basedev->state < DASD_STATE_READY)
1666 return; 1703 return;
1667 /* Now we try to fetch requests from the request queue */ 1704 /* Now we try to fetch requests from the request queue */
1668 while (!blk_queue_plugged(queue) && 1705 while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) {
1669 elv_next_request(queue)) {
1670
1671 req = elv_next_request(queue);
1672
1673 if (basedev->features & DASD_FEATURE_READONLY && 1706 if (basedev->features & DASD_FEATURE_READONLY &&
1674 rq_data_dir(req) == WRITE) { 1707 rq_data_dir(req) == WRITE) {
1675 DBF_DEV_EVENT(DBF_ERR, basedev, 1708 DBF_DEV_EVENT(DBF_ERR, basedev,
1676 "Rejecting write request %p", 1709 "Rejecting write request %p",
1677 req); 1710 req);
1678 blkdev_dequeue_request(req); 1711 blk_start_request(req);
1679 dasd_end_request(req, -EIO); 1712 __blk_end_request_all(req, -EIO);
1680 continue; 1713 continue;
1681 } 1714 }
1682 cqr = basedev->discipline->build_cp(basedev, block, req); 1715 cqr = basedev->discipline->build_cp(basedev, block, req);
@@ -1704,8 +1737,8 @@ static void __dasd_process_request_queue(struct dasd_block *block)
1704 "CCW creation failed (rc=%ld) " 1737 "CCW creation failed (rc=%ld) "
1705 "on request %p", 1738 "on request %p",
1706 PTR_ERR(cqr), req); 1739 PTR_ERR(cqr), req);
1707 blkdev_dequeue_request(req); 1740 blk_start_request(req);
1708 dasd_end_request(req, -EIO); 1741 __blk_end_request_all(req, -EIO);
1709 continue; 1742 continue;
1710 } 1743 }
1711 /* 1744 /*
@@ -1714,7 +1747,7 @@ static void __dasd_process_request_queue(struct dasd_block *block)
1714 */ 1747 */
1715 cqr->callback_data = (void *) req; 1748 cqr->callback_data = (void *) req;
1716 cqr->status = DASD_CQR_FILLED; 1749 cqr->status = DASD_CQR_FILLED;
1717 blkdev_dequeue_request(req); 1750 blk_start_request(req);
1718 list_add_tail(&cqr->blocklist, &block->ccw_queue); 1751 list_add_tail(&cqr->blocklist, &block->ccw_queue);
1719 dasd_profile_start(block, cqr, req); 1752 dasd_profile_start(block, cqr, req);
1720 } 1753 }
@@ -1731,7 +1764,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr)
1731 status = cqr->block->base->discipline->free_cp(cqr, req); 1764 status = cqr->block->base->discipline->free_cp(cqr, req);
1732 if (status <= 0) 1765 if (status <= 0)
1733 error = status ? status : -EIO; 1766 error = status ? status : -EIO;
1734 dasd_end_request(req, error); 1767 __blk_end_request_all(req, error);
1735} 1768}
1736 1769
1737/* 1770/*
@@ -2003,7 +2036,7 @@ static void dasd_setup_queue(struct dasd_block *block)
2003{ 2036{
2004 int max; 2037 int max;
2005 2038
2006 blk_queue_hardsect_size(block->request_queue, block->bp_block); 2039 blk_queue_logical_block_size(block->request_queue, block->bp_block);
2007 max = block->base->discipline->max_blocks << block->s2b_shift; 2040 max = block->base->discipline->max_blocks << block->s2b_shift;
2008 blk_queue_max_sectors(block->request_queue, max); 2041 blk_queue_max_sectors(block->request_queue, max);
2009 blk_queue_max_phys_segments(block->request_queue, -1L); 2042 blk_queue_max_phys_segments(block->request_queue, -1L);
@@ -2038,10 +2071,8 @@ static void dasd_flush_request_queue(struct dasd_block *block)
2038 return; 2071 return;
2039 2072
2040 spin_lock_irq(&block->request_queue_lock); 2073 spin_lock_irq(&block->request_queue_lock);
2041 while ((req = elv_next_request(block->request_queue))) { 2074 while ((req = blk_fetch_request(block->request_queue)))
2042 blkdev_dequeue_request(req); 2075 __blk_end_request_all(req, -EIO);
2043 dasd_end_request(req, -EIO);
2044 }
2045 spin_unlock_irq(&block->request_queue_lock); 2076 spin_unlock_irq(&block->request_queue_lock);
2046} 2077}
2047 2078
@@ -2397,6 +2428,12 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
2397 case CIO_OPER: 2428 case CIO_OPER:
2398 /* FIXME: add a sanity check. */ 2429 /* FIXME: add a sanity check. */
2399 device->stopped &= ~DASD_STOPPED_DC_WAIT; 2430 device->stopped &= ~DASD_STOPPED_DC_WAIT;
2431 if (device->stopped & DASD_UNRESUMED_PM) {
2432 device->stopped &= ~DASD_UNRESUMED_PM;
2433 dasd_restore_device(device);
2434 ret = 1;
2435 break;
2436 }
2400 dasd_schedule_device_bh(device); 2437 dasd_schedule_device_bh(device);
2401 if (device->block) 2438 if (device->block)
2402 dasd_schedule_block_bh(device->block); 2439 dasd_schedule_block_bh(device->block);
@@ -2407,6 +2444,89 @@ int dasd_generic_notify(struct ccw_device *cdev, int event)
2407 return ret; 2444 return ret;
2408} 2445}
2409 2446
2447int dasd_generic_pm_freeze(struct ccw_device *cdev)
2448{
2449 struct dasd_ccw_req *cqr, *n;
2450 int rc;
2451 struct list_head freeze_queue;
2452 struct dasd_device *device = dasd_device_from_cdev(cdev);
2453
2454 if (IS_ERR(device))
2455 return PTR_ERR(device);
2456 /* disallow new I/O */
2457 device->stopped |= DASD_STOPPED_PM;
2458 /* clear active requests */
2459 INIT_LIST_HEAD(&freeze_queue);
2460 spin_lock_irq(get_ccwdev_lock(cdev));
2461 rc = 0;
2462 list_for_each_entry_safe(cqr, n, &device->ccw_queue, devlist) {
2463 /* Check status and move request to flush_queue */
2464 if (cqr->status == DASD_CQR_IN_IO) {
2465 rc = device->discipline->term_IO(cqr);
2466 if (rc) {
2467 /* unable to terminate requeust */
2468 dev_err(&device->cdev->dev,
2469 "Unable to terminate request %p "
2470 "on suspend\n", cqr);
2471 spin_unlock_irq(get_ccwdev_lock(cdev));
2472 dasd_put_device(device);
2473 return rc;
2474 }
2475 }
2476 list_move_tail(&cqr->devlist, &freeze_queue);
2477 }
2478
2479 spin_unlock_irq(get_ccwdev_lock(cdev));
2480
2481 list_for_each_entry_safe(cqr, n, &freeze_queue, devlist) {
2482 wait_event(dasd_flush_wq,
2483 (cqr->status != DASD_CQR_CLEAR_PENDING));
2484 if (cqr->status == DASD_CQR_CLEARED)
2485 cqr->status = DASD_CQR_QUEUED;
2486 }
2487 /* move freeze_queue to start of the ccw_queue */
2488 spin_lock_irq(get_ccwdev_lock(cdev));
2489 list_splice_tail(&freeze_queue, &device->ccw_queue);
2490 spin_unlock_irq(get_ccwdev_lock(cdev));
2491
2492 if (device->discipline->freeze)
2493 rc = device->discipline->freeze(device);
2494
2495 dasd_put_device(device);
2496 return rc;
2497}
2498EXPORT_SYMBOL_GPL(dasd_generic_pm_freeze);
2499
2500int dasd_generic_restore_device(struct ccw_device *cdev)
2501{
2502 struct dasd_device *device = dasd_device_from_cdev(cdev);
2503 int rc = 0;
2504
2505 if (IS_ERR(device))
2506 return PTR_ERR(device);
2507
2508 /* allow new IO again */
2509 device->stopped &= ~DASD_STOPPED_PM;
2510 device->stopped &= ~DASD_UNRESUMED_PM;
2511
2512 dasd_schedule_device_bh(device);
2513 if (device->block)
2514 dasd_schedule_block_bh(device->block);
2515
2516 if (device->discipline->restore)
2517 rc = device->discipline->restore(device);
2518 if (rc)
2519 /*
2520 * if the resume failed for the DASD we put it in
2521 * an UNRESUMED stop state
2522 */
2523 device->stopped |= DASD_UNRESUMED_PM;
2524
2525 dasd_put_device(device);
2526 return 0;
2527}
2528EXPORT_SYMBOL_GPL(dasd_generic_restore_device);
2529
2410static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, 2530static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
2411 void *rdc_buffer, 2531 void *rdc_buffer,
2412 int rdc_buffer_size, 2532 int rdc_buffer_size,
@@ -2442,12 +2562,12 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device,
2442 2562
2443 2563
2444int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, 2564int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic,
2445 void **rdc_buffer, int rdc_buffer_size) 2565 void *rdc_buffer, int rdc_buffer_size)
2446{ 2566{
2447 int ret; 2567 int ret;
2448 struct dasd_ccw_req *cqr; 2568 struct dasd_ccw_req *cqr;
2449 2569
2450 cqr = dasd_generic_build_rdc(device, *rdc_buffer, rdc_buffer_size, 2570 cqr = dasd_generic_build_rdc(device, rdc_buffer, rdc_buffer_size,
2451 magic); 2571 magic);
2452 if (IS_ERR(cqr)) 2572 if (IS_ERR(cqr))
2453 return PTR_ERR(cqr); 2573 return PTR_ERR(cqr);