Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-only
2 : /*
3 : * Copyright (C) 2010 FUJITSU LIMITED
4 : * Copyright (C) 2010 Tomohiro Kusumi <kusumi.tomohiro@jp.fujitsu.com>
5 : */
6 : #include <linux/kernel.h>
7 : #include <linux/trace_seq.h>
8 : #include <asm/unaligned.h>
9 : #include <trace/events/scsi.h>
10 :
11 : #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
12 : #define SERVICE_ACTION32(cdb) (get_unaligned_be16(&cdb[8]))
13 :
14 : static const char *
15 : scsi_trace_misc(struct trace_seq *, unsigned char *, int);
16 :
17 : static const char *
18 0 : scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
19 : {
20 0 : const char *ret = trace_seq_buffer_ptr(p);
21 0 : u32 lba, txlen;
22 :
23 0 : lba = get_unaligned_be24(&cdb[1]) & 0x1fffff;
24 : /*
25 : * From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256
26 : * logical blocks shall be read (READ(6)) or written (WRITE(6)).
27 : */
28 0 : txlen = cdb[4] ? cdb[4] : 256;
29 :
30 0 : trace_seq_printf(p, "lba=%u txlen=%u", lba, txlen);
31 0 : trace_seq_putc(p, 0);
32 :
33 0 : return ret;
34 : }
35 :
36 : static const char *
37 0 : scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
38 : {
39 0 : const char *ret = trace_seq_buffer_ptr(p);
40 0 : u32 lba, txlen;
41 :
42 0 : lba = get_unaligned_be32(&cdb[2]);
43 0 : txlen = get_unaligned_be16(&cdb[7]);
44 :
45 0 : trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen,
46 0 : cdb[1] >> 5);
47 :
48 0 : if (cdb[0] == WRITE_SAME)
49 0 : trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
50 :
51 0 : trace_seq_putc(p, 0);
52 :
53 0 : return ret;
54 : }
55 :
56 : static const char *
57 0 : scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
58 : {
59 0 : const char *ret = trace_seq_buffer_ptr(p);
60 0 : u32 lba, txlen;
61 :
62 0 : lba = get_unaligned_be32(&cdb[2]);
63 0 : txlen = get_unaligned_be32(&cdb[6]);
64 :
65 0 : trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen,
66 0 : cdb[1] >> 5);
67 0 : trace_seq_putc(p, 0);
68 :
69 0 : return ret;
70 : }
71 :
72 : static const char *
73 0 : scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
74 : {
75 0 : const char *ret = trace_seq_buffer_ptr(p);
76 0 : u64 lba;
77 0 : u32 txlen;
78 :
79 0 : lba = get_unaligned_be64(&cdb[2]);
80 0 : txlen = get_unaligned_be32(&cdb[10]);
81 :
82 0 : trace_seq_printf(p, "lba=%llu txlen=%u protect=%u", lba, txlen,
83 0 : cdb[1] >> 5);
84 :
85 0 : if (cdb[0] == WRITE_SAME_16)
86 0 : trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
87 :
88 0 : trace_seq_putc(p, 0);
89 :
90 0 : return ret;
91 : }
92 :
93 : static const char *
94 0 : scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
95 : {
96 0 : const char *ret = trace_seq_buffer_ptr(p), *cmd;
97 0 : u64 lba;
98 0 : u32 ei_lbrt, txlen;
99 :
100 0 : switch (SERVICE_ACTION32(cdb)) {
101 : case READ_32:
102 : cmd = "READ";
103 : break;
104 0 : case VERIFY_32:
105 0 : cmd = "VERIFY";
106 0 : break;
107 0 : case WRITE_32:
108 0 : cmd = "WRITE";
109 0 : break;
110 0 : case WRITE_SAME_32:
111 0 : cmd = "WRITE_SAME";
112 0 : break;
113 0 : default:
114 0 : trace_seq_puts(p, "UNKNOWN");
115 0 : goto out;
116 : }
117 :
118 0 : lba = get_unaligned_be64(&cdb[12]);
119 0 : ei_lbrt = get_unaligned_be32(&cdb[20]);
120 0 : txlen = get_unaligned_be32(&cdb[28]);
121 :
122 0 : trace_seq_printf(p, "%s_32 lba=%llu txlen=%u protect=%u ei_lbrt=%u",
123 0 : cmd, lba, txlen, cdb[10] >> 5, ei_lbrt);
124 :
125 0 : if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
126 0 : trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
127 :
128 0 : out:
129 0 : trace_seq_putc(p, 0);
130 :
131 0 : return ret;
132 : }
133 :
134 : static const char *
135 0 : scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
136 : {
137 0 : const char *ret = trace_seq_buffer_ptr(p);
138 0 : unsigned int regions = get_unaligned_be16(&cdb[7]);
139 :
140 0 : trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
141 0 : trace_seq_putc(p, 0);
142 :
143 0 : return ret;
144 : }
145 :
146 : static const char *
147 0 : scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
148 : {
149 0 : const char *ret = trace_seq_buffer_ptr(p), *cmd;
150 0 : u64 lba;
151 0 : u32 alloc_len;
152 :
153 0 : switch (SERVICE_ACTION16(cdb)) {
154 : case SAI_READ_CAPACITY_16:
155 : cmd = "READ_CAPACITY_16";
156 : break;
157 0 : case SAI_GET_LBA_STATUS:
158 0 : cmd = "GET_LBA_STATUS";
159 0 : break;
160 0 : default:
161 0 : trace_seq_puts(p, "UNKNOWN");
162 0 : goto out;
163 : }
164 :
165 0 : lba = get_unaligned_be64(&cdb[2]);
166 0 : alloc_len = get_unaligned_be32(&cdb[10]);
167 :
168 0 : trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, lba, alloc_len);
169 :
170 0 : out:
171 0 : trace_seq_putc(p, 0);
172 :
173 0 : return ret;
174 : }
175 :
176 : static const char *
177 0 : scsi_trace_maintenance_in(struct trace_seq *p, unsigned char *cdb, int len)
178 : {
179 0 : const char *ret = trace_seq_buffer_ptr(p), *cmd;
180 0 : u32 alloc_len;
181 :
182 0 : switch (SERVICE_ACTION16(cdb)) {
183 : case MI_REPORT_IDENTIFYING_INFORMATION:
184 : cmd = "REPORT_IDENTIFYING_INFORMATION";
185 : break;
186 0 : case MI_REPORT_TARGET_PGS:
187 0 : cmd = "REPORT_TARGET_PORT_GROUPS";
188 0 : break;
189 0 : case MI_REPORT_ALIASES:
190 0 : cmd = "REPORT_ALIASES";
191 0 : break;
192 0 : case MI_REPORT_SUPPORTED_OPERATION_CODES:
193 0 : cmd = "REPORT_SUPPORTED_OPERATION_CODES";
194 0 : break;
195 0 : case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS:
196 0 : cmd = "REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS";
197 0 : break;
198 0 : case MI_REPORT_PRIORITY:
199 0 : cmd = "REPORT_PRIORITY";
200 0 : break;
201 0 : case MI_REPORT_TIMESTAMP:
202 0 : cmd = "REPORT_TIMESTAMP";
203 0 : break;
204 0 : case MI_MANAGEMENT_PROTOCOL_IN:
205 0 : cmd = "MANAGEMENT_PROTOCOL_IN";
206 0 : break;
207 0 : default:
208 0 : trace_seq_puts(p, "UNKNOWN");
209 0 : goto out;
210 : }
211 :
212 0 : alloc_len = get_unaligned_be32(&cdb[6]);
213 :
214 0 : trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len);
215 :
216 0 : out:
217 0 : trace_seq_putc(p, 0);
218 :
219 0 : return ret;
220 : }
221 :
222 : static const char *
223 0 : scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len)
224 : {
225 0 : const char *ret = trace_seq_buffer_ptr(p), *cmd;
226 0 : u32 alloc_len;
227 :
228 0 : switch (SERVICE_ACTION16(cdb)) {
229 : case MO_SET_IDENTIFYING_INFORMATION:
230 : cmd = "SET_IDENTIFYING_INFORMATION";
231 : break;
232 0 : case MO_SET_TARGET_PGS:
233 0 : cmd = "SET_TARGET_PORT_GROUPS";
234 0 : break;
235 0 : case MO_CHANGE_ALIASES:
236 0 : cmd = "CHANGE_ALIASES";
237 0 : break;
238 0 : case MO_SET_PRIORITY:
239 0 : cmd = "SET_PRIORITY";
240 0 : break;
241 0 : case MO_SET_TIMESTAMP:
242 0 : cmd = "SET_TIMESTAMP";
243 0 : break;
244 0 : case MO_MANAGEMENT_PROTOCOL_OUT:
245 0 : cmd = "MANAGEMENT_PROTOCOL_OUT";
246 0 : break;
247 0 : default:
248 0 : trace_seq_puts(p, "UNKNOWN");
249 0 : goto out;
250 : }
251 :
252 0 : alloc_len = get_unaligned_be32(&cdb[6]);
253 :
254 0 : trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len);
255 :
256 0 : out:
257 0 : trace_seq_putc(p, 0);
258 :
259 0 : return ret;
260 : }
261 :
262 : static const char *
263 0 : scsi_trace_zbc_in(struct trace_seq *p, unsigned char *cdb, int len)
264 : {
265 0 : const char *ret = trace_seq_buffer_ptr(p), *cmd;
266 0 : u64 zone_id;
267 0 : u32 alloc_len;
268 0 : u8 options;
269 :
270 0 : switch (SERVICE_ACTION16(cdb)) {
271 0 : case ZI_REPORT_ZONES:
272 0 : cmd = "REPORT_ZONES";
273 0 : break;
274 0 : default:
275 0 : trace_seq_puts(p, "UNKNOWN");
276 0 : goto out;
277 : }
278 :
279 0 : zone_id = get_unaligned_be64(&cdb[2]);
280 0 : alloc_len = get_unaligned_be32(&cdb[10]);
281 0 : options = cdb[14] & 0x3f;
282 :
283 0 : trace_seq_printf(p, "%s zone=%llu alloc_len=%u options=%u partial=%u",
284 : cmd, (unsigned long long)zone_id, alloc_len,
285 : options, (cdb[14] >> 7) & 1);
286 :
287 0 : out:
288 0 : trace_seq_putc(p, 0);
289 :
290 0 : return ret;
291 : }
292 :
293 : static const char *
294 0 : scsi_trace_zbc_out(struct trace_seq *p, unsigned char *cdb, int len)
295 : {
296 0 : const char *ret = trace_seq_buffer_ptr(p), *cmd;
297 0 : u64 zone_id;
298 :
299 0 : switch (SERVICE_ACTION16(cdb)) {
300 : case ZO_CLOSE_ZONE:
301 : cmd = "CLOSE_ZONE";
302 : break;
303 : case ZO_FINISH_ZONE:
304 : cmd = "FINISH_ZONE";
305 : break;
306 : case ZO_OPEN_ZONE:
307 : cmd = "OPEN_ZONE";
308 : break;
309 : case ZO_RESET_WRITE_POINTER:
310 : cmd = "RESET_WRITE_POINTER";
311 : break;
312 0 : default:
313 0 : trace_seq_puts(p, "UNKNOWN");
314 0 : goto out;
315 : }
316 :
317 0 : zone_id = get_unaligned_be64(&cdb[2]);
318 :
319 0 : trace_seq_printf(p, "%s zone=%llu all=%u", cmd,
320 0 : (unsigned long long)zone_id, cdb[14] & 1);
321 :
322 0 : out:
323 0 : trace_seq_putc(p, 0);
324 :
325 0 : return ret;
326 : }
327 :
328 : static const char *
329 0 : scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
330 : {
331 0 : switch (SERVICE_ACTION32(cdb)) {
332 0 : case READ_32:
333 : case VERIFY_32:
334 : case WRITE_32:
335 : case WRITE_SAME_32:
336 0 : return scsi_trace_rw32(p, cdb, len);
337 0 : default:
338 0 : return scsi_trace_misc(p, cdb, len);
339 : }
340 : }
341 :
342 : static const char *
343 0 : scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
344 : {
345 0 : const char *ret = trace_seq_buffer_ptr(p);
346 :
347 0 : trace_seq_putc(p, '-');
348 0 : trace_seq_putc(p, 0);
349 :
350 0 : return ret;
351 : }
352 :
353 : const char *
354 0 : scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
355 : {
356 0 : switch (cdb[0]) {
357 0 : case READ_6:
358 : case WRITE_6:
359 0 : return scsi_trace_rw6(p, cdb, len);
360 0 : case READ_10:
361 : case VERIFY:
362 : case WRITE_10:
363 : case WRITE_SAME:
364 0 : return scsi_trace_rw10(p, cdb, len);
365 0 : case READ_12:
366 : case VERIFY_12:
367 : case WRITE_12:
368 0 : return scsi_trace_rw12(p, cdb, len);
369 0 : case READ_16:
370 : case VERIFY_16:
371 : case WRITE_16:
372 : case WRITE_SAME_16:
373 0 : return scsi_trace_rw16(p, cdb, len);
374 0 : case UNMAP:
375 0 : return scsi_trace_unmap(p, cdb, len);
376 0 : case SERVICE_ACTION_IN_16:
377 0 : return scsi_trace_service_action_in(p, cdb, len);
378 0 : case VARIABLE_LENGTH_CMD:
379 0 : return scsi_trace_varlen(p, cdb, len);
380 0 : case MAINTENANCE_IN:
381 0 : return scsi_trace_maintenance_in(p, cdb, len);
382 0 : case MAINTENANCE_OUT:
383 0 : return scsi_trace_maintenance_out(p, cdb, len);
384 0 : case ZBC_IN:
385 0 : return scsi_trace_zbc_in(p, cdb, len);
386 0 : case ZBC_OUT:
387 0 : return scsi_trace_zbc_out(p, cdb, len);
388 0 : default:
389 0 : return scsi_trace_misc(p, cdb, len);
390 : }
391 : }
|