aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorStefan Weinhuber <wein@de.ibm.com>2010-08-09 12:12:59 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-08-09 12:12:54 -0400
commitf932bcea6b7317312ab38df12a84710fc6c67a81 (patch)
tree6476fb6c8423ee65bc8b73182436ccfc7361ed05 /drivers/s390
parenteafd2b6ddd8604998bdfbf7550b23795c07f03bb (diff)
[S390] dasd: allocate fallback cqr for reserve/release
The DASD reserve and release ioctls use the preallocated memory pool of the respective device to build their CCW requests. However, when the device is busy, the pool may already be empty and the ioctl fails. Usually this can be recovered by calling the ioctl again, but in a situation in which we need to issue an unconditional reserve to make a device operational again, this would be not recoverable. To avoid a failure due to lack of memory, DASD device driver will preallocate enough memory for a single reserve/release request, which can be used if normal allocation fails. Signed-off-by: Stefan Weinhuber <wein@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/block/dasd_eckd.c73
1 files changed, 60 insertions, 13 deletions
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index ab84da5592e8..0483b2e76b11 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -82,6 +82,14 @@ static struct ccw_driver dasd_eckd_driver; /* see below */
82#define INIT_CQR_UNFORMATTED 1 82#define INIT_CQR_UNFORMATTED 1
83#define INIT_CQR_ERROR 2 83#define INIT_CQR_ERROR 2
84 84
85/* emergency request for reserve/release */
86static struct {
87 struct dasd_ccw_req cqr;
88 struct ccw1 ccw;
89 char data[32];
90} *dasd_reserve_req;
91static DEFINE_MUTEX(dasd_reserve_mutex);
92
85 93
86/* initial attempt at a probe function. this can be simplified once 94/* initial attempt at a probe function. this can be simplified once
87 * the other detection code is gone */ 95 * the other detection code is gone */
@@ -2645,15 +2653,23 @@ dasd_eckd_release(struct dasd_device *device)
2645 struct dasd_ccw_req *cqr; 2653 struct dasd_ccw_req *cqr;
2646 int rc; 2654 int rc;
2647 struct ccw1 *ccw; 2655 struct ccw1 *ccw;
2656 int useglobal;
2648 2657
2649 if (!capable(CAP_SYS_ADMIN)) 2658 if (!capable(CAP_SYS_ADMIN))
2650 return -EACCES; 2659 return -EACCES;
2651 2660
2661 useglobal = 0;
2652 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); 2662 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
2653 if (IS_ERR(cqr)) { 2663 if (IS_ERR(cqr)) {
2654 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2664 mutex_lock(&dasd_reserve_mutex);
2655 "Could not allocate initialization request"); 2665 useglobal = 1;
2656 return PTR_ERR(cqr); 2666 cqr = &dasd_reserve_req->cqr;
2667 memset(cqr, 0, sizeof(*cqr));
2668 memset(&dasd_reserve_req->ccw, 0,
2669 sizeof(dasd_reserve_req->ccw));
2670 cqr->cpaddr = &dasd_reserve_req->ccw;
2671 cqr->data = &dasd_reserve_req->data;
2672 cqr->magic = DASD_ECKD_MAGIC;
2657 } 2673 }
2658 ccw = cqr->cpaddr; 2674 ccw = cqr->cpaddr;
2659 ccw->cmd_code = DASD_ECKD_CCW_RELEASE; 2675 ccw->cmd_code = DASD_ECKD_CCW_RELEASE;
@@ -2671,7 +2687,10 @@ dasd_eckd_release(struct dasd_device *device)
2671 2687
2672 rc = dasd_sleep_on_immediatly(cqr); 2688 rc = dasd_sleep_on_immediatly(cqr);
2673 2689
2674 dasd_sfree_request(cqr, cqr->memdev); 2690 if (useglobal)
2691 mutex_unlock(&dasd_reserve_mutex);
2692 else
2693 dasd_sfree_request(cqr, cqr->memdev);
2675 return rc; 2694 return rc;
2676} 2695}
2677 2696
@@ -2687,15 +2706,23 @@ dasd_eckd_reserve(struct dasd_device *device)
2687 struct dasd_ccw_req *cqr; 2706 struct dasd_ccw_req *cqr;
2688 int rc; 2707 int rc;
2689 struct ccw1 *ccw; 2708 struct ccw1 *ccw;
2709 int useglobal;
2690 2710
2691 if (!capable(CAP_SYS_ADMIN)) 2711 if (!capable(CAP_SYS_ADMIN))
2692 return -EACCES; 2712 return -EACCES;
2693 2713
2714 useglobal = 0;
2694 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); 2715 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
2695 if (IS_ERR(cqr)) { 2716 if (IS_ERR(cqr)) {
2696 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2717 mutex_lock(&dasd_reserve_mutex);
2697 "Could not allocate initialization request"); 2718 useglobal = 1;
2698 return PTR_ERR(cqr); 2719 cqr = &dasd_reserve_req->cqr;
2720 memset(cqr, 0, sizeof(*cqr));
2721 memset(&dasd_reserve_req->ccw, 0,
2722 sizeof(dasd_reserve_req->ccw));
2723 cqr->cpaddr = &dasd_reserve_req->ccw;
2724 cqr->data = &dasd_reserve_req->data;
2725 cqr->magic = DASD_ECKD_MAGIC;
2699 } 2726 }
2700 ccw = cqr->cpaddr; 2727 ccw = cqr->cpaddr;
2701 ccw->cmd_code = DASD_ECKD_CCW_RESERVE; 2728 ccw->cmd_code = DASD_ECKD_CCW_RESERVE;
@@ -2713,7 +2740,10 @@ dasd_eckd_reserve(struct dasd_device *device)
2713 2740
2714 rc = dasd_sleep_on_immediatly(cqr); 2741 rc = dasd_sleep_on_immediatly(cqr);
2715 2742
2716 dasd_sfree_request(cqr, cqr->memdev); 2743 if (useglobal)
2744 mutex_unlock(&dasd_reserve_mutex);
2745 else
2746 dasd_sfree_request(cqr, cqr->memdev);
2717 return rc; 2747 return rc;
2718} 2748}
2719 2749
@@ -2728,15 +2758,23 @@ dasd_eckd_steal_lock(struct dasd_device *device)
2728 struct dasd_ccw_req *cqr; 2758 struct dasd_ccw_req *cqr;
2729 int rc; 2759 int rc;
2730 struct ccw1 *ccw; 2760 struct ccw1 *ccw;
2761 int useglobal;
2731 2762
2732 if (!capable(CAP_SYS_ADMIN)) 2763 if (!capable(CAP_SYS_ADMIN))
2733 return -EACCES; 2764 return -EACCES;
2734 2765
2766 useglobal = 0;
2735 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); 2767 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
2736 if (IS_ERR(cqr)) { 2768 if (IS_ERR(cqr)) {
2737 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2769 mutex_lock(&dasd_reserve_mutex);
2738 "Could not allocate initialization request"); 2770 useglobal = 1;
2739 return PTR_ERR(cqr); 2771 cqr = &dasd_reserve_req->cqr;
2772 memset(cqr, 0, sizeof(*cqr));
2773 memset(&dasd_reserve_req->ccw, 0,
2774 sizeof(dasd_reserve_req->ccw));
2775 cqr->cpaddr = &dasd_reserve_req->ccw;
2776 cqr->data = &dasd_reserve_req->data;
2777 cqr->magic = DASD_ECKD_MAGIC;
2740 } 2778 }
2741 ccw = cqr->cpaddr; 2779 ccw = cqr->cpaddr;
2742 ccw->cmd_code = DASD_ECKD_CCW_SLCK; 2780 ccw->cmd_code = DASD_ECKD_CCW_SLCK;
@@ -2754,7 +2792,10 @@ dasd_eckd_steal_lock(struct dasd_device *device)
2754 2792
2755 rc = dasd_sleep_on_immediatly(cqr); 2793 rc = dasd_sleep_on_immediatly(cqr);
2756 2794
2757 dasd_sfree_request(cqr, cqr->memdev); 2795 if (useglobal)
2796 mutex_unlock(&dasd_reserve_mutex);
2797 else
2798 dasd_sfree_request(cqr, cqr->memdev);
2758 return rc; 2799 return rc;
2759} 2800}
2760 2801
@@ -3488,10 +3529,15 @@ dasd_eckd_init(void)
3488 int ret; 3529 int ret;
3489 3530
3490 ASCEBC(dasd_eckd_discipline.ebcname, 4); 3531 ASCEBC(dasd_eckd_discipline.ebcname, 4);
3532 dasd_reserve_req = kmalloc(sizeof(*dasd_reserve_req),
3533 GFP_KERNEL | GFP_DMA);
3534 if (!dasd_reserve_req)
3535 return -ENOMEM;
3491 ret = ccw_driver_register(&dasd_eckd_driver); 3536 ret = ccw_driver_register(&dasd_eckd_driver);
3492 if (!ret) 3537 if (!ret)
3493 wait_for_device_probe(); 3538 wait_for_device_probe();
3494 3539 else
3540 kfree(dasd_reserve_req);
3495 return ret; 3541 return ret;
3496} 3542}
3497 3543
@@ -3499,6 +3545,7 @@ static void __exit
3499dasd_eckd_cleanup(void) 3545dasd_eckd_cleanup(void)
3500{ 3546{
3501 ccw_driver_unregister(&dasd_eckd_driver); 3547 ccw_driver_unregister(&dasd_eckd_driver);
3548 kfree(dasd_reserve_req);
3502} 3549}
3503 3550
3504module_init(dasd_eckd_init); 3551module_init(dasd_eckd_init);