[RFC] xhci: fix dma mask setup in xhci.c

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This patch adds a check on whether the host machine
supports the xHC DMA address mask and sets the DMA
mask for coherent DMA address allocation via an
explicit call to dma_set_coherent_mask().

According to DMA-API-HOWTO, if coherent DMA address
mask has not been set explicitly via dma_set_coherent_mask(),
and the driver calls dma_alloc_coherent() or
dma_pool_create() to allocate consistent DMA memory
blocks, the consistent DMA mapping interface will
return by default DMA addresses which are 32-bit
addressable.

Hence, if 64-bit DMA mapping is supported, it
is appropriate to call dma_set_coherent_mask()
with DMA_BIT_MASK(64) to take advantage of it.

Also, according to DMA-API-HOWTO, dma_set_coherent_mask()
is guaranteed to set successfully the same or a smaller
mask as dma_set_mask().

Signed-off-by: Xenia Ragiadakou <burzalodowa@xxxxxxxxx>
---

After this change, (i have a 64-bit machine) the
consistent_dma_mask_bits entry for xhci controller
that appears under:
/sys/devices/pci0000:00/0000:00:<device.function>/
changed from 32 to 64.
I did not find another way to test this change.

 drivers/usb/host/xhci.c |   32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index b4aa79d..887db65 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -4662,11 +4662,21 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
 		 */
 		xhci = hcd_to_xhci(hcd);
 		temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
-		if (HCC_64BIT_ADDR(temp)) {
+		/*
+		 * Check if host machine supports 64 bit DMA address mask
+		 * and enable it for both streaming and coherent DMA transfers.
+		 * Otherwise, use 32bit DMA mask, if it is supported.
+		 */
+		if (HCC_64BIT_ADDR(temp) &&
+		    !dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64))) {
 			xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
-			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+			dma_set_coherent_mask(hcd->self.controller,
+					      DMA_BIT_MASK(64));
 		} else {
-			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+			if (dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)))
+				goto error;
+			dma_set_coherent_mask(hcd->self.controller,
+					      DMA_BIT_MASK(32));
 		}
 		return 0;
 	}
@@ -4700,11 +4710,21 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
 	xhci_dbg(xhci, "Reset complete\n");
 
 	temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
-	if (HCC_64BIT_ADDR(temp)) {
+	/*
+	 * Check if host machine supports 64 bit DMA address mask
+	 * and enable it for both streaming and coherent DMA transfers.
+	 * Otherwise, use 32bit DMA mask, if it is supported.
+	 */
+	if (HCC_64BIT_ADDR(temp) &&
+	    !dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64))) {
 		xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
-		dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
+		dma_set_coherent_mask(hcd->self.controller,
+				      DMA_BIT_MASK(64));
 	} else {
-		dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
+		if (dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32)))
+			goto error;
+		dma_set_coherent_mask(hcd->self.controller,
+				      DMA_BIT_MASK(32));
 	}
 
 	xhci_dbg(xhci, "Calling HCD init\n");
-- 
1.7.10.4

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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux