From 7810687661302c6f304c7c5119c9562893567564 Mon Sep 17 00:00:00 2001 From: Shaik Sajida Bhanu Date: Wed, 30 Sep 2020 19:11:44 +0530 Subject: [PATCH] mmc: Add IPC tracing events for eMMC and SD card This changes adds IPC tracing events for eMMC and SD card to trace significant events used for debug purpose. Change-Id: I9b2f86110e9be8a914c51b8796fef5a0ef2c06ad Signed-off-by: Shaik Sajida Bhanu --- drivers/mmc/core/host.c | 11 +++++++++++ drivers/mmc/core/mmc.c | 8 ++++++++ drivers/mmc/core/sd.c | 5 +++++ drivers/mmc/host/cqhci.c | 17 +++++++++++++++++ drivers/mmc/host/sdhci.c | 35 +++++++++++++++++++++++++++++++++++ include/linux/mmc/host.h | 16 ++++++++++++++++ 6 files changed, 92 insertions(+) diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index ac5f12cfa0dd..f05377081ca5 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c @@ -708,6 +708,12 @@ int mmc_add_host(struct mmc_host *host) mmc_add_host_debugfs(host); #endif +#ifdef CONFIG_MMC_IPC_LOGGING + host->ipc_log_ctxt = ipc_log_context_create(NUM_LOG_PAGES, dev_name(&host->class_dev), 0); + if (!host->ipc_log_ctxt) + pr_err("%s: Error getting ipc_log_ctxt\n", __func__); +#endif + #if defined(CONFIG_SDC_QTI) err = sysfs_create_group(&host->class_dev.kobj, &clk_scaling_attr_grp); if (err) @@ -741,6 +747,11 @@ void mmc_remove_host(struct mmc_host *host) mmc_remove_host_debugfs(host); #endif +#ifdef CONFIG_MMC_IPC_LOGGING + ipc_log_context_destroy(host->ipc_log_ctxt); + host->ipc_log_ctxt = NULL; +#endif + #if defined(CONFIG_SDC_QTI) sysfs_remove_group(&host->class_dev.kobj, &clk_scaling_attr_grp); #endif diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index f94ad2ca3ebe..4a2e782e1318 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -2251,6 +2251,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) return err; } #endif + mmc_log_string(host, "Enter\n"); mmc_claim_host(host); if (mmc_card_suspended(host->card)) @@ -2274,6 +2275,7 @@ static int _mmc_suspend(struct mmc_host *host, bool is_suspend) mmc_card_set_suspended(host->card); } out: + mmc_log_string(host, "Exit err: %d\n", err); mmc_release_host(host); #if defined(CONFIG_SDC_QTI) if (err) @@ -2319,6 +2321,7 @@ static int _mmc_resume(struct mmc_host *host) } #endif + mmc_log_string(host, "Enter\n"); mmc_power_up(host, host->card->ocr); err = mmc_init_card(host, host->card->ocr, host->card); mmc_card_clr_suspended(host->card); @@ -2335,6 +2338,7 @@ out: mmc_hostname(host), __func__, err); out: #endif + mmc_log_string(host, "Exit err %d\n", err); return err; } @@ -2365,6 +2369,7 @@ static int mmc_shutdown(struct mmc_host *host) if (!err) err = _mmc_suspend(host, false); + mmc_log_string(host, "done err %d\n", err); return err; } @@ -2374,6 +2379,7 @@ static int mmc_shutdown(struct mmc_host *host) static int mmc_resume(struct mmc_host *host) { pm_runtime_enable(&host->card->dev); + mmc_log_string(host, "Done\n"); return 0; } @@ -2392,6 +2398,7 @@ static int mmc_runtime_suspend(struct mmc_host *host) pr_err("%s: error %d doing aggressive suspend\n", mmc_hostname(host), err); + mmc_log_string(host, "done err %d\n", err); return err; } @@ -2407,6 +2414,7 @@ static int mmc_runtime_resume(struct mmc_host *host) pr_err("%s: error %d doing runtime resume\n", mmc_hostname(host), err); + mmc_log_string(host, "done err %d\n", err); return 0; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index a6ced8dce879..db361871de16 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -1237,6 +1237,7 @@ static int _mmc_sd_suspend(struct mmc_host *host) } #endif mmc_claim_host(host); + mmc_log_string(host, "Enter\n"); if (mmc_card_suspended(host->card)) goto out; @@ -1251,6 +1252,7 @@ static int _mmc_sd_suspend(struct mmc_host *host) out: mmc_release_host(host); + mmc_log_string(host, "Exit err: %d\n", err); return err; } @@ -1279,6 +1281,7 @@ static int _mmc_sd_resume(struct mmc_host *host) int err = 0; mmc_claim_host(host); + mmc_log_string(host, "Enter\n"); if (!mmc_card_suspended(host->card)) goto out; @@ -1297,6 +1300,7 @@ static int _mmc_sd_resume(struct mmc_host *host) #endif out: mmc_release_host(host); + mmc_log_string(host, "Exit err: %d\n", err); return err; } @@ -1306,6 +1310,7 @@ out: static int mmc_sd_resume(struct mmc_host *host) { pm_runtime_enable(&host->card->dev); + mmc_log_string(host, "done\n"); return 0; } diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c index 266cb15645e6..dd429fcf226e 100644 --- a/drivers/mmc/host/cqhci.c +++ b/drivers/mmc/host/cqhci.c @@ -102,6 +102,15 @@ static void cqhci_dumpregs(struct cqhci_host *cq_host) { struct mmc_host *mmc = cq_host->mmc; + mmc_log_string(mmc, + "CQHCI_CTL=0x%08x CQHCI_IS=0x%08x CQHCI_ISTE=0x%08x CQHCI_ISGE=0x%08x CQHCI_TDBR=0x%08x CQHCI_TCN=0x%08x CQHCI_DQS=0x%08x CQHCI_DPT=0x%08x CQHCI_TERRI=0x%08x CQHCI_CRI=0x%08x CQHCI_CRA=0x%08x CQHCI_CRDCT=0x%08x\n", + cqhci_readl(cq_host, CQHCI_CTL), cqhci_readl(cq_host, CQHCI_IS), + cqhci_readl(cq_host, CQHCI_ISTE), cqhci_readl(cq_host, CQHCI_ISGE), + cqhci_readl(cq_host, CQHCI_TDBR), cqhci_readl(cq_host, CQHCI_TCN), + cqhci_readl(cq_host, CQHCI_DQS), cqhci_readl(cq_host, CQHCI_DPT), + cqhci_readl(cq_host, CQHCI_TERRI), cqhci_readl(cq_host, CQHCI_CRI), + cqhci_readl(cq_host, CQHCI_CRA), cqhci_readl(cq_host, CQHCI_CRDCT)); + CQHCI_DUMP("============ CQHCI REGISTER DUMP ===========\n"); CQHCI_DUMP("Caps: 0x%08x | Version: 0x%08x\n", @@ -284,6 +293,7 @@ static void __cqhci_enable(struct cqhci_host *cq_host) cqhci_set_irqs(cq_host, CQHCI_IS_MASK); cq_host->activated = true; + mmc_log_string(mmc, "CQ enabled\n"); } static void __cqhci_disable(struct cqhci_host *cq_host) @@ -297,6 +307,7 @@ static void __cqhci_disable(struct cqhci_host *cq_host) cq_host->mmc->cqe_on = false; cq_host->activated = false; + mmc_log_string(cq_host->mmc, "CQ disabled\n"); } int cqhci_deactivate(struct mmc_host *mmc) @@ -616,6 +627,7 @@ static int cqhci_request(struct mmc_host *mmc, struct mmc_request *mrq) cq_host->slot[tag].flags = 0; cq_host->qcnt += 1; + mmc_log_string(mmc, "tag: %d\n", tag); /* Make sure descriptors are ready before ringing the doorbell */ wmb(); cqhci_writel(cq_host, 1 << tag, CQHCI_TDBR); @@ -767,6 +779,8 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, cqhci_writel(cq_host, status, CQHCI_IS); pr_debug("%s: cqhci: IRQ status: 0x%08x\n", mmc_hostname(mmc), status); + mmc_log_string(mmc, "CQIS: 0x%x cmd_error : %d data_err: %d\n", + status, cmd_error, data_error); if ((status & CQHCI_IS_RED) || cmd_error || data_error) cqhci_error_irq(mmc, status, cmd_error, data_error); @@ -784,6 +798,7 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, /* complete the corresponding mrq */ pr_debug("%s: cqhci: completing tag %lu\n", mmc_hostname(mmc), tag); + mmc_log_string(mmc, "completing tag -> %lu\n", tag); cqhci_finish_mrq(mmc, tag); } @@ -917,6 +932,7 @@ static bool cqhci_halt(struct mmc_host *mmc, unsigned int timeout) if (!ret) pr_debug("%s: cqhci: Failed to halt\n", mmc_hostname(mmc)); + mmc_log_string(mmc, "halt done with ret %d\n", ret); return ret; } @@ -1055,6 +1071,7 @@ static void cqhci_recovery_finish(struct mmc_host *mmc) cqhci_set_irqs(cq_host, CQHCI_IS_MASK); pr_debug("%s: cqhci: recovery done\n", mmc_hostname(mmc)); + mmc_log_string(mmc, "recovery done\n"); } static const struct mmc_cqe_ops cqhci_cqe_ops = { diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2de42bb29c10..ee0470c355ac 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -52,6 +52,15 @@ static bool sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) void sdhci_dumpregs(struct sdhci_host *host) { + mmc_log_string(host->mmc, + "BLOCK_SIZE=0x%08x BLOCK_COUNT=0x%08x COMMAND=0x%08x INT_STATUS=0x%08x INT_ENABLE=0x%08x SIGNAL_ENABLE=0x%08x\n", + sdhci_readw(host, SDHCI_BLOCK_SIZE), + sdhci_readw(host, SDHCI_BLOCK_COUNT), + sdhci_readw(host, SDHCI_COMMAND), + sdhci_readl(host, SDHCI_INT_STATUS), + sdhci_readl(host, SDHCI_INT_ENABLE), + sdhci_readl(host, SDHCI_SIGNAL_ENABLE)); + SDHCI_DUMP("============ SDHCI REGISTER DUMP ===========\n"); SDHCI_DUMP("Sys addr: 0x%08x | Version: 0x%08x\n", @@ -115,6 +124,10 @@ void sdhci_dumpregs(struct sdhci_host *host) host->ops->dump_vendor_regs(host); #endif +#ifdef CONFIG_MMC_IPC_LOGGING + host->mmc->stop_tracing = true; +#endif + SDHCI_DUMP("============================================\n"); } EXPORT_SYMBOL_GPL(sdhci_dumpregs); @@ -226,6 +239,8 @@ void sdhci_reset(struct sdhci_host *host, u8 mask) if (timedout) { pr_err("%s: Reset 0x%x never completed.\n", mmc_hostname(host->mmc), (int)mask); + mmc_log_string(host->mmc, "%s: Reset 0x%x never completed.\n", + (int)mask); sdhci_dumpregs(host); return; } @@ -1486,6 +1501,8 @@ static bool sdhci_send_command_retry(struct sdhci_host *host, if (!timeout--) { pr_err("%s: Controller never released inhibit bit(s).\n", mmc_hostname(host->mmc)); + mmc_log_string(host->mmc, + "Controller never released inhibit bit(s).\n"); sdhci_dumpregs(host); cmd->error = -EIO; return false; @@ -1732,6 +1749,7 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) if (timedout) { pr_err("%s: Internal clock never stabilised.\n", mmc_hostname(host->mmc)); + mmc_log_string(host->mmc, "Internal clock never stabilised.\n"); sdhci_dumpregs(host); return; } @@ -1754,6 +1772,8 @@ void sdhci_enable_clk(struct sdhci_host *host, u16 clk) if (timedout) { pr_err("%s: PLL clock never stabilised.\n", mmc_hostname(host->mmc)); + mmc_log_string(host->mmc, + "PLL clock never stabilised.\n"); sdhci_dumpregs(host); return; } @@ -2906,6 +2926,8 @@ static void sdhci_timeout_timer(struct timer_list *t) #endif pr_err("%s: Timeout waiting for hardware cmd interrupt.\n", mmc_hostname(host->mmc)); + mmc_log_string(host->mmc, + "Timeout waiting for hardware cmd interrupt.\n"); sdhci_dumpregs(host); host->cmd->error = -ETIMEDOUT; @@ -2931,6 +2953,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t) #endif pr_err("%s: Timeout waiting for hardware interrupt.\n", mmc_hostname(host->mmc)); + mmc_log_string(host->mmc, "Timeout waiting for hardware interrupt.\n"); sdhci_dumpregs(host); if (host->data) { @@ -2982,6 +3005,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) return; pr_err("%s: Got command interrupt 0x%08x even though no command operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); + mmc_log_string(host->mmc, + "Got command interrupt 0x%08x even though no command operation was in progress.\n", + (unsigned int)intmask); sdhci_dumpregs(host); return; } @@ -3123,6 +3149,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) pr_err("%s: Got data interrupt 0x%08x even though no data operation was in progress.\n", mmc_hostname(host->mmc), (unsigned)intmask); + mmc_log_string(host->mmc, + "Got data interrupt 0x%08x even though no data operation was in progress.\n", + (unsigned int)intmask); sdhci_dumpregs(host); return; @@ -3348,6 +3377,9 @@ out: if (unexpected) { pr_err("%s: Unexpected interrupt 0x%08x.\n", mmc_hostname(host->mmc), unexpected); + mmc_log_string(host->mmc, + "Unexpected interrupt 0x%08x.\n", + unexpected); sdhci_dumpregs(host); } @@ -3698,6 +3730,9 @@ bool sdhci_cqe_irq(struct sdhci_host *host, u32 intmask, int *cmd_error, sdhci_writel(host, intmask, SDHCI_INT_STATUS); pr_err("%s: CQE: Unexpected interrupt 0x%08x.\n", mmc_hostname(host->mmc), intmask); + mmc_log_string(host->mmc, + "CQE: Unexpected interrupt 0x%08x.\n", + intmask); sdhci_dumpregs(host); } diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 68afb7a6f447..cb0c9e3e0d56 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -18,6 +18,7 @@ #include #include #include +#include struct mmc_ios { unsigned int clock; /* clock rate */ @@ -537,6 +538,11 @@ struct mmc_host { struct led_trigger *led; /* activity led */ +#ifdef CONFIG_MMC_IPC_LOGGING + void *ipc_log_ctxt; + bool stop_tracing; +#endif + #ifdef CONFIG_REGULATOR bool regulator_enabled; /* regulator state */ #endif @@ -590,6 +596,16 @@ void mmc_free_host(struct mmc_host *); int mmc_of_parse(struct mmc_host *host); int mmc_of_parse_voltage(struct device_node *np, u32 *mask); +#ifdef CONFIG_MMC_IPC_LOGGING +#define NUM_LOG_PAGES 10 +#define mmc_log_string(mmc_host, fmt, ...) do {\ + if ((mmc_host)->ipc_log_ctxt && !(mmc_host)->stop_tracing) \ + ipc_log_string((mmc_host)->ipc_log_ctxt, "%s: " fmt, __func__, ##__VA_ARGS__); \ + } while (0) +#else +#define mmc_log_string(mmc_host, fmt, ...) do { } while (0) +#endif + static inline void *mmc_priv(struct mmc_host *host) { return (void *)host->private;