Message ID | 1413883585-16299-14-git-send-email-adrian.hunter@intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tuesday 21 October 2014 12:26:23 Adrian Hunter wrote: > + return 0; > + > + if (host->flags & SDHCI_USE_64_BIT_DMA) { > + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) { > + host->flags &= ~SDHCI_USE_64_BIT_DMA; > + } else { > + err = dma_coerce_mask_and_coherent(dev, > + DMA_BIT_MASK(64)); > + if (err) > + dev_warn(dev, "Failed to set 64-bit DMA mask\n"); > + } > + } > + > + if (err) > + err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); > + > + c->dma_setup = !err; > Never use dma_coerce_mask_and_coherent(), it will ignore limitations of the upstream bus. Use dma_set_mask_and_coherent instead. If it fails, I think you need to clear the SDHCI_USE_64_BIT_DMA flag. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 21/10/14 12:33, Arnd Bergmann wrote: > On Tuesday 21 October 2014 12:26:23 Adrian Hunter wrote: >> + return 0; >> + >> + if (host->flags & SDHCI_USE_64_BIT_DMA) { >> + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) { >> + host->flags &= ~SDHCI_USE_64_BIT_DMA; >> + } else { >> + err = dma_coerce_mask_and_coherent(dev, >> + DMA_BIT_MASK(64)); >> + if (err) >> + dev_warn(dev, "Failed to set 64-bit DMA mask\n"); >> + } >> + } >> + >> + if (err) >> + err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); >> + >> + c->dma_setup = !err; >> > > Never use dma_coerce_mask_and_coherent(), it will ignore limitations of > the upstream bus. Use dma_set_mask_and_coherent instead. If it fails, > I think you need to clear the SDHCI_USE_64_BIT_DMA flag. The sdhci-acpi device is a platform devices created by acpi. dev->dma_mask is NULL so dma_set_mask_and_coherent will always fail unless I add: if (!dev->dma_mask) dev->dma_mask = &dev->coherent_dma_mask; -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Tuesday 21 October 2014 13:45:20 Adrian Hunter wrote: > On 21/10/14 12:33, Arnd Bergmann wrote: > > On Tuesday 21 October 2014 12:26:23 Adrian Hunter wrote: > >> + return 0; > >> + > >> + if (host->flags & SDHCI_USE_64_BIT_DMA) { > >> + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) { > >> + host->flags &= ~SDHCI_USE_64_BIT_DMA; > >> + } else { > >> + err = dma_coerce_mask_and_coherent(dev, > >> + DMA_BIT_MASK(64)); > >> + if (err) > >> + dev_warn(dev, "Failed to set 64-bit DMA mask\n"); > >> + } > >> + } > >> + > >> + if (err) > >> + err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); > >> + > >> + c->dma_setup = !err; > >> > > > > Never use dma_coerce_mask_and_coherent(), it will ignore limitations of > > the upstream bus. Use dma_set_mask_and_coherent instead. If it fails, > > I think you need to clear the SDHCI_USE_64_BIT_DMA flag. > > The sdhci-acpi device is a platform devices created by acpi. dev->dma_mask > is NULL so dma_set_mask_and_coherent will always fail > unless I add: > > if (!dev->dma_mask) > dev->dma_mask = &dev->coherent_dma_mask; > That's a bug in the ACPI code. Fix that instead of working around it in random drivers. Arnd -- To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 9cccc0e..637c6c4 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -76,6 +76,7 @@ struct sdhci_acpi_host { const struct sdhci_acpi_slot *slot; struct platform_device *pdev; bool use_runtime_pm; + bool dma_setup; }; static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) @@ -85,7 +86,30 @@ static inline bool sdhci_acpi_flag(struct sdhci_acpi_host *c, unsigned int flag) static int sdhci_acpi_enable_dma(struct sdhci_host *host) { - return 0; + struct sdhci_acpi_host *c = sdhci_priv(host); + struct device *dev = &c->pdev->dev; + int err = -1; + + if (c->dma_setup) + return 0; + + if (host->flags & SDHCI_USE_64_BIT_DMA) { + if (host->quirks2 & SDHCI_QUIRK2_BROKEN_64_BIT_DMA) { + host->flags &= ~SDHCI_USE_64_BIT_DMA; + } else { + err = dma_coerce_mask_and_coherent(dev, + DMA_BIT_MASK(64)); + if (err) + dev_warn(dev, "Failed to set 64-bit DMA mask\n"); + } + } + + if (err) + err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); + + c->dma_setup = !err; + + return err; } static void sdhci_acpi_int_hw_reset(struct sdhci_host *host) @@ -305,21 +329,6 @@ static int sdhci_acpi_probe(struct platform_device *pdev) goto err_free; } - if (!dev->dma_mask) { - u64 dma_mask; - - if (sdhci_readl(host, SDHCI_CAPABILITIES) & SDHCI_CAN_64BIT) { - /* 64-bit DMA is not supported at present */ - dma_mask = DMA_BIT_MASK(32); - } else { - dma_mask = DMA_BIT_MASK(32); - } - - err = dma_coerce_mask_and_coherent(dev, dma_mask); - if (err) - goto err_free; - } - if (c->slot) { if (c->slot->probe_slot) { err = c->slot->probe_slot(pdev, hid, uid);
Set the DMA mask during the first call to ->enable_dma() to make use of the SDHCI_USE_64_BIT_DMA flag. Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> --- drivers/mmc/host/sdhci-acpi.c | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-)