Skip to content

Commit b1ac62a

Browse files
diandersstorulf
authored andcommitted
mmc: cqhci: Avoid false "cqhci: CQE stuck on" by not open-coding timeout loop
Open-coding a timeout loop invariably leads to errors with handling the timeout properly in one corner case or another. In the case of cqhci we might report "CQE stuck on" even if it wasn't stuck on. You'd just need this sequence of events to happen in cqhci_off(): 1. Call ktime_get(). 2. Something happens to interrupt the CPU for > 100 us (context switch or interrupt). 3. Check time and; set "timed_out" to true since > 100 us. 4. Read CQHCI_CTL. 5. Both "reg & CQHCI_HALT" and "timed_out" are true, so break. 6. Since "timed_out" is true, falsely print the error message. Rather than fixing the polling loop, use readx_poll_timeout() like many people do. This has been time tested to handle the corner cases. Fixes: a408022 ("mmc: cqhci: support for command queue enabled host") Signed-off-by: Douglas Anderson <[email protected]> Acked-by: Adrian Hunter <[email protected]> Cc: [email protected] Link: https://lore.kernel.org/r/20200413162717.1.Idece266f5c8793193b57a1ddb1066d030c6af8e0@changeid Signed-off-by: Ulf Hansson <[email protected]>
1 parent ddca109 commit b1ac62a

File tree

1 file changed

+10
-11
lines changed

1 file changed

+10
-11
lines changed

drivers/mmc/host/cqhci.c

+10-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <linux/delay.h>
66
#include <linux/highmem.h>
77
#include <linux/io.h>
8+
#include <linux/iopoll.h>
89
#include <linux/module.h>
910
#include <linux/dma-mapping.h>
1011
#include <linux/slab.h>
@@ -349,12 +350,16 @@ static int cqhci_enable(struct mmc_host *mmc, struct mmc_card *card)
349350
/* CQHCI is idle and should halt immediately, so set a small timeout */
350351
#define CQHCI_OFF_TIMEOUT 100
351352

353+
static u32 cqhci_read_ctl(struct cqhci_host *cq_host)
354+
{
355+
return cqhci_readl(cq_host, CQHCI_CTL);
356+
}
357+
352358
static void cqhci_off(struct mmc_host *mmc)
353359
{
354360
struct cqhci_host *cq_host = mmc->cqe_private;
355-
ktime_t timeout;
356-
bool timed_out;
357361
u32 reg;
362+
int err;
358363

359364
if (!cq_host->enabled || !mmc->cqe_on || cq_host->recovery_halt)
360365
return;
@@ -364,15 +369,9 @@ static void cqhci_off(struct mmc_host *mmc)
364369

365370
cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL);
366371

367-
timeout = ktime_add_us(ktime_get(), CQHCI_OFF_TIMEOUT);
368-
while (1) {
369-
timed_out = ktime_compare(ktime_get(), timeout) > 0;
370-
reg = cqhci_readl(cq_host, CQHCI_CTL);
371-
if ((reg & CQHCI_HALT) || timed_out)
372-
break;
373-
}
374-
375-
if (timed_out)
372+
err = readx_poll_timeout(cqhci_read_ctl, cq_host, reg,
373+
reg & CQHCI_HALT, 0, CQHCI_OFF_TIMEOUT);
374+
if (err < 0)
376375
pr_err("%s: cqhci: CQE stuck on\n", mmc_hostname(mmc));
377376
else
378377
pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc));

0 commit comments

Comments
 (0)