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