diff mbox

[13/15] mmc: sdhci-acpi: Add 64-bit DMA support

Message ID 1413883585-16299-14-git-send-email-adrian.hunter@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Adrian Hunter Oct. 21, 2014, 9:26 a.m. UTC
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(-)

Comments

Arnd Bergmann Oct. 21, 2014, 9:33 a.m. UTC | #1
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
Adrian Hunter Oct. 21, 2014, 10:45 a.m. UTC | #2
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
Arnd Bergmann Oct. 21, 2014, 11:05 a.m. UTC | #3
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 mbox

Patch

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);