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

Commit 52643dd8 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "mmc: host: Update error stats to track different mmc errors"

parents 787891b4 cd78bbb1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3461,6 +3461,8 @@ static enum blk_eh_timer_return mmc_blk_cmdq_req_timed_out(struct request *req)
	else
		mrq->data->error = -ETIMEDOUT;

	host->err_stats[MMC_ERR_CMDQ_REQ_TIMEOUT]++;

	if (mrq->cmd && mrq->cmd->error) {
		if (!(mrq->req->cmd_flags & REQ_PREFLUSH)) {
			/*
+77 −0
Original line number Diff line number Diff line
@@ -381,6 +381,79 @@ static int mmc_err_state_clear(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(mmc_err_state, mmc_err_state_get,
		mmc_err_state_clear, "%llu\n");

static int mmc_err_stats_show(struct seq_file *file, void *data)
{
	struct mmc_host *host = (struct mmc_host *)file->private;

	if (!host)
		return -EINVAL;

	seq_printf(file, "# Command Timeout Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_CMD_TIMEOUT]);

	seq_printf(file, "# Command CRC Errors Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_CMD_CRC]);

	seq_printf(file, "# Data Timeout Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_DAT_TIMEOUT]);

	seq_printf(file, "# Data CRC Errors Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_DAT_CRC]);

	seq_printf(file, "# Auto-Cmd Error Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_ADMA]);

	seq_printf(file, "# ADMA Error Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_ADMA]);

	seq_printf(file, "# Tuning Error Occurred:\t %d\n",
		   host->err_stats[MMC_ERR_TUNING]);

	seq_printf(file, "# CMDQ RED Errors:\t\t %d\n",
		   host->err_stats[MMC_ERR_CMDQ_RED]);

	seq_printf(file, "# CMDQ GCE Errors:\t\t %d\n",
		   host->err_stats[MMC_ERR_CMDQ_GCE]);

	seq_printf(file, "# CMDQ ICCE Errors:\t\t %d\n",
		   host->err_stats[MMC_ERR_CMDQ_ICCE]);

	seq_printf(file, "# Request Timedout:\t %d\n",
		   host->err_stats[MMC_ERR_REQ_TIMEOUT]);

	seq_printf(file, "# CMDQ Request Timedout:\t %d\n",
		   host->err_stats[MMC_ERR_CMDQ_REQ_TIMEOUT]);

	seq_printf(file, "# ICE Config Errors:\t\t %d\n",
		   host->err_stats[MMC_ERR_ICE_CFG]);
	return 0;
}

static int mmc_err_stats_open(struct inode *inode, struct file *file)
{
	return single_open(file, mmc_err_stats_show, inode->i_private);
}

static ssize_t mmc_err_stats_write(struct file *filp, const char __user *ubuf,
				   size_t cnt, loff_t *ppos)
{
	struct mmc_host *host = filp->f_mapping->host->i_private;

	if (!host)
		return -EINVAL;

	pr_debug("%s: Resetting MMC error statistics", __func__);
	memset(host->err_stats, 0, sizeof(host->err_stats));

	return cnt;
}

static const struct file_operations mmc_err_stats_fops = {
	.open	= mmc_err_stats_open,
	.read	= seq_read,
	.write	= mmc_err_stats_write,
};

void mmc_add_host_debugfs(struct mmc_host *host)
{
	struct dentry *root;
@@ -430,6 +503,10 @@ void mmc_add_host_debugfs(struct mmc_host *host)
		&mmc_err_state))
		goto err_node;

	if (!debugfs_create_file("err_stats", 0600, root, host,
		&mmc_err_stats_fops))
		goto err_node;

#ifdef CONFIG_MMC_CLKGATE
	if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR),
				root, &host->clk_delay))
+4 −0
Original line number Diff line number Diff line
@@ -803,6 +803,7 @@ static int cmdq_request(struct mmc_host *mmc, struct mmc_request *mrq)
	if (cq_host->ops->crypto_cfg) {
		err = cq_host->ops->crypto_cfg(mmc, mrq, tag, &ice_ctx);
		if (err) {
			mmc->err_stats[MMC_ERR_ICE_CFG]++;
			pr_err("%s: failed to configure crypto: err %d tag %d\n",
					mmc_hostname(mmc), err, tag);
			goto out;
@@ -1015,6 +1016,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
				mmc->card->bkops.needs_check = true;

			mrq->cmdq_req->resp_err = true;
			mmc->err_stats[MMC_ERR_CMDQ_RED]++;
			pr_err("%s: Response error (0x%08x) from card !!!",
				mmc_hostname(mmc), cmdq_readl(cq_host, CQCRA));

@@ -1030,6 +1032,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
		if (stat_err & CQIS_GCE) {
			if (mrq->data)
				mrq->data->error = -EIO;
			mmc->err_stats[MMC_ERR_CMDQ_GCE]++;
			pr_err("%s: Crypto generic error while processing task %lu!",
				mmc_hostname(mmc), tag);
			MMC_TRACE(mmc, "%s: GCE error detected with tag %lu\n",
@@ -1054,6 +1057,7 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
			if (dbr_set ^ dev_pend_set)
				tag = ffs(dbr_set ^ dev_pend_set) - 1;
			mrq = get_req_by_tag(cq_host, tag);
			mmc->err_stats[MMC_ERR_CMDQ_ICCE]++;
			pr_err("%s: Crypto config error while processing task %lu!",
				mmc_hostname(mmc), tag);
			MMC_TRACE(mmc, "%s: ICCE error with tag %lu\n",
+5 −0
Original line number Diff line number Diff line
@@ -1281,6 +1281,11 @@ int sdhci_msm_execute_tuning(struct sdhci_host *host, u32 opcode)
			pr_debug("%s: %s: found *** good *** phase = %d\n",
				mmc_hostname(mmc), __func__, phase);
		} else {
			/* Ignore crc errors occurred during tuning */
			if (cmd.error)
				mmc->err_stats[MMC_ERR_CMD_CRC]--;
			else if (data.error)
				mmc->err_stats[MMC_ERR_DAT_CRC]--;
			pr_debug("%s: %s: found ## bad ## phase = %d\n",
				mmc_hostname(mmc), __func__, phase);
		}
+36 −14
Original line number Diff line number Diff line
@@ -2491,6 +2491,8 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode)
		 */
		mmc_retune_disable(mmc);
		err = host->ops->platform_execute_tuning(host, opcode);
		if (err)
			host->mmc->err_stats[MMC_ERR_TUNING]++;
		mmc_retune_enable(mmc);
		return err;
	}
