Thread (3 messages) 3 messages, 3 authors, 2021-09-06

Re: [PATCH] mmc: dw_mmc: Only inject fault before done/error

From: Ulf Hansson <hidden>
Date: 2021-09-06 17:09:53
Also in: lkml

On Wed, 25 Aug 2021 at 13:42, Vincent Whitchurch
[off-list ref] wrote:
The fault injection function can set EVENT_DATA_ERROR but skip the
setting of ->data_status to an error status if it hits just after a data
over interrupt.  This confuses the tasklet which can later end up
triggering the WARN_ON(host->cmd || ..) in dw_mci_request_end() since
dw_mci_data_complete() would return success.

Prevent the fault injection function from doing this since this is not a
real case, and ensure that the fault injection doesn't race with a real
error either.

Signed-off-by: Vincent Whitchurch <redacted>
Applied for fixes and by adding a fixes tag, thanks!

Kind regards
Uffe

quoted hunk ↗ jump to hunk
---
 drivers/mmc/host/dw_mmc.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 6578cc64ae9e..380f9aa56eb2 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -1802,10 +1802,15 @@ static enum hrtimer_restart dw_mci_fault_timer(struct hrtimer *t)

        spin_lock_irqsave(&host->irq_lock, flags);

-       if (!host->data_status)
+       /*
+        * Only inject an error if we haven't already got an error or data over
+        * interrupt.
+        */
+       if (!host->data_status) {
                host->data_status = SDMMC_INT_DCRC;
-       set_bit(EVENT_DATA_ERROR, &host->pending_events);
-       tasklet_schedule(&host->tasklet);
+               set_bit(EVENT_DATA_ERROR, &host->pending_events);
+               tasklet_schedule(&host->tasklet);
+       }

        spin_unlock_irqrestore(&host->irq_lock, flags);
@@ -2721,12 +2726,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
                }

                if (pending & DW_MCI_DATA_ERROR_FLAGS) {
+                       spin_lock(&host->irq_lock);
+
                        /* if there is an error report DATA_ERROR */
                        mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
                        host->data_status = pending;
                        smp_wmb(); /* drain writebuffer */
                        set_bit(EVENT_DATA_ERROR, &host->pending_events);
                        tasklet_schedule(&host->tasklet);
+
+                       spin_unlock(&host->irq_lock);
                }

                if (pending & SDMMC_INT_DATA_OVER) {
--
2.28.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help