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(p); 13 u16 sqid = get_unaligned_le16(cdw10); 14 15 trace_seq_printf(p, "sqid=%u", sqid); 16 trace_seq_putc(p, 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(p); 24 u16 sqid = get_unaligned_le16(cdw10); 25 u16 qsize = get_unaligned_le16(cdw10 + 2); 26 u16 sq_flags = get_unaligned_le16(cdw10 + 4); 27 u16 cqid = get_unaligned_le16(cdw10 + 6); 28 29 30 trace_seq_printf(p, "sqid=%u, qsize=%u, sq_flags=0x%x, cqid=%u", 31 sqid, qsize, sq_flags, cqid); 32 trace_seq_putc(p, 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(p); 40 u16 cqid = get_unaligned_le16(cdw10); 41 42 trace_seq_printf(p, "cqid=%u", cqid); 43 trace_seq_putc(p, 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(p); 51 u16 cqid = get_unaligned_le16(cdw10); 52 u16 qsize = get_unaligned_le16(cdw10 + 2); 53 u16 cq_flags = get_unaligned_le16(cdw10 + 4); 54 u16 irq_vector = get_unaligned_le16(cdw10 + 6); 55 56 trace_seq_printf(p, "cqid=%u, qsize=%u, cq_flags=0x%x, irq_vector=%u", 57 cqid, qsize, cq_flags, irq_vector); 58 trace_seq_putc(p, 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(p); 66 u8 cns = cdw10[0]; 67 u16 ctrlid = get_unaligned_le16(cdw10 + 2); 68 69 trace_seq_printf(p, "cns=%u, ctrlid=%u", cns, ctrlid); 70 trace_seq_putc(p, 0); 71 72 return ret; 73 } 74 75 static const char *nvme_trace_admin_get_features(struct trace_seq *p, 76 u8 *cdw10) 77 { 78 const char *ret = trace_seq_buffer_ptr(p); 79 u8 fid = cdw10[0]; 80 u8 sel = cdw10[1] & 0x7; 81 u32 cdw11 = get_unaligned_le32(cdw10 + 4); 82 83 trace_seq_printf(p, "fid=0x%x sel=0x%x cdw11=0x%x", fid, sel, cdw11); 84 trace_seq_putc(p, 0); 85 86 return ret; 87 } 88 89 static const char *nvme_trace_get_lba_status(struct trace_seq *p, 90 u8 *cdw10) 91 { 92 const char *ret = trace_seq_buffer_ptr(p); 93 u64 slba = get_unaligned_le64(cdw10); 94 u32 mndw = get_unaligned_le32(cdw10 + 8); 95 u16 rl = get_unaligned_le16(cdw10 + 12); 96 u8 atype = cdw10[15]; 97 98 trace_seq_printf(p, "slba=0x%llx, mndw=0x%x, rl=0x%x, atype=%u", 99 slba, mndw, rl, atype); 100 trace_seq_putc(p, 0); 101 102 return ret; 103 } 104 105 static const char *nvme_trace_read_write(struct trace_seq *p, u8 *cdw10) 106 { 107 const char *ret = trace_seq_buffer_ptr(p); 108 u64 slba = get_unaligned_le64(cdw10); 109 u16 length = get_unaligned_le16(cdw10 + 8); 110 u16 control = get_unaligned_le16(cdw10 + 10); 111 u32 dsmgmt = get_unaligned_le32(cdw10 + 12); 112 u32 reftag = get_unaligned_le32(cdw10 + 16); 113 114 trace_seq_printf(p, 115 "slba=%llu, len=%u, ctrl=0x%x, dsmgmt=%u, reftag=%u", 116 slba, length, control, dsmgmt, reftag); 117 trace_seq_putc(p, 0); 118 119 return ret; 120 } 121 122 static const char *nvme_trace_dsm(struct trace_seq *p, u8 *cdw10) 123 { 124 const char *ret = trace_seq_buffer_ptr(p); 125 126 trace_seq_printf(p, "nr=%u, attributes=%u", 127 get_unaligned_le32(cdw10), 128 get_unaligned_le32(cdw10 + 4)); 129 trace_seq_putc(p, 0); 130 131 return ret; 132 } 133 134 static const char *nvme_trace_common(struct trace_seq *p, u8 *cdw10) 135 { 136 const char *ret = trace_seq_buffer_ptr(p); 137 138 trace_seq_printf(p, "cdw10=%*ph", 24, cdw10); 139 trace_seq_putc(p, 0); 140 141 return ret; 142 } 143 144 const char *nvme_trace_parse_admin_cmd(struct trace_seq *p, 145 u8 opcode, u8 *cdw10) 146 { 147 switch (opcode) { 148 case nvme_admin_delete_sq: 149 return nvme_trace_delete_sq(p, cdw10); 150 case nvme_admin_create_sq: 151 return nvme_trace_create_sq(p, cdw10); 152 case nvme_admin_delete_cq: 153 return nvme_trace_delete_cq(p, cdw10); 154 case nvme_admin_create_cq: 155 return nvme_trace_create_cq(p, cdw10); 156 case nvme_admin_identify: 157 return nvme_trace_admin_identify(p, cdw10); 158 case nvme_admin_get_features: 159 return nvme_trace_admin_get_features(p, cdw10); 160 case nvme_admin_get_lba_status: 161 return nvme_trace_get_lba_status(p, cdw10); 162 default: 163 return nvme_trace_common(p, cdw10); 164 } 165 } 166 167 const char *nvme_trace_parse_nvm_cmd(struct trace_seq *p, 168 u8 opcode, u8 *cdw10) 169 { 170 switch (opcode) { 171 case nvme_cmd_read: 172 case nvme_cmd_write: 173 case nvme_cmd_write_zeroes: 174 return nvme_trace_read_write(p, cdw10); 175 case nvme_cmd_dsm: 176 return nvme_trace_dsm(p, cdw10); 177 default: 178 return nvme_trace_common(p, cdw10); 179 } 180 } 181 182 static const char *nvme_trace_fabrics_property_set(struct trace_seq *p, u8 *spc) 183 { 184 const char *ret = trace_seq_buffer_ptr(p); 185 u8 attrib = spc[0]; 186 u32 ofst = get_unaligned_le32(spc + 4); 187 u64 value = get_unaligned_le64(spc + 8); 188 189 trace_seq_printf(p, "attrib=%u, ofst=0x%x, value=0x%llx", 190 attrib, ofst, value); 191 trace_seq_putc(p, 0); 192 return ret; 193 } 194 195 static const char *nvme_trace_fabrics_connect(struct trace_seq *p, u8 *spc) 196 { 197 const char *ret = trace_seq_buffer_ptr(p); 198 u16 recfmt = get_unaligned_le16(spc); 199 u16 qid = get_unaligned_le16(spc + 2); 200 u16 sqsize = get_unaligned_le16(spc + 4); 201 u8 cattr = spc[6]; 202 u32 kato = get_unaligned_le32(spc + 8); 203 204 trace_seq_printf(p, "recfmt=%u, qid=%u, sqsize=%u, cattr=%u, kato=%u", 205 recfmt, qid, sqsize, cattr, kato); 206 trace_seq_putc(p, 0); 207 return ret; 208 } 209 210 static const char *nvme_trace_fabrics_property_get(struct trace_seq *p, u8 *spc) 211 { 212 const char *ret = trace_seq_buffer_ptr(p); 213 u8 attrib = spc[0]; 214 u32 ofst = get_unaligned_le32(spc + 4); 215 216 trace_seq_printf(p, "attrib=%u, ofst=0x%x", attrib, ofst); 217 trace_seq_putc(p, 0); 218 return ret; 219 } 220 221 static const char *nvme_trace_fabrics_common(struct trace_seq *p, u8 *spc) 222 { 223 const char *ret = trace_seq_buffer_ptr(p); 224 225 trace_seq_printf(p, "specific=%*ph", 24, spc); 226 trace_seq_putc(p, 0); 227 return ret; 228 } 229 230 const char *nvme_trace_parse_fabrics_cmd(struct trace_seq *p, 231 u8 fctype, u8 *spc) 232 { 233 switch (fctype) { 234 case nvme_fabrics_type_property_set: 235 return nvme_trace_fabrics_property_set(p, spc); 236 case nvme_fabrics_type_connect: 237 return nvme_trace_fabrics_connect(p, spc); 238 case nvme_fabrics_type_property_get: 239 return nvme_trace_fabrics_property_get(p, spc); 240 default: 241 return nvme_trace_fabrics_common(p, spc); 242 } 243 } 244 245 const char *nvme_trace_disk_name(struct trace_seq *p, char *name) 246 { 247 const char *ret = trace_seq_buffer_ptr(p); 248 249 if (*name) 250 trace_seq_printf(p, "disk=%s, ", name); 251 trace_seq_putc(p, 0); 252 253 return ret; 254 } 255 256 EXPORT_TRACEPOINT_SYMBOL_GPL(nvme_sq); 257