diff options
Diffstat (limited to 'drivers/s390/scsi/zfcp_scsi.c')
-rw-r--r-- | drivers/s390/scsi/zfcp_scsi.c | 185 |
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 | ||
50 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, | 50 | static struct zfcp_unit *zfcp_unit_lookup(struct zfcp_adapter *, int, scsi_id_t, |
51 | scsi_lun_t); | 51 | scsi_lun_t); |
52 | static struct zfcp_port *zfcp_port_lookup(struct zfcp_adapter *, int, | ||
53 | scsi_id_t); | ||
54 | 52 | ||
55 | static struct device_attribute *zfcp_sysfs_sdev_attrs[]; | 53 | static 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 | ||
409 | static struct zfcp_port * | ||
410 | zfcp_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 | */ |
734 | static void | 720 | static struct fc_host_statistics* |
735 | zfcp_get_port_id(struct scsi_target *starget) | 721 | zfcp_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 | ||
751 | static void | 735 | static void |
752 | zfcp_get_port_name(struct scsi_target *starget) | 736 | zfcp_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); | 769 | static void |
760 | port = zfcp_port_lookup(adapter, starget->channel, starget->id); | 770 | zfcp_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 | */ | ||
802 | static struct fc_host_statistics * | ||
803 | zfcp_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 | ||
768 | static void | 838 | static void |
769 | zfcp_get_node_name(struct scsi_target *starget) | 839 | zfcp_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 | ||
785 | struct fc_function_template zfcp_transport_functions = { | 861 | struct 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 | }; |