From: Swen Schillig <[EMAIL PROTECTED]>
add statistics and other zfcp related information to sysfs
The zfcp adapter provides a variety of information which was never
published to the external world. This patch adds a few of those "statistics"
to the sysfs tree structure.
These are reflected in the following attributes
/sys/bus/ccw/drivers/zfcp/0.0.1707
/* information for the virtual adapter */
statistic_services/
requests
megabytes
utilization
seconds_active
/* LUN specific info for channel- and fabric-latency */
0x500507630300c562/0x401040a600000000/
read_latency
write_latency
cmd_latency
Signed-off-by: Swen Schillig <[EMAIL PROTECTED]>
---
drivers/s390/scsi/Makefile | 2
drivers/s390/scsi/zfcp_aux.c | 30 ++++
drivers/s390/scsi/zfcp_def.h | 58 +++++----
drivers/s390/scsi/zfcp_ext.h | 32 ++---
drivers/s390/scsi/zfcp_fsf.c | 1
drivers/s390/scsi/zfcp_fsf.h | 29 ++++
drivers/s390/scsi/zfcp_qdio.c | 34 +++++
drivers/s390/scsi/zfcp_sysfs_statistics.c | 191 ++++++++++++++++++++++++++++++
drivers/s390/scsi/zfcp_sysfs_unit.c | 63 +++++++++
9 files changed, 394 insertions(+), 46 deletions(-)
Index: HEAD/drivers/s390/scsi/zfcp_def.h
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_def.h
+++ HEAD/drivers/s390/scsi/zfcp_def.h
@@ -1,23 +1,23 @@
-/*
+/*
* This file is part of the zfcp device driver for
* FCP adapters for IBM System z9 and zSeries.
*
* (C) Copyright IBM Corp. 2002, 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
#ifndef ZFCP_DEF_H
#define ZFCP_DEF_H
@@ -90,7 +90,7 @@ zfcp_address_to_sg(void *address, struct
#define ZFCP_DEVICE_TYPE 0x1732
#define ZFCP_DEVICE_MODEL 0x03
#define ZFCP_DEVICE_MODEL_PRIV 0x04
-
+
/* allow as many chained SBALs as are supported by hardware */
#define ZFCP_MAX_SBALS_PER_REQ FSF_MAX_SBALS_PER_REQ
#define ZFCP_MAX_SBALS_PER_CT_REQ FSF_MAX_SBALS_PER_REQ
@@ -508,7 +508,7 @@ struct zfcp_rc_entry {
/*
* this allows removal of logging code by the preprocessor
- * (the most detailed log level still to be compiled in is specified,
+ * (the most detailed log level still to be compiled in is specified,
* higher log levels are removed)
*/
#define ZFCP_LOG_LEVEL_LIMIT ZFCP_LOG_LEVEL_TRACE
@@ -546,7 +546,7 @@ do { \
if (ZFCP_LOG_CHECK(level)) \
_ZFCP_LOG(fmt, ##args); \
} while (0)
-
+
#if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL
# define ZFCP_LOG_NORMAL(fmt, args...) do { } while (0)
#else
@@ -583,8 +583,8 @@ do { \
/*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/
-/*
- * Note, the leftmost status byte is common among adapter, port
+/*
+ * Note, the leftmost status byte is common among adapter, port
* and unit
*/
#define ZFCP_COMMON_FLAGS 0xfff00000
@@ -868,6 +868,17 @@ struct zfcp_erp_action {
struct timer_list timer;
};
+struct latency_cont {
+ u32 channel;
+ u32 fabric;
+ u32 counter;
+};
+
+struct zfcp_latencies {
+ struct latency_cont read;
+ struct latency_cont write;
+ struct latency_cont cmd;
+};
struct zfcp_adapter {
struct list_head list; /* list of adapters */
@@ -883,6 +894,7 @@ struct zfcp_adapter {
u32 adapter_features; /* FCP channel features */
u32 connection_features; /* host connection
features */
u32 hardware_version; /* of FCP channel */
+ u16 timer_ticks; /* time int for a tick */
struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
struct list_head port_list_head; /* remote port list */
struct list_head port_remove_lh; /* head of ports to be
@@ -930,6 +942,7 @@ struct zfcp_adapter {
struct zfcp_scsi_dbf_record scsi_dbf_buf;
struct zfcp_adapter_mempool pool; /* Adapter memory pools */
struct qdio_initialize qdio_init_data; /* for qdio_establish */
+ struct device stat_services;
struct device generic_services; /* directory for WKA ports */
struct fc_host_statistics *fc_stats;
struct fsf_qtcb_bottom_port *stats_reset_data;
@@ -986,6 +999,7 @@ struct zfcp_unit {
all scsi_scan_target
requests have been
completed. */
+ struct zfcp_latencies latencies;
};
/* FSF request */
@@ -1007,7 +1021,7 @@ struct zfcp_fsf_req {
u32 fsf_command; /* FSF Command copy */
struct fsf_qtcb *qtcb; /* address of associated QTCB */
u32 seq_no; /* Sequence number of request */
- unsigned long data; /* private data of request */
+ unsigned long data; /* private data of request */
struct timer_list timer; /* used for erp or scsi er */
struct zfcp_erp_action *erp_action; /* used if this request is
issued on behalf of erp */
Index: HEAD/drivers/s390/scsi/zfcp_fsf.c
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_fsf.c
+++ HEAD/drivers/s390/scsi/zfcp_fsf.c
@@ -2079,6 +2079,7 @@ zfcp_fsf_exchange_config_evaluate(struct
fc_host_supported_classes(shost) =
FC_COS_CLASS2 | FC_COS_CLASS3;
adapter->hydra_version = bottom->adapter_type;
+ adapter->timer_ticks = bottom->timer_interval;
if (fc_host_permanent_port_name(shost) == -1)
fc_host_permanent_port_name(shost) =
fc_host_port_name(shost);
Index: HEAD/drivers/s390/scsi/zfcp_fsf.h
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_fsf.h
+++ HEAD/drivers/s390/scsi/zfcp_fsf.h
@@ -213,6 +213,7 @@
#define FSF_FEATURE_HBAAPI_MANAGEMENT 0x00000010
#define FSF_FEATURE_ELS_CT_CHAINED_SBALS 0x00000020
#define FSF_FEATURE_UPDATE_ALERT 0x00000100
+#define FSF_FEATURE_MEASUREMENT_DATA 0x00000200
/* host connection features */
#define FSF_FEATURE_NPIV_MODE 0x00000001
@@ -322,11 +323,18 @@ struct fsf_link_down_info {
u8 vendor_specific_code;
} __attribute__ ((packed));
+struct fsf_qual_latency_info {
+ u32 channel_lat;
+ u32 fabric_lat;
+ u8 res1[8];
+} __attribute__ ((packed));
+
union fsf_prot_status_qual {
u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)];
struct fsf_qual_version_error version_error;
struct fsf_qual_sequence_error sequence_error;
struct fsf_link_down_info link_down_info;
+ struct fsf_qual_latency_info latency_info;
} __attribute__ ((packed));
struct fsf_qtcb_prefix {
@@ -340,6 +348,15 @@ struct fsf_qtcb_prefix {
u8 res1[20];
} __attribute__ ((packed));
+struct fsf_statistics_info {
+ u64 input_req;
+ u64 output_req;
+ u64 control_req;
+ u64 input_mb;
+ u64 output_mb;
+ u64 seconds_act;
+} __attribute__ ((packed));
+
union fsf_status_qual {
u8 byte[FSF_STATUS_QUALIFIER_SIZE];
u16 halfword[FSF_STATUS_QUALIFIER_SIZE / sizeof (u16)];
@@ -427,7 +444,9 @@ struct fsf_qtcb_bottom_config {
u32 fc_link_speed;
u32 adapter_type;
u32 peer_d_id;
- u8 res2[12];
+ u8 res1[2];
+ u16 timer_interval;
+ u8 res2[8];
u32 s_id;
struct fsf_nport_serv_param nport_serv_param;
u8 reserved_nport_serv_param[16];
@@ -436,7 +455,8 @@ struct fsf_qtcb_bottom_config {
u32 hardware_version;
u8 serial_number[32];
struct fsf_nport_serv_param plogi_payload;
- u8 res4[160];
+ struct fsf_statistics_info stat_info;
+ u8 res4[112];
} __attribute__ ((packed));
struct fsf_qtcb_bottom_port {
@@ -469,7 +489,10 @@ struct fsf_qtcb_bottom_port {
u64 control_requests;
u64 input_mb; /* where 1 MByte == 1.000.000 Bytes */
u64 output_mb; /* where 1 MByte == 1.000.000 Bytes */
- u8 res2[256];
+ u8 cp_util;
+ u8 cb_util;
+ u8 a_util;
+ u8 res2[253];
} __attribute__ ((packed));
union fsf_qtcb_bottom {
Index: HEAD/drivers/s390/scsi/zfcp_qdio.c
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_qdio.c
+++ HEAD/drivers/s390/scsi/zfcp_qdio.c
@@ -177,7 +177,7 @@ zfcp_qdio_handler_error_check(struct zfc
* which is set again in case we have missed by a mile.
*/
zfcp_erp_adapter_reopen(
- adapter,
+ adapter,
ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED |
ZFCP_STATUS_COMMON_ERP_FAILED);
}
@@ -241,6 +241,8 @@ static void zfcp_qdio_reqid_check(struct
{
struct zfcp_fsf_req *fsf_req;
unsigned long flags;
+ struct fsf_qual_latency_info *lat_inf;
+ struct zfcp_unit *unit;
debug_long_event(adapter->erp_dbf, 4, req_id);
@@ -255,6 +257,36 @@ static void zfcp_qdio_reqid_check(struct
panic("error: unknown request id (%ld) on adapter %s.\n",
req_id, zfcp_get_busid_by_adapter(adapter));
+ if ((fsf_req->fsf_command == FSF_QTCB_FCP_CMND) &&
+ (fsf_req->qtcb->prefix.prot_status &
+ (FSF_PROT_GOOD | FSF_PROT_FSF_STATUS_PRESENTED))) {
+ lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
+ unit = fsf_req->unit;
+ switch(fsf_req->qtcb->bottom.io.data_direction) {
+ case FSF_DATADIR_READ:
+ unit->latencies.read.channel +=
+ lat_inf->channel_lat;
+ unit->latencies.read.fabric +=
+ lat_inf->fabric_lat;
+ unit->latencies.read.counter++;
+ break;
+ case FSF_DATADIR_WRITE:
+ unit->latencies.write.channel +=
+ lat_inf->channel_lat;
+ unit->latencies.write.fabric +=
+ lat_inf->fabric_lat;
+ unit->latencies.write.counter++;
+ break;
+ case FSF_DATADIR_CMND:
+ unit->latencies.cmd.channel +=
+ lat_inf->channel_lat;
+ unit->latencies.cmd.fabric +=
+ lat_inf->fabric_lat;
+ unit->latencies.cmd.counter++;
+ break;
+ }
+ }
+
zfcp_reqlist_remove(adapter, fsf_req);
atomic_dec(&adapter->reqs_active);
spin_unlock_irqrestore(&adapter->req_list_lock, flags);
Index: HEAD/drivers/s390/scsi/zfcp_sysfs_unit.c
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_sysfs_unit.c
+++ HEAD/drivers/s390/scsi/zfcp_sysfs_unit.c
@@ -125,6 +125,66 @@ zfcp_sysfs_unit_failed_show(struct devic
static DEVICE_ATTR(failed, S_IWUSR | S_IRUGO, zfcp_sysfs_unit_failed_show,
zfcp_sysfs_unit_failed_store);
+static ssize_t
+zfcp_sysfs_unit_read_latency_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ struct zfcp_unit *unit;
+ struct zfcp_latencies *lat;
+ struct zfcp_adapter *adapter;
+
+ unit = dev_get_drvdata(dev);
+ lat = &unit->latencies;
+ adapter = unit->port->adapter;
+
+ return sprintf(buf, "%u %u %u\n",
+ lat->read.fabric * adapter->timer_ticks / 1000,
+ lat->read.channel * adapter->timer_ticks / 1000,
+ lat->read.counter);
+}
+
+static DEVICE_ATTR(read_latency, S_IRUGO, zfcp_sysfs_unit_read_latency_show,
+ NULL);
+
+static ssize_t
+zfcp_sysfs_unit_write_latency_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ struct zfcp_unit *unit;
+ struct zfcp_latencies *lat;
+ struct zfcp_adapter *adapter;
+
+ unit = dev_get_drvdata(dev);
+ lat = &unit->latencies;
+ adapter = unit->port->adapter;
+
+ return sprintf(buf, "%u %u %u\n",
+ lat->write.fabric * adapter->timer_ticks / 1000,
+ lat->write.channel * adapter->timer_ticks / 1000,
+ lat->write.counter);
+}
+
+static DEVICE_ATTR(write_latency, S_IRUGO, zfcp_sysfs_unit_write_latency_show,
+ NULL);
+
+static ssize_t
+zfcp_sysfs_unit_cmd_latency_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ struct zfcp_unit *unit;
+ struct zfcp_latencies *lat;
+ struct zfcp_adapter *adapter;
+
+ unit = dev_get_drvdata(dev);
+ lat = &unit->latencies;
+ adapter = unit->port->adapter;
+
+ return sprintf(buf, "%u %u %u\n",
+ lat->cmd.fabric * adapter->timer_ticks / 1000,
+ lat->cmd.channel * adapter->timer_ticks / 1000,
+ lat->cmd.counter);
+}
+
+static DEVICE_ATTR(cmd_latency, S_IRUGO, zfcp_sysfs_unit_cmd_latency_show,
+ NULL);
+
static struct attribute *zfcp_unit_attrs[] = {
&dev_attr_failed.attr,
&dev_attr_in_recovery.attr,
@@ -132,6 +192,9 @@ static struct attribute *zfcp_unit_attrs
&dev_attr_access_denied.attr,
&dev_attr_access_shared.attr,
&dev_attr_access_readonly.attr,
+ &dev_attr_read_latency.attr,
+ &dev_attr_write_latency.attr,
+ &dev_attr_cmd_latency.attr,
NULL
};
Index: HEAD/drivers/s390/scsi/zfcp_ext.h
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_ext.h
+++ HEAD/drivers/s390/scsi/zfcp_ext.h
@@ -1,22 +1,22 @@
-/*
+/*
* This file is part of the zfcp device driver for
* FCP adapters for IBM System z9 and zSeries.
*
* (C) Copyright IBM Corp. 2002, 2006
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef ZFCP_EXT_H
@@ -37,6 +37,8 @@ extern int zfcp_sysfs_unit_create_files
extern void zfcp_sysfs_unit_remove_files(struct device *);
extern void zfcp_sysfs_port_release(struct device *);
extern void zfcp_sysfs_unit_release(struct device *);
+extern int zfcp_sysfs_statistic_services_create_files(struct device *);
+extern void zfcp_sysfs_statistic_services_remove_files(struct device *);
/**************************** CONFIGURATION *********************************/
extern struct zfcp_unit *zfcp_get_unit_by_lun(struct zfcp_port *, fcp_lun_t);
Index: HEAD/drivers/s390/scsi/zfcp_aux.c
===================================================================
--- HEAD.orig/drivers/s390/scsi/zfcp_aux.c
+++ HEAD/drivers/s390/scsi/zfcp_aux.c
@@ -887,7 +887,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit
/*
* Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI
* commands.
- * It also genrates fcp-nameserver request/response buffer and unsolicited
+ * It also genrates fcp-nameserver request/response buffer and unsolicited
* status read fsf_req buffers.
*
* locks: must only be called with zfcp_data.config_sema taken
@@ -978,7 +978,7 @@ zfcp_adapter_enqueue(struct ccw_device *
struct zfcp_adapter *adapter;
/*
- * Note: It is safe to release the list_lock, as any list changes
+ * Note: It is safe to release the list_lock, as any list changes
* are protected by the config_sema, which must be held to get here
*/
@@ -1059,13 +1059,33 @@ zfcp_adapter_enqueue(struct ccw_device *
if (zfcp_sysfs_adapter_create_files(&ccw_device->dev))
goto sysfs_failed;
+ adapter->stat_services.parent = &adapter->ccw_device->dev;
+ adapter->stat_services.release = zfcp_dummy_release;
+ snprintf(adapter->stat_services.bus_id, BUS_ID_SIZE,
+ "statistic_services");
+ dev_set_drvdata(&adapter->stat_services, adapter);
+
+ if (device_register(&adapter->stat_services)) {
+ ZFCP_LOG_NORMAL("SSS:stat_reg failed.\n");
+ goto services_failed;
+ }
+ ZFCP_LOG_NORMAL("SSS:stat_reg succeeded.\n");
+
+ if (zfcp_sysfs_statistic_services_create_files(&adapter->stat_services))
+ {
+ ZFCP_LOG_NORMAL("SSS: create files failed.\n");
+ goto sysfs_failed;
+ }
+
+ ZFCP_LOG_NORMAL("SSS:create files succeeded.\n");
+
adapter->generic_services.parent = &adapter->ccw_device->dev;
adapter->generic_services.release = zfcp_dummy_release;
snprintf(adapter->generic_services.bus_id, BUS_ID_SIZE,
"generic_services");
if (device_register(&adapter->generic_services))
- goto generic_services_failed;
+ goto services_failed;
/* put allocated adapter at list tail */
write_lock_irq(&zfcp_data.config_lock);
@@ -1077,7 +1097,7 @@ zfcp_adapter_enqueue(struct ccw_device *
goto out;
- generic_services_failed:
+ services_failed:
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
sysfs_failed:
dev_set_drvdata(&ccw_device->dev, NULL);
@@ -1110,6 +1130,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter
zfcp_adapter_scsi_unregister(adapter);
device_unregister(&adapter->generic_services);
+ zfcp_sysfs_statistic_services_remove_files(&adapter->stat_services);
+ device_unregister(&adapter->stat_services);
zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev);
dev_set_drvdata(&adapter->ccw_device->dev, NULL);
/* sanity check: no pending FSF requests */
Index: HEAD/drivers/s390/scsi/Makefile
===================================================================
--- HEAD.orig/drivers/s390/scsi/Makefile
+++ HEAD/drivers/s390/scsi/Makefile
@@ -4,6 +4,6 @@
zfcp-objs := zfcp_aux.o zfcp_ccw.o zfcp_scsi.o zfcp_erp.o zfcp_qdio.o \
zfcp_fsf.o zfcp_dbf.o zfcp_sysfs_adapter.o zfcp_sysfs_port.o \
- zfcp_sysfs_unit.o zfcp_sysfs_driver.o
+ zfcp_sysfs_unit.o zfcp_sysfs_driver.o zfcp_sysfs_statistics.o
obj-$(CONFIG_ZFCP) += zfcp.o
Index: HEAD/drivers/s390/scsi/zfcp_sysfs_statistics.c
===================================================================
--- /dev/null
+++ HEAD/drivers/s390/scsi/zfcp_sysfs_statistics.c
@@ -0,0 +1,191 @@
+/*
+ * This file is part of the zfcp device driver for
+ * FCP adapters for IBM System z9 and zSeries.
+ *
+ * (C) Copyright IBM Corp. 2002, 2006
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "zfcp_ext.h"
+
+#define ZFCP_LOG_AREA ZFCP_LOG_AREA_CONFIG
+
+
+static ssize_t
+zfcp_sysfs_adapter_utilization_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_port *qtcb_port;
+ int retval;
+
+ adapter = dev_get_drvdata(dev);
+
+ qtcb_port = kzalloc(sizeof(struct fsf_qtcb_bottom_port), GFP_KERNEL);
+ if (!qtcb_port) {
+ ZFCP_LOG_NORMAL("error: cannot allocate memory for exchange "
+ "port data request (adapter %s).\n",
+ zfcp_get_busid_by_adapter(adapter));
+ return (ssize_t) 0;
+ }
+
+ retval = zfcp_fsf_exchange_port_data_sync(adapter, qtcb_port);
+ if (retval) {
+ ZFCP_LOG_NORMAL("error: exchange port data request failed for "
+ "adapter %s.\n",
+ zfcp_get_busid_by_adapter(adapter));
+ kfree(qtcb_port);
+ return (ssize_t) 0;
+ }
+
+ 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 DEVICE_ATTR(utilization, S_IRUGO, zfcp_sysfs_adapter_utilization_show,
+ NULL);
+
+static ssize_t
+zfcp_sysfs_adapter_request_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_config *qtcb_config;
+ int retval;
+
+ adapter = dev_get_drvdata(dev);
+
+ qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
+ GFP_KERNEL);
+ if (!qtcb_config) {
+ ZFCP_LOG_NORMAL("error: cannot allocate memory for exchange "
+ "configuration data request (adapter %s).\n",
+ zfcp_get_busid_by_adapter(adapter));
+ return (ssize_t) 0;
+ }
+
+ retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
+ if (retval)
+ ZFCP_LOG_NORMAL("error: exchange configuration data request "
+ "failed for adapter %s.\n",
+ zfcp_get_busid_by_adapter(adapter));
+ else
+ retval = sprintf(buf, "%lu %lu %lu\n",
+ qtcb_config->stat_info.input_req,
+ qtcb_config->stat_info.output_req,
+ qtcb_config->stat_info.control_req);
+
+ kfree(qtcb_config);
+ return (retval > 0) ? retval : (ssize_t) 0;
+}
+
+static DEVICE_ATTR(requests, S_IRUGO, zfcp_sysfs_adapter_request_show, NULL);
+
+static ssize_t
+zfcp_sysfs_adapter_mb_show(struct device *dev,
+ struct device_attribute *attr, char *buf) {
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_config *qtcb_config;
+ int retval;
+
+ adapter = dev_get_drvdata(dev);
+
+ qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
+ GFP_KERNEL);
+
+ if (!qtcb_config) {
+ ZFCP_LOG_NORMAL("error: cannot allocate memory for exchange "
+ "configuration data request (adapter %s).\n",
+ zfcp_get_busid_by_adapter(adapter));
+ return (ssize_t) 0;
+ }
+
+ retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
+ if (retval)
+ ZFCP_LOG_NORMAL("error: exchnage configuration data request "
+ "failed for adapter %s.\n",
+ zfcp_get_busid_by_adapter(adapter));
+ else
+ retval = sprintf(buf, "%lu %lu\n",
+ qtcb_config->stat_info.input_mb,
+ qtcb_config->stat_info.output_mb);
+
+ kfree(qtcb_config);
+ return (retval > 0) ? retval : (ssize_t) 0;
+}
+
+static DEVICE_ATTR(megabytes, S_IRUGO, zfcp_sysfs_adapter_mb_show, NULL);
+
+static ssize_t
+zfcp_sysfs_adapter_seconds_active_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf) {
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_config *qtcb_config;
+ int retval;
+
+ adapter = dev_get_drvdata(dev);
+
+ qtcb_config = kzalloc(sizeof(struct fsf_qtcb_bottom_config),
+ GFP_KERNEL);
+
+ if (!qtcb_config) {
+ ZFCP_LOG_NORMAL("error: cannot allocate memory for exchange "
+ "configuration data request (adapter %s).\n",
+ zfcp_get_busid_by_adapter(adapter));
+ return (ssize_t) 0;
+ }
+
+ retval = zfcp_fsf_exchange_config_data_sync(adapter, qtcb_config);
+ if (retval)
+ ZFCP_LOG_NORMAL("error: exchange configuration data request "
+ "failed for adapter %s.\n",
+ zfcp_get_busid_by_adapter(adapter));
+ else
+ retval = sprintf(buf, "%lu\n",
+ qtcb_config->stat_info.seconds_act);
+
+ kfree(qtcb_config);
+ return (retval > 0) ? retval: (ssize_t) 0;
+}
+
+static DEVICE_ATTR(seconds_active, S_IRUGO,
+ zfcp_sysfs_adapter_seconds_active_show, NULL);
+
+static struct attribute *zfcp_statistic_services_attrs[] = {
+ &dev_attr_utilization.attr,
+ &dev_attr_requests.attr,
+ &dev_attr_megabytes.attr,
+ &dev_attr_seconds_active.attr,
+ NULL
+};
+
+static struct attribute_group zfcp_statistic_services_attr_group = {
+ .attrs = zfcp_statistic_services_attrs,
+};
+
+int
+zfcp_sysfs_statistic_services_create_files(struct device *dev){
+ return sysfs_create_group(&dev->kobj,
+ &zfcp_statistic_services_attr_group);
+}
+
+void
+zfcp_sysfs_statistic_services_remove_files(struct device *dev) {
+ sysfs_remove_group(&dev->kobj, &zfcp_statistic_services_attr_group);
+}
+
+#undef ZFCP_LOG_AREA
-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html