162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci#include <linux/bitops.h> 362306a36Sopenharmony_ci#include <linux/seq_file.h> 462306a36Sopenharmony_ci#include <scsi/scsi_cmnd.h> 562306a36Sopenharmony_ci#include <scsi/scsi_dbg.h> 662306a36Sopenharmony_ci#include <scsi/scsi_host.h> 762306a36Sopenharmony_ci#include "scsi_debugfs.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#define SCSI_CMD_FLAG_NAME(name)[const_ilog2(SCMD_##name)] = #name 1062306a36Sopenharmony_cistatic const char *const scsi_cmd_flags[] = { 1162306a36Sopenharmony_ci SCSI_CMD_FLAG_NAME(TAGGED), 1262306a36Sopenharmony_ci SCSI_CMD_FLAG_NAME(INITIALIZED), 1362306a36Sopenharmony_ci SCSI_CMD_FLAG_NAME(LAST), 1462306a36Sopenharmony_ci}; 1562306a36Sopenharmony_ci#undef SCSI_CMD_FLAG_NAME 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_cistatic int scsi_flags_show(struct seq_file *m, const unsigned long flags, 1862306a36Sopenharmony_ci const char *const *flag_name, int flag_name_count) 1962306a36Sopenharmony_ci{ 2062306a36Sopenharmony_ci bool sep = false; 2162306a36Sopenharmony_ci int i; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci for_each_set_bit(i, &flags, BITS_PER_LONG) { 2462306a36Sopenharmony_ci if (sep) 2562306a36Sopenharmony_ci seq_puts(m, "|"); 2662306a36Sopenharmony_ci sep = true; 2762306a36Sopenharmony_ci if (i < flag_name_count && flag_name[i]) 2862306a36Sopenharmony_ci seq_puts(m, flag_name[i]); 2962306a36Sopenharmony_ci else 3062306a36Sopenharmony_ci seq_printf(m, "%d", i); 3162306a36Sopenharmony_ci } 3262306a36Sopenharmony_ci return 0; 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_civoid scsi_show_rq(struct seq_file *m, struct request *rq) 3662306a36Sopenharmony_ci{ 3762306a36Sopenharmony_ci struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq), *cmd2; 3862306a36Sopenharmony_ci struct Scsi_Host *shost = cmd->device->host; 3962306a36Sopenharmony_ci int alloc_ms = jiffies_to_msecs(jiffies - cmd->jiffies_at_alloc); 4062306a36Sopenharmony_ci int timeout_ms = jiffies_to_msecs(rq->timeout); 4162306a36Sopenharmony_ci const char *list_info = NULL; 4262306a36Sopenharmony_ci char buf[80] = "(?)"; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci spin_lock_irq(shost->host_lock); 4562306a36Sopenharmony_ci list_for_each_entry(cmd2, &shost->eh_abort_list, eh_entry) { 4662306a36Sopenharmony_ci if (cmd == cmd2) { 4762306a36Sopenharmony_ci list_info = "on eh_abort_list"; 4862306a36Sopenharmony_ci goto unlock; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci list_for_each_entry(cmd2, &shost->eh_cmd_q, eh_entry) { 5262306a36Sopenharmony_ci if (cmd == cmd2) { 5362306a36Sopenharmony_ci list_info = "on eh_cmd_q"; 5462306a36Sopenharmony_ci goto unlock; 5562306a36Sopenharmony_ci } 5662306a36Sopenharmony_ci } 5762306a36Sopenharmony_ciunlock: 5862306a36Sopenharmony_ci spin_unlock_irq(shost->host_lock); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci __scsi_format_command(buf, sizeof(buf), cmd->cmnd, cmd->cmd_len); 6162306a36Sopenharmony_ci seq_printf(m, ", .cmd=%s, .retries=%d, .allowed=%d, .result = %#x, %s%s.flags=", 6262306a36Sopenharmony_ci buf, cmd->retries, cmd->allowed, cmd->result, 6362306a36Sopenharmony_ci list_info ? : "", list_info ? ", " : ""); 6462306a36Sopenharmony_ci scsi_flags_show(m, cmd->flags, scsi_cmd_flags, 6562306a36Sopenharmony_ci ARRAY_SIZE(scsi_cmd_flags)); 6662306a36Sopenharmony_ci seq_printf(m, ", .timeout=%d.%03d, allocated %d.%03d s ago", 6762306a36Sopenharmony_ci timeout_ms / 1000, timeout_ms % 1000, 6862306a36Sopenharmony_ci alloc_ms / 1000, alloc_ms % 1000); 6962306a36Sopenharmony_ci} 70