Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Copyright (C) 2010 FUJITSU LIMITED
0004  * Copyright (C) 2010 Tomohiro Kusumi <kusumi.tomohiro@jp.fujitsu.com>
0005  */
0006 #include <linux/kernel.h>
0007 #include <linux/trace_seq.h>
0008 #include <asm/unaligned.h>
0009 #include <trace/events/scsi.h>
0010 
0011 #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
0012 #define SERVICE_ACTION32(cdb) (get_unaligned_be16(&cdb[8]))
0013 
0014 static const char *
0015 scsi_trace_misc(struct trace_seq *, unsigned char *, int);
0016 
0017 static const char *
0018 scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
0019 {
0020     const char *ret = trace_seq_buffer_ptr(p);
0021     u32 lba, txlen;
0022 
0023     lba = get_unaligned_be24(&cdb[1]) & 0x1fffff;
0024     /*
0025      * From SBC-2: a TRANSFER LENGTH field set to zero specifies that 256
0026      * logical blocks shall be read (READ(6)) or written (WRITE(6)).
0027      */
0028     txlen = cdb[4] ? cdb[4] : 256;
0029 
0030     trace_seq_printf(p, "lba=%u txlen=%u", lba, txlen);
0031     trace_seq_putc(p, 0);
0032 
0033     return ret;
0034 }
0035 
0036 static const char *
0037 scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
0038 {
0039     const char *ret = trace_seq_buffer_ptr(p);
0040     u32 lba, txlen;
0041 
0042     lba = get_unaligned_be32(&cdb[2]);
0043     txlen = get_unaligned_be16(&cdb[7]);
0044 
0045     trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen,
0046              cdb[1] >> 5);
0047 
0048     if (cdb[0] == WRITE_SAME)
0049         trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
0050 
0051     trace_seq_putc(p, 0);
0052 
0053     return ret;
0054 }
0055 
0056 static const char *
0057 scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
0058 {
0059     const char *ret = trace_seq_buffer_ptr(p);
0060     u32 lba, txlen;
0061 
0062     lba = get_unaligned_be32(&cdb[2]);
0063     txlen = get_unaligned_be32(&cdb[6]);
0064 
0065     trace_seq_printf(p, "lba=%u txlen=%u protect=%u", lba, txlen,
0066              cdb[1] >> 5);
0067     trace_seq_putc(p, 0);
0068 
0069     return ret;
0070 }
0071 
0072 static const char *
0073 scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
0074 {
0075     const char *ret = trace_seq_buffer_ptr(p);
0076     u64 lba;
0077     u32 txlen;
0078 
0079     lba = get_unaligned_be64(&cdb[2]);
0080     txlen = get_unaligned_be32(&cdb[10]);
0081 
0082     trace_seq_printf(p, "lba=%llu txlen=%u protect=%u", lba, txlen,
0083              cdb[1] >> 5);
0084 
0085     if (cdb[0] == WRITE_SAME_16)
0086         trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
0087 
0088     trace_seq_putc(p, 0);
0089 
0090     return ret;
0091 }
0092 
0093 static const char *
0094 scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
0095 {
0096     const char *ret = trace_seq_buffer_ptr(p), *cmd;
0097     u64 lba;
0098     u32 ei_lbrt, txlen;
0099 
0100     switch (SERVICE_ACTION32(cdb)) {
0101     case READ_32:
0102         cmd = "READ";
0103         break;
0104     case VERIFY_32:
0105         cmd = "VERIFY";
0106         break;
0107     case WRITE_32:
0108         cmd = "WRITE";
0109         break;
0110     case WRITE_SAME_32:
0111         cmd = "WRITE_SAME";
0112         break;
0113     default:
0114         trace_seq_puts(p, "UNKNOWN");
0115         goto out;
0116     }
0117 
0118     lba = get_unaligned_be64(&cdb[12]);
0119     ei_lbrt = get_unaligned_be32(&cdb[20]);
0120     txlen = get_unaligned_be32(&cdb[28]);
0121 
0122     trace_seq_printf(p, "%s_32 lba=%llu txlen=%u protect=%u ei_lbrt=%u",
0123              cmd, lba, txlen, cdb[10] >> 5, ei_lbrt);
0124 
0125     if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
0126         trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
0127 
0128 out:
0129     trace_seq_putc(p, 0);
0130 
0131     return ret;
0132 }
0133 
0134 static const char *
0135 scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
0136 {
0137     const char *ret = trace_seq_buffer_ptr(p);
0138     unsigned int regions = get_unaligned_be16(&cdb[7]);
0139 
0140     trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
0141     trace_seq_putc(p, 0);
0142 
0143     return ret;
0144 }
0145 
0146 static const char *
0147 scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
0148 {
0149     const char *ret = trace_seq_buffer_ptr(p), *cmd;
0150     u64 lba;
0151     u32 alloc_len;
0152 
0153     switch (SERVICE_ACTION16(cdb)) {
0154     case SAI_READ_CAPACITY_16:
0155         cmd = "READ_CAPACITY_16";
0156         break;
0157     case SAI_GET_LBA_STATUS:
0158         cmd = "GET_LBA_STATUS";
0159         break;
0160     default:
0161         trace_seq_puts(p, "UNKNOWN");
0162         goto out;
0163     }
0164 
0165     lba = get_unaligned_be64(&cdb[2]);
0166     alloc_len = get_unaligned_be32(&cdb[10]);
0167 
0168     trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd, lba, alloc_len);
0169 
0170 out:
0171     trace_seq_putc(p, 0);
0172 
0173     return ret;
0174 }
0175 
0176 static const char *
0177 scsi_trace_maintenance_in(struct trace_seq *p, unsigned char *cdb, int len)
0178 {
0179     const char *ret = trace_seq_buffer_ptr(p), *cmd;
0180     u32 alloc_len;
0181 
0182     switch (SERVICE_ACTION16(cdb)) {
0183     case MI_REPORT_IDENTIFYING_INFORMATION:
0184         cmd = "REPORT_IDENTIFYING_INFORMATION";
0185         break;
0186     case MI_REPORT_TARGET_PGS:
0187         cmd = "REPORT_TARGET_PORT_GROUPS";
0188         break;
0189     case MI_REPORT_ALIASES:
0190         cmd = "REPORT_ALIASES";
0191         break;
0192     case MI_REPORT_SUPPORTED_OPERATION_CODES:
0193         cmd = "REPORT_SUPPORTED_OPERATION_CODES";
0194         break;
0195     case MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS:
0196         cmd = "REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS";
0197         break;
0198     case MI_REPORT_PRIORITY:
0199         cmd = "REPORT_PRIORITY";
0200         break;
0201     case MI_REPORT_TIMESTAMP:
0202         cmd = "REPORT_TIMESTAMP";
0203         break;
0204     case MI_MANAGEMENT_PROTOCOL_IN:
0205         cmd = "MANAGEMENT_PROTOCOL_IN";
0206         break;
0207     default:
0208         trace_seq_puts(p, "UNKNOWN");
0209         goto out;
0210     }
0211 
0212     alloc_len = get_unaligned_be32(&cdb[6]);
0213 
0214     trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len);
0215 
0216 out:
0217     trace_seq_putc(p, 0);
0218 
0219     return ret;
0220 }
0221 
0222 static const char *
0223 scsi_trace_maintenance_out(struct trace_seq *p, unsigned char *cdb, int len)
0224 {
0225     const char *ret = trace_seq_buffer_ptr(p), *cmd;
0226     u32 alloc_len;
0227 
0228     switch (SERVICE_ACTION16(cdb)) {
0229     case MO_SET_IDENTIFYING_INFORMATION:
0230         cmd = "SET_IDENTIFYING_INFORMATION";
0231         break;
0232     case MO_SET_TARGET_PGS:
0233         cmd = "SET_TARGET_PORT_GROUPS";
0234         break;
0235     case MO_CHANGE_ALIASES:
0236         cmd = "CHANGE_ALIASES";
0237         break;
0238     case MO_SET_PRIORITY:
0239         cmd = "SET_PRIORITY";
0240         break;
0241     case MO_SET_TIMESTAMP:
0242         cmd = "SET_TIMESTAMP";
0243         break;
0244     case MO_MANAGEMENT_PROTOCOL_OUT:
0245         cmd = "MANAGEMENT_PROTOCOL_OUT";
0246         break;
0247     default:
0248         trace_seq_puts(p, "UNKNOWN");
0249         goto out;
0250     }
0251 
0252     alloc_len = get_unaligned_be32(&cdb[6]);
0253 
0254     trace_seq_printf(p, "%s alloc_len=%u", cmd, alloc_len);
0255 
0256 out:
0257     trace_seq_putc(p, 0);
0258 
0259     return ret;
0260 }
0261 
0262 static const char *
0263 scsi_trace_zbc_in(struct trace_seq *p, unsigned char *cdb, int len)
0264 {
0265     const char *ret = trace_seq_buffer_ptr(p), *cmd;
0266     u64 zone_id;
0267     u32 alloc_len;
0268     u8 options;
0269 
0270     switch (SERVICE_ACTION16(cdb)) {
0271     case ZI_REPORT_ZONES:
0272         cmd = "REPORT_ZONES";
0273         break;
0274     default:
0275         trace_seq_puts(p, "UNKNOWN");
0276         goto out;
0277     }
0278 
0279     zone_id = get_unaligned_be64(&cdb[2]);
0280     alloc_len = get_unaligned_be32(&cdb[10]);
0281     options = cdb[14] & 0x3f;
0282 
0283     trace_seq_printf(p, "%s zone=%llu alloc_len=%u options=%u partial=%u",
0284              cmd, (unsigned long long)zone_id, alloc_len,
0285              options, (cdb[14] >> 7) & 1);
0286 
0287 out:
0288     trace_seq_putc(p, 0);
0289 
0290     return ret;
0291 }
0292 
0293 static const char *
0294 scsi_trace_zbc_out(struct trace_seq *p, unsigned char *cdb, int len)
0295 {
0296     const char *ret = trace_seq_buffer_ptr(p), *cmd;
0297     u64 zone_id;
0298 
0299     switch (SERVICE_ACTION16(cdb)) {
0300     case ZO_CLOSE_ZONE:
0301         cmd = "CLOSE_ZONE";
0302         break;
0303     case ZO_FINISH_ZONE:
0304         cmd = "FINISH_ZONE";
0305         break;
0306     case ZO_OPEN_ZONE:
0307         cmd = "OPEN_ZONE";
0308         break;
0309     case ZO_RESET_WRITE_POINTER:
0310         cmd = "RESET_WRITE_POINTER";
0311         break;
0312     default:
0313         trace_seq_puts(p, "UNKNOWN");
0314         goto out;
0315     }
0316 
0317     zone_id = get_unaligned_be64(&cdb[2]);
0318 
0319     trace_seq_printf(p, "%s zone=%llu all=%u", cmd,
0320              (unsigned long long)zone_id, cdb[14] & 1);
0321 
0322 out:
0323     trace_seq_putc(p, 0);
0324 
0325     return ret;
0326 }
0327 
0328 static const char *
0329 scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
0330 {
0331     switch (SERVICE_ACTION32(cdb)) {
0332     case READ_32:
0333     case VERIFY_32:
0334     case WRITE_32:
0335     case WRITE_SAME_32:
0336         return scsi_trace_rw32(p, cdb, len);
0337     default:
0338         return scsi_trace_misc(p, cdb, len);
0339     }
0340 }
0341 
0342 static const char *
0343 scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
0344 {
0345     const char *ret = trace_seq_buffer_ptr(p);
0346 
0347     trace_seq_putc(p, '-');
0348     trace_seq_putc(p, 0);
0349 
0350     return ret;
0351 }
0352 
0353 const char *
0354 scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
0355 {
0356     switch (cdb[0]) {
0357     case READ_6:
0358     case WRITE_6:
0359         return scsi_trace_rw6(p, cdb, len);
0360     case READ_10:
0361     case VERIFY:
0362     case WRITE_10:
0363     case WRITE_SAME:
0364         return scsi_trace_rw10(p, cdb, len);
0365     case READ_12:
0366     case VERIFY_12:
0367     case WRITE_12:
0368         return scsi_trace_rw12(p, cdb, len);
0369     case READ_16:
0370     case VERIFY_16:
0371     case WRITE_16:
0372     case WRITE_SAME_16:
0373         return scsi_trace_rw16(p, cdb, len);
0374     case UNMAP:
0375         return scsi_trace_unmap(p, cdb, len);
0376     case SERVICE_ACTION_IN_16:
0377         return scsi_trace_service_action_in(p, cdb, len);
0378     case VARIABLE_LENGTH_CMD:
0379         return scsi_trace_varlen(p, cdb, len);
0380     case MAINTENANCE_IN:
0381         return scsi_trace_maintenance_in(p, cdb, len);
0382     case MAINTENANCE_OUT:
0383         return scsi_trace_maintenance_out(p, cdb, len);
0384     case ZBC_IN:
0385         return scsi_trace_zbc_in(p, cdb, len);
0386     case ZBC_OUT:
0387         return scsi_trace_zbc_out(p, cdb, len);
0388     default:
0389         return scsi_trace_misc(p, cdb, len);
0390     }
0391 }