blob: 22472d140ef7c6bce8955edbc37d1c9270eee10a [file] [log] [blame]
Kei Tokunagabf816232010-04-01 20:41:40 +09001/*
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>
Hannes Reinecke5141f162016-03-24 15:21:19 +010020#include <asm/unaligned.h>
Kei Tokunagabf816232010-04-01 20:41:40 +090021#include <trace/events/scsi.h>
22
Martin K. Petersenc446c1f2010-03-23 01:16:57 -040023#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
Bart Van Asschec87b9e72019-11-01 14:14:47 -070024#define SERVICE_ACTION32(cdb) (get_unaligned_be16(&cdb[8]))
Kei Tokunagabf816232010-04-01 20:41:40 +090025
26static const char *
27scsi_trace_misc(struct trace_seq *, unsigned char *, int);
28
29static const char *
30scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
31{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -040032 const char *ret = trace_seq_buffer_ptr(p);
Bart Van Assche41e2db92019-11-05 13:55:53 -080033 u32 lba = 0, txlen;
Kei Tokunagabf816232010-04-01 20:41:40 +090034
35 lba |= ((cdb[1] & 0x1F) << 16);
36 lba |= (cdb[2] << 8);
37 lba |= cdb[3];
Bart Van Assche41e2db92019-11-05 13:55:53 -080038 /*
39 * From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256
40 * logical blocks shall be read (READ(6)) or written (WRITE(6)).
41 */
42 txlen = cdb[4] ? cdb[4] : 256;
Kei Tokunagabf816232010-04-01 20:41:40 +090043
Bart Van Assche41e2db92019-11-05 13:55:53 -080044 trace_seq_printf(p, "lba=%u txlen=%u", lba, txlen);
Kei Tokunagabf816232010-04-01 20:41:40 +090045 trace_seq_putc(p, 0);
46
47 return ret;
48}
49
50static const char *
51scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
52{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -040053 const char *ret = trace_seq_buffer_ptr(p);
Bart Van Asschec87b9e72019-11-01 14:14:47 -070054 u32 lba, txlen;
Kei Tokunagabf816232010-04-01 20:41:40 +090055
Bart Van Asschec87b9e72019-11-01 14:14:47 -070056 lba = get_unaligned_be32(&cdb[2]);
57 txlen = get_unaligned_be16(&cdb[7]);
Kei Tokunagabf816232010-04-01 20:41:40 +090058
Bart Van Asschec87b9e72019-11-01 14:14:47 -070059 trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen,
Martin K. Petersenc446c1f2010-03-23 01:16:57 -040060 cdb[1] >> 5);
Martin K. Petersenc498bf12011-05-18 00:46:34 -040061
62 if (cdb[0] == WRITE_SAME)
63 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
64
Kei Tokunagabf816232010-04-01 20:41:40 +090065 trace_seq_putc(p, 0);
66
67 return ret;
68}
69
70static const char *
71scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
72{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -040073 const char *ret = trace_seq_buffer_ptr(p);
Bart Van Asschec87b9e72019-11-01 14:14:47 -070074 u32 lba, txlen;
Kei Tokunagabf816232010-04-01 20:41:40 +090075
Bart Van Asschec87b9e72019-11-01 14:14:47 -070076 lba = get_unaligned_be32(&cdb[2]);
77 txlen = get_unaligned_be32(&cdb[6]);
Kei Tokunagabf816232010-04-01 20:41:40 +090078
Bart Van Asschec87b9e72019-11-01 14:14:47 -070079 trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen,
Martin K. Petersenc446c1f2010-03-23 01:16:57 -040080 cdb[1] >> 5);
Kei Tokunagabf816232010-04-01 20:41:40 +090081 trace_seq_putc(p, 0);
82
83 return ret;
84}
85
86static const char *
87scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
88{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -040089 const char *ret = trace_seq_buffer_ptr(p);
Bart Van Asschec87b9e72019-11-01 14:14:47 -070090 u64 lba;
91 u32 txlen;
Kei Tokunagabf816232010-04-01 20:41:40 +090092
Bart Van Asschec87b9e72019-11-01 14:14:47 -070093 lba = get_unaligned_be64(&cdb[2]);
94 txlen = get_unaligned_be32(&cdb[10]);
Kei Tokunagabf816232010-04-01 20:41:40 +090095
Bart Van Asschec87b9e72019-11-01 14:14:47 -070096 trace_seq_printf(p, "lba=%llu txlen=%u protect=%u", lba, txlen,
Martin K. Petersenc446c1f2010-03-23 01:16:57 -040097 cdb[1] >> 5);
98
99 if (cdb[0] == WRITE_SAME_16)
100 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
101
Kei Tokunagabf816232010-04-01 20:41:40 +0900102 trace_seq_putc(p, 0);
103
104 return ret;
105}
106
107static const char *
108scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
109{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -0400110 const char *ret = trace_seq_buffer_ptr(p), *cmd;
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700111 u64 lba;
112 u32 ei_lbrt, txlen;
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400113
114 switch (SERVICE_ACTION32(cdb)) {
115 case READ_32:
116 cmd = "READ";
117 break;
118 case VERIFY_32:
119 cmd = "VERIFY";
120 break;
121 case WRITE_32:
122 cmd = "WRITE";
123 break;
124 case WRITE_SAME_32:
125 cmd = "WRITE_SAME";
126 break;
127 default:
Rasmus Villemoes91c40f22014-12-03 00:10:52 +0100128 trace_seq_puts(p, "UNKNOWN");
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400129 goto out;
130 }
Kei Tokunagabf816232010-04-01 20:41:40 +0900131
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700132 lba = get_unaligned_be64(&cdb[12]);
133 ei_lbrt = get_unaligned_be32(&cdb[20]);
134 txlen = get_unaligned_be32(&cdb[28]);
Kei Tokunagabf816232010-04-01 20:41:40 +0900135
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700136 trace_seq_printf(p, "%s_32 lba=%llu txlen=%u protect=%u ei_lbrt=%u",
137 cmd, lba, txlen, cdb[10] >> 5, ei_lbrt);
Kei Tokunagabf816232010-04-01 20:41:40 +0900138
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400139 if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
140 trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
141
142out:
143 trace_seq_putc(p, 0);
144
145 return ret;
146}
147
148static const char *
149scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
150{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -0400151 const char *ret = trace_seq_buffer_ptr(p);
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700152 unsigned int regions = get_unaligned_be16(&cdb[7]);
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400153
154 trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
155 trace_seq_putc(p, 0);
156
157 return ret;
158}
159
160static const char *
161scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
162{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -0400163 const char *ret = trace_seq_buffer_ptr(p), *cmd;
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700164 u64 lba;
165 u32 alloc_len;
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400166
167 switch (SERVICE_ACTION16(cdb)) {
168 case SAI_READ_CAPACITY_16:
169 cmd = "READ_CAPACITY_16";
170 break;
171 case SAI_GET_LBA_STATUS:
172 cmd = "GET_LBA_STATUS";
173 break;
174 default:
Rasmus Villemoes91c40f22014-12-03 00:10:52 +0100175 trace_seq_puts(p, "UNKNOWN");
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400176 goto out;
177 }
178
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700179 lba = get_unaligned_be64(&cdb[2]);
180 alloc_len = get_unaligned_be32(&cdb[10]);
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400181
Bart Van Asschec87b9e72019-11-01 14:14:47 -0700182 trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, lba, alloc_len);
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400183
184out:
Kei Tokunagabf816232010-04-01 20:41:40 +0900185 trace_seq_putc(p, 0);
186
187 return ret;
188}
189
190static const char *
Hannes Reinecke5141f162016-03-24 15:21:19 +0100191scsi_trace_maintenance_in(struct trace_seq *p, unsigned char *cdb, int len)
192{
193 const char *ret = trace_seq_buffer_ptr(p), *cmd;
194 u32 alloc_len;
195
196 switch (SERVICE_ACTION16(cdb)) {
197 case MI_REPORT_IDENTIFYING_INFORMATION:
198 cmd = "REPORT_IDENTIFYING_INFORMATION";
199 break;
200 case MI_REPORT_TARGET_PGS:
201 cmd = "REPORT_TARGET_PORT_GROUPS";
202 break;
203 case MI_REPORT_ALIASES:
204 cmd = "REPORT_ALIASES";
205 break;
206 case MI_REPORT_SUPPORTED_OPERATION_CODES:
207 cmd = "REPORT_SUPPORTED_OPERATION_CODES";
208 break;
209 case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS:
210 cmd = "REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS";
211 break;
212 case MI_REPORT_PRIORITY:
213 cmd = "REPORT_PRIORITY";
214 break;
215 case MI_REPORT_TIMESTAMP:
216 cmd = "REPORT_TIMESTAMP";
217 break;
218 case MI_MANAGEMENT_PROTOCOL_IN:
219 cmd = "MANAGEMENT_PROTOCOL_IN";
220 break;
221 default:
222 trace_seq_puts(p, "UNKNOWN");
223 goto out;
224 }
225
226 alloc_len = get_unaligned_be32(&cdb[6]);
227
228 trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len);
229
230out:
231 trace_seq_putc(p, 0);
232
233 return ret;
234}
235
236static const char *
237scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len)
238{
239 const char *ret = trace_seq_buffer_ptr(p), *cmd;
240 u32 alloc_len;
241
242 switch (SERVICE_ACTION16(cdb)) {
243 case MO_SET_IDENTIFYING_INFORMATION:
244 cmd = "SET_IDENTIFYING_INFORMATION";
245 break;
246 case MO_SET_TARGET_PGS:
247 cmd = "SET_TARGET_PORT_GROUPS";
248 break;
249 case MO_CHANGE_ALIASES:
250 cmd = "CHANGE_ALIASES";
251 break;
252 case MO_SET_PRIORITY:
253 cmd = "SET_PRIORITY";
254 break;
255 case MO_SET_TIMESTAMP:
256 cmd = "SET_TIMESTAMP";
257 break;
258 case MO_MANAGEMENT_PROTOCOL_OUT:
259 cmd = "MANAGEMENT_PROTOCOL_OUT";
260 break;
261 default:
262 trace_seq_puts(p, "UNKNOWN");
263 goto out;
264 }
265
266 alloc_len = get_unaligned_be32(&cdb[6]);
267
268 trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len);
269
270out:
271 trace_seq_putc(p, 0);
272
273 return ret;
274}
275
276static const char *
Hannes Reinecke0008f1e2016-03-24 17:23:56 +0100277scsi_trace_zbc_in(struct trace_seq *p, unsigned char *cdb, int len)
278{
279 const char *ret = trace_seq_buffer_ptr(p), *cmd;
280 u64 zone_id;
281 u32 alloc_len;
282 u8 options;
283
284 switch (SERVICE_ACTION16(cdb)) {
285 case ZI_REPORT_ZONES:
286 cmd = "REPORT_ZONES";
287 break;
288 default:
289 trace_seq_puts(p, "UNKNOWN");
290 goto out;
291 }
292
293 zone_id = get_unaligned_be64(&cdb[2]);
294 alloc_len = get_unaligned_be32(&cdb[10]);
295 options = cdb[14] & 0x3f;
296
297 trace_seq_printf(p, "%s zone=%llu alloc_len=%u options=%u partial=%u",
298 cmd, (unsigned long long)zone_id, alloc_len,
299 options, (cdb[14] >> 7) & 1);
300
301out:
302 trace_seq_putc(p, 0);
303
304 return ret;
305}
306
307static const char *
308scsi_trace_zbc_out(struct trace_seq *p, unsigned char *cdb, int len)
309{
310 const char *ret = trace_seq_buffer_ptr(p), *cmd;
311 u64 zone_id;
312
313 switch (SERVICE_ACTION16(cdb)) {
314 case ZO_CLOSE_ZONE:
315 cmd = "CLOSE_ZONE";
316 break;
317 case ZO_FINISH_ZONE:
318 cmd = "FINISH_ZONE";
319 break;
320 case ZO_OPEN_ZONE:
321 cmd = "OPEN_ZONE";
322 break;
323 case ZO_RESET_WRITE_POINTER:
324 cmd = "RESET_WRITE_POINTER";
325 break;
326 default:
327 trace_seq_puts(p, "UNKNOWN");
328 goto out;
329 }
330
331 zone_id = get_unaligned_be64(&cdb[2]);
332
333 trace_seq_printf(p, "%s zone=%llu all=%u", cmd,
334 (unsigned long long)zone_id, cdb[14] & 1);
335
336out:
337 trace_seq_putc(p, 0);
338
339 return ret;
340}
341
342static const char *
Kei Tokunagabf816232010-04-01 20:41:40 +0900343scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
344{
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400345 switch (SERVICE_ACTION32(cdb)) {
Kei Tokunagabf816232010-04-01 20:41:40 +0900346 case READ_32:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400347 case VERIFY_32:
Kei Tokunagabf816232010-04-01 20:41:40 +0900348 case WRITE_32:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400349 case WRITE_SAME_32:
Kei Tokunagabf816232010-04-01 20:41:40 +0900350 return scsi_trace_rw32(p, cdb, len);
351 default:
352 return scsi_trace_misc(p, cdb, len);
353 }
354}
355
356static const char *
357scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
358{
Steven Rostedt (Red Hat)7b039cb2014-06-26 09:42:41 -0400359 const char *ret = trace_seq_buffer_ptr(p);
Kei Tokunagabf816232010-04-01 20:41:40 +0900360
Rasmus Villemoesf50332f2014-12-03 00:10:54 +0100361 trace_seq_putc(p, '-');
Kei Tokunagabf816232010-04-01 20:41:40 +0900362 trace_seq_putc(p, 0);
363
364 return ret;
365}
366
367const char *
368scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
369{
370 switch (cdb[0]) {
371 case READ_6:
372 case WRITE_6:
373 return scsi_trace_rw6(p, cdb, len);
374 case READ_10:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400375 case VERIFY:
Kei Tokunagabf816232010-04-01 20:41:40 +0900376 case WRITE_10:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400377 case WRITE_SAME:
Kei Tokunagabf816232010-04-01 20:41:40 +0900378 return scsi_trace_rw10(p, cdb, len);
379 case READ_12:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400380 case VERIFY_12:
Kei Tokunagabf816232010-04-01 20:41:40 +0900381 case WRITE_12:
382 return scsi_trace_rw12(p, cdb, len);
383 case READ_16:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400384 case VERIFY_16:
Kei Tokunagabf816232010-04-01 20:41:40 +0900385 case WRITE_16:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400386 case WRITE_SAME_16:
Kei Tokunagabf816232010-04-01 20:41:40 +0900387 return scsi_trace_rw16(p, cdb, len);
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400388 case UNMAP:
389 return scsi_trace_unmap(p, cdb, len);
Hannes Reineckeeb846d92014-11-17 14:25:19 +0100390 case SERVICE_ACTION_IN_16:
Martin K. Petersenc446c1f2010-03-23 01:16:57 -0400391 return scsi_trace_service_action_in(p, cdb, len);
Kei Tokunagabf816232010-04-01 20:41:40 +0900392 case VARIABLE_LENGTH_CMD:
393 return scsi_trace_varlen(p, cdb, len);
Hannes Reinecke5141f162016-03-24 15:21:19 +0100394 case MAINTENANCE_IN:
395 return scsi_trace_maintenance_in(p, cdb, len);
396 case MAINTENANCE_OUT:
397 return scsi_trace_maintenance_out(p, cdb, len);
Hannes Reinecke0008f1e2016-03-24 17:23:56 +0100398 case ZBC_IN:
399 return scsi_trace_zbc_in(p, cdb, len);
400 case ZBC_OUT:
401 return scsi_trace_zbc_out(p, cdb, len);
Kei Tokunagabf816232010-04-01 20:41:40 +0900402 default:
403 return scsi_trace_misc(p, cdb, len);
404 }
405}