diff options
Diffstat (limited to 'drivers/s390/block/dasd_devmap.c')
-rw-r--r-- | drivers/s390/block/dasd_devmap.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index df17f0f9cb0f..620fab01b710 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -50,6 +50,7 @@ struct dasd_devmap { unsigned short features; struct dasd_device *device; struct dasd_copy_relation *copy; + unsigned int aq_mask; }; /* @@ -1476,6 +1477,128 @@ dasd_eer_store(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(eer_enabled, 0644, dasd_eer_show, dasd_eer_store); /* + * aq_mask controls if the DASD should be quiesced on certain triggers + * The aq_mask attribute is interpreted as bitmap of the DASD_EER_* triggers. + */ +static ssize_t dasd_aq_mask_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dasd_devmap *devmap; + unsigned int aq_mask = 0; + + devmap = dasd_find_busid(dev_name(dev)); + if (!IS_ERR(devmap)) + aq_mask = devmap->aq_mask; + + return sysfs_emit(buf, "%d\n", aq_mask); +} + +static ssize_t dasd_aq_mask_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dasd_devmap *devmap; + unsigned int val; + + if (kstrtouint(buf, 0, &val) || val > DASD_EER_VALID) + return -EINVAL; + + devmap = dasd_devmap_from_cdev(to_ccwdev(dev)); + if (IS_ERR(devmap)) + return PTR_ERR(devmap); + + spin_lock(&dasd_devmap_lock); + devmap->aq_mask = val; + if (devmap->device) + devmap->device->aq_mask = devmap->aq_mask; + spin_unlock(&dasd_devmap_lock); + + return count; +} + +static DEVICE_ATTR(aq_mask, 0644, dasd_aq_mask_show, dasd_aq_mask_store); + +/* + * aq_requeue controls if requests are returned to the blocklayer on quiesce + * or if requests are only not started + */ +static ssize_t dasd_aqr_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dasd_devmap *devmap; + int flag; + + devmap = dasd_find_busid(dev_name(dev)); + if (!IS_ERR(devmap)) + flag = (devmap->features & DASD_FEATURE_REQUEUEQUIESCE) != 0; + else + flag = (DASD_FEATURE_DEFAULT & + DASD_FEATURE_REQUEUEQUIESCE) != 0; + return sysfs_emit(buf, "%d\n", flag); +} + +static ssize_t dasd_aqr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + bool val; + int rc; + + if (kstrtobool(buf, &val)) + return -EINVAL; + + rc = dasd_set_feature(to_ccwdev(dev), DASD_FEATURE_REQUEUEQUIESCE, val); + + return rc ? : count; +} + +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 @@ -2324,6 +2447,9 @@ static struct attribute * dasd_attrs[] = { &dev_attr_copy_pair.attr, &dev_attr_copy_role.attr, &dev_attr_ping.attr, + &dev_attr_aq_mask.attr, + &dev_attr_aq_requeue.attr, + &dev_attr_aq_timeouts.attr, NULL, }; |