@@ -2919,8 +2921,10 @@ static void sdhci_timeout_timer(unsigned long data)
	spin_lock_irqsave(&host->lock, flags);

	if (host->cmd && !sdhci_data_line_cmd(host->cmd)) {
		host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]++;
		pr_err("%s: Timeout waiting for hardware cmd interrupt.\n",
		       mmc_hostname(host->mmc));
		MMC_TRACE(host->mmc, "Timeout waiting for h/w interrupt\n");
		sdhci_dumpregs(host);

		host->cmd->error = -ETIMEDOUT;
@@ -2942,6 +2946,7 @@ static void sdhci_timeout_data_timer(unsigned long data)

	if (host->data || host->data_cmd ||
	    (host->cmd && sdhci_data_line_cmd(host->cmd))) {
		host->mmc->err_stats[MMC_ERR_REQ_TIMEOUT]++;
		pr_err("%s: Timeout waiting for hardware interrupt.\n",
		       mmc_hostname(host->mmc));
		MMC_TRACE(host->mmc, "Timeout waiting for h/w interrupt\n");
@@ -3000,13 +3005,17 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
	if (intmask & (SDHCI_INT_TIMEOUT | SDHCI_INT_CRC |
		       SDHCI_INT_END_BIT | SDHCI_INT_INDEX |
		       SDHCI_INT_AUTO_CMD_ERR)) {
		if (intmask & SDHCI_INT_TIMEOUT)
		if (intmask & SDHCI_INT_TIMEOUT) {
			host->cmd->error = -ETIMEDOUT;
		else
			host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++;
		} else {
			host->cmd->error = -EILSEQ;
			host->mmc->err_stats[MMC_ERR_CMD_CRC]++;
		}

		if (intmask & SDHCI_INT_AUTO_CMD_ERR) {
			auto_cmd_status = host->auto_cmd_err_sts;
			host->mmc->err_stats[MMC_ERR_AUTO_CMD]++;
			pr_err_ratelimited("%s: %s: AUTO CMD err sts 0x%08x\n",
				mmc_hostname(host->mmc), __func__, auto_cmd_status);
			if (auto_cmd_status & (SDHCI_AUTO_CMD12_NOT_EXEC |
@@ -3134,6 +3143,7 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
			if (intmask & SDHCI_INT_DATA_TIMEOUT) {
				host->data_cmd = NULL;
				data_cmd->error = -ETIMEDOUT;
				host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++;
				sdhci_finish_mrq(host, data_cmd->mrq);
				return;
			}
@@ -3157,16 +3167,21 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
		return;
	}

	if (intmask & SDHCI_INT_DATA_TIMEOUT)
	if (intmask & SDHCI_INT_DATA_TIMEOUT) {
		host->data->error = -ETIMEDOUT;
		host->mmc->err_stats[MMC_ERR_DAT_TIMEOUT]++;
	}
	else if (intmask & SDHCI_INT_DATA_END_BIT)
		host->data->error = -EILSEQ;
	else if ((intmask & SDHCI_INT_DATA_CRC) &&
		(command != MMC_BUS_TEST_R))
		(command != MMC_BUS_TEST_R)) {
		host->data->error = -EILSEQ;
		host->mmc->err_stats[MMC_ERR_DAT_CRC]++;
	}
	else if (intmask & SDHCI_INT_ADMA_ERROR) {
		pr_err("%s: ADMA error\n", mmc_hostname(host->mmc));
		sdhci_adma_show_error(host);
		host->mmc->err_stats[MMC_ERR_ADMA]++;
		host->data->error = -EIO;
		if (host->ops->adma_workaround)
			host->ops->adma_workaround(host, intmask);
@@ -3245,24 +3260,31 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
}

#ifdef CONFIG_MMC_CQ_HCI
static int sdhci_get_cmd_err(u32 intmask)
static int sdhci_get_cmd_err(struct sdhci_host *host, u32 intmask)
{
	if (intmask & SDHCI_INT_TIMEOUT)
	if (intmask & SDHCI_INT_TIMEOUT) {
		host->mmc->err_stats[MMC_ERR_CMD_TIMEOUT]++;
		return -ETIMEDOUT;
	else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
			    SDHCI_INT_INDEX))
	} else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
			    SDHCI_INT_INDEX)) {
		host->mmc->err_stats[MMC_ERR_CMD_CRC]++;
		return -EILSEQ;
	}
	return 0;
}

