xhci: fix dma mask setup in xhci.c
authorXenia Ragiadakou <burzalodowa@gmail.com>
Wed, 14 Aug 2013 02:55:19 +0000 (05:55 +0300)
committerSarah Sharp <sarah.a.sharp@linux.intel.com>
Wed, 14 Aug 2013 04:16:42 +0000 (21:16 -0700)
The function dma_set_mask() tests internally whether the dma_mask pointer
for the device is initialized and fails if the dma_mask pointer is NULL.
On pci platforms, the device dma_mask pointer is initialized, when pci
devices are enumerated, to point to the pci_dev->dma_mask which is 0xffffffff.
However, for non-pci platforms, the dma_mask pointer may not be initialized
and in that case dma_set_mask() will fail.

This patch initializes the dma_mask and the coherent_dma_mask to 32bits
in xhci_plat_probe(), before the call to usb_create_hcd() that sets the
"uses_dma" flag for the usb bus and the call to usb_add_hcd() that creates
coherent dma pools for the usb hcd.

Moreover, a call to dma_set_mask() does not set the device coherent_dma_mask.
Since the xhci-hcd driver calls dma_alloc_coherent() and dma_pool_alloc()
to allocate consistent DMA memory blocks, the coherent DMA address mask
has to be set explicitly.

This patch sets the coherent_dma_mask to 64bits in xhci_gen_setup() when
the xHC is capable for 64-bit DMA addressing.

If dma_set_mask() succeeds, for a given bitmask, it is guaranteed that
the given bitmask is also supported for consistent DMA mappings.

Other changes introduced in this patch are:

- The return value of dma_set_mask() is checked to ensure that the required
  dma bitmask conforms with the host system's addressing capabilities.

- The dma_mask setup code for the non-primary hcd was removed since both
  primary and non-primary hcd refer to the same generic device whose
  dma_mask and coherent_dma_mask are already set during the setup of
  the primary hcd.

- The code for reading the HCCPARAMS register to find out the addressing
  capabilities of xHC was removed since its value is already cached in
  xhci->hccparams.

- hcd->self.controller was replaced with the dev variable since it is
  already available.

Signed-off-by: Xenia Ragiadakou <burzalodowa@gmail.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c

index 3fcdaea21e24ad937e6e6f5e6933f8f6d5a408b3..be5e70d2300c8ba759b2f43486582ecc10798f0a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+#include <linux/dma-mapping.h>
 
 #include "xhci.h"
 
@@ -105,6 +106,15 @@ static int xhci_plat_probe(struct platform_device *pdev)
        if (!res)
                return -ENODEV;
 
+       /* Initialize dma_mask and coherent_dma_mask to 32-bits */
+       ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+       if (ret)
+               return ret;
+       if (!pdev->dev.dma_mask)
+               pdev->dev.dma_mask = &pdev->dev.coherent_dma_mask;
+       else
+               dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+
        hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev));
        if (!hcd)
                return -ENOMEM;
index eeb94d1090597197c959c5758baa8ae14a96e633..e43b3889ab7a65de7940f8a9b1526212b8af593e 100644 (file)
@@ -4825,7 +4825,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
        struct xhci_hcd         *xhci;
        struct device           *dev = hcd->self.controller;
        int                     retval;
-       u32                     temp;
 
        /* Accept arbitrarily long scatter-gather lists */
        hcd->self.sg_tablesize = ~0;
@@ -4853,14 +4852,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                /* xHCI private pointer was set in xhci_pci_probe for the second
                 * registered roothub.
                 */
-               xhci = hcd_to_xhci(hcd);
-               temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
-               if (HCC_64BIT_ADDR(temp)) {
-                       xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
-                       dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
-               } else {
-                       dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
-               }
                return 0;
        }
 
@@ -4899,12 +4890,12 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
                goto error;
        xhci_dbg(xhci, "Reset complete\n");
 
-       temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
-       if (HCC_64BIT_ADDR(temp)) {
+       /* Set dma_mask and coherent_dma_mask to 64-bits,
+        * if xHC supports 64-bit addressing */
+       if (HCC_64BIT_ADDR(xhci->hcc_params) &&
+                       !dma_set_mask(dev, DMA_BIT_MASK(64))) {
                xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
-               dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
-       } else {
-               dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+               dma_set_coherent_mask(dev, DMA_BIT_MASK(64));
        }
 
        xhci_dbg(xhci, "Calling HCD init\n");