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