mmc: cmdq_hci: ice: Handle ICE HCI errors in cmdq mode
With ICE HCI addition in SDHC, couple of errors conditions got introduced. These errors would be detected by ICE HCI and triggers interrupt. The two errors are: 1. Generic Crypto Error (GCE): This error is detected during the transfer. Need to reset SDHC to recover. 2. Invalid Crypto Configuration Error (ICCE): The HW detects it before the beginning of the transfer and terminates the transfer before actual execution started. Driver has to handle these error for recovering ICE-HCI from these error conditions. This patch is for handling there errors in cmdq mode. Change-Id: Ia10075aca429cbc49ccccdae5c0499c7a176b8a2 Signed-off-by: Veerabhadrarao Badiganti <vbadigan@codeaurora.org>
This commit is contained in:
parent
2a7bbea49b
commit
83333ef2f4
3 changed files with 90 additions and 3 deletions
|
@ -145,6 +145,29 @@ static void cmdq_clear_set_irqs(struct cmdq_host *cq_host, u32 clear, u32 set)
|
|||
mb();
|
||||
}
|
||||
|
||||
static int cmdq_clear_task_poll(struct cmdq_host *cq_host, unsigned int tag)
|
||||
{
|
||||
int retries = 100;
|
||||
|
||||
cmdq_clear_set_irqs(cq_host, CQIS_TCL, 0);
|
||||
cmdq_writel(cq_host, 1<<tag, CQTCLR);
|
||||
while (retries) {
|
||||
/*
|
||||
* Task Clear register and doorbell,
|
||||
* both should indicate that task is cleared
|
||||
*/
|
||||
if ((cmdq_readl(cq_host, CQTCLR) & 1<<tag) ||
|
||||
(cmdq_readl(cq_host, CQTDBR) & 1<<tag)) {
|
||||
udelay(5);
|
||||
retries--;
|
||||
continue;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
cmdq_clear_set_irqs(cq_host, 0, CQIS_TCL);
|
||||
return retries ? 0 : -ETIMEDOUT;
|
||||
}
|
||||
|
||||
#define DRV_NAME "cmdq-host"
|
||||
|
||||
|
@ -857,6 +880,8 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
|
|||
struct mmc_request *mrq;
|
||||
int ret;
|
||||
u32 dbr_set = 0;
|
||||
u32 dev_pend_set = 0;
|
||||
int stat_err = 0;
|
||||
|
||||
status = cmdq_readl(cq_host, CQIS);
|
||||
|
||||
|
@ -865,7 +890,9 @@ irqreturn_t cmdq_irq(struct mmc_host *mmc, int err)
|
|||
MMC_TRACE(mmc, "%s: CQIS: 0x%x err: %d\n",
|
||||
__func__, status, err);
|
||||
|
||||
if (err || (status & CQIS_RED)) {
|
||||
stat_err = status & (CQIS_RED | CQIS_GCE | CQIS_ICCE);
|
||||
|
||||
if (err || stat_err) {
|
||||
err_info = cmdq_readl(cq_host, CQTERRI);
|
||||
pr_err("%s: err: %d status: 0x%08x task-err-info (0x%08lx)\n",
|
||||
mmc_hostname(mmc), err, status, err_info);
|
||||
|
@ -968,7 +995,7 @@ skip_cqterri:
|
|||
* CQE detected a reponse error from device
|
||||
* In most cases, this would require a reset.
|
||||
*/
|
||||
if (status & CQIS_RED) {
|
||||
if (stat_err & CQIS_RED) {
|
||||
/*
|
||||
* will check if the RED error is due to a bkops
|
||||
* exception once the queue is empty
|
||||
|
@ -987,6 +1014,62 @@ skip_cqterri:
|
|||
mrq->cmdq_req->resp_arg = cmdq_readl(cq_host, CQCRA);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic Crypto error detected by CQE.
|
||||
* Its a fatal, would require cmdq reset.
|
||||
*/
|
||||
if (stat_err & CQIS_GCE) {
|
||||
if (mrq->data)
|
||||
mrq->data->error = -EIO;
|
||||
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",
|
||||
__func__, tag);
|
||||
}
|
||||
/*
|
||||
* Invalid crypto config error detected by CQE, clear the task.
|
||||
* Task can be cleared only when CQE is halt state.
|
||||
*/
|
||||
if (stat_err & CQIS_ICCE) {
|
||||
/*
|
||||
* Invalid Crypto Config Error is detected at the
|
||||
* beginning of the transfer before the actual execution
|
||||
* started. So just clear the task in CQE. No need to
|
||||
* clear in device. Only the task which caused ICCE has
|
||||
* to be cleared. Other tasks can be continue processing
|
||||
* The first task which is about to be prepared would
|
||||
* cause ICCE Error.
|
||||
*/
|
||||
dbr_set = cmdq_readl(cq_host, CQTDBR);
|
||||
dev_pend_set = cmdq_readl(cq_host, CQDPT);
|
||||
if (dbr_set ^ dev_pend_set)
|
||||
tag = ffs(dbr_set ^ dev_pend_set) - 1;
|
||||
mrq = get_req_by_tag(cq_host, tag);
|
||||
pr_err("%s: Crypto config error while processing task %lu!",
|
||||
mmc_hostname(mmc), tag);
|
||||
MMC_TRACE(mmc, "%s: ICCE error with tag %lu\n",
|
||||
__func__, tag);
|
||||
if (mrq->data)
|
||||
mrq->data->error = -EIO;
|
||||
else if (mrq->cmd)
|
||||
mrq->cmd->error = -EIO;
|
||||
/*
|
||||
* If CQE is halted and tag is valid then clear the task
|
||||
* then un-halt CQE and set flag to skip error recovery.
|
||||
* If any of the condtions is not met thene it will
|
||||
* enter into default error recovery path.
|
||||
*/
|
||||
if (!ret && (dbr_set ^ dev_pend_set)) {
|
||||
ret = cmdq_clear_task_poll(cq_host, tag);
|
||||
if (ret) {
|
||||
pr_err("%s: %s: task[%lu] clear failed ret=%d\n",
|
||||
mmc_hostname(mmc),
|
||||
__func__, tag, ret);
|
||||
} else if (!cmdq_halt_poll(mmc, false)) {
|
||||
mrq->cmdq_req->skip_err_handling = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
cmdq_finish_data(mmc, tag);
|
||||
} else {
|
||||
cmdq_writel(cq_host, status, CQIS);
|
||||
|
@ -1052,6 +1135,7 @@ static int cmdq_halt_poll(struct mmc_host *mmc, bool halt)
|
|||
cq_host->ops->clear_set_irqs(mmc, true);
|
||||
cmdq_writel(cq_host, cmdq_readl(cq_host, CQCTL) & ~HALT,
|
||||
CQCTL);
|
||||
mmc_host_clr_halt(mmc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#define CQIS_TCC (1 << 1)
|
||||
#define CQIS_RED (1 << 2)
|
||||
#define CQIS_TCL (1 << 3)
|
||||
#define CQIS_GCE (1 << 4)
|
||||
#define CQIS_ICCE (1 << 5)
|
||||
|
||||
/* interrupt status enable */
|
||||
#define CQISTE 0x14
|
||||
|
@ -112,7 +114,7 @@
|
|||
/* command response argument */
|
||||
#define CQCRA 0x5C
|
||||
|
||||
#define CQ_INT_ALL 0xF
|
||||
#define CQ_INT_ALL 0x3F
|
||||
#define CQIC_DEFAULT_ICCTH 31
|
||||
#define CQIC_DEFAULT_ICTOVAL 1
|
||||
|
||||
|
|
|
@ -208,6 +208,7 @@ struct mmc_cmdq_req {
|
|||
unsigned int resp_arg;
|
||||
unsigned int dev_pend_tasks;
|
||||
bool resp_err;
|
||||
bool skip_err_handling;
|
||||
int tag; /* used for command queuing */
|
||||
u8 ctx_id;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue