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