1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * NVM Express device driver tracepoints |
4 | * Copyright (c) 2018 Johannes Thumshirn, SUSE Linux GmbH |
5 | */ |
6 | |
7 | #include <asm/unaligned.h> |
8 | #include "trace.h" |
9 | |
10 | static const char *nvme_trace_delete_sq(struct trace_seq *p, u8 *cdw10) |
11 | { |
12 | const char *ret = trace_seq_buffer_ptr(s: p); |
13 | u16 sqid = get_unaligned_le16(p: cdw10); |
14 | |
15 | trace_seq_printf(s: p, fmt: "sqid=%u" , sqid); |
16 | trace_seq_putc(s: p, c: 0); |
17 | |
18 | return ret; |
19 | } |
20 | |
21 | static const char *nvme_trace_create_sq(struct trace_seq *p, u8 *cdw10) |
22 | { |
23 | const char *ret = trace_seq_buffer_ptr(s: p); |
24 | u16 sqid = get_unaligned_le16(p: cdw10); |
25 | u16 qsize = get_unaligned_le16(p: cdw10 + 2); |
26 | u16 sq_flags = get_unaligned_le16(p: cdw10 + 4); |
27 | u16 cqid = get_unaligned_le16(p: cdw10 + 6); |
28 | |
29 | |
30 | trace_seq_printf(s: p, fmt: "sqid=%u, qsize=%u, sq_flags=0x%x, cqid=%u" , |
31 | sqid, qsize, sq_flags, cqid); |
32 | trace_seq_putc(s: p, c: 0); |
33 | |
34 | return ret; |
35 | } |
36 | |
37 | static const char *nvme_trace_delete_cq(struct trace_seq *p, u8 *cdw10) |
38 | { |
39 | const char *ret = trace_seq_buffer_ptr(s: p); |
40 | u16 cqid = get_unaligned_le16(p: cdw10); |
41 | |
42 | trace_seq_printf(s: p, fmt: "cqid=%u" , cqid); |
43 | trace_seq_putc(s: p, c: 0); |
44 | |
45 | return ret; |
46 | } |
47 | |
48 | static const char *nvme_trace_create_cq(struct trace_seq *p, u8 *cdw10) |
49 | { |
50 | const char *ret = trace_seq_buffer_ptr(s: p); |
51 | u16 cqid = get_unaligned_le16(p: cdw10); |
52 | u16 qsize = get_unaligned_le16(p: cdw10 + 2); |
53 | u16 cq_flags = get_unaligned_le16(p: cdw10 + 4); |
54 | u16 irq_vector = get_unaligned_le16(p: cdw10 + 6); |
55 | |
56 | trace_seq_printf(s: p, fmt: "cqid=%u, qsize=%u, cq_flags=0x%x, irq_vector=%u" , |
57 | cqid, qsize, cq_flags, irq_vector); |
58 | trace_seq_putc(s: p, c: 0); |
59 | |
60 | return ret; |
61 | } |
62 | |
63 | static const char *nvme_trace_admin_identify(struct trace_seq *p, u8 *cdw10) |
64 | { |
65 | const char *ret = trace_seq_buffer_ptr(s: p); |
66 | u8 cns = cdw10[0]; |
67 | u16 ctrlid = get_unaligned_le16(p: cdw10 + 2); |
68 | |
69 | trace_seq_printf(s: p, fmt: "cns=%u, ctrlid=%u" , cns, ctrlid); |
70 | trace_seq_putc(s: p, c: 0); |
71 | |
72 | return ret; |
73 | } |
74 | |
75 | static const char *nvme_trace_admin_set_features(struct trace_seq *p, |
76 | u8 *cdw10) |
77 | { |
78 | const char *ret = trace_seq_buffer_ptr(s: p); |
79 | u8 fid = cdw10[0]; |
80 | u8 sv = cdw10[3] & 0x8; |
81 | u32 cdw11 = get_unaligned_le32(p: cdw10 + 4); |
82 | |
83 | trace_seq_printf(s: p, fmt: "fid=0x%x, sv=0x%x, cdw11=0x%x" , fid, sv, cdw11); |
84 | trace_seq_putc(s: p, c: 0); |
85 | |
86 | return ret; |
87 | } |
88 | |
89 | static const char *nvme_trace_admin_get_features(struct trace_seq *p, |
90 | u8 *cdw10) |
91 | { |
92 | const char *ret = trace_seq_buffer_ptr(s: p); |
93 | u8 fid = cdw10[0]; |
94 | u8 sel = cdw10[1] & 0x7; |
95 | u32 cdw11 = get_unaligned_le32(p: cdw10 + 4); |
96 | |
97 | trace_seq_printf(s: p, fmt: "fid=0x%x, sel=0x%x, cdw11=0x%x" , fid, sel, cdw11); |
98 | trace_seq_putc(s: p, c: 0); |
99 | |
100 | return ret; |
101 | } |
102 | |
103 | static const char *nvme_trace_get_lba_status(struct trace_seq *p, |
104 | u8 *cdw10) |
105 | { |
106 | const char *ret = trace_seq_buffer_ptr(s: p); |
107 | u64 slba = get_unaligned_le64(p: cdw10); |
108 | u32 mndw = get_unaligned_le32(p: cdw10 + 8); |
109 | u16 rl = get_unaligned_le16(p: cdw10 + 12); |
110 | u8 atype = cdw10[15]; |
111 | |
112 | trace_seq_printf(s: p, fmt: "slba=0x%llx, mndw=0x%x, rl=0x%x, atype=%u" , |
113 | slba, mndw, rl, atype); |
114 | trace_seq_putc(s: p, c: 0); |
115 | |
116 | return ret; |
117 | } |
118 | |
119 | static const char *nvme_trace_admin_format_nvm(struct trace_seq *p, u8 *cdw10) |
120 | { |
121 | const char *ret = trace_seq_buffer_ptr(s: p); |
122 | u8 lbaf = cdw10[0] & 0xF; |
123 | u8 mset = (cdw10[0] >> 4) & 0x1; |
124 | u8 pi = (cdw10[0] >> 5) & 0x7; |
125 | u8 pil = cdw10[1] & 0x1; |
126 | u8 ses = (cdw10[1] >> 1) & 0x7; |
127 | |
128 | trace_seq_printf(s: p, fmt: "lbaf=%u, mset=%u, pi=%u, pil=%u, ses=%u" , |
129 | lbaf, mset, pi, pil, ses); |
130 | |
131 | trace_seq_putc(s: p, c: 0); |
132 | |
133 | return ret; |
134 | } |
135 | |
136 | static const char *nvme_trace_read_write(struct trace_seq *p, u8 *cdw10) |
137 | { |
138 | const char *ret = trace_seq_buffer_ptr(s: p); |
139 | u64 slba = get_unaligned_le64(p: cdw10); |
140 | u16 length = get_unaligned_le16(p: cdw10 + 8); |
141 | u16 control = get_unaligned_le16(p: cdw10 + 10); |
142 | u32 dsmgmt = get_unaligned_le32(p: cdw10 + 12); |
143 | u32 reftag = get_unaligned_le32(p: cdw10 + 16); |
144 | |
145 | trace_seq_printf(s: p, |
146 | fmt: "slba=%llu, len=%u, ctrl=0x%x, dsmgmt=%u, reftag=%u" , |
147 | slba, length, control, dsmgmt, reftag); |
148 | trace_seq_putc(s: p, c: 0); |
149 | |
150 | return ret; |
151 | } |
152 | |
153 | static const char *nvme_trace_dsm(struct trace_seq *p, u8 *cdw10) |
154 | { |
155 | const char *ret = trace_seq_buffer_ptr(s: p); |
156 | |
157 | trace_seq_printf(s: p, fmt: "nr=%u, attributes=%u" , |
158 | get_unaligned_le32(p: cdw10), |
159 | get_unaligned_le32(p: cdw10 + 4)); |
160 | trace_seq_putc(s: p, c: 0); |
161 | |
162 | return ret; |
163 | } |
164 | |
165 | static const char *nvme_trace_zone_mgmt_send(struct trace_seq *p, u8 *cdw10) |
166 | { |
167 | const char *ret = trace_seq_buffer_ptr(s: p); |
168 | u64 slba = get_unaligned_le64(p: cdw10); |
169 | u8 zsa = cdw10[12]; |
170 | u8 all = cdw10[13]; |
171 | |
172 | trace_seq_printf(s: p, fmt: "slba=%llu, zsa=%u, all=%u" , slba, zsa, all); |
173 | trace_seq_putc(s: p, c: 0); |
174 | |
175 | return ret; |
176 | } |
177 | |
178 | static const char *nvme_trace_zone_mgmt_recv(struct trace_seq *p, u8 *cdw10) |
179 | { |
180 | const char *ret = trace_seq_buffer_ptr(s: p); |
181 | u64 slba = get_unaligned_le64(p: cdw10); |
182 | u32 numd = get_unaligned_le32(p: cdw10 + 8); |
183 | u8 zra = cdw10[12]; |
184 | u8 zrasf = cdw10[13]; |
185 | u8 pr = cdw10[14]; |
186 | |
187 | trace_seq_printf(s: p, fmt: "slba=%llu, numd=%u, zra=%u, zrasf=%u, pr=%u" , |
188 | slba, numd, zra, zrasf, pr); |
189 | trace_seq_putc(s: p, c: 0); |
190 | |
191 | return ret; |
192 | } |
193 | |
194 | static const char *nvme_trace_common(struct trace_seq *p, u8 *cdw10) |
195 | { |
196 | const char *ret = trace_seq_buffer_ptr(s: p); |
197 | |
198 | trace_seq_printf(s: p, fmt: "cdw10=%*ph" , 24, cdw10); |
199 | trace_seq_putc(s: p, c: 0); |
200 | |
201 | return ret; |
202 | } |
203 | |
204 | const char *nvme_trace_parse_admin_cmd(struct trace_seq *p, |
205 | u8 opcode, u8 *cdw10) |
206 | { |
207 | switch (opcode) { |
208 | case nvme_admin_delete_sq: |
209 | return nvme_trace_delete_sq(p, cdw10); |
210 | case nvme_admin_create_sq: |
211 | return nvme_trace_create_sq(p, cdw10); |
212 | case nvme_admin_delete_cq: |
213 | return nvme_trace_delete_cq(p, cdw10); |
214 | case nvme_admin_create_cq: |
215 | return nvme_trace_create_cq(p, cdw10); |
216 | case nvme_admin_identify: |
217 | return nvme_trace_admin_identify(p, cdw10); |
218 | case nvme_admin_set_features: |
219 | return nvme_trace_admin_set_features(p, cdw10); |
220 | case nvme_admin_get_features: |
221 | return nvme_trace_admin_get_features(p, cdw10); |
222 | case nvme_admin_get_lba_status: |
223 | return nvme_trace_get_lba_status(p, cdw10); |
224 | case nvme_admin_format_nvm: |
225 | return nvme_trace_admin_format_nvm(p, cdw10); |
226 | default: |
227 | return nvme_trace_common(p, cdw10); |
228 | } |
229 | } |
230 | |
231 | const char *nvme_trace_parse_nvm_cmd(struct trace_seq *p, |
232 | u8 opcode, u8 *cdw10) |
233 | { |
234 | switch (opcode) { |
235 | case nvme_cmd_read: |
236 | case nvme_cmd_write: |
237 | case nvme_cmd_write_zeroes: |
238 | case nvme_cmd_zone_append: |
239 | return nvme_trace_read_write(p, cdw10); |
240 | case nvme_cmd_dsm: |
241 | return nvme_trace_dsm(p, cdw10); |
242 | case nvme_cmd_zone_mgmt_send: |
243 | return nvme_trace_zone_mgmt_send(p, cdw10); |
244 | case nvme_cmd_zone_mgmt_recv: |
245 | return nvme_trace_zone_mgmt_recv(p, cdw10); |
246 | default: |
247 | return nvme_trace_common(p, cdw10); |
248 | } |
249 | } |
250 | |
251 | static const char *nvme_trace_fabrics_property_set(struct trace_seq *p, u8 *spc) |
252 | { |
253 | const char *ret = trace_seq_buffer_ptr(s: p); |
254 | u8 attrib = spc[0]; |
255 | u32 ofst = get_unaligned_le32(p: spc + 4); |
256 | u64 value = get_unaligned_le64(p: spc + 8); |
257 | |
258 | trace_seq_printf(s: p, fmt: "attrib=%u, ofst=0x%x, value=0x%llx" , |
259 | attrib, ofst, value); |
260 | trace_seq_putc(s: p, c: 0); |
261 | return ret; |
262 | } |
263 | |
264 | static const char *nvme_trace_fabrics_connect(struct trace_seq *p, u8 *spc) |
265 | { |
266 | const char *ret = trace_seq_buffer_ptr(s: p); |
267 | u16 recfmt = get_unaligned_le16(p: spc); |
268 | u16 qid = get_unaligned_le16(p: spc + 2); |
269 | u16 sqsize = get_unaligned_le16(p: spc + 4); |
270 | u8 cattr = spc[6]; |
271 | u32 kato = get_unaligned_le32(p: spc + 8); |
272 | |
273 | trace_seq_printf(s: p, fmt: "recfmt=%u, qid=%u, sqsize=%u, cattr=%u, kato=%u" , |
274 | recfmt, qid, sqsize, cattr, kato); |
275 | trace_seq_putc(s: p, c: 0); |
276 | return ret; |
277 | } |
278 | |
279 | static const char *nvme_trace_fabrics_property_get(struct trace_seq *p, u8 *spc) |
280 | { |
281 | const char *ret = trace_seq_buffer_ptr(s: p); |
282 | u8 attrib = spc[0]; |
283 | u32 ofst = get_unaligned_le32(p: spc + 4); |
284 | |
285 | trace_seq_printf(s: p, fmt: "attrib=%u, ofst=0x%x" , attrib, ofst); |
286 | trace_seq_putc(s: p, c: 0); |
287 | return ret; |
288 | } |
289 | |
290 | static const char *nvme_trace_fabrics_auth_send(struct trace_seq *p, u8 *spc) |
291 | { |
292 | const char *ret = trace_seq_buffer_ptr(s: p); |
293 | u8 spsp0 = spc[1]; |
294 | u8 spsp1 = spc[2]; |
295 | u8 secp = spc[3]; |
296 | u32 tl = get_unaligned_le32(p: spc + 4); |
297 | |
298 | trace_seq_printf(s: p, fmt: "spsp0=%02x, spsp1=%02x, secp=%02x, tl=%u" , |
299 | spsp0, spsp1, secp, tl); |
300 | trace_seq_putc(s: p, c: 0); |
301 | return ret; |
302 | } |
303 | |
304 | static const char *nvme_trace_fabrics_auth_receive(struct trace_seq *p, u8 *spc) |
305 | { |
306 | const char *ret = trace_seq_buffer_ptr(s: p); |
307 | u8 spsp0 = spc[1]; |
308 | u8 spsp1 = spc[2]; |
309 | u8 secp = spc[3]; |
310 | u32 al = get_unaligned_le32(p: spc + 4); |
311 | |
312 | trace_seq_printf(s: p, fmt: "spsp0=%02x, spsp1=%02x, secp=%02x, al=%u" , |
313 | spsp0, spsp1, secp, al); |
314 | trace_seq_putc(s: p, c: 0); |
315 | return ret; |
316 | } |
317 | |
318 | static const char *nvme_trace_fabrics_common(struct trace_seq *p, u8 *spc) |
319 | { |
320 | const char *ret = trace_seq_buffer_ptr(s: p); |
321 | |
322 | trace_seq_printf(s: p, fmt: "specific=%*ph" , 24, spc); |
323 | trace_seq_putc(s: p, c: 0); |
324 | return ret; |
325 | } |
326 | |
327 | const char *nvme_trace_parse_fabrics_cmd(struct trace_seq *p, |
328 | u8 fctype, u8 *spc) |
329 | { |
330 | switch (fctype) { |
331 | case nvme_fabrics_type_property_set: |
332 | return nvme_trace_fabrics_property_set(p, spc); |
333 | case nvme_fabrics_type_connect: |
334 | return nvme_trace_fabrics_connect(p, spc); |
335 | case nvme_fabrics_type_property_get: |
336 | return nvme_trace_fabrics_property_get(p, spc); |
337 | case nvme_fabrics_type_auth_send: |
338 | return nvme_trace_fabrics_auth_send(p, spc); |
339 | case nvme_fabrics_type_auth_receive: |
340 | return nvme_trace_fabrics_auth_receive(p, spc); |
341 | default: |
342 | return nvme_trace_fabrics_common(p, spc); |
343 | } |
344 | } |
345 | |
346 | const char *nvme_trace_disk_name(struct trace_seq *p, char *name) |
347 | { |
348 | const char *ret = trace_seq_buffer_ptr(s: p); |
349 | |
350 | if (*name) |
351 | trace_seq_printf(s: p, fmt: "disk=%s, " , name); |
352 | trace_seq_putc(s: p, c: 0); |
353 | |
354 | return ret; |
355 | } |
356 | |
357 | EXPORT_TRACEPOINT_SYMBOL_GPL(nvme_sq); |
358 | |