From e9a8ea44931c3a5c89809d00046cb1a0d4a24986 Mon Sep 17 00:00:00 2001 From: Sarthak Garg Date: Thu, 30 Dec 2021 17:40:46 +0530 Subject: [PATCH] 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: Sarthak Garg --- drivers/mmc/host/sdhci.c | 54 ++++++++++++++++++++++++++++++++++++++-- drivers/mmc/host/sdhci.h | 6 ++++- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index ad0b4b331811..27049955e774 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -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; } diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index af6071b1de3d..7b7fa18a7644 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -15,7 +15,7 @@ #include #include #include - +#include #include /* @@ -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; };