From 5cb802766e9cdc9a56e8ce8e4686692ebbcfb5cc Mon Sep 17 00:00:00 2001 From: Xenia Ragiadakou Date: Mon, 23 Dec 2013 16:59:02 +0100 Subject: [PATCH 197/203] xhci: fix dma mask setup in xhci.c 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 Signed-off-by: Sarah Sharp Conflicts: drivers/usb/host/xhci-plat.c --- drivers/usb/host/xhci-plat.c | 10 ++++++++++ drivers/usb/host/xhci.c | 19 +++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "xhci.h" @@ -105,6 +106,15 @@ static int xhci_plat_probe(struct platfo 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; --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -4657,7 +4657,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, 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; @@ -4685,14 +4684,6 @@ int xhci_gen_setup(struct usb_hcd *hcd, /* 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; } @@ -4731,12 +4722,12 @@ int xhci_gen_setup(struct usb_hcd *hcd, 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");