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 <[email protected]>
This commit is contained in:
Shaik Sajida Bhanu 2020-09-30 19:11:44 +05:30
commit 7810687661
6 changed files with 92 additions and 0 deletions

View file

@ -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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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 = {

View file

@ -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);
}

View file

@ -18,6 +18,7 @@
#include <linux/mmc/card.h>
#include <linux/mmc/pm.h>
#include <linux/dma-direction.h>
#include <linux/ipc_logging.h>
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;