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

Commit e9a8ea44 authored by Sarthak Garg's avatar Sarthak Garg
Browse files

mmc: sdhci: Dump registers in case of DATA CRC/timeout errors



Dump registers in case of Data CRC/timeout errors and print other
useful information.

This contains below patches as well:

4c196de7e0fd mmc: sdhci: rate limit sdhci_dumpregs() prints
16dabee056d4 mmc: sdhci: Add timestamp debug info for data timeout error
e00d878df07e mmc: sdhci: Avoid dumping registers when SD card removed.

Change-Id: I5efe8ff4bacc5da3a05829be7cac4ce40f9fc584
Signed-off-by: default avatarSarthak Garg <quic_sartgarg@quicinc.com>
parent 8cd841af
Loading
Loading
Loading
Loading
+52 −2
Original line number Diff line number Diff line
@@ -43,6 +43,11 @@

#define MAX_TUNING_LOOP 40

#if defined(CONFIG_SDC_QTI)
#define SDHCI_DBG_DUMP_RS_INTERVAL (10 * HZ)
#define SDHCI_DBG_DUMP_RS_BURST 2
#endif

static unsigned int debug_quirks = 0;
static unsigned int debug_quirks2;

@@ -1486,6 +1491,10 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
		timeout += 10 * HZ;
	sdhci_mod_timer(host, cmd->mrq, timeout);

#if defined(CONFIG_SDC_QTI)
	if (cmd->data)
		host->data_start_time = ktime_get();
#endif
	sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND);
	mmc_log_string(host->mmc,
		"updated ARGUMENT=0x%08x ARGUMENT_MODE=0x%08x COMMAND=0x%08x\n",
@@ -3127,6 +3136,10 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
{
	u32 command;

#if defined(CONFIG_SDC_QTI)
	bool pr_msg = false;
#endif

	/* CMD19 generates _only_ Buffer Read Ready interrupt */
	if (intmask & SDHCI_INT_DATA_AVAIL) {
		command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND));
@@ -3217,9 +3230,41 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
			host->ops->adma_workaround(host, intmask);
	}

	if (host->data->error)
	if (host->data->error) {
#if defined(CONFIG_SDC_QTI)
		if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_TIMEOUT
					| SDHCI_INT_DATA_END_BIT)) {
			command = SDHCI_GET_CMD(sdhci_readw(host,
							    SDHCI_COMMAND));
			if ((command != MMC_SEND_TUNING_BLOCK_HS200) &&
			    (command != MMC_SEND_TUNING_BLOCK))
				pr_msg = true;
		} else {
			pr_msg = true;
		}

		if (host->mmc->ops->get_cd &&
				!host->mmc->ops->get_cd(host->mmc)) {
			pr_msg = false;
			pr_err("%s: Got data error(%d) during card removal\n",
				mmc_hostname(host->mmc), host->data->error);
		}

		if (pr_msg && __ratelimit(&host->dbg_dump_rs)) {
			pr_err("%s: data txfr (0x%08x) error: %d after %lld ms\n",
			       mmc_hostname(host->mmc), intmask,
			       host->data->error, ktime_to_ms(ktime_sub(
			       ktime_get(), host->data_start_time)));
			mmc_log_string(host->mmc,
				"data txfr (0x%08x) error: %d after %lld ms\n",
				intmask, host->data->error,
				ktime_to_ms(ktime_sub(ktime_get(),
				host->data_start_time)));
			sdhci_dumpregs(host);
		}
#endif
		sdhci_finish_data(host);
	else {
	} else {
		if (intmask & (SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL))
			sdhci_transfer_pio(host);

@@ -3830,6 +3875,11 @@ struct sdhci_host *sdhci_alloc_host(struct device *dev,
	 */
	host->adma_table_cnt = SDHCI_MAX_SEGS * 2 + 1;

#if defined(CONFIG_SDC_QTI)
	ratelimit_state_init(&host->dbg_dump_rs, SDHCI_DBG_DUMP_RS_INTERVAL,
			SDHCI_DBG_DUMP_RS_BURST);
#endif

	return host;
}

+5 −1
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
#include <linux/io.h>
#include <linux/leds.h>
#include <linux/interrupt.h>

#include <linux/ratelimit.h>
#include <linux/mmc/host.h>

/*
@@ -616,6 +616,10 @@ struct sdhci_host {

	u64			data_timeout;

#if defined(CONFIG_SDC_QTI)
	ktime_t data_start_time;
	struct ratelimit_state dbg_dump_rs;
#endif
	unsigned long private[0] ____cacheline_aligned;
};