summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-11-05 15:50:03 +0100
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2014-03-04 15:38:14 -0800
commit84c1e40fd794a883431fc7688f653d3faa0265f0 (patch)
tree20a93c606bf709a6a364ff3b25945c63ecbac8af
parent127329d76b8534fb58c207db1f172d8468b828ff (diff)
xhci: The trb_address_map radix tree expects 1KB segment memory aligment
If we align segment dma pool memory to 64 bytes, then a segment can be located at 0x10000040 - 0x1000043f, and a segment from another ring at 0x10000440 - 0x1000083f. The last trb in the first segment at 0x10000430 will then translate to the same radix tree key as the first trb of the second segment, while they are in different rings! This patches fixes this by changing the alignment of the dma pool to be 1KB rather then 64 bytes. An alternative fix would be to reduce the shift used to calculate the radix tree keys, but that would (slighlty) grow the radix trees so I believe this is the better fix. Note this patch is mostly theoretical since in practice I've not seen the dma_pool actually return not 1KB aligned memory. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
-rw-r--r--drivers/usb/host/xhci-mem.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 60fc6720007f..c089668308ad 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -158,7 +158,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
*
* The radix tree maps the upper portion of the TRB DMA address to a ring
* segment that has the same upper portion of DMA addresses. For example, say I
- * have segments of size 1KB, that are always 64-byte aligned. A segment may
+ * have segments of size 1KB, that are always 1KB aligned. A segment may
* start at 0x10c91000 and end at 0x10c913f0. If I use the upper 10 bits, the
* key to the stream ID is 0x43244. I can use the DMA address of the TRB to
* pass the radix tree a key to get the right stream ID:
@@ -2375,11 +2375,12 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
/*
* Initialize the ring segment pool. The ring must be a contiguous
* structure comprised of TRBs. The TRBs must be 16 byte aligned,
- * however, the command ring segment needs 64-byte aligned segments,
- * so we pick the greater alignment need.
+ * however, the command ring segment needs 64-byte aligned segments
+ * and our use of dma addresses in the trb_address_map radix tree needs
+ * TRB_SEGMENT_SIZE alignment, so we pick the greater alignment need.
*/
xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
- TRB_SEGMENT_SIZE, 64, xhci->page_size);
+ TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
/* See Table 46 and Note on Figure 55 */
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,