aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/scsi/zfcp_scsi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r--drivers/s390/scsi/zfcp_scsi.c185
1 files changed, 131 insertions, 54 deletions
diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c
index 66608d13a634..5ca0992e97f4 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -49,8 +49,6 @@ static int zfcp_task_management_function(struct zfcp_unit *, u8,
49 49
50static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, 50static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t,
51 scsi_lun_t); 51 scsi_lun_t);
52static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int,
53 scsi_id_t);
54 52
55static struct device_attribute *zfcp_sysfs_sdev_attrs[]; 53static struct device_attribute *zfcp_sysfs_sdev_attrs[];
56 54
@@ -406,18 +404,6 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id,
406 return retval; 404 return retval;
407} 405}
408 406
409static struct zfcp_port *
410zfcp_port_lookup(struct zfcp_adapter *adapter, int channel, scsi_id_t id)
411{
412 struct zfcp_port *port;
413
414 list_for_each_entry(port, &adapter->port_list_head, list) {
415 if (port->rport && (id == port->rport->scsi_target_id))
416 return port;
417 }
418 return (struct zfcp_port *) NULL;
419}
420
421/** 407/**
422 * zfcp_scsi_eh_abort_handler - abort the specified SCSI command 408 * zfcp_scsi_eh_abort_handler - abort the specified SCSI command
423 * @scpnt: pointer to scsi_cmnd to be aborted 409 * @scpnt: pointer to scsi_cmnd to be aborted
@@ -731,61 +717,148 @@ zfcp_fsf_start_scsi_er_timer(struct zfcp_adapter *adapter)
731/* 717/*
732 * Support functions for FC transport class 718 * Support functions for FC transport class
733 */ 719 */
734static void 720static struct fc_host_statistics*
735zfcp_get_port_id(struct scsi_target *starget) 721zfcp_init_fc_host_stats(struct zfcp_adapter *adapter)
736{ 722{
737 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 723 struct fc_host_statistics *fc_stats;
738 struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0];
739 struct zfcp_port *port;
740 unsigned long flags;
741 724
742 read_lock_irqsave(&zfcp_data.config_lock, flags); 725 if (!adapter->fc_stats) {
743 port = zfcp_port_lookup(adapter, starget->channel, starget->id); 726 fc_stats = kmalloc(sizeof(*fc_stats), GFP_KERNEL);
744 if (port) 727 if (!fc_stats)
745 fc_starget_port_id(starget) = port->d_id; 728 return NULL;
746 else 729 adapter->fc_stats = fc_stats; /* freed in adater_dequeue */
747 fc_starget_port_id(starget) = -1; 730 }
748 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 731 memset(adapter->fc_stats, 0, sizeof(*adapter->fc_stats));
732 return adapter->fc_stats;
749} 733}
750 734
751static void 735static void
752zfcp_get_port_name(struct scsi_target *starget) 736zfcp_adjust_fc_host_stats(struct fc_host_statistics *fc_stats,
737 struct fsf_qtcb_bottom_port *data,
738 struct fsf_qtcb_bottom_port *old)
753{ 739{
754 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 740 fc_stats->seconds_since_last_reset = data->seconds_since_last_reset -
755 struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; 741 old->seconds_since_last_reset;
756 struct zfcp_port *port; 742 fc_stats->tx_frames = data->tx_frames - old->tx_frames;
757 unsigned long flags; 743 fc_stats->tx_words = data->tx_words - old->tx_words;
744 fc_stats->rx_frames = data->rx_frames - old->rx_frames;
745 fc_stats->rx_words = data->rx_words - old->rx_words;
746 fc_stats->lip_count = data->lip - old->lip;
747 fc_stats->nos_count = data->nos - old->nos;
748 fc_stats->error_frames = data->error_frames - old->error_frames;
749 fc_stats->dumped_frames = data->dumped_frames - old->dumped_frames;
750 fc_stats->link_failure_count = data->link_failure - old->link_failure;
751 fc_stats->loss_of_sync_count = data->loss_of_sync - old->loss_of_sync;
752 fc_stats->loss_of_signal_count = data->loss_of_signal -
753 old->loss_of_signal;
754 fc_stats->prim_seq_protocol_err_count = data->psp_error_counts -
755 old->psp_error_counts;
756 fc_stats->invalid_tx_word_count = data->invalid_tx_words -
757 old->invalid_tx_words;
758 fc_stats->invalid_crc_count = data->invalid_crcs - old->invalid_crcs;
759 fc_stats->fcp_input_requests = data->input_requests -
760 old->input_requests;
761 fc_stats->fcp_output_requests = data->output_requests -
762 old->output_requests;
763 fc_stats->fcp_control_requests = data->control_requests -
764 old->control_requests;
765 fc_stats->fcp_input_megabytes = data->input_mb - old->input_mb;
766 fc_stats->fcp_output_megabytes = data->output_mb - old->output_mb;
767}
758 768
759 read_lock_irqsave(&zfcp_data.config_lock, flags); 769static void
760 port = zfcp_port_lookup(adapter, starget->channel, starget->id); 770zfcp_set_fc_host_stats(struct fc_host_statistics *fc_stats,
761 if (port) 771 struct fsf_qtcb_bottom_port *data)
762 fc_starget_port_name(starget) = port->wwpn; 772{
763 else 773 fc_stats->seconds_since_last_reset = data->seconds_since_last_reset;
764 fc_starget_port_name(starget) = -1; 774 fc_stats->tx_frames = data->tx_frames;
765 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 775 fc_stats->tx_words = data->tx_words;
776 fc_stats->rx_frames = data->rx_frames;
777 fc_stats->rx_words = data->rx_words;
778 fc_stats->lip_count = data->lip;
779 fc_stats->nos_count = data->nos;
780 fc_stats->error_frames = data->error_frames;
781 fc_stats->dumped_frames = data->dumped_frames;
782 fc_stats->link_failure_count = data->link_failure;
783 fc_stats->loss_of_sync_count = data->loss_of_sync;
784 fc_stats->loss_of_signal_count = data->loss_of_signal;
785 fc_stats->prim_seq_protocol_err_count = data->psp_error_counts;
786 fc_stats->invalid_tx_word_count = data->invalid_tx_words;
787 fc_stats->invalid_crc_count = data->invalid_crcs;
788 fc_stats->fcp_input_requests = data->input_requests;
789 fc_stats->fcp_output_requests = data->output_requests;
790 fc_stats->fcp_control_requests = data->control_requests;
791 fc_stats->fcp_input_megabytes = data->input_mb;
792 fc_stats->fcp_output_megabytes = data->output_mb;
793}
794
795/**
796 * zfcp_get_fc_host_stats - provide fc_host_statistics for scsi_transport_fc
797 *
798 * assumption: scsi_transport_fc synchronizes calls of
799 * get_fc_host_stats and reset_fc_host_stats
800 * (XXX to be checked otherwise introduce locking)
801 */
802static struct fc_host_statistics *
803zfcp_get_fc_host_stats(struct Scsi_Host *shost)
804{
805 struct zfcp_adapter *adapter;
806 struct fc_host_statistics *fc_stats;
807 struct fsf_qtcb_bottom_port *data;
808 int ret;
809
810 adapter = (struct zfcp_adapter *)shost->hostdata[0];
811 fc_stats = zfcp_init_fc_host_stats(adapter);
812 if (!fc_stats)
813 return NULL;
814
815 data = kmalloc(sizeof(*data), GFP_KERNEL);
816 if (!data)
817 return NULL;
818 memset(data, 0, sizeof(*data));
819
820 ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
821 if (ret) {
822 kfree(data);
823 return NULL; /* XXX return zeroed fc_stats? */
824 }
825
826 if (adapter->stats_reset &&
827 ((jiffies/HZ - adapter->stats_reset) <
828 data->seconds_since_last_reset)) {
829 zfcp_adjust_fc_host_stats(fc_stats, data,
830 adapter->stats_reset_data);
831 } else
832 zfcp_set_fc_host_stats(fc_stats, data);
833
834 kfree(data);
835 return fc_stats;
766} 836}
767 837
768static void 838static void
769zfcp_get_node_name(struct scsi_target *starget) 839zfcp_reset_fc_host_stats(struct Scsi_Host *shost)
770{ 840{
771 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); 841 struct zfcp_adapter *adapter;
772 struct zfcp_adapter *adapter = (struct zfcp_adapter *)shost->hostdata[0]; 842 struct fsf_qtcb_bottom_port *data, *old_data;
773 struct zfcp_port *port; 843 int ret;
774 unsigned long flags;
775 844
776 read_lock_irqsave(&zfcp_data.config_lock, flags); 845 adapter = (struct zfcp_adapter *)shost->hostdata[0];
777 port = zfcp_port_lookup(adapter, starget->channel, starget->id); 846 data = kmalloc(sizeof(*data), GFP_KERNEL);
778 if (port) 847 if (!data)
779 fc_starget_node_name(starget) = port->wwnn; 848 return;
780 else 849 memset(data, 0, sizeof(*data));
781 fc_starget_node_name(starget) = -1; 850
782 read_unlock_irqrestore(&zfcp_data.config_lock, flags); 851 ret = zfcp_fsf_exchange_port_data(NULL, adapter, data);
852 if (ret == 0) {
853 adapter->stats_reset = jiffies/HZ;
854 old_data = adapter->stats_reset_data;
855 adapter->stats_reset_data = data; /* finally freed in
856 adater_dequeue */
857 kfree(old_data);
858 }
783} 859}
784 860
785struct fc_function_template zfcp_transport_functions = { 861struct fc_function_template zfcp_transport_functions = {
786 .get_starget_port_id = zfcp_get_port_id,
787 .get_starget_port_name = zfcp_get_port_name,
788 .get_starget_node_name = zfcp_get_node_name,
789 .show_starget_port_id = 1, 862 .show_starget_port_id = 1,
790 .show_starget_port_name = 1, 863 .show_starget_port_name = 1,
791 .show_starget_node_name = 1, 864 .show_starget_node_name = 1,
@@ -795,6 +868,10 @@ struct fc_function_template zfcp_transport_functions = {
795 .show_host_supported_classes = 1, 868 .show_host_supported_classes = 1,
796 .show_host_maxframe_size = 1, 869 .show_host_maxframe_size = 1,
797 .show_host_serial_number = 1, 870 .show_host_serial_number = 1,
871 .get_fc_host_stats = zfcp_get_fc_host_stats,
872 .reset_fc_host_stats = zfcp_reset_fc_host_stats,
873 /* no functions registered for following dynamic attributes but
874 directly set by LLDD */
798 .show_host_speed = 1, 875 .show_host_speed = 1,
799 .show_host_port_id = 1, 876 .show_host_port_id = 1,
800}; 877};