提交 7c8faa86 编写于 作者: S Stefan Haberland 提交者: Martin Schwidefsky

[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: NStefan Haberland <stefan.haberland@de.ibm.com>
Signed-off-by: NMartin Schwidefsky <schwidefsky@de.ibm.com>
上级 f932bcea
...@@ -1083,6 +1083,49 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, ...@@ -1083,6 +1083,49 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store);
/*
* expiration time for default requests
*/
static ssize_t
dasd_expires_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct dasd_device *device;
int len;
device = dasd_device_from_cdev(to_ccwdev(dev));
if (IS_ERR(device))
return -ENODEV;
len = snprintf(buf, PAGE_SIZE, "%lu\n", device->default_expires);
dasd_put_device(device);
return len;
}
static ssize_t
dasd_expires_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dasd_device *device;
unsigned long val;
device = dasd_device_from_cdev(to_ccwdev(dev));
if (IS_ERR(device))
return -ENODEV;
if ((strict_strtoul(buf, 10, &val) != 0) ||
(val > DASD_EXPIRES_MAX) || val == 0) {
dasd_put_device(device);
return -EINVAL;
}
if (val)
device->default_expires = val;
dasd_put_device(device);
return count;
}
static DEVICE_ATTR(expires, 0644, dasd_expires_show, dasd_expires_store);
static struct attribute * dasd_attrs[] = { static struct attribute * dasd_attrs[] = {
&dev_attr_readonly.attr, &dev_attr_readonly.attr,
&dev_attr_discipline.attr, &dev_attr_discipline.attr,
...@@ -1094,6 +1137,7 @@ static struct attribute * dasd_attrs[] = { ...@@ -1094,6 +1137,7 @@ static struct attribute * dasd_attrs[] = {
&dev_attr_eer_enabled.attr, &dev_attr_eer_enabled.attr,
&dev_attr_erplog.attr, &dev_attr_erplog.attr,
&dev_attr_failfast.attr, &dev_attr_failfast.attr,
&dev_attr_expires.attr,
NULL, NULL,
}; };
......
...@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL"); ...@@ -43,7 +43,7 @@ MODULE_LICENSE("GPL");
sizeof(struct dasd_diag_req)) / \ sizeof(struct dasd_diag_req)) / \
sizeof(struct dasd_diag_bio)) / 2) sizeof(struct dasd_diag_bio)) / 2)
#define DIAG_MAX_RETRIES 32 #define DIAG_MAX_RETRIES 32
#define DIAG_TIMEOUT 50 * HZ #define DIAG_TIMEOUT 50
static struct dasd_discipline dasd_diag_discipline; static struct dasd_discipline dasd_diag_discipline;
...@@ -360,6 +360,8 @@ dasd_diag_check_device(struct dasd_device *device) ...@@ -360,6 +360,8 @@ dasd_diag_check_device(struct dasd_device *device)
goto out; goto out;
} }
device->default_expires = DIAG_TIMEOUT;
/* Figure out position of label block */ /* Figure out position of label block */
switch (private->rdc_data.vdev_class) { switch (private->rdc_data.vdev_class) {
case DEV_CLASS_FBA: case DEV_CLASS_FBA:
...@@ -563,7 +565,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, ...@@ -563,7 +565,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev,
cqr->startdev = memdev; cqr->startdev = memdev;
cqr->memdev = memdev; cqr->memdev = memdev;
cqr->block = block; cqr->block = block;
cqr->expires = DIAG_TIMEOUT; cqr->expires = memdev->default_expires * HZ;
cqr->status = DASD_CQR_FILLED; cqr->status = DASD_CQR_FILLED;
return cqr; return cqr;
} }
......
...@@ -1115,8 +1115,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) ...@@ -1115,8 +1115,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
struct dasd_eckd_private *private; struct dasd_eckd_private *private;
struct dasd_block *block; struct dasd_block *block;
struct dasd_uid temp_uid; struct dasd_uid temp_uid;
int is_known, rc; int is_known, rc, i;
int readonly; int readonly;
unsigned long value;
if (!ccw_device_is_pathgroup(device->cdev)) { if (!ccw_device_is_pathgroup(device->cdev)) {
dev_warn(&device->cdev->dev, dev_warn(&device->cdev->dev,
...@@ -1151,6 +1152,18 @@ dasd_eckd_check_characteristics(struct dasd_device *device) ...@@ -1151,6 +1152,18 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
if (rc) if (rc)
goto out_err1; goto out_err1;
/* set default timeout */
device->default_expires = DASD_EXPIRES;
if (private->gneq) {
value = 1;
for (i = 0; i < private->gneq->timeout.value; i++)
value = 10 * value;
value = value * private->gneq->timeout.number;
/* do not accept useless values */
if (value != 0 && value <= DASD_EXPIRES_MAX)
device->default_expires = value;
}
/* Generate device unique id */ /* Generate device unique id */
rc = dasd_eckd_generate_uid(device); rc = dasd_eckd_generate_uid(device);
if (rc) if (rc)
...@@ -1981,7 +1994,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( ...@@ -1981,7 +1994,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single(
cqr->startdev = startdev; cqr->startdev = startdev;
cqr->memdev = startdev; cqr->memdev = startdev;
cqr->block = block; cqr->block = block;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */ cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
cqr->lpm = private->path_data.ppm; cqr->lpm = private->path_data.ppm;
cqr->retries = 256; cqr->retries = 256;
cqr->buildclk = get_clock(); cqr->buildclk = get_clock();
...@@ -2158,7 +2171,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( ...@@ -2158,7 +2171,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track(
cqr->startdev = startdev; cqr->startdev = startdev;
cqr->memdev = startdev; cqr->memdev = startdev;
cqr->block = block; cqr->block = block;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */ cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
cqr->lpm = private->path_data.ppm; cqr->lpm = private->path_data.ppm;
cqr->retries = 256; cqr->retries = 256;
cqr->buildclk = get_clock(); cqr->buildclk = get_clock();
...@@ -2406,7 +2419,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( ...@@ -2406,7 +2419,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track(
cqr->startdev = startdev; cqr->startdev = startdev;
cqr->memdev = startdev; cqr->memdev = startdev;
cqr->block = block; cqr->block = block;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */ cqr->expires = startdev->default_expires * HZ; /* default 5 minutes */
cqr->lpm = private->path_data.ppm; cqr->lpm = private->path_data.ppm;
cqr->retries = 256; cqr->retries = 256;
cqr->buildclk = get_clock(); cqr->buildclk = get_clock();
......
...@@ -320,7 +320,12 @@ struct dasd_gneq { ...@@ -320,7 +320,12 @@ struct dasd_gneq {
__u8 identifier:2; __u8 identifier:2;
__u8 reserved:6; __u8 reserved:6;
} __attribute__ ((packed)) flags; } __attribute__ ((packed)) flags;
__u8 reserved[7]; __u8 reserved[5];
struct {
__u8 value:2;
__u8 number:6;
} __attribute__ ((packed)) timeout;
__u8 reserved3;
__u16 subsystemID; __u16 subsystemID;
__u8 reserved2[22]; __u8 reserved2[22];
} __attribute__ ((packed)); } __attribute__ ((packed));
......
...@@ -163,6 +163,8 @@ dasd_fba_check_characteristics(struct dasd_device *device) ...@@ -163,6 +163,8 @@ dasd_fba_check_characteristics(struct dasd_device *device)
return rc; return rc;
} }
device->default_expires = DASD_EXPIRES;
readonly = dasd_device_is_ro(device); readonly = dasd_device_is_ro(device);
if (readonly) if (readonly)
set_bit(DASD_FLAG_DEVICE_RO, &device->flags); 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,7 +372,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev,
cqr->startdev = memdev; cqr->startdev = memdev;
cqr->memdev = memdev; cqr->memdev = memdev;
cqr->block = block; cqr->block = block;
cqr->expires = 5 * 60 * HZ; /* 5 minutes */ cqr->expires = memdev->default_expires * HZ; /* default 5 minutes */
cqr->retries = 32; cqr->retries = 32;
cqr->buildclk = get_clock(); cqr->buildclk = get_clock();
cqr->status = DASD_CQR_FILLED; cqr->status = DASD_CQR_FILLED;
......
...@@ -186,7 +186,7 @@ struct dasd_ccw_req { ...@@ -186,7 +186,7 @@ struct dasd_ccw_req {
/* ... and how */ /* ... and how */
unsigned long starttime; /* jiffies time of request start */ unsigned long starttime; /* jiffies time of request start */
int expires; /* expiration period in jiffies */ unsigned long expires; /* expiration period in jiffies */
char lpm; /* logical path mask */ char lpm; /* logical path mask */
void *data; /* pointer to data area */ void *data; /* pointer to data area */
...@@ -224,6 +224,9 @@ struct dasd_ccw_req { ...@@ -224,6 +224,9 @@ struct dasd_ccw_req {
#define DASD_CQR_CLEARED 0x84 /* request was cleared */ #define DASD_CQR_CLEARED 0x84 /* request was cleared */
#define DASD_CQR_SUCCESS 0x85 /* request was successful */ #define DASD_CQR_SUCCESS 0x85 /* request was successful */
/* default expiration time*/
#define DASD_EXPIRES 300
#define DASD_EXPIRES_MAX 40000000
/* per dasd_ccw_req flags */ /* per dasd_ccw_req flags */
#define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */ #define DASD_CQR_FLAGS_USE_ERP 0 /* use ERP for this request */
...@@ -404,6 +407,9 @@ struct dasd_device { ...@@ -404,6 +407,9 @@ struct dasd_device {
/* hook for alias management */ /* hook for alias management */
struct list_head alias_list; struct list_head alias_list;
/* default expiration time in s */
unsigned long default_expires;
}; };
struct dasd_block { struct dasd_block {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册