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

Commit 7fe6d9ab authored by Venkat Gopalakrishnan's avatar Venkat Gopalakrishnan
Browse files

mmc: sdhci: Add tracepoints to enhance debugging



Instrument the sdhci driver with tracepoints to aid in
debugging issues and identifying latencies in the following
path:
* CMD completion
* DATA completion
* DMA preparation
* Post DMA cleanup

Change-Id: Ie8cd0c2fb6c1bd6ab13883123be021081f8b8f78
Signed-off-by: default avatarVenkat Gopalakrishnan <venkatg@codeaurora.org>
parent 6eb2af6d
Loading
Loading
Loading
Loading
+14 −5
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@
#include <linux/mmc/slot-gpio.h>
#include <linux/mmc/sdio.h>

#include <trace/events/mmc.h>

#include "sdhci.h"

#define DRIVER_NAME "sdhci"
@@ -756,6 +758,9 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
	u8 *align;
	char *buffer;
	unsigned long flags;
	u32 command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));

	trace_mmc_adma_table_post(command, data->sg_len);

	if (data->flags & MMC_DATA_READ)
		direction = DMA_FROM_DEVICE;
@@ -972,6 +977,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)

	if (host->flags & SDHCI_REQ_USE_DMA) {
		if (host->flags & SDHCI_USE_ADMA) {
			trace_mmc_adma_table_pre(cmd->opcode, data->sg_len);
			ret = sdhci_adma_table_pre(host, data);
			if (ret) {
				/*
@@ -1227,6 +1233,7 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)

	if (cmd->data)
		host->data_start_time = ktime_get();
	trace_mmc_cmd_rw_start(cmd->opcode, cmd->arg, cmd->flags);
	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
}

@@ -2786,6 +2793,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
		return;
	}

	trace_mmc_cmd_rw_end(host->cmd->opcode, intmask,
				sdhci_readl(host, SDHCI_RESPONSE));

	if (intmask & SDHCI_INT_TIMEOUT)
		host->cmd->error = -ETIMEDOUT;
	else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
@@ -2882,9 +2892,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
	bool pr_msg = false;
	BUG_ON(intmask == 0);

	command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
	trace_mmc_data_rw_end(command, intmask);

	/* CMD19 generates _only_ Buffer Read Ready interrupt */
	if (intmask & SDHCI_INT_DATA_AVAIL) {
		command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
		if (command == MMC_SEND_TUNING_BLOCK ||
		    command == MMC_SEND_TUNING_BLOCK_HS200 ||
		    command == MMC_SEND_TUNING_BLOCK_HS400) {
@@ -2923,8 +2935,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
	else if (intmask & SDHCI_INT_DATA_END_BIT)
		host->data->error = -EILSEQ;
	else if ((intmask & SDHCI_INT_DATA_CRC) &&
		SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND))
			!= MMC_BUS_TEST_R)
		(command != MMC_BUS_TEST_R))
		host->data->error = -EILSEQ;
	else if (intmask & SDHCI_INT_ADMA_ERROR) {
		pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
@@ -2935,8 +2946,6 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
	}
	if (host->data->error) {
		if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT)) {
			command = SDHCI_GET_CMD(sdhci_readw(host,
							    SDHCI_COMMAND));
			if ((command != MMC_SEND_TUNING_BLOCK_HS400) &&
			    (command != MMC_SEND_TUNING_BLOCK_HS200) &&
			    (command != MMC_SEND_TUNING_BLOCK)) {
+72 −1
Original line number Diff line number Diff line
/*
 * Copyright (C) 2013 Google, Inc.
 * Copyright (c) 2013, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
 *
 * This software is licensed under the terms of the GNU General Public
 * License version 2, as published by the Free Software Foundation, and
@@ -87,6 +87,77 @@ DEFINE_EVENT_CONDITION(mmc_blk_rw_class, mmc_blk_rw_end,
		      (cmd == MMC_WRITE_MULTIPLE_BLOCK)) &&
		      data));

TRACE_EVENT(mmc_cmd_rw_start,
	TP_PROTO(unsigned int cmd, unsigned int arg, unsigned int flags),
	TP_ARGS(cmd, arg, flags),
	TP_STRUCT__entry(
		__field(unsigned int, cmd)
		__field(unsigned int, arg)
		__field(unsigned int, flags)
	),
	TP_fast_assign(
		__entry->cmd = cmd;
		__entry->arg = arg;
		__entry->flags = flags;
	),
	TP_printk("cmd=%u,arg=0x%08x,flags=0x%08x",
		  __entry->cmd, __entry->arg, __entry->flags)
);

TRACE_EVENT(mmc_cmd_rw_end,
	TP_PROTO(unsigned int cmd, unsigned int status, unsigned int resp),
	TP_ARGS(cmd, status, resp),
	TP_STRUCT__entry(
		__field(unsigned int, cmd)
		__field(unsigned int, status)
		__field(unsigned int, resp)
	),
	TP_fast_assign(
		__entry->cmd = cmd;
		__entry->status = status;
		__entry->resp = resp;
	),
	TP_printk("cmd=%u,int_status=0x%08x,response=0x%08x",
		  __entry->cmd, __entry->status, __entry->resp)
);

TRACE_EVENT(mmc_data_rw_end,
	TP_PROTO(unsigned int cmd, unsigned int status),
	TP_ARGS(cmd, status),
	TP_STRUCT__entry(
		__field(unsigned int, cmd)
		__field(unsigned int, status)
	),
	TP_fast_assign(
		__entry->cmd = cmd;
		__entry->status = status;
	),
	TP_printk("cmd=%u,int_status=0x%08x",
		  __entry->cmd, __entry->status)
);

DECLARE_EVENT_CLASS(mmc_adma_class,
	TP_PROTO(unsigned int cmd, unsigned int len),
	TP_ARGS(cmd, len),
	TP_STRUCT__entry(
		__field(unsigned int, cmd)
		__field(unsigned int, len)
	),
	TP_fast_assign(
		__entry->cmd = cmd;
		__entry->len = len;
	),
	TP_printk("cmd=%u,sg_len=0x%08x", __entry->cmd, __entry->len)
);

DEFINE_EVENT(mmc_adma_class, mmc_adma_table_pre,
	TP_PROTO(unsigned int cmd, unsigned int len),
	TP_ARGS(cmd, len));

DEFINE_EVENT(mmc_adma_class, mmc_adma_table_post,
	TP_PROTO(unsigned int cmd, unsigned int len),
	TP_ARGS(cmd, len));

TRACE_EVENT(mmc_clk,
	TP_PROTO(char *print_info),