[lkml]   [2009]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
Messages in this thread
Patch in this message
Subject[046/119] USB: xhci: Fix TRB physical to virtual address translation.
2.6.31-stable review patch.  If anyone has any objections, please let us know.

From: Sarah Sharp <>

commit 2fa88daa6f299bfb83672c3b525d786ad03b4735 upstream.

The trb_in_td() function in the xHCI driver is supposed to translate a
physical transfer buffer request (TRB) into a virtual pointer to the ring
segment that TRB is in.

Unfortunately, a mistake in this function may cause endless loops as the
driver searches through the linked list of ring segments over and over
again. Fix a couple bugs that may lead to loops or bad output:

1. Bail out if we get a NULL pointer when translating the segment's
private structure and the starting DMA address of the segment chunk. If
this happens, we've been handed a starting TRB pointer from a different

2. Make sure the function works when there's multiple segments in the
ring. In the while loop to search through the ring segments, use the
current segment variable (cur_seg), rather than the starting segment
variable (start_seg) that is passed in.

3. Stop searching the ring if we've run through all the segments in the

Signed-off-by: Sarah Sharp <>
Signed-off-by: Greg Kroah-Hartman <>

drivers/usb/host/xhci-ring.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)

--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -822,9 +822,11 @@ static struct xhci_segment *trb_in_td(
cur_seg = start_seg;

do {
+ if (start_dma == 0)
+ return 0;
/* We may get an event for a Link TRB in the middle of a TD */
end_seg_dma = xhci_trb_virt_to_dma(cur_seg,
- &start_seg->trbs[TRBS_PER_SEGMENT - 1]);
+ &cur_seg->trbs[TRBS_PER_SEGMENT - 1]);
/* If the end TRB isn't in this segment, this is set to 0 */
end_trb_dma = xhci_trb_virt_to_dma(cur_seg, end_trb);

@@ -851,8 +853,9 @@ static struct xhci_segment *trb_in_td(
cur_seg = cur_seg->next;
start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]);
- } while (1);
+ } while (cur_seg != start_seg);

+ return 0;


 \ /
  Last update: 2009-12-07 01:55    [W:0.235 / U:1.392 seconds]
©2003-2018 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site