]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.19/mmc-sdhci-fix-data-command-crc-error-handling.patch
f1ebd439d21c02022b57a969200b54380e06dcc3
[thirdparty/kernel/stable-queue.git] / queue-4.19 / mmc-sdhci-fix-data-command-crc-error-handling.patch
1 From 5f57a6d1cf7a6e344e49e2d80124abe148c57468 Mon Sep 17 00:00:00 2001
2 From: Adrian Hunter <adrian.hunter@intel.com>
3 Date: Thu, 15 Nov 2018 15:53:41 +0200
4 Subject: mmc: sdhci: Fix data command CRC error handling
5
6 [ Upstream commit 4bf780996669280171c9cd58196512849b93434e ]
7
8 Existing data command CRC error handling is non-standard and does not work
9 with some Intel host controllers. Specifically, the assumption that the host
10 controller will continue operating normally after the error interrupt,
11 is not valid. Change the driver to handle the error in the same manner
12 as a data CRC error, taking care to ensure that the data line reset is
13 done for single or multi-block transfers, and it is done before
14 unmapping DMA.
15
16 Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
17 Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
18 Signed-off-by: Sasha Levin <sashal@kernel.org>
19 ---
20 drivers/mmc/host/sdhci.c | 40 +++++++++++++++-------------------------
21 1 file changed, 15 insertions(+), 25 deletions(-)
22
23 diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
24 index 654051e00117..4bfaca33a477 100644
25 --- a/drivers/mmc/host/sdhci.c
26 +++ b/drivers/mmc/host/sdhci.c
27 @@ -1078,8 +1078,7 @@ static bool sdhci_needs_reset(struct sdhci_host *host, struct mmc_request *mrq)
28 return (!(host->flags & SDHCI_DEVICE_DEAD) &&
29 ((mrq->cmd && mrq->cmd->error) ||
30 (mrq->sbc && mrq->sbc->error) ||
31 - (mrq->data && ((mrq->data->error && !mrq->data->stop) ||
32 - (mrq->data->stop && mrq->data->stop->error))) ||
33 + (mrq->data && mrq->data->stop && mrq->data->stop->error) ||
34 (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)));
35 }
36
37 @@ -1131,6 +1130,16 @@ static void sdhci_finish_data(struct sdhci_host *host)
38 host->data = NULL;
39 host->data_cmd = NULL;
40
41 + /*
42 + * The controller needs a reset of internal state machines upon error
43 + * conditions.
44 + */
45 + if (data->error) {
46 + if (!host->cmd || host->cmd == data_cmd)
47 + sdhci_do_reset(host, SDHCI_RESET_CMD);
48 + sdhci_do_reset(host, SDHCI_RESET_DATA);
49 + }
50 +
51 if ((host->flags & (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA)) ==
52 (SDHCI_REQ_USE_DMA | SDHCI_USE_ADMA))
53 sdhci_adma_table_post(host, data);
54 @@ -1155,17 +1164,6 @@ static void sdhci_finish_data(struct sdhci_host *host)
55 if (data->stop &&
56 (data->error ||
57 !data->mrq->sbc)) {
58 -
59 - /*
60 - * The controller needs a reset of internal state machines
61 - * upon error conditions.
62 - */
63 - if (data->error) {
64 - if (!host->cmd || host->cmd == data_cmd)
65 - sdhci_do_reset(host, SDHCI_RESET_CMD);
66 - sdhci_do_reset(host, SDHCI_RESET_DATA);
67 - }
68 -
69 /*
70 * 'cap_cmd_during_tfr' request must not use the command line
71 * after mmc_command_done() has been called. It is upper layer's
72 @@ -2642,7 +2640,7 @@ static void sdhci_timeout_data_timer(struct timer_list *t)
73 * *
74 \*****************************************************************************/
75
76 -static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
77 +static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p)
78 {
79 if (!host->cmd) {
80 /*
81 @@ -2665,20 +2663,12 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
82 else
83 host->cmd->error = -EILSEQ;
84
85 - /*
86 - * If this command initiates a data phase and a response
87 - * CRC error is signalled, the card can start transferring
88 - * data - the card may have received the command without
89 - * error. We must not terminate the mmc_request early.
90 - *
91 - * If the card did not receive the command or returned an
92 - * error which prevented it sending data, the data phase
93 - * will time out.
94 - */
95 + /* Treat data command CRC error the same as data CRC error */
96 if (host->cmd->data &&
97 (intmask & (SDHCI_INT_CRC | SDHCI_INT_TIMEOUT)) ==
98 SDHCI_INT_CRC) {
99 host->cmd = NULL;
100 + *intmask_p |= SDHCI_INT_DATA_CRC;
101 return;
102 }
103
104 @@ -2906,7 +2896,7 @@ static irqreturn_t sdhci_irq(int irq, void *dev_id)
105 }
106
107 if (intmask & SDHCI_INT_CMD_MASK)
108 - sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
109 + sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK, &intmask);
110
111 if (intmask & SDHCI_INT_DATA_MASK)
112 sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
113 --
114 2.19.1
115