summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/ufs/ufshcd.c52
-rw-r--r--include/trace/events/ufs.h38
2 files changed, 89 insertions, 1 deletions
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index ebbc9f00685e..764442247c08 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -337,6 +337,51 @@ static inline void ufshcd_remove_non_printable(char *val)
*val = ' ';
}
+#ifdef CONFIG_TRACEPOINTS
+static void ufshcd_add_command_trace(struct ufs_hba *hba,
+ unsigned int tag, const char *str)
+{
+ sector_t lba = -1;
+ u8 opcode = 0;
+ u32 intr, doorbell;
+ struct ufshcd_lrb *lrbp;
+ int transfer_len = -1;
+
+ lrbp = &hba->lrb[tag];
+
+ if (lrbp->cmd) { /* data phase exists */
+ opcode = (u8)(*lrbp->cmd->cmnd);
+ if ((opcode == READ_10) || (opcode == WRITE_10)) {
+ /*
+ * Currently we only fully trace read(10) and write(10)
+ * commands
+ */
+ if (lrbp->cmd->request && lrbp->cmd->request->bio)
+ lba =
+ lrbp->cmd->request->bio->bi_iter.bi_sector;
+ transfer_len = be32_to_cpu(
+ lrbp->ucd_req_ptr->sc.exp_data_transfer_len);
+ }
+ }
+
+ intr = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
+ doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ trace_ufshcd_command(dev_name(hba->dev), str, tag,
+ doorbell, transfer_len, intr, lba, opcode);
+}
+
+static inline void ufshcd_cond_add_cmd_trace(struct ufs_hba *hba,
+ unsigned int tag, const char *str)
+{
+ ufshcd_add_command_trace(hba, tag, str);
+}
+#else
+static inline void ufshcd_cond_add_cmd_trace(struct ufs_hba *hba,
+ unsigned int tag, const char *str)
+{
+}
+#endif
+
static void ufshcd_print_host_regs(struct ufs_hba *hba)
{
/*
@@ -1656,6 +1701,7 @@ int ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
/* Make sure that doorbell is commited immediately */
wmb();
+ ufshcd_cond_add_cmd_trace(hba, task_tag, "send");
UFSHCD_UPDATE_TAG_STATS(hba, task_tag);
return ret;
}
@@ -4475,6 +4521,7 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
lrbp = &hba->lrb[index];
cmd = lrbp->cmd;
if (cmd) {
+ ufshcd_cond_add_cmd_trace(hba, index, "complete");
UFSHCD_UPDATE_TAG_STATS_COMPLETION(hba, cmd);
result = ufshcd_transfer_rsp_status(hba, lrbp);
scsi_dma_unmap(cmd);
@@ -4488,8 +4535,11 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
__ufshcd_pm_qos_release(hba);
__ufshcd_hibern8_release(hba);
} else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) {
- if (hba->dev_cmd.complete)
+ if (hba->dev_cmd.complete) {
+ ufshcd_cond_add_cmd_trace(hba, index,
+ "dev_complete");
complete(hba->dev_cmd.complete);
+ }
}
}
diff --git a/include/trace/events/ufs.h b/include/trace/events/ufs.h
index b239bbb43b62..5dea878179f6 100644
--- a/include/trace/events/ufs.h
+++ b/include/trace/events/ufs.h
@@ -203,6 +203,44 @@ DEFINE_EVENT(ufshcd_template, ufshcd_init,
TP_PROTO(const char *dev_name, int err, s64 usecs,
const char *dev_state, const char *link_state),
TP_ARGS(dev_name, err, usecs, dev_state, link_state));
+
+TRACE_EVENT(ufshcd_command,
+ TP_PROTO(const char *dev_name, const char *str, unsigned int tag,
+ u32 doorbell, int transfer_len, u32 intr, u64 lba,
+ u8 opcode),
+
+ TP_ARGS(dev_name, str, tag, doorbell, transfer_len, intr, lba, opcode),
+
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name)
+ __string(str, str)
+ __field(unsigned int, tag)
+ __field(u32, doorbell)
+ __field(int, transfer_len)
+ __field(u32, intr)
+ __field(u64, lba)
+ __field(u8, opcode)
+ ),
+
+ TP_fast_assign(
+ __assign_str(dev_name, dev_name);
+ __assign_str(str, str);
+ __entry->tag = tag;
+ __entry->doorbell = doorbell;
+ __entry->transfer_len = transfer_len;
+ __entry->intr = intr;
+ __entry->lba = lba;
+ __entry->opcode = opcode;
+ ),
+
+ TP_printk(
+ "%s: %s: tag: %u, DB: 0x%x, size: %d, IS: %u, LBA: %llu, opcode: 0x%x",
+ __get_str(str), __get_str(dev_name), __entry->tag,
+ __entry->doorbell, __entry->transfer_len,
+ __entry->intr, __entry->lba, (u32)__entry->opcode
+ )
+);
+
#endif /* if !defined(_TRACE_UFS_H) || defined(TRACE_HEADER_MULTI_READ) */
/* This part must be outside protection */