aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/s390/scsi/zfcp_aux.c8
-rw-r--r--drivers/s390/scsi/zfcp_def.h20
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c44
-rw-r--r--drivers/s390/scsi/zfcp_fsf.h11
4 files changed, 82 insertions, 1 deletions
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 8c7e2b778ef1..d23027a2f2f0 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -847,6 +847,14 @@ zfcp_unit_enqueue(struct zfcp_port *port, fcp_lun_t fcp_lun)
847 /* mark unit unusable as long as sysfs registration is not complete */ 847 /* mark unit unusable as long as sysfs registration is not complete */
848 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status); 848 atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
849 849
850 spin_lock_init(&unit->latencies.lock);
851 unit->latencies.write.channel.min = 0xFFFFFFFF;
852 unit->latencies.write.fabric.min = 0xFFFFFFFF;
853 unit->latencies.read.channel.min = 0xFFFFFFFF;
854 unit->latencies.read.fabric.min = 0xFFFFFFFF;
855 unit->latencies.cmd.channel.min = 0xFFFFFFFF;
856 unit->latencies.cmd.fabric.min = 0xFFFFFFFF;
857
850 if (device_register(&unit->sysfs_device)) { 858 if (device_register(&unit->sysfs_device)) {
851 kfree(unit); 859 kfree(unit);
852 return NULL; 860 return NULL;
diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h
index bda8c77b22da..306fcd0cae31 100644
--- a/drivers/s390/scsi/zfcp_def.h
+++ b/drivers/s390/scsi/zfcp_def.h
@@ -708,6 +708,24 @@ struct zfcp_erp_action {
708 struct timer_list timer; 708 struct timer_list timer;
709}; 709};
710 710
711struct fsf_latency_record {
712 u32 min;
713 u32 max;
714 u64 sum;
715};
716
717struct latency_cont {
718 struct fsf_latency_record channel;
719 struct fsf_latency_record fabric;
720 u64 counter;
721};
722
723struct zfcp_latencies {
724 struct latency_cont read;
725 struct latency_cont write;
726 struct latency_cont cmd;
727 spinlock_t lock;
728};
711 729
712struct zfcp_adapter { 730struct zfcp_adapter {
713 struct list_head list; /* list of adapters */ 731 struct list_head list; /* list of adapters */
@@ -723,6 +741,7 @@ struct zfcp_adapter {
723 u32 adapter_features; /* FCP channel features */ 741 u32 adapter_features; /* FCP channel features */
724 u32 connection_features; /* host connection features */ 742 u32 connection_features; /* host connection features */
725 u32 hardware_version; /* of FCP channel */ 743 u32 hardware_version; /* of FCP channel */
744 u16 timer_ticks; /* time int for a tick */
726 struct Scsi_Host *scsi_host; /* Pointer to mid-layer */ 745 struct Scsi_Host *scsi_host; /* Pointer to mid-layer */
727 struct list_head port_list_head; /* remote port list */ 746 struct list_head port_list_head; /* remote port list */
728 struct list_head port_remove_lh; /* head of ports to be 747 struct list_head port_remove_lh; /* head of ports to be
@@ -822,6 +841,7 @@ struct zfcp_unit {
822 struct scsi_device *device; /* scsi device struct pointer */ 841 struct scsi_device *device; /* scsi device struct pointer */
823 struct zfcp_erp_action erp_action; /* pending error recovery */ 842 struct zfcp_erp_action erp_action; /* pending error recovery */
824 atomic_t erp_counter; 843 atomic_t erp_counter;
844 struct zfcp_latencies latencies;
825}; 845};
826 846
827/* FSF request */ 847/* FSF request */
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index b2ea4ea051f5..1e7136483c1b 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -2005,6 +2005,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok)
2005 fc_host_supported_classes(shost) = 2005 fc_host_supported_classes(shost) =
2006 FC_COS_CLASS2 | FC_COS_CLASS3; 2006 FC_COS_CLASS2 | FC_COS_CLASS3;
2007 adapter->hydra_version = bottom->adapter_type; 2007 adapter->hydra_version = bottom->adapter_type;
2008 adapter->timer_ticks = bottom->timer_interval;
2008 if (fc_host_permanent_port_name(shost) == -1) 2009 if (fc_host_permanent_port_name(shost) == -1)
2009 fc_host_permanent_port_name(shost) = 2010 fc_host_permanent_port_name(shost) =
2010 fc_host_port_name(shost); 2011 fc_host_port_name(shost);
@@ -3649,6 +3650,46 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter,
3649 return fsf_req; 3650 return fsf_req;
3650} 3651}
3651 3652
3653static void zfcp_fsf_update_lat(struct fsf_latency_record *lat_rec, u32 lat)
3654{
3655 lat_rec->sum += lat;
3656 if (lat_rec->min > lat)
3657 lat_rec->min = lat;
3658 if (lat_rec->max < lat)
3659 lat_rec->max = lat;
3660}
3661
3662static void zfcp_fsf_req_latency(struct zfcp_fsf_req *fsf_req)
3663{
3664 struct fsf_qual_latency_info *lat_inf;
3665 struct latency_cont *lat;
3666 struct zfcp_unit *unit;
3667 unsigned long flags;
3668
3669 lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
3670 unit = fsf_req->unit;
3671
3672 switch (fsf_req->qtcb->bottom.io.data_direction) {
3673 case FSF_DATADIR_READ:
3674 lat = &unit->latencies.read;
3675 break;
3676 case FSF_DATADIR_WRITE:
3677 lat = &unit->latencies.write;
3678 break;
3679 case FSF_DATADIR_CMND:
3680 lat = &unit->latencies.cmd;
3681 break;
3682 default:
3683 return;
3684 }
3685
3686 spin_lock_irqsave(&unit->latencies.lock, flags);
3687 zfcp_fsf_update_lat(&lat->channel, lat_inf->channel_lat);
3688 zfcp_fsf_update_lat(&lat->fabric, lat_inf->fabric_lat);
3689 lat->counter++;
3690 spin_unlock_irqrestore(&unit->latencies.lock, flags);
3691}
3692
3652/* 3693/*
3653 * function: zfcp_fsf_send_fcp_command_handler 3694 * function: zfcp_fsf_send_fcp_command_handler
3654 * 3695 *
@@ -3922,6 +3963,9 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req)
3922 fcp_rsp_iu->fcp_sns_len); 3963 fcp_rsp_iu->fcp_sns_len);
3923 } 3964 }
3924 3965
3966 if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
3967 zfcp_fsf_req_latency(fsf_req);
3968
3925 /* check FCP_RSP_INFO */ 3969 /* check FCP_RSP_INFO */
3926 if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) { 3970 if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
3927 ZFCP_LOG_DEBUG("rsp_len is valid\n"); 3971 ZFCP_LOG_DEBUG("rsp_len is valid\n");
diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h
index 099970b27001..8b1a7d9c840f 100644
--- a/drivers/s390/scsi/zfcp_fsf.h
+++ b/drivers/s390/scsi/zfcp_fsf.h
@@ -323,11 +323,18 @@ struct fsf_link_down_info {
323 u8 vendor_specific_code; 323 u8 vendor_specific_code;
324} __attribute__ ((packed)); 324} __attribute__ ((packed));
325 325
326struct fsf_qual_latency_info {
327 u32 channel_lat;
328 u32 fabric_lat;
329 u8 res1[8];
330} __attribute__ ((packed));
331
326union fsf_prot_status_qual { 332union fsf_prot_status_qual {
327 u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)]; 333 u64 doubleword[FSF_PROT_STATUS_QUAL_SIZE / sizeof(u64)];
328 struct fsf_qual_version_error version_error; 334 struct fsf_qual_version_error version_error;
329 struct fsf_qual_sequence_error sequence_error; 335 struct fsf_qual_sequence_error sequence_error;
330 struct fsf_link_down_info link_down_info; 336 struct fsf_link_down_info link_down_info;
337 struct fsf_qual_latency_info latency_info;
331} __attribute__ ((packed)); 338} __attribute__ ((packed));
332 339
333struct fsf_qtcb_prefix { 340struct fsf_qtcb_prefix {
@@ -437,7 +444,9 @@ struct fsf_qtcb_bottom_config {
437 u32 fc_link_speed; 444 u32 fc_link_speed;
438 u32 adapter_type; 445 u32 adapter_type;
439 u32 peer_d_id; 446 u32 peer_d_id;
440 u8 res2[12]; 447 u8 res1[2];
448 u16 timer_interval;
449 u8 res2[8];
441 u32 s_id; 450 u32 s_id;
442 struct fsf_nport_serv_param nport_serv_param; 451 struct fsf_nport_serv_param nport_serv_param;
443 u8 reserved_nport_serv_param[16]; 452 u8 reserved_nport_serv_param[16];