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