| 1 | |
| 2 | #include <linux/bitops.h>
|
| 3 | #include <linux/cleanup.h>
|
| 4 | #include <linux/seq_file.h>
|
| 5 | #include <scsi/scsi_cmnd.h>
|
| 6 | #include <scsi/scsi_dbg.h>
|
| 7 | #include <scsi/scsi_host.h>
|
| 8 | #include "scsi_debugfs.h"
|
| 9 |
|
| 10 | #define SCSI_CMD_FLAG_NAME(name)[const_ilog2(SCMD_##name)] = #name
|
| 11 | static const char *const scsi_cmd_flags[] = {
|
| 12 | SCSI_CMD_FLAG_NAME(TAGGED),
|
| 13 | SCSI_CMD_FLAG_NAME(INITIALIZED),
|
| 14 | SCSI_CMD_FLAG_NAME(LAST),
|
| 15 | };
|
| 16 | #undef SCSI_CMD_FLAG_NAME
|
| 17 |
|
| 18 | static int scsi_flags_show(struct seq_file *m, const unsigned long flags,
|
| 19 | const char *const *flag_name, int flag_name_count)
|
| 20 | {
|
| 21 | bool sep = false;
|
| 22 | int i;
|
| 23 |
|
| 24 | for_each_set_bit(i, &flags, BITS_PER_LONG) {
|
| 25 | if (sep)
|
| 26 | seq_puts(m, "|");
|
| 27 | sep = true;
|
| 28 | if (i < flag_name_count && flag_name[i])
|
| 29 | seq_puts(m, flag_name[i]);
|
| 30 | else
|
| 31 | seq_printf(m, "%d", i);
|
| 32 | }
|
| 33 | return 0;
|
| 34 | }
|
| 35 |
|
| 36 | static const char *scsi_cmd_list_info(struct scsi_cmnd *cmd)
|
| 37 | {
|
| 38 | struct Scsi_Host *shost = cmd->device->host;
|
| 39 | struct scsi_cmnd *cmd2;
|
| 40 |
|
| 41 | guard(spinlock_irq)(shost->host_lock);
|
| 42 |
|
| 43 | list_for_each_entry(cmd2, &shost->eh_abort_list, eh_entry)
|
| 44 | if (cmd == cmd2)
|
| 45 | return "on eh_abort_list";
|
| 46 |
|
| 47 | list_for_each_entry(cmd2, &shost->eh_cmd_q, eh_entry)
|
| 48 | if (cmd == cmd2)
|
| 49 | return "on eh_cmd_q";
|
| 50 |
|
| 51 | return NULL;
|
| 52 | }
|
| 53 |
|
| 54 | void scsi_show_rq(struct seq_file *m, struct request *rq)
|
| 55 | {
|
| 56 | struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
|
| 57 | int alloc_ms = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc);
|
| 58 | int timeout_ms = jiffies_to_msecs(rq->timeout);
|
| 59 | char buf[80] = "(?)";
|
| 60 |
|
| 61 | if (cmd->flags & SCMD_INITIALIZED) {
|
| 62 | const char *list_info = scsi_cmd_list_info(cmd);
|
| 63 |
|
| 64 | __scsi_format_command(buf, sizeof(buf), cmd->cmnd, cmd->cmd_len);
|
| 65 | seq_printf(m, ", .cmd=%s, .retries=%d, .allowed=%d, .result = %#x%s%s",
|
| 66 | buf, cmd->retries, cmd->allowed, cmd->result,
|
| 67 | list_info ? ", " : "", list_info ? : "");
|
| 68 | seq_printf(m, ", .timeout=%d.%03d, allocated %d.%03d s ago",
|
| 69 | timeout_ms / 1000, timeout_ms % 1000,
|
| 70 | alloc_ms / 1000, alloc_ms % 1000);
|
| 71 | }
|
| 72 | seq_printf(m, ", .flags=");
|
| 73 | scsi_flags_show(m, cmd->flags, scsi_cmd_flags,
|
| 74 | ARRAY_SIZE(scsi_cmd_flags));
|
| 75 | }
|