Patch "mmc: cqhci: Avoid false "cqhci: CQE stuck on" by not open-coding timeout loop" has been added to the 5.6-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    mmc: cqhci: Avoid false "cqhci: CQE stuck on" by not open-coding timeout loop

to the 5.6-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     mmc-cqhci-avoid-false-cqhci-cqe-stuck-on-by-not-open.patch
and it can be found in the queue-5.6 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit dcf87da7219f20a0c62454f554ccad4a13cec3bc
Author: Douglas Anderson <dianders@xxxxxxxxxxxx>
Date:   Mon Apr 13 16:27:27 2020 -0700

    mmc: cqhci: Avoid false "cqhci: CQE stuck on" by not open-coding timeout loop
    
    commit b1ac62a7ac386d76968af5f374a4a7a82a35fe31 upstream.
    
    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: a4080225f51d ("mmc: cqhci: support for command queue enabled host")
    Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
    Acked-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
    Cc: stable@xxxxxxxxxxxxxxx
    Link: https://lore.kernel.org/r/20200413162717.1.Idece266f5c8793193b57a1ddb1066d030c6af8e0@changeid
    Signed-off-by: Ulf Hansson <ulf.hansson@xxxxxxxxxx>
    Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

diff --git a/drivers/mmc/host/cqhci.c b/drivers/mmc/host/cqhci.c
index 5047f7343ffcf..c19f4c3f115a4 100644
--- a/drivers/mmc/host/cqhci.c
+++ b/drivers/mmc/host/cqhci.c
@@ -5,6 +5,7 @@
 #include <linux/delay.h>
 #include <linux/highmem.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
@@ -343,12 +344,16 @@ static int cqhci_enable(struct mmc_host *mmc, struct mmc_card *card)
 /* CQHCI is idle and should halt immediately, so set a small timeout */
 #define CQHCI_OFF_TIMEOUT 100
 
+static u32 cqhci_read_ctl(struct cqhci_host *cq_host)
+{
+	return cqhci_readl(cq_host, CQHCI_CTL);
+}
+
 static void cqhci_off(struct mmc_host *mmc)
 {
 	struct cqhci_host *cq_host = mmc->cqe_private;
-	ktime_t timeout;
-	bool timed_out;
 	u32 reg;
+	int err;
 
 	if (!cq_host->enabled || !mmc->cqe_on || cq_host->recovery_halt)
 		return;
@@ -358,15 +363,9 @@ static void cqhci_off(struct mmc_host *mmc)
 
 	cqhci_writel(cq_host, CQHCI_HALT, CQHCI_CTL);
 
-	timeout = ktime_add_us(ktime_get(), CQHCI_OFF_TIMEOUT);
-	while (1) {
-		timed_out = ktime_compare(ktime_get(), timeout) > 0;
-		reg = cqhci_readl(cq_host, CQHCI_CTL);
-		if ((reg & CQHCI_HALT) || timed_out)
-			break;
-	}
-
-	if (timed_out)
+	err = readx_poll_timeout(cqhci_read_ctl, cq_host, reg,
+				 reg & CQHCI_HALT, 0, CQHCI_OFF_TIMEOUT);
+	if (err < 0)
 		pr_err("%s: cqhci: CQE stuck on\n", mmc_hostname(mmc));
 	else
 		pr_debug("%s: cqhci: CQE off\n", mmc_hostname(mmc));



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux