Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5021cdab authored by Lee Susman's avatar Lee Susman
Browse files

scsi: ufs: add trace event for ufs commands



Use the ftrace infrastructure to conditionally trace ufs command events.
New trace event is created, which samples the following ufs command data:
- device name
- optional identification string
- task tag
- doorbell register
- number of transfer bytes
- interrupt status register
- request start LBA
- command opcode

Currently we only fully trace read(10) and write(10) commands.
All other commands which pass through ufshcd_send_command() will be
printed with "-1" in the lba and transfer_len fields.

Usage:
	echo 1 > /sys/kernel/debug/tracing/events/ufs/enable
	cat /sys/kernel/debug/tracing/trace_pipe

Change-Id: Id6e16a8c0b2a833c5453ed9923384f641e374a71
Signed-off-by: default avatarLee Susman <lsusman@codeaurora.org>
parent 104105f6
Loading
Loading
Loading
Loading
+51 −1
Original line number Diff line number Diff line
@@ -310,6 +310,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_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)
{
	if (FTRACE_EVENT_ENABLED(ufshcd_command))
		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)
{
	/*
@@ -1061,6 +1106,7 @@ void ufshcd_send_command(struct ufs_hba *hba, unsigned int task_tag)
	ufshcd_clk_scaling_start_busy(hba);
	__set_bit(task_tag, &hba->outstanding_reqs);
	ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
	ufshcd_cond_add_cmd_trace(hba, task_tag, "send");
	UFSHCD_UPDATE_TAG_STATS(hba, task_tag);
}

@@ -3632,6 +3678,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);
@@ -3643,10 +3690,13 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba)
			cmd->scsi_done(cmd);
			__ufshcd_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);
			}
		}
	}

	/* clear corresponding bits of completed commands */
	hba->outstanding_reqs ^= completed_reqs;
+38 −0
Original line number Diff line number Diff line
@@ -143,6 +143,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 */