Commit b68999ea authored by James Bottomley's avatar James Bottomley

SCSI: Add FC transport host statistics

From: 	James.Smart@Emulex.Com

This patch updates the fc_transport with statistics for local FC ports
(e.g. Hosts).  The statistics are defined per HBAAPI v2.0 definitions.

Caveats:
------------
- The information below is supplied by a simple test driver 
that does not
  talk to real hardware, but fully acts as a LLDD that supports the
  fc transport.


This patch results in the following in /sys/class:
-----------------------------------------------------

[jsmart@elxware class]$ cd /sys/class
[jsmart@elxware class]$ ls
fc_host       graphics  misc     pci_bus       scsi_host  usb_host
fc_transport  input     net      scsi_device   tty        vc
firmware      mem       netlink  scsi_generic  usb
[jsmart@elxware class]$ cd fc_host
[jsmart@elxware fc_host]$ ls
host4

[jsmart@elxware fc_host]$ cd host4
[jsmart@elxware host4]$ ls
device                 host_link_down_tmo           statistics
[jsmart@elxware host4]$ ls -ld *
lrwxrwxrwx  1 root root    0 Oct 13 17:16 device -> 
../../../devices/platform/host4
-rw-r--r--  1 root root 4096 Oct 13 17:16 host_link_down_tmo
drwxr-xr-x  2 root root    0 Oct 13 17:16 statistics

