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 initialization of the device dma_mask pointer is performed when pci devices are enumerated and is set to point to the pci_dev->dma_mask which is 0xffffffff. However, for non-pci platforms, the dma_mask pointer remains uninitialized and dma_set_mask() will fail. Also, 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, otherwise the DMA mapping interface will return by default DMA addresses which are 32-bit addressable. This patch removes the dma_mask setup code from xhci_gen_setup() and places it in xhci_pci_setup() and xhci_plat_setup(). The dma_mask setup must be done before the call to xhci_gen_setup() which allocates and maps to dma addresses the xhci-hcd buffers. For pci platforms, the dma_mask and coherent_dma_mask are set by default to 32bit DMA addresses. If both the xHC controller and the host support 64bit DMA addresses, the device dma_mask and coherent_dma_mask will be set to 64bits. For non-pci platforms, the dma_mask pointer is initialized to point to the coherent_dma_mask since the same value will be assigned to both. If dma_set_mask() succeeds, for a given bitmask, it is guaranteed that the given bitmask is also supported for consistent DMA mappings. That is the reason why this patch does not add checks when setting the coherent_dma_mask. Signed-off-by: Xenia Ragiadakou <burzalodowa@xxxxxxxxx> --- Differences from version 1 and 2: The dma_mask setup code was removed from the xhci_gen_setup() function defined in xhci.c and was placed in xhci_pci_setup(), defined in xhci-pci.c, and in xhci_plat_setup(), defined in xhci-plat.c. The dma mask setup code has to be called after the mapping of host controller registers and before the allocation of xhci memory buffers, so it was placed in the driver's 'reset' callback function before the call to xhci_gen_setup(). Initialization of the dma_mask pointer was added for non-pci platforms, following a remark made by Andy Shevchenco. drivers/usb/host/xhci-pci.c | 19 ++++++++++++++++++- drivers/usb/host/xhci-plat.c | 26 ++++++++++++++++++++++++++ drivers/usb/host/xhci.c | 17 ----------------- 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index cc24e39..dff5a22 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -122,9 +122,26 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) static int xhci_pci_setup(struct usb_hcd *hcd) { struct xhci_hcd *xhci; - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); + struct pci_dev *pdev; + struct device *dev; int retval; + dev = hcd->self.controller; + pdev = to_pci_dev(dev); + + if (usb_hcd_is_primary_hcd(hcd)) { + struct xhci_cap_regs __iomem *cap_regs; + u32 hcc_params; + + cap_regs = hcd->regs; + hcc_params = readl(&cap_regs->hcc_params); + if (HCC_64BIT_ADDR(hcc_params) && + !dma_set_mask(dev, DMA_BIT_MASK(64))) { + dev_dbg(dev, "Enabling 64-bit DMA addresses.\n"); + dma_set_coherent_mask(dev, DMA_BIT_MASK(64)); + } + } + retval = xhci_gen_setup(hcd, xhci_pci_quirks); if (retval) return retval; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 51e22bf..d718134 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -30,6 +30,32 @@ static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) /* called during probe() after chip reset completes */ static int xhci_plat_setup(struct usb_hcd *hcd) { + struct device *dev; + int retval; + + dev = hcd->self.controller; + dev->dma_mask = &dev->dma_coherent_mask; + + if (usb_hcd_is_primary_hcd(hcd)) { + struct xhci_cap_regs __iomem *cap_regs; + u32 hcc_params; + + cap_regs = hcd->regs; + hcc_params = readl(&cap_regs->hcc_params); + if (HCC_64BIT_ADDR(hcc_params) && + !dma_set_mask(dev, DMA_BIT_MASK(64))) { + dev_dbg(dev, "Enabling 64-bit DMA addresses.\n"); + } else { + retval = dma_set_mask(dev, DMA_BIT_MASK(32)); + if (retval) { + dev->dma_mask = NULL; + hcd->self.uses_dma = 0; + return retval; + } + } + hcd->self.uses_dma = 1; + } + return xhci_gen_setup(hcd, xhci_plat_quirks); } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 189ca85..32e5493 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4761,7 +4761,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; @@ -4789,14 +4788,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; } @@ -4828,14 +4819,6 @@ 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)) { - 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)); - } - xhci_dbg(xhci, "Calling HCD init\n"); /* Initialize HCD and host controller data structures. */ retval = xhci_init(hcd); -- 1.8.3.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html