diff options
-rw-r--r-- | drivers/s390/block/dasd.c | 11 | ||||
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 47 | ||||
-rw-r--r-- | drivers/s390/block/dasd_eckd.c | 1 | ||||
-rw-r--r-- | drivers/s390/block/dasd_int.h | 1 |
4 files changed, 60 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 8186473b9aa7..1bfd0e17a4dc 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -1954,6 +1954,16 @@ static void __dasd_device_process_final_queue(struct dasd_device *device, } /* + * check if device should be autoquiesced due to too many timeouts + */ +static void __dasd_device_check_autoquiesce_timeout(struct dasd_device *device, + struct dasd_ccw_req *cqr) +{ + if ((device->default_retries - cqr->retries) >= device->aq_timeouts) + dasd_handle_autoquiesce(device, cqr, DASD_EER_TIMEOUTS); +} + +/* * Take a look at the first request on the ccw queue and check * if it reached its expire time. If so, terminate the IO. */ @@ -1987,6 +1997,7 @@ static void __dasd_device_check_expire(struct dasd_device *device) "remaining\n", cqr, (cqr->expires/HZ), cqr->retries); } + __dasd_device_check_autoquiesce_timeout(device, cqr); } } diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index 95c7959c7949..620fab01b710 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -1553,6 +1553,52 @@ static ssize_t dasd_aqr_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(aq_requeue, 0644, dasd_aqr_show, dasd_aqr_store); /* + * aq_timeouts controls how much retries have to time out until + * a device gets autoquiesced + */ +static ssize_t +dasd_aq_timeouts_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 = sysfs_emit(buf, "%u\n", device->aq_timeouts); + dasd_put_device(device); + return len; +} + +static ssize_t +dasd_aq_timeouts_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dasd_device *device; + unsigned int val; + + device = dasd_device_from_cdev(to_ccwdev(dev)); + if (IS_ERR(device)) + return -ENODEV; + + if ((kstrtouint(buf, 10, &val) != 0) || + val > DASD_RETRIES_MAX || val == 0) { + dasd_put_device(device); + return -EINVAL; + } + + if (val) + device->aq_timeouts = val; + + dasd_put_device(device); + return count; +} + +static DEVICE_ATTR(aq_timeouts, 0644, dasd_aq_timeouts_show, + dasd_aq_timeouts_store); + +/* * expiration time for default requests */ static ssize_t @@ -2403,6 +2449,7 @@ static struct attribute * dasd_attrs[] = { &dev_attr_ping.attr, &dev_attr_aq_mask.attr, &dev_attr_aq_requeue.attr, + &dev_attr_aq_timeouts.attr, NULL, }; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 1a69f97e88fb..ade1369fe5ed 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -2109,6 +2109,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) device->default_retries = DASD_RETRIES; device->path_thrhld = DASD_ECKD_PATH_THRHLD; device->path_interval = DASD_ECKD_PATH_INTERVAL; + device->aq_timeouts = DASD_RETRIES_MAX; if (private->conf.gneq) { value = 1; diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index c4633a4aeeb1..33f812f0e515 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -638,6 +638,7 @@ struct dasd_device { struct kset *paths_info; struct dasd_copy_relation *copy; unsigned long aq_mask; + unsigned int aq_timeouts; }; struct dasd_block { |