[jsmart@elxware host4]$ cd statistics
dumped_frames         invalid_crc_count      
prim_seq_protocol_err_count
error_frames          invalid_tx_word_count  reset_statistics
fcp_control_requests  link_failure_count     rx_frames
fcp_input_megabytes   lip_count              rx_words
fcp_input_requests    loss_of_signal_count   seconds_since_last_reset
fcp_output_megabytes  loss_of_sync_count     tx_frames
fcp_output_requests   nos_count              tx_words
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 5a0cd4a7
......@@ -279,6 +279,112 @@ static CLASS_DEVICE_ATTR(host_##field, S_IRUGO | S_IWUSR, \
fc_host_rw_attr(link_down_tmo, "%d\n");
/*
* Host Statistics Management
*/
/* Show a given an attribute in the statistics group */
static ssize_t
fc_stat_show(const struct class_device *cdev, char *buf, unsigned long offset)
{
struct Scsi_Host *shost = transport_class_to_shost(cdev);
struct fc_internal *i = to_fc_internal(shost->transportt);
struct fc_host_statistics *stats;
ssize_t ret = -ENOENT;
if (offset > sizeof(struct fc_host_statistics) ||
offset % sizeof(uint64_t) != 0)
WARN_ON(1);
if (i->f->get_fc_host_stats) {
stats = (i->f->get_fc_host_stats)(shost);
if (stats)
ret = snprintf(buf, 20, "0x%llx\n",
*(uint64_t *)(((u8 *) stats) + offset));
}
return ret;
}
/* generate a read-only statistics attribute */
#define fc_host_statistic(name) \
static ssize_t show_fcstat_##name(struct class_device *cd, char *buf) \
{ \
return fc_stat_show(cd, buf, \
offsetof(struct fc_host_statistics, name)); \
} \
static CLASS_DEVICE_ATTR(name, S_IRUGO, show_fcstat_##name, NULL)
fc_host_statistic(seconds_since_last_reset);
fc_host_statistic(tx_frames);
fc_host_statistic(tx_words);
fc_host_statistic(rx_frames);
fc_host_statistic(rx_words);
fc_host_statistic(lip_count);
fc_host_statistic(nos_count);
fc_host_statistic(error_frames);
fc_host_statistic(dumped_frames);
fc_host_statistic(link_failure_count);
fc_host_statistic(loss_of_sync_count);
fc_host_statistic(loss_of_signal_count);
fc_host_statistic(prim_seq_protocol_err_count);
fc_host_statistic(invalid_tx_word_count);
fc_host_statistic(invalid_crc_count);
fc_host_statistic(fcp_input_requests);
fc_host_statistic(fcp_output_requests);
fc_host_statistic(fcp_control_requests);
fc_host_statistic(fcp_input_megabytes);
fc_host_statistic(fcp_output_megabytes);
static ssize_t
fc_reset_statistics(struct class_device *cdev, const char *buf,
size_t count)
{
struct Scsi_Host *shost = transport_class_to_shost(cdev);
struct fc_internal *i = to_fc_internal(shost->transportt);
/* ignore any data value written to the attribute */
if (i->f->reset_fc_host_stats) {
i->f->reset_fc_host_stats(shost);
return count;
}
return -ENOENT;
}
static CLASS_DEVICE_ATTR(reset_statistics, S_IWUSR, NULL, fc_reset_statistics);
static struct attribute *fc_statistics_attrs[] = {
&class_device_attr_seconds_since_last_reset.attr,
&class_device_attr_tx_frames.attr,
&class_device_attr_tx_words.attr,
&class_device_attr_rx_frames.attr,
&class_device_attr_rx_words.attr,
&class_device_attr_lip_count.attr,
&class_device_attr_nos_count.attr,
&class_device_attr_error_frames.attr,
&class_device_attr_dumped_frames.attr,
&class_device_attr_link_failure_count.attr,
&class_device_attr_loss_of_sync_count.attr,
&class_device_attr_loss_of_signal_count.attr,
&class_device_attr_prim_seq_protocol_err_count.attr,
&class_device_attr_invalid_tx_word_count.attr,
&class_device_attr_invalid_crc_count.attr,
&class_device_attr_fcp_input_requests.attr,
&class_device_attr_fcp_output_requests.attr,
&class_device_attr_fcp_control_requests.attr,
&class_device_attr_fcp_input_megabytes.attr,
&class_device_attr_fcp_output_megabytes.attr,
&class_device_attr_reset_statistics.attr,
NULL
};
static struct attribute_group fc_statistics_group = {
.name = "statistics",
.attrs = fc_statistics_attrs,
};
struct scsi_transport_template *
fc_attach_transport(struct fc_function_template *ft)
......@@ -303,6 +409,10 @@ fc_attach_transport(struct fc_function_template *ft)
i->t.host_setup = &fc_setup_host_transport_attrs;
i->t.host_destroy = &fc_destroy_host;
i->t.host_size = sizeof(struct fc_host_attrs);
if (ft->get_fc_host_stats)
i->t.host_statistics = &fc_statistics_group;
i->f = ft;
......
......@@ -43,6 +43,39 @@ struct fc_starget_attrs { /* aka fc_target_attrs */
#define fc_starget_dev_loss_work(x) \
(((struct fc_starget_attrs *)&(x)->starget_data)->dev_loss_work)
/*
* FC Local Port (Host) Statistics
*/
/* FC Statistics - Following FC HBAAPI v2.0 guidelines */
struct fc_host_statistics {
/* port statistics */
uint64_t seconds_since_last_reset;
uint64_t tx_frames;
uint64_t tx_words;
uint64_t rx_frames;
uint64_t rx_words;
uint64_t lip_count;
uint64_t nos_count;
uint64_t error_frames;
uint64_t dumped_frames;
uint64_t link_failure_count;
uint64_t loss_of_sync_count;
uint64_t loss_of_signal_count;
uint64_t prim_seq_protocol_err_count;
uint64_t invalid_tx_word_count;
uint64_t invalid_crc_count;
/* fc4 statistics (only FCP supported currently) */
uint64_t fcp_input_requests;
uint64_t fcp_output_requests;
uint64_t fcp_control_requests;
uint64_t fcp_input_megabytes;
uint64_t fcp_output_megabytes;
};
struct fc_host_attrs {
uint32_t link_down_tmo; /* Link Down timeout in seconds. */
struct work_struct link_down_work;
......@@ -65,6 +98,9 @@ struct fc_function_template {
void (*get_host_link_down_tmo)(struct Scsi_Host *);
void (*set_host_link_down_tmo)(struct Scsi_Host *, uint32_t);
struct fc_host_statistics * (*get_fc_host_stats)(struct Scsi_Host *);
void (*reset_fc_host_stats)(struct Scsi_Host *);
/*
* The driver sets these to tell the transport class it
* wants the attributes displayed in sysfs. If the show_ flag
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment