| From 6dfc920b0a9d2bca6513a50dbce394ef09af459a Mon Sep 17 00:00:00 2001 |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| Date: Sun, 22 Sep 2019 11:26:53 +0100 |
| Subject: [PATCH] mmc: sdhci: improve ADMA error reporting |
| |
| commit d1c536e3177390da43d99f20143b810c35433d1f upstream. |
| |
| ADMA errors are potentially data corrupting events; although we print |
| the register state, we do not usefully print the ADMA descriptors. |
| Worse than that, we print them by referencing their virtual address |
| which is meaningless when the register state gives us the DMA address |
| of the failing descriptor. |
| |
| Print the ADMA descriptors giving their DMA addresses rather than their |
| virtual addresses, and print them using SDHCI_DUMP() rather than DBG(). |
| |
| We also do not show the correct value of the interrupt status register; |
| the register dump shows the current value, after we have cleared the |
| pending interrupts we are going to service. What is more useful is to |
| print the interrupts that _were_ pending at the time the ADMA error was |
| encountered. Fix that too. |
| |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| Acked-by: Adrian Hunter <adrian.hunter@intel.com> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c |
| index c66e66fbaeb4..7f1e990e35f2 100644 |
| --- a/drivers/mmc/host/sdhci.c |
| +++ b/drivers/mmc/host/sdhci.c |
| @@ -2857,6 +2857,7 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask, u32 *intmask_p) |
| static void sdhci_adma_show_error(struct sdhci_host *host) |
| { |
| void *desc = host->adma_table; |
| + dma_addr_t dma = host->adma_addr; |
| |
| sdhci_dumpregs(host); |
| |
| @@ -2864,18 +2865,21 @@ static void sdhci_adma_show_error(struct sdhci_host *host) |
| struct sdhci_adma2_64_desc *dma_desc = desc; |
| |
| if (host->flags & SDHCI_USE_64_BIT_DMA) |
| - DBG("%p: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", |
| - desc, le32_to_cpu(dma_desc->addr_hi), |
| + SDHCI_DUMP("%08llx: DMA 0x%08x%08x, LEN 0x%04x, Attr=0x%02x\n", |
| + (unsigned long long)dma, |
| + le32_to_cpu(dma_desc->addr_hi), |
| le32_to_cpu(dma_desc->addr_lo), |
| le16_to_cpu(dma_desc->len), |
| le16_to_cpu(dma_desc->cmd)); |
| else |
| - DBG("%p: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", |
| - desc, le32_to_cpu(dma_desc->addr_lo), |
| + SDHCI_DUMP("%08llx: DMA 0x%08x, LEN 0x%04x, Attr=0x%02x\n", |
| + (unsigned long long)dma, |
| + le32_to_cpu(dma_desc->addr_lo), |
| le16_to_cpu(dma_desc->len), |
| le16_to_cpu(dma_desc->cmd)); |
| |
| desc += host->desc_sz; |
| + dma += host->desc_sz; |
| |
| if (dma_desc->cmd & cpu_to_le16(ADMA2_END)) |
| break; |
| @@ -2951,7 +2955,8 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) |
| != MMC_BUS_TEST_R) |
| host->data->error = -EILSEQ; |
| else if (intmask & SDHCI_INT_ADMA_ERROR) { |
| - pr_err("%s: ADMA error\n", mmc_hostname(host->mmc)); |
| + pr_err("%s: ADMA error: 0x%08x\n", mmc_hostname(host->mmc), |
| + intmask); |
| sdhci_adma_show_error(host); |
| host->data->error = -EIO; |
| if (host->ops->adma_workaround) |
| -- |
| 2.7.4 |
| |