aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h18
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c114
2 files changed, 130 insertions, 2 deletions
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 8cce5cc11d50..099970b27001 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -213,6 +213,7 @@
213#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010 213#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
214#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020 214#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
215#define FSF_FEATURE_UPDATE_ALERT 0x00000100 215#define FSF_FEATURE_UPDATE_ALERT 0x00000100
216#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
216 217
217/* host connection features */ 218/* host connection features */
218#define FSF_FEATURE_NPIV_MODE 0x00000001 219#define FSF_FEATURE_NPIV_MODE 0x00000001
@@ -340,6 +341,15 @@ struct fsf_qtcb_prefix {
340 u8 res1[20]; 341 u8 res1[20];
341} __attribute__ ((packed)); 342} __attribute__ ((packed));
342 343
344struct fsf_statistics_info {
345 u64 input_req;
346 u64 output_req;
347 u64 control_req;
348 u64 input_mb;
349 u64 output_mb;
350 u64 seconds_act;
351} __attribute__ ((packed));
352
343union fsf_status_qual { 353union fsf_status_qual {
344 u8 byte[FSF_STATUS_QUALIFIER_SIZE]; 354 u8 byte[FSF_STATUS_QUALIFIER_SIZE];
345 u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)]; 355 u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
@@ -436,7 +446,8 @@ struct fsf_qtcb_bottom_config {
436 u32 hardware_version; 446 u32 hardware_version;
437 u8 serial_number[32]; 447 u8 serial_number[32];
438 struct fsf_nport_serv_param plogi_payload; 448 struct fsf_nport_serv_param plogi_payload;
439 u8 res4[160]; 449 struct fsf_statistics_info stat_info;
450 u8 res4[112];
440} __attribute__ ((packed)); 451} __attribute__ ((packed));
441 452
442struct fsf_qtcb_bottom_port { 453struct fsf_qtcb_bottom_port {
@@ -469,7 +480,10 @@ struct fsf_qtcb_bottom_port {
469 u64 control_requests; 480 u64 control_requests;
470 u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */ 481 u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */
471 u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */ 482 u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */
472 u8 res2[256]; 483 u8 cp_util;
484 u8 cb_util;
485 u8 a_util;
486 u8 res2[253];
473} __attribute__ ((packed)); 487} __attribute__ ((packed));
474 488
475union fsf_qtcb_bottom { 489union fsf_qtcb_bottom {
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index f81850624eed..01687559dc06 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -40,6 +40,7 @@ static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int,
40 unsigned int, unsigned int); 40 unsigned int, unsigned int);
41 41
42static struct device_attribute *zfcp_sysfs_sdev_attrs[]; 42static struct device_attribute *zfcp_sysfs_sdev_attrs[];
43static struct device_attribute *zfcp_a_stats_attrs[];
43 44
44struct zfcp_data zfcp_data = { 45struct zfcp_data zfcp_data = {
45 .scsi_host_template = { 46 .scsi_host_template = {
@@ -61,6 +62,7 @@ struct zfcp_data zfcp_data = {
61 .use_clustering = 1, 62 .use_clustering = 1,
62 .sdev_attrs = zfcp_sysfs_sdev_attrs, 63 .sdev_attrs = zfcp_sysfs_sdev_attrs,
63 .max_sectors = ZFCP_MAX_SECTORS, 64 .max_sectors = ZFCP_MAX_SECTORS,
65 .shost_attrs = zfcp_a_stats_attrs,
64 }, 66 },
65 .driver_version = ZFCP_VERSION, 67 .driver_version = ZFCP_VERSION,
66}; 68};
@@ -809,4 +811,116 @@ static struct device_attribute *zfcp_sysfs_sdev_attrs[] = {
809 NULL 811 NULL
810}; 812};
811 813
814static ssize_t zfcp_sysfs_adapter_util_show(struct device *dev,
815 struct device_attribute *attr,
816 char *buf)
817{
818 struct Scsi_Host *scsi_host = dev_to_shost(dev);
819 struct fsf_qtcb_bottom_port *qtcb_port;
820 int retval;
821 struct zfcp_adapter *adapter;
822
823 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
824 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
825 return -EOPNOTSUPP;
826
827 qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
828 if (!qtcb_port)
829 return -ENOMEM;
830
831 retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
832 if (!retval)
833 retval = sprintf(buf, "%u %u %u\n", qtcb_port->cp_util,
834 qtcb_port->cb_util, qtcb_port->a_util);
835 kfree(qtcb_port);
836 return retval;
837}
838
839static int zfcp_sysfs_adapter_ex_config(struct device *dev,
840 struct fsf_statistics_info *stat_inf)
841{
842 int retval;
843 struct fsf_qtcb_bottom_config *qtcb_config;
844 struct Scsi_Host *scsi_host = dev_to_shost(dev);
845 struct zfcp_adapter *adapter;
846
847 adapter = (struct zfcp_adapter *) scsi_host->hostdata[0];
848 if (!(adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA))
849 return -EOPNOTSUPP;
850
851 qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
852 GFP_KERNEL);
853 if (!qtcb_config)
854 return -ENOMEM;
855
856 retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
857 if (!retval)
858 *stat_inf = qtcb_config->stat_info;
859
860 kfree(qtcb_config);
861 return retval;
862}
863
864static ssize_t zfcp_sysfs_adapter_request_show(struct device *dev,
865 struct device_attribute *attr,
866 char *buf)
867{
868 struct fsf_statistics_info stat_info;
869 int retval;
870
871 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
872 if (retval)
873 return retval;
874
875 return sprintf(buf, "%llu %llu %llu\n",
876 (unsigned long long) stat_info.input_req,
877 (unsigned long long) stat_info.output_req,
878 (unsigned long long) stat_info.control_req);
879}
880
881static ssize_t zfcp_sysfs_adapter_mb_show(struct device *dev,
882 struct device_attribute *attr,
883 char *buf)
884{
885 struct fsf_statistics_info stat_info;
886 int retval;
887
888 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
889 if (retval)
890 return retval;
891
892 return sprintf(buf, "%llu %llu\n",
893 (unsigned long long) stat_info.input_mb,
894 (unsigned long long) stat_info.output_mb);
895}
896
897static ssize_t zfcp_sysfs_adapter_sec_active_show(struct device *dev,
898 struct device_attribute *attr,
899 char *buf)
900{
901 struct fsf_statistics_info stat_info;
902 int retval;
903
904 retval = zfcp_sysfs_adapter_ex_config(dev, &stat_info);
905 if (retval)
906 return retval;
907
908 return sprintf(buf, "%llu\n",
909 (unsigned long long) stat_info.seconds_act);
910}
911
912static DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_util_show, NULL);
913static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
914static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
915static DEVICE_ATTR(seconds_active, S_IRUGO,
916 zfcp_sysfs_adapter_sec_active_show, NULL);
917
918static struct device_attribute *zfcp_a_stats_attrs[] = {
919 &dev_attr_utilization,
920 &dev_attr_requests,
921 &dev_attr_megabytes,
922 &dev_attr_seconds_active,
923 NULL
924};
925
812#undef ZFCP_LOG_AREA 926#undef ZFCP_LOG_AREA