static int sdhci_get_data_err(u32 intmask)
static int sdhci_get_data_err(struct sdhci_host *host, u32 intmask)
{
	if (intmask & SDHCI_INT_DATA_TIMEOUT)
	if (intmask & SDHCI_INT_DATA_TIMEOUT) {
		host->mmc->err_stats[MMC_ERR_DAT_TIMEOUT]++;
		return -ETIMEDOUT;
	else if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC))
	} else if (intmask & (SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC)) {
		host->mmc->err_stats[MMC_ERR_DAT_CRC]++;
		return -EILSEQ;
	else if (intmask & SDHCI_INT_ADMA_ERROR)
	} else if (intmask & MMC_ERR_ADMA) {
		host->mmc->err_stats[MMC_ERR_ADMA]++;
		return -EIO;
	}
	return 0;
}

@@ -3273,9 +3295,9 @@ static irqreturn_t sdhci_cmdq_irq(struct sdhci_host *host, u32 intmask)
	irqreturn_t ret;

	if (intmask & SDHCI_INT_CMD_MASK)
		err = sdhci_get_cmd_err(intmask);
		err = sdhci_get_cmd_err(host, intmask);
	else if (intmask & SDHCI_INT_DATA_MASK)
		err = sdhci_get_data_err(intmask);
		err = sdhci_get_data_err(host, intmask);

	ret = cmdq_irq(host->mmc, err);
	if (err) {
Loading