1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: (kernel):FCP - Performance Data colletion & analysis
5 This patch writes the channel and fabric latencies in nanoseconds per
6 request via blktrace for later analysis. The utilization of the inbound
7 and outbound adapter queue is also reported.
9 Signed-off-by: Stefan Raspl <raspl@linux.vnet.ibm.com>
10 Signed-off-by: Martin Peschke <mp3@de.ibm.com>
11 Signed-off-by: Christof Schmitt <christof.schmitt@de.ibm.com>
13 Acked-by: John Jolly <jjolly@suse.de>
16 drivers/s390/scsi/zfcp_def.h | 2 ++
17 drivers/s390/scsi/zfcp_fsf.c | 34 ++++++++++++++++++++++++++++++++++
18 drivers/s390/scsi/zfcp_fsf.h | 12 ++++++++++++
19 drivers/s390/scsi/zfcp_qdio.c | 1 +
20 4 files changed, 49 insertions(+)
22 --- a/drivers/s390/scsi/zfcp_fsf.c
23 +++ b/drivers/s390/scsi/zfcp_fsf.c
25 * Copyright IBM Corporation 2002, 2008
28 +#include <linux/blktrace_api.h>
31 static void zfcp_fsf_request_timeout_handler(unsigned long data)
32 @@ -834,6 +835,7 @@ static int zfcp_fsf_req_send(struct zfcp
33 list_add_tail(&req->list, &adapter->req_list[idx]);
34 spin_unlock(&adapter->req_list_lock);
36 + req->qdio_outb_usage = atomic_read(&req_q->count);
37 req->issued = get_clock();
38 if (zfcp_qdio_send(req)) {
39 /* Queues are down..... */
40 @@ -2036,6 +2038,36 @@ static void zfcp_fsf_req_latency(struct
41 spin_unlock_irqrestore(&unit->latencies.lock, flags);
44 +#ifdef CONFIG_BLK_DEV_IO_TRACE
45 +static void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
47 + struct fsf_qual_latency_info *lat_inf;
48 + struct scsi_cmnd *scsi_cmnd = (struct scsi_cmnd *)fsf_req->data;
49 + struct request *req = scsi_cmnd->request;
50 + struct zfcp_blk_drv_data trace;
51 + int ticks = fsf_req->adapter->timer_ticks;
54 + trace.magic = ZFCP_BLK_DRV_DATA_MAGIC;
55 + if (fsf_req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA) {
56 + trace.flags |= ZFCP_BLK_LAT_VALID;
57 + lat_inf = &fsf_req->qtcb->prefix.prot_status_qual.latency_info;
58 + trace.channel_lat = lat_inf->channel_lat * ticks;
59 + trace.fabric_lat = lat_inf->fabric_lat * ticks;
61 + if (fsf_req->status & ZFCP_STATUS_FSFREQ_ERROR)
62 + trace.flags |= ZFCP_BLK_REQ_ERROR;
63 + trace.inb_usage = fsf_req->qdio_inb_usage;
64 + trace.outb_usage = fsf_req->qdio_outb_usage;
66 + blk_add_driver_data(req->q, req, &trace, sizeof(trace));
69 +static inline void zfcp_fsf_trace_latency(struct zfcp_fsf_req *fsf_req)
74 static void zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *req)
76 struct scsi_cmnd *scpnt = req->data;
77 @@ -2068,6 +2100,8 @@ static void zfcp_fsf_send_fcp_command_ta
78 if (req->adapter->adapter_features & FSF_FEATURE_MEASUREMENT_DATA)
79 zfcp_fsf_req_latency(req);
81 + zfcp_fsf_trace_latency(req);
83 if (unlikely(fcp_rsp_iu->validity.bits.fcp_rsp_len_valid)) {
84 if (fcp_rsp_info[3] == RSP_CODE_GOOD)
85 set_host_byte(scpnt, DID_OK);
86 --- a/drivers/s390/scsi/zfcp_def.h
87 +++ b/drivers/s390/scsi/zfcp_def.h
88 @@ -638,6 +638,8 @@ struct zfcp_fsf_req {
89 unsigned long long issued; /* request sent time (STCK) */
90 struct zfcp_unit *unit;
91 void (*handler)(struct zfcp_fsf_req *);
92 + u16 qdio_outb_usage;/* usage of outbound queue */
93 + u16 qdio_inb_usage; /* usage of inbound queue */
97 --- a/drivers/s390/scsi/zfcp_qdio.c
98 +++ b/drivers/s390/scsi/zfcp_qdio.c
99 @@ -115,6 +115,7 @@ static void zfcp_qdio_reqid_check(struct
100 spin_unlock_irqrestore(&adapter->req_list_lock, flags);
102 fsf_req->sbal_response = sbal_idx;
103 + fsf_req->qdio_inb_usage = atomic_read(&adapter->resp_q.count);
104 zfcp_fsf_req_complete(fsf_req);
107 --- a/drivers/s390/scsi/zfcp_fsf.h
108 +++ b/drivers/s390/scsi/zfcp_fsf.h
109 @@ -514,4 +514,16 @@ struct fsf_qtcb {
110 u8 log[FSF_QTCB_LOG_SIZE];
111 } __attribute__ ((packed));
113 +struct zfcp_blk_drv_data {
114 +#define ZFCP_BLK_DRV_DATA_MAGIC 0x1
116 +#define ZFCP_BLK_LAT_VALID 0x1
117 +#define ZFCP_BLK_REQ_ERROR 0x2
123 +} __attribute__ ((packed));