]> Pileus Git - ~andy/linux/blob - drivers/scsi/scsi_trace.c
[SCSI] add scsi trace core functions and put trace points
[~andy/linux] / drivers / scsi / scsi_trace.c
1 /*
2  * Copyright (C) 2010 FUJITSU LIMITED
3  * Copyright (C) 2010 Tomohiro Kusumi <kusumi.tomohiro@jp.fujitsu.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18 #include <linux/kernel.h>
19 #include <linux/trace_seq.h>
20 #include <trace/events/scsi.h>
21
22 #define SERVICE_ACTION(cdb) ((cdb[8] << 8) | cdb[9])
23
24 static const char *
25 scsi_trace_misc(struct trace_seq *, unsigned char *, int);
26
27 static const char *
28 scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
29 {
30         const char *ret = p->buffer + p->len;
31         sector_t lba = 0, txlen = 0;
32
33         lba |= ((cdb[1] & 0x1F) << 16);
34         lba |=  (cdb[2] << 8);
35         lba |=   cdb[3];
36         txlen = cdb[4];
37
38         trace_seq_printf(p, "lba=%llu txlen=%llu",
39                          (unsigned long long)lba, (unsigned long long)txlen);
40         trace_seq_putc(p, 0);
41
42         return ret;
43 }
44
45 static const char *
46 scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
47 {
48         const char *ret = p->buffer + p->len;
49         sector_t lba = 0, txlen = 0;
50
51         lba |= (cdb[2] << 24);
52         lba |= (cdb[3] << 16);
53         lba |= (cdb[4] << 8);
54         lba |=  cdb[5];
55         txlen |= (cdb[7] << 8);
56         txlen |=  cdb[8];
57
58         trace_seq_printf(p, "lba=%llu txlen=%llu",
59                          (unsigned long long)lba, (unsigned long long)txlen);
60         trace_seq_putc(p, 0);
61
62         return ret;
63 }
64
65 static const char *
66 scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
67 {
68         const char *ret = p->buffer + p->len;
69         sector_t lba = 0, txlen = 0;
70
71         lba |= (cdb[2] << 24);
72         lba |= (cdb[3] << 16);
73         lba |= (cdb[4] << 8);
74         lba |=  cdb[5];
75         txlen |= (cdb[6] << 24);
76         txlen |= (cdb[7] << 16);
77         txlen |= (cdb[8] << 8);
78         txlen |=  cdb[9];
79
80         trace_seq_printf(p, "lba=%llu txlen=%llu",
81                          (unsigned long long)lba, (unsigned long long)txlen);
82         trace_seq_putc(p, 0);
83
84         return ret;
85 }
86
87 static const char *
88 scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
89 {
90         const char *ret = p->buffer + p->len;
91         sector_t lba = 0, txlen = 0;
92
93         lba |= ((u64)cdb[2] << 56);
94         lba |= ((u64)cdb[3] << 48);
95         lba |= ((u64)cdb[4] << 40);
96         lba |= ((u64)cdb[5] << 32);
97         lba |= (cdb[6] << 24);
98         lba |= (cdb[7] << 16);
99         lba |= (cdb[8] << 8);
100         lba |=  cdb[9];
101         txlen |= (cdb[10] << 24);
102         txlen |= (cdb[11] << 16);
103         txlen |= (cdb[12] << 8);
104         txlen |=  cdb[13];
105
106         trace_seq_printf(p, "lba=%llu txlen=%llu",
107                          (unsigned long long)lba, (unsigned long long)txlen);
108         trace_seq_putc(p, 0);
109
110         return ret;
111 }
112
113 static const char *
114 scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
115 {
116         const char *ret = p->buffer + p->len;
117         sector_t lba = 0, txlen = 0;
118
119         lba |= ((u64)cdb[12] << 56);
120         lba |= ((u64)cdb[13] << 48);
121         lba |= ((u64)cdb[14] << 40);
122         lba |= ((u64)cdb[15] << 32);
123         lba |= (cdb[16] << 24);
124         lba |= (cdb[17] << 16);
125         lba |= (cdb[18] << 8);
126         lba |=  cdb[19];
127         txlen |= (cdb[28] << 24);
128         txlen |= (cdb[29] << 16);
129         txlen |= (cdb[30] << 8);
130         txlen |=  cdb[31];
131
132         trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu",
133                         (SERVICE_ACTION(cdb) == READ_32 ? "READ" : "WRITE"),
134                         (unsigned long long)lba, (unsigned long long)txlen);
135
136         trace_seq_putc(p, 0);
137
138         return ret;
139 }
140
141 static const char *
142 scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
143 {
144         switch (SERVICE_ACTION(cdb)) {
145         case READ_32:
146         case WRITE_32:
147                 return scsi_trace_rw32(p, cdb, len);
148         default:
149                 return scsi_trace_misc(p, cdb, len);
150         }
151 }
152
153 static const char *
154 scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
155 {
156         const char *ret = p->buffer + p->len;
157
158         trace_seq_printf(p, "-");
159         trace_seq_putc(p, 0);
160
161         return ret;
162 }
163
164 const char *
165 scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
166 {
167         switch (cdb[0]) {
168         case READ_6:
169         case WRITE_6:
170                 return scsi_trace_rw6(p, cdb, len);
171         case READ_10:
172         case WRITE_10:
173                 return scsi_trace_rw10(p, cdb, len);
174         case READ_12:
175         case WRITE_12:
176                 return scsi_trace_rw12(p, cdb, len);
177         case READ_16:
178         case WRITE_16:
179                 return scsi_trace_rw16(p, cdb, len);
180         case VARIABLE_LENGTH_CMD:
181                 return scsi_trace_varlen(p, cdb, len);
182         default:
183                 return scsi_trace_misc(p, cdb, len);
184         }
185 }