linux/drivers/scsi/scsi_trace.c
<<
>>
Prefs
   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
  14static const char *
  15scsi_trace_misc(struct trace_seq *, unsigned char *, int);
  16
  17static const char *
  18scsi_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
  35static const char *
  36scsi_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
  60static const char *
  61scsi_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
  83static const char *
  84scsi_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
 114static const char *
 115scsi_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
 163out:
 164        trace_seq_putc(p, 0);
 165
 166        return ret;
 167}
 168
 169static const char *
 170scsi_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
 181static const char *
 182scsi_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
 216out:
 217        trace_seq_putc(p, 0);
 218
 219        return ret;
 220}
 221
 222static const char *
 223scsi_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
 262out:
 263        trace_seq_putc(p, 0);
 264
 265        return ret;
 266}
 267
 268static const char *
 269scsi_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
 302out:
 303        trace_seq_putc(p, 0);
 304
 305        return ret;
 306}
 307
 308static const char *
 309scsi_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
 333out:
 334        trace_seq_putc(p, 0);
 335
 336        return ret;
 337}
 338
 339static const char *
 340scsi_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
 368out:
 369        trace_seq_putc(p, 0);
 370
 371        return ret;
 372}
 373
 374static const char *
 375scsi_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
 388static const char *
 389scsi_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
 399const char *
 400scsi_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