+/**
+ * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
+ *
+ * assumption: scsi_transport_fc synchronizes calls of
+ * get_fc_host_stats and reset_fc_host_stats
+ * (XXX to be checked otherwise introduce locking)
+ */
+static struct fc_host_statistics *
+zfcp_get_fc_host_stats(struct Scsi_Host *shost)
+{
+ struct zfcp_adapter *adapter;
+ struct fc_host_statistics *fc_stats;
+ struct fsf_qtcb_bottom_port *data;
+ int ret;
+
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ fc_stats = zfcp_init_fc_host_stats(adapter);
+ if (!fc_stats)
+ return NULL;
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;
+
+ ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+ if (ret) {
+ kfree(data);
+ return NULL; /* XXX return zeroed fc_stats? */
+ }
+
+ if (adapter->stats_reset &&
+ ((jiffies/HZ - adapter->stats_reset) <
+ data->seconds_since_last_reset)) {
+ zfcp_adjust_fc_host_stats(fc_stats, data,
+ adapter->stats_reset_data);
+ } else
+ zfcp_set_fc_host_stats(fc_stats, data);
+
+ kfree(data);
+ return fc_stats;
+}
+
+static void
+zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
+{
+ struct zfcp_adapter *adapter;
+ struct fsf_qtcb_bottom_port *data, *old_data;
+ int ret;
+
+ adapter = (struct zfcp_adapter *)shost->hostdata[0];
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return;
+
+ ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
+ if (ret == 0) {
+ adapter->stats_reset = jiffies/HZ;
+ old_data = adapter->stats_reset_data;
+ adapter->stats_reset_data = data; /* finally freed in
+ adater_dequeue */
+ kfree(old_data);
+ }
+}
+
+static void zfcp_set_rport_dev_loss_tmo(struct fc_rport *rport, u32 timeout)
+{
+ rport->dev_loss_tmo = timeout;
+}
+
+struct fc_function_template zfcp_transport_functions = {
+ .show_starget_port_id = 1,
+ .show_starget_port_name = 1,
+ .show_starget_node_name = 1,
+ .show_rport_supported_classes = 1,
+ .show_rport_maxframe_size = 1,
+ .show_rport_dev_loss_tmo = 1,
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_permanent_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_supported_speeds = 1,
+ .show_host_maxframe_size = 1,
+ .show_host_serial_number = 1,
+ .get_fc_host_stats = zfcp_get_fc_host_stats,
+ .reset_fc_host_stats = zfcp_reset_fc_host_stats,
+ .set_rport_dev_loss_tmo = zfcp_set_rport_dev_loss_tmo,
+ /* no functions registered for following dynamic attributes but
+ directly set by LLDD */
+ .show_host_port_type = 1,
+ .show_host_speed = 1,
+ .show_host_port_id = 1,
+};