On 22/06/20 8:44 am, chen jiangnan wrote: > From 547e5635c04f4f9d62cbc1e3a4b4527f87c4e83b Mon Sep 17 00:00:00 2001 > From: JiangnanChen <chen.jiangnan@xxxxxxxxxxxxxx> > Date: Mon, 22 Jun 2020 05:32:21 +0000 > Subject: [PATCH] Fix CQE task queue timeout. CQE notifies the software that Please separate subject from commit message. > task has completed through task completion notification (TCN), but some CQE > will occasionally mark the task in the pending state (via DPT). At this time, > if a QBR task (such as flush cache) is followed, the entire command queue > will be blocked, causing the mmc subsystem to report a timeout error, and cqe > enters the recovery process. It seems like this is a workaround for broken HW, so you could create a quirk for this, but making use of the ->write_l host op is cleaner for cqhci. e.g. in your driver, for the broken controller set cqhci_host_ops write_l to use the following: static void ???_cqhci_writel(struct cqhci_host *cq_host, u32 val, int reg) { writel_relaxed(val, cq_host->mmio + reg); if (reg == CQHCI_TCN) { u32 pend_status = cqhci_readl(cq_host, CQHCI_DPT); if (val & pend_status) { pr_debug("%s: cqhci conflict: TCN: 0x%08lx DPT: 0x%08lx\n", mmc_hostname(cq_host->mmc), val, pend_status); cqhci_writel(cq_host, val & pend_status, CQHCI_TCLR); } } } > > Signed-off-by: JiangnanChen <chen.jiangnan@xxxxxxxxxxxxxx> > --- > drivers/mmc/host/cqhci.c | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c > index 75934f3c117e..b8c7f6119ac4 100644 > --- a/drivers/mmc/host/cqhci.c > +++ b/drivers/mmc/host/cqhci.c > @@ -760,7 +760,7 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, > int data_error) > { > u32 status; > - unsigned long tag = 0, comp_status; > + unsigned long tag = 0, comp_status, pend_status; > struct cqhci_host *cq_host = mmc->cqe_private; > > status = cqhci_readl(cq_host, CQHCI_IS); > @@ -778,6 +778,13 @@ irqreturn_t cqhci_irq(struct mmc_host *mmc, u32 intmask, int cmd_error, > pr_debug("%s: cqhci: TCN: 0x%08lx\n", > mmc_hostname(mmc), comp_status); > > + pend_status = cqhci_readl(cq_host, CQHCI_DPT); > + if (comp_status & pend_status) { > + pr_debug("%s: cqhci conflict: TCN: 0x%08lx DPT: 0x%08lx\n", > + mmc_hostname(mmc), comp_status, pend_status); > + cqhci_writel(cq_host, comp_status & pend_status, CQHCI_TCLR); > + } > + > spin_lock(&cq_host->lock); > > for_each_set_bit(tag, &comp_status, cq_host->num_slots) { > -- > 2.17.1