aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/block
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 17:01:26 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-08-10 17:01:26 -0400
commit0d6ffdb8f151a2b685c7b45bde7ab2d49fc1bb00 (patch)
tree1768c906e87750dc897a2f113e335886d9b906e8 /drivers/s390/block
parent7233e392760b3493095d3d5885cb15e44493d74a (diff)
parent7c8faa86290c1a2607d6b768a0b874ec392a5c2a (diff)
Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6: [S390] dasd: tunable missing interrupt handler [S390] dasd: allocate fallback cqr for reserve/release [S390] topology: use default MC domain initializer [S390] initrd: change default load address [S390] cmm, smsgiucv_app: convert sender to uppercase [S390] cmm: add missing __init/__exit annotations [S390] cio: use all available paths for some internal I/O [S390] ccwreq: add ability to use all paths [S390] cio: ccw_device_online_store return -EINVAL in case of missing driver [S390] cio: Log the response from the unit check handler [S390] cio: CHSC SIOSL Support
Diffstat (limited to 'drivers/s390/block')
-rw-r--r--drivers/s390/block/dasd_devmap.c44
-rw-r--r--drivers/s390/block/dasd_diag.c6
-rw-r--r--drivers/s390/block/dasd_eckd.c94
-rw-r--r--drivers/s390/block/dasd_eckd.h7
-rw-r--r--drivers/s390/block/dasd_fba.c4
-rw-r--r--drivers/s390/block/dasd_int.h8
6 files changed, 141 insertions, 22 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c
index bed7b4634ccd..8d41f3ed38d7 100644
--- a/drivers/s390/block/dasd_devmap.c
+++ b/drivers/s390/block/dasd_devmap.c
@@ -1083,6 +1083,49 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr,
1083 1083
1084static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); 1084static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
1085 1085
1086/*
1087 * expiration time for default requests
1088 */
1089static ssize_t
1090dasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf)
1091{
1092 struct dasd_device *device;
1093 int len;
1094
1095 device = dasd_device_from_cdev(to_ccwdev(dev));
1096 if (IS_ERR(device))
1097 return -ENODEV;
1098 len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires);
1099 dasd_put_device(device);
1100 return len;
1101}
1102
1103static ssize_t
1104dasd_expires_store(struct device *dev, struct device_attribute *attr,
1105 const char *buf, size_t count)
1106{
1107 struct dasd_device *device;
1108 unsigned long val;
1109
1110 device = dasd_device_from_cdev(to_ccwdev(dev));
1111 if (IS_ERR(device))
1112 return -ENODEV;
1113
1114 if ((strict_strtoul(buf, 10, &val) != 0) ||
1115 (val > DASD_EXPIRES_MAX) || val == 0) {
1116 dasd_put_device(device);
1117 return -EINVAL;
1118 }
1119
1120 if (val)
1121 device->default_expires = val;
1122
1123 dasd_put_device(device);
1124 return count;
1125}
1126
1127static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store);
1128
1086static struct attribute * dasd_attrs[] = { 1129static struct attribute * dasd_attrs[] = {
1087 &dev_attr_readonly.attr, 1130 &dev_attr_readonly.attr,
1088 &dev_attr_discipline.attr, 1131 &dev_attr_discipline.attr,
@@ -1094,6 +1137,7 @@ static struct attribute * dasd_attrs[] = {
1094 &dev_attr_eer_enabled.attr, 1137 &dev_attr_eer_enabled.attr,
1095 &dev_attr_erplog.attr, 1138 &dev_attr_erplog.attr,
1096 &dev_attr_failfast.attr, 1139 &dev_attr_failfast.attr,
1140 &dev_attr_expires.attr,
1097 NULL, 1141 NULL,
1098}; 1142};
1099 1143
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 687f323cdc38..2b3bc3ec0541 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL");
43 sizeof(struct dasd_diag_req)) / \ 43 sizeof(struct dasd_diag_req)) / \
44 sizeof(struct dasd_diag_bio)) / 2) 44 sizeof(struct dasd_diag_bio)) / 2)
45#define DIAG_MAX_RETRIES 32 45#define DIAG_MAX_RETRIES 32
46#define DIAG_TIMEOUT 50 * HZ 46#define DIAG_TIMEOUT 50
47 47
48static struct dasd_discipline dasd_diag_discipline; 48static struct dasd_discipline dasd_diag_discipline;
49 49
@@ -360,6 +360,8 @@ dasd_diag_check_device(struct dasd_device *device)
360 goto out; 360 goto out;
361 } 361 }
362 362
363 device->default_expires = DIAG_TIMEOUT;
364
363 /* Figure out position of label block */ 365 /* Figure out position of label block */
364 switch (private->rdc_data.vdev_class) { 366 switch (private->rdc_data.vdev_class) {
365 case DEV_CLASS_FBA: 367 case DEV_CLASS_FBA:
@@ -563,7 +565,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
563 cqr->startdev = memdev; 565 cqr->startdev = memdev;
564 cqr->memdev = memdev; 566 cqr->memdev = memdev;
565 cqr->block = block; 567 cqr->block = block;
566 cqr->expires = DIAG_TIMEOUT; 568 cqr->expires = memdev->default_expires * HZ;
567 cqr->status = DASD_CQR_FILLED; 569 cqr->status = DASD_CQR_FILLED;
568 return cqr; 570 return cqr;
569} 571}
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index ab84da5592e8..66360c24bd48 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 */
@@ -1107,8 +1115,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1107 struct dasd_eckd_private *private; 1115 struct dasd_eckd_private *private;
1108 struct dasd_block *block; 1116 struct dasd_block *block;
1109 struct dasd_uid temp_uid; 1117 struct dasd_uid temp_uid;
1110 int is_known, rc; 1118 int is_known, rc, i;
1111 int readonly; 1119 int readonly;
1120 unsigned long value;
1112 1121
1113 if (!ccw_device_is_pathgroup(device->cdev)) { 1122 if (!ccw_device_is_pathgroup(device->cdev)) {
1114 dev_warn(&device->cdev->dev, 1123 dev_warn(&device->cdev->dev,
@@ -1143,6 +1152,18 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1143 if (rc) 1152 if (rc)
1144 goto out_err1; 1153 goto out_err1;
1145 1154
1155 /* set default timeout */
1156 device->default_expires = DASD_EXPIRES;
1157 if (private->gneq) {
1158 value = 1;
1159 for (i = 0; i < private->gneq->timeout.value; i++)
1160 value = 10 * value;
1161 value = value * private->gneq->timeout.number;
1162 /* do not accept useless values */
1163 if (value != 0 && value <= DASD_EXPIRES_MAX)
1164 device->default_expires = value;
1165 }
1166
1146 /* Generate device unique id */ 1167 /* Generate device unique id */
1147 rc = dasd_eckd_generate_uid(device); 1168 rc = dasd_eckd_generate_uid(device);
1148 if (rc) 1169 if (rc)
@@ -1973,7 +1994,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
1973 cqr->startdev = startdev; 1994 cqr->startdev = startdev;
1974 cqr->memdev = startdev; 1995 cqr->memdev = startdev;
1975 cqr->block = block; 1996 cqr->block = block;
1976 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 1997 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
1977 cqr->lpm = private->path_data.ppm; 1998 cqr->lpm = private->path_data.ppm;
1978 cqr->retries = 256; 1999 cqr->retries = 256;
1979 cqr->buildclk = get_clock(); 2000 cqr->buildclk = get_clock();
@@ -2150,7 +2171,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
2150 cqr->startdev = startdev; 2171 cqr->startdev = startdev;
2151 cqr->memdev = startdev; 2172 cqr->memdev = startdev;
2152 cqr->block = block; 2173 cqr->block = block;
2153 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 2174 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2154 cqr->lpm = private->path_data.ppm; 2175 cqr->lpm = private->path_data.ppm;
2155 cqr->retries = 256; 2176 cqr->retries = 256;
2156 cqr->buildclk = get_clock(); 2177 cqr->buildclk = get_clock();
@@ -2398,7 +2419,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
2398 cqr->startdev = startdev; 2419 cqr->startdev = startdev;
2399 cqr->memdev = startdev; 2420 cqr->memdev = startdev;
2400 cqr->block = block; 2421 cqr->block = block;
2401 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 2422 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2402 cqr->lpm = private->path_data.ppm; 2423 cqr->lpm = private->path_data.ppm;
2403 cqr->retries = 256; 2424 cqr->retries = 256;
2404 cqr->buildclk = get_clock(); 2425 cqr->buildclk = get_clock();
@@ -2645,15 +2666,23 @@ dasd_eckd_release(struct dasd_device *device)
2645 struct dasd_ccw_req *cqr; 2666 struct dasd_ccw_req *cqr;
2646 int rc; 2667 int rc;
2647 struct ccw1 *ccw; 2668 struct ccw1 *ccw;
2669 int useglobal;
2648 2670
2649 if (!capable(CAP_SYS_ADMIN)) 2671 if (!capable(CAP_SYS_ADMIN))
2650 return -EACCES; 2672 return -EACCES;
2651 2673
2674 useglobal = 0;
2652 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); 2675 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
2653 if (IS_ERR(cqr)) { 2676 if (IS_ERR(cqr)) {
2654 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2677 mutex_lock(&dasd_reserve_mutex);
2655 "Could not allocate initialization request"); 2678 useglobal = 1;
2656 return PTR_ERR(cqr); 2679 cqr = &dasd_reserve_req->cqr;
2680 memset(cqr, 0, sizeof(*cqr));
2681 memset(&dasd_reserve_req->ccw, 0,
2682 sizeof(dasd_reserve_req->ccw));
2683 cqr->cpaddr = &dasd_reserve_req->ccw;
2684 cqr->data = &dasd_reserve_req->data;
2685 cqr->magic = DASD_ECKD_MAGIC;
2657 } 2686 }
2658 ccw = cqr->cpaddr; 2687 ccw = cqr->cpaddr;
2659 ccw->cmd_code = DASD_ECKD_CCW_RELEASE; 2688 ccw->cmd_code = DASD_ECKD_CCW_RELEASE;
@@ -2671,7 +2700,10 @@ dasd_eckd_release(struct dasd_device *device)
2671 2700
2672 rc = dasd_sleep_on_immediatly(cqr); 2701 rc = dasd_sleep_on_immediatly(cqr);
2673 2702
2674 dasd_sfree_request(cqr, cqr->memdev); 2703 if (useglobal)
2704 mutex_unlock(&dasd_reserve_mutex);
2705 else
2706 dasd_sfree_request(cqr, cqr->memdev);
2675 return rc; 2707 return rc;
2676} 2708}
2677 2709
@@ -2687,15 +2719,23 @@ dasd_eckd_reserve(struct dasd_device *device)
2687 struct dasd_ccw_req *cqr; 2719 struct dasd_ccw_req *cqr;
2688 int rc; 2720 int rc;
2689 struct ccw1 *ccw; 2721 struct ccw1 *ccw;
2722 int useglobal;
2690 2723
2691 if (!capable(CAP_SYS_ADMIN)) 2724 if (!capable(CAP_SYS_ADMIN))
2692 return -EACCES; 2725 return -EACCES;
2693 2726
2727 useglobal = 0;
2694 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); 2728 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
2695 if (IS_ERR(cqr)) { 2729 if (IS_ERR(cqr)) {
2696 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2730 mutex_lock(&dasd_reserve_mutex);
2697 "Could not allocate initialization request"); 2731 useglobal = 1;
2698 return PTR_ERR(cqr); 2732 cqr = &dasd_reserve_req->cqr;
2733 memset(cqr, 0, sizeof(*cqr));
2734 memset(&dasd_reserve_req->ccw, 0,
2735 sizeof(dasd_reserve_req->ccw));
2736 cqr->cpaddr = &dasd_reserve_req->ccw;
2737 cqr->data = &dasd_reserve_req->data;
2738 cqr->magic = DASD_ECKD_MAGIC;
2699 } 2739 }
2700 ccw = cqr->cpaddr; 2740 ccw = cqr->cpaddr;
2701 ccw->cmd_code = DASD_ECKD_CCW_RESERVE; 2741 ccw->cmd_code = DASD_ECKD_CCW_RESERVE;
@@ -2713,7 +2753,10 @@ dasd_eckd_reserve(struct dasd_device *device)
2713 2753
2714 rc = dasd_sleep_on_immediatly(cqr); 2754 rc = dasd_sleep_on_immediatly(cqr);
2715 2755
2716 dasd_sfree_request(cqr, cqr->memdev); 2756 if (useglobal)
2757 mutex_unlock(&dasd_reserve_mutex);
2758 else
2759 dasd_sfree_request(cqr, cqr->memdev);
2717 return rc; 2760 return rc;
2718} 2761}
2719 2762
@@ -2728,15 +2771,23 @@ dasd_eckd_steal_lock(struct dasd_device *device)
2728 struct dasd_ccw_req *cqr; 2771 struct dasd_ccw_req *cqr;
2729 int rc; 2772 int rc;
2730 struct ccw1 *ccw; 2773 struct ccw1 *ccw;
2774 int useglobal;
2731 2775
2732 if (!capable(CAP_SYS_ADMIN)) 2776 if (!capable(CAP_SYS_ADMIN))
2733 return -EACCES; 2777 return -EACCES;
2734 2778
2779 useglobal = 0;
2735 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); 2780 cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device);
2736 if (IS_ERR(cqr)) { 2781 if (IS_ERR(cqr)) {
2737 DBF_DEV_EVENT(DBF_WARNING, device, "%s", 2782 mutex_lock(&dasd_reserve_mutex);
2738 "Could not allocate initialization request"); 2783 useglobal = 1;
2739 return PTR_ERR(cqr); 2784 cqr = &dasd_reserve_req->cqr;
2785 memset(cqr, 0, sizeof(*cqr));
2786 memset(&dasd_reserve_req->ccw, 0,
2787 sizeof(dasd_reserve_req->ccw));
2788 cqr->cpaddr = &dasd_reserve_req->ccw;
2789 cqr->data = &dasd_reserve_req->data;
2790 cqr->magic = DASD_ECKD_MAGIC;
2740 } 2791 }
2741 ccw = cqr->cpaddr; 2792 ccw = cqr->cpaddr;
2742 ccw->cmd_code = DASD_ECKD_CCW_SLCK; 2793 ccw->cmd_code = DASD_ECKD_CCW_SLCK;
@@ -2754,7 +2805,10 @@ dasd_eckd_steal_lock(struct dasd_device *device)
2754 2805
2755 rc = dasd_sleep_on_immediatly(cqr); 2806 rc = dasd_sleep_on_immediatly(cqr);
2756 2807
2757 dasd_sfree_request(cqr, cqr->memdev); 2808 if (useglobal)
2809 mutex_unlock(&dasd_reserve_mutex);
2810 else
2811 dasd_sfree_request(cqr, cqr->memdev);
2758 return rc; 2812 return rc;
2759} 2813}
2760 2814
@@ -3488,10 +3542,15 @@ dasd_eckd_init(void)
3488 int ret; 3542 int ret;
3489 3543
3490 ASCEBC(dasd_eckd_discipline.ebcname, 4); 3544 ASCEBC(dasd_eckd_discipline.ebcname, 4);
3545 dasd_reserve_req = kmalloc(sizeof(*dasd_reserve_req),
3546 GFP_KERNEL | GFP_DMA);
3547 if (!dasd_reserve_req)
3548 return -ENOMEM;
3491 ret = ccw_driver_register(&dasd_eckd_driver); 3549 ret = ccw_driver_register(&dasd_eckd_driver);
3492 if (!ret) 3550 if (!ret)
3493 wait_for_device_probe(); 3551 wait_for_device_probe();
3494 3552 else
3553 kfree(dasd_reserve_req);
3495 return ret; 3554 return ret;
3496} 3555}
3497 3556
@@ -3499,6 +3558,7 @@ static void __exit
3499dasd_eckd_cleanup(void) 3558dasd_eckd_cleanup(void)
3500{ 3559{
3501 ccw_driver_unregister(&dasd_eckd_driver); 3560 ccw_driver_unregister(&dasd_eckd_driver);
3561 kfree(dasd_reserve_req);
3502} 3562}
3503 3563
3504module_init(dasd_eckd_init); 3564module_init(dasd_eckd_init);
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h
index dd6385a5af14..0eb49655a6cd 100644
--- a/drivers/s390/block/dasd_eckd.h
+++ b/drivers/s390/block/dasd_eckd.h
@@ -320,7 +320,12 @@ struct dasd_gneq {
320 __u8 identifier:2; 320 __u8 identifier:2;
321 __u8 reserved:6; 321 __u8 reserved:6;
322 } __attribute__ ((packed)) flags; 322 } __attribute__ ((packed)) flags;
323 __u8 reserved[7]; 323 __u8 reserved[5];
324 struct {
325 __u8 value:2;
326 __u8 number:6;
327 } __attribute__ ((packed)) timeout;
328 __u8 reserved3;
324 __u16 subsystemID; 329 __u16 subsystemID;
325 __u8 reserved2[22]; 330 __u8 reserved2[22];
326} __attribute__ ((packed)); 331} __attribute__ ((packed));
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index 37282b90eecc..bec5486e0e6d 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -163,6 +163,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
163 return rc; 163 return rc;
164 } 164 }
165 165
166 device->default_expires = DASD_EXPIRES;
167
166 readonly = dasd_device_is_ro(device); 168 readonly = dasd_device_is_ro(device);
167 if (readonly) 169 if (readonly)
168 set_bit(DASD_FLAG_DEVICE_RO, &device->flags); 170 set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
@@ -370,7 +372,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
370 cqr->startdev = memdev; 372 cqr->startdev = memdev;
371 cqr->memdev = memdev; 373 cqr->memdev = memdev;
372 cqr->block = block; 374 cqr->block = block;
373 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 375 cqr->expires = memdev->default_expires * HZ; /* default 5 minutes */
374 cqr->retries = 32; 376 cqr->retries = 32;
375 cqr->buildclk = get_clock(); 377 cqr->buildclk = get_clock();
376 cqr->status = DASD_CQR_FILLED; 378 cqr->status = DASD_CQR_FILLED;
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h
index 49b431d135e0..500678d7116c 100644
--- a/drivers/s390/block/dasd_int.h
+++ b/drivers/s390/block/dasd_int.h
@@ -186,7 +186,7 @@ struct dasd_ccw_req {
186 186
187 /* ... and how */ 187 /* ... and how */
188 unsigned long starttime; /* jiffies time of request start */ 188 unsigned long starttime; /* jiffies time of request start */
189 int expires; /* expiration period in jiffies */ 189 unsigned long expires; /* expiration period in jiffies */
190 char lpm; /* logical path mask */ 190 char lpm; /* logical path mask */
191 void *data; /* pointer to data area */ 191 void *data; /* pointer to data area */
192 192
@@ -224,6 +224,9 @@ struct dasd_ccw_req {
224#define DASD_CQR_CLEARED 0x84 /* request was cleared */ 224#define DASD_CQR_CLEARED 0x84 /* request was cleared */
225#define DASD_CQR_SUCCESS 0x85 /* request was successful */ 225#define DASD_CQR_SUCCESS 0x85 /* request was successful */
226 226
227/* default expiration time*/
228#define DASD_EXPIRES 300
229#define DASD_EXPIRES_MAX 40000000
227 230
228/* per dasd_ccw_req flags */ 231/* per dasd_ccw_req flags */
229#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ 232#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
@@ -404,6 +407,9 @@ struct dasd_device {
404 407
405 /* hook for alias management */ 408 /* hook for alias management */
406 struct list_head alias_list; 409 struct list_head alias_list;
410
411 /* default expiration time in s */
412 unsigned long default_expires;
407}; 413};
408 414
409struct dasd_block { 415struct dasd_block {