aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorStefan Haberland <stefan.haberland@de.ibm.com>2010-08-09 12:13:00 -0400
committerMartin Schwidefsky <sky@mschwide.boeblingen.de.ibm.com>2010-08-09 12:12:54 -0400
commit7c8faa86290c1a2607d6b768a0b874ec392a5c2a (patch)
tree7cb94efdbd3ce3c5eb8fb7a2b7d8a5bedebcb1a2 /drivers/s390
parentf932bcea6b7317312ab38df12a84710fc6c67a81 (diff)
[S390] dasd: tunable missing interrupt handler
This feature provides a user interface to specify the timeout for missing interrupts for standard I/O operations. Signed-off-by: Stefan Haberland <stefan.haberland@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'drivers/s390')
-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.c21
-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, 81 insertions, 9 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 0483b2e76b11..66360c24bd48 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -1115,8 +1115,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1115 struct dasd_eckd_private *private; 1115 struct dasd_eckd_private *private;
1116 struct dasd_block *block; 1116 struct dasd_block *block;
1117 struct dasd_uid temp_uid; 1117 struct dasd_uid temp_uid;
1118 int is_known, rc; 1118 int is_known, rc, i;
1119 int readonly; 1119 int readonly;
1120 unsigned long value;
1120 1121
1121 if (!ccw_device_is_pathgroup(device->cdev)) { 1122 if (!ccw_device_is_pathgroup(device->cdev)) {
1122 dev_warn(&device->cdev->dev, 1123 dev_warn(&device->cdev->dev,
@@ -1151,6 +1152,18 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
1151 if (rc) 1152 if (rc)
1152 goto out_err1; 1153 goto out_err1;
1153 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
1154 /* Generate device unique id */ 1167 /* Generate device unique id */
1155 rc = dasd_eckd_generate_uid(device); 1168 rc = dasd_eckd_generate_uid(device);
1156 if (rc) 1169 if (rc)
@@ -1981,7 +1994,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
1981 cqr->startdev = startdev; 1994 cqr->startdev = startdev;
1982 cqr->memdev = startdev; 1995 cqr->memdev = startdev;
1983 cqr->block = block; 1996 cqr->block = block;
1984 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 1997 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
1985 cqr->lpm = private->path_data.ppm; 1998 cqr->lpm = private->path_data.ppm;
1986 cqr->retries = 256; 1999 cqr->retries = 256;
1987 cqr->buildclk = get_clock(); 2000 cqr->buildclk = get_clock();
@@ -2158,7 +2171,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
2158 cqr->startdev = startdev; 2171 cqr->startdev = startdev;
2159 cqr->memdev = startdev; 2172 cqr->memdev = startdev;
2160 cqr->block = block; 2173 cqr->block = block;
2161 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 2174 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2162 cqr->lpm = private->path_data.ppm; 2175 cqr->lpm = private->path_data.ppm;
2163 cqr->retries = 256; 2176 cqr->retries = 256;
2164 cqr->buildclk = get_clock(); 2177 cqr->buildclk = get_clock();
@@ -2406,7 +2419,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
2406 cqr->startdev = startdev; 2419 cqr->startdev = startdev;
2407 cqr->memdev = startdev; 2420 cqr->memdev = startdev;
2408 cqr->block = block; 2421 cqr->block = block;
2409 cqr->expires = 5 * 60 * HZ; /* 5 minutes */ 2422 cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
2410 cqr->lpm = private->path_data.ppm; 2423 cqr->lpm = private->path_data.ppm;
2411 cqr->retries = 256; 2424 cqr->retries = 256;
2412 cqr->buildclk = get_clock(); 2425 cqr->buildclk = get_clock();
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 {