@@ -19,9 +19,6 @@
#include "zfcp_ext.h"
#include "zfcp_def.h"
-/* Max age of data in a diagnostics buffer before it needs a refresh (in ms). */
-#define ZFCP_DIAG_MAX_AGE (5 * 1000)
-
static DECLARE_WAIT_QUEUE_HEAD(__zfcp_diag_publish_wait);
/**
@@ -38,9 +35,6 @@ static DECLARE_WAIT_QUEUE_HEAD(__zfcp_diag_publish_wait);
*/
int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
{
- /* set the timestamp so that the first test on age will always fail */
- const unsigned long initial_timestamp =
- jiffies - msecs_to_jiffies(ZFCP_DIAG_MAX_AGE);
struct zfcp_diag_adapter *diag;
struct zfcp_diag_header *hdr;
@@ -48,13 +42,16 @@ int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
if (diag == NULL)
return -ENOMEM;
+ diag->max_age = (5 * 1000); /* default value: 5 s */
+
/* setup header for port_data */
hdr = &diag->port_data.header;
spin_lock_init(&hdr->access_lock);
hdr->buffer = &diag->port_data.data;
hdr->buffer_size = sizeof(diag->port_data.data);
- hdr->timestamp = initial_timestamp;
+ /* set the timestamp so that the first test on age will always fail */
+ hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
/* setup header for config_data */
hdr = &diag->config_data.header;
@@ -62,7 +59,8 @@ int zfcp_diag_adapter_setup(struct zfcp_adapter *const adapter)
spin_lock_init(&hdr->access_lock);
hdr->buffer = &diag->config_data.data;
hdr->buffer_size = sizeof(diag->config_data.data);
- hdr->timestamp = initial_timestamp;
+ /* set the timestamp so that the first test on age will always fail */
+ hdr->timestamp = jiffies - msecs_to_jiffies(diag->max_age);
adapter->diagnostics = diag;
return 0;
@@ -240,7 +238,8 @@ static int __zfcp_diag_update_buffer(struct zfcp_adapter *const adapter,
}
static bool
-__zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_header *const hdr)
+__zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_adapter *const diag,
+ const struct zfcp_diag_header *const hdr)
__must_hold(hdr->access_lock)
{
const unsigned long now = jiffies;
@@ -252,7 +251,7 @@ __zfcp_diag_test_buffer_age_isfresh(const struct zfcp_diag_header *const hdr)
if (!time_after_eq(now, hdr->timestamp))
return false;
- if (jiffies_to_msecs(now - hdr->timestamp) >= ZFCP_DIAG_MAX_AGE)
+ if (jiffies_to_msecs(now - hdr->timestamp) >= diag->max_age)
return false;
return true;
@@ -291,7 +290,9 @@ int zfcp_diag_update_buffer_limited(struct zfcp_adapter *const adapter,
spin_lock_irqsave(&hdr->access_lock, flags);
- for (rc = 0; !__zfcp_diag_test_buffer_age_isfresh(hdr); rc = 0) {
+ for (rc = 0;
+ !__zfcp_diag_test_buffer_age_isfresh(adapter->diagnostics, hdr);
+ rc = 0) {
rc = __zfcp_diag_update_buffer(adapter, hdr, buffer_update,
&flags);
if (rc != -EAGAIN)
@@ -42,6 +42,8 @@ struct zfcp_diag_header {
* adapter.
* @sysfs_established: flag showing that the associated sysfs-group was created
* during run of zfcp_adapter_enqueue().
+ * @max_age: maximum age of data in diagnostic buffers before they need to be
+ * refreshed (in ms).
* @port_data: data retrieved using exchange port data.
* @port_data.header: header with metadata for the cache in @port_data.data.
* @port_data.data: cached QTCB Bottom of command exchange port data.
@@ -52,6 +54,8 @@ struct zfcp_diag_header {
struct zfcp_diag_adapter {
u64 sysfs_established :1;
+ unsigned long max_age;
+
struct {
struct zfcp_diag_header header;
struct fsf_qtcb_bottom_port data;
@@ -326,6 +326,50 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev,
static ZFCP_DEV_ATTR(adapter, port_remove, S_IWUSR, NULL,
zfcp_sysfs_port_remove_store);
+static ssize_t
+zfcp_sysfs_adapter_diag_max_age_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
+ ssize_t rc;
+
+ if (!adapter)
+ return -ENODEV;
+
+ /* ceil(log(2^64 - 1) / log(10)) = 20 */
+ rc = scnprintf(buf, 20 + 2, "%lu\n", adapter->diagnostics->max_age);
+
+ zfcp_ccw_adapter_put(adapter);
+ return rc;
+}
+
+static ssize_t
+zfcp_sysfs_adapter_diag_max_age_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct zfcp_adapter *adapter = zfcp_ccw_adapter_by_cdev(to_ccwdev(dev));
+ unsigned long max_age;
+ ssize_t rc;
+
+ if (!adapter)
+ return -ENODEV;
+
+ rc = kstrtoul(buf, 10, &max_age);
+ if (rc != 0)
+ goto out;
+
+ adapter->diagnostics->max_age = max_age;
+
+ rc = count;
+out:
+ zfcp_ccw_adapter_put(adapter);
+ return rc;
+}
+static ZFCP_DEV_ATTR(adapter, diag_max_age, 0644,
+ zfcp_sysfs_adapter_diag_max_age_show,
+ zfcp_sysfs_adapter_diag_max_age_store);
+
static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_adapter_failed.attr,
&dev_attr_adapter_in_recovery.attr,
@@ -338,6 +382,7 @@ static struct attribute *zfcp_adapter_attrs[] = {
&dev_attr_adapter_lic_version.attr,
&dev_attr_adapter_status.attr,
&dev_attr_adapter_hardware_version.attr,
+ &dev_attr_adapter_diag_max_age.attr,
NULL
};