xref: /openbmc/linux/drivers/scsi/scsi_trace.c (revision 2d68bb26)
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 scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
357 {
358 	switch (cdb[0]) {
359 	case READ_6:
360 	case WRITE_6:
361 		return scsi_trace_rw6(p, cdb, len);
362 	case READ_10:
363 	case VERIFY:
364 	case WRITE_10:
365 	case WRITE_SAME:
366 		return scsi_trace_rw10(p, cdb, len);
367 	case READ_12:
368 	case VERIFY_12:
369 	case WRITE_12:
370 		return scsi_trace_rw12(p, cdb, len);
371 	case READ_16:
372 	case VERIFY_16:
373 	case WRITE_16:
374 	case WRITE_SAME_16:
375 		return scsi_trace_rw16(p, cdb, len);
376 	case UNMAP:
377 		return scsi_trace_unmap(p, cdb, len);
378 	case SERVICE_ACTION_IN_16:
379 		return scsi_trace_service_action_in(p, cdb, len);
380 	case VARIABLE_LENGTH_CMD:
381 		return scsi_trace_varlen(p, cdb, len);
382 	case MAINTENANCE_IN:
383 		return scsi_trace_maintenance_in(p, cdb, len);
384 	case MAINTENANCE_OUT:
385 		return scsi_trace_maintenance_out(p, cdb, len);
386 	case ZBC_IN:
387 		return scsi_trace_zbc_in(p, cdb, len);
388 	case ZBC_OUT:
389 		return scsi_trace_zbc_out(p, cdb, len);
390 	default:
391 		return scsi_trace_misc(p, cdb, len);
392 	}
393 }
394