|
@@ -40,6 +40,7 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
|
|
|
unsigned int, unsigned int);
|
|
|
|
|
|
static struct device_attribute *zfcp_sysfs_sdev_attrs[];
|
|
|
+static struct device_attribute *zfcp_a_stats_attrs[];
|
|
|
|
|
|
struct zfcp_data zfcp_data = {
|
|
|
.scsi_host_template = {
|
|
@@ -61,6 +62,7 @@ struct zfcp_data zfcp_data = {
|
|
|
.use_clustering = 1,
|
|
|
.sdev_attrs = zfcp_sysfs_sdev_attrs,
|
|
|
.max_sectors = ZFCP_MAX_SECTORS,
|
|
|
+ .shost_attrs = zfcp_a_stats_attrs,
|
|
|
},
|
|
|
.driver_version = ZFCP_VERSION,
|
|
|
};
|
|
@@ -809,4 +811,116 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
|
|
|
NULL
|
|
|
};
|
|
|
|
|
|
+static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct Scsi_Host *scsi_host = dev_to_shost(dev);
|
|
|
+ struct fsf_qtcb_bottom_port *qtcb_port;
|
|
|
+ int retval;
|
|
|
+ struct zfcp_adapter *adapter;
|
|
|
+
|
|
|
+ adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
|
|
|
+ if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
|
|
|
+ if (!qtcb_port)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
|
|
|
+ if (!retval)
|
|
|
+ retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
|
|
|
+ qtcb_port->cb_util, qtcb_port->a_util);
|
|
|
+ kfree(qtcb_port);
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
+static int zfcp_sysfs_adapter_ex_config(struct device *dev,
|
|
|
+ struct fsf_statistics_info *stat_inf)
|
|
|
+{
|
|
|
+ int retval;
|
|
|
+ struct fsf_qtcb_bottom_config *qtcb_config;
|
|
|
+ struct Scsi_Host *scsi_host = dev_to_shost(dev);
|
|
|
+ struct zfcp_adapter *adapter;
|
|
|
+
|
|
|
+ adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
|
|
|
+ if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!qtcb_config)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
|
|
|
+ if (!retval)
|
|
|
+ *stat_inf = qtcb_config->stat_info;
|
|
|
+
|
|
|
+ kfree(qtcb_config);
|
|
|
+ return retval;
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t zfcp_sysfs_adapter_request_show(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct fsf_statistics_info stat_info;
|
|
|
+ int retval;
|
|
|
+
|
|
|
+ retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ return sprintf(buf, "%llu %llu %llu\n",
|
|
|
+ (unsigned long long) stat_info.input_req,
|
|
|
+ (unsigned long long) stat_info.output_req,
|
|
|
+ (unsigned long long) stat_info.control_req);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t zfcp_sysfs_adapter_mb_show(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct fsf_statistics_info stat_info;
|
|
|
+ int retval;
|
|
|
+
|
|
|
+ retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ return sprintf(buf, "%llu %llu\n",
|
|
|
+ (unsigned long long) stat_info.input_mb,
|
|
|
+ (unsigned long long) stat_info.output_mb);
|
|
|
+}
|
|
|
+
|
|
|
+static ssize_t zfcp_sysfs_adapter_sec_active_show(struct device *dev,
|
|
|
+ struct device_attribute *attr,
|
|
|
+ char *buf)
|
|
|
+{
|
|
|
+ struct fsf_statistics_info stat_info;
|
|
|
+ int retval;
|
|
|
+
|
|
|
+ retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+
|
|
|
+ return sprintf(buf, "%llu\n",
|
|
|
+ (unsigned long long) stat_info.seconds_act);
|
|
|
+}
|
|
|
+
|
|
|
+static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
|
|
|
+static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
|
|
|
+static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
|
|
|
+static DEVICE_ATTR(seconds_active, S_IRUGO,
|
|
|
+ zfcp_sysfs_adapter_sec_active_show, NULL);
|
|
|
+
|
|
|
+static struct device_attribute *zfcp_a_stats_attrs[] = {
|
|
|
+ &dev_attr_utilization,
|
|
|
+ &dev_attr_requests,
|
|
|
+ &dev_attr_megabytes,
|
|
|
+ &dev_attr_seconds_active,
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
#undef ZFCP_LOG_AREA
|