aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorSarah Sharp <sarah.a.sharp@linux.intel.com>2010-05-18 19:05:26 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:30 -0400
commit44ebd037c54f80db3121ac9f5fe6e677b76e11d5 (patch)
treed0a3784e7a7005086ab9842e6d047172bb37d385 /drivers/usb/host/xhci-ring.c
parentbc88d2eba5e19d10dd546e428314909d889b3b6a (diff)
USB: xhci: Fix check for room on the ring.
The length of the scatter gather list a driver can enqueue is limited by the bus' sg_tablesize to 62 entries. Each entry will be described by at least one transfer request block (TRB). If the entry's buffer crosses a 64KB boundary, then that entry will have to be described by two or more TRBs. So even if the USB device driver respects sg_tablesize, the whole scatter list may take more than 62 TRBs to describe, and won't fit on the ring. Don't assume that an empty ring means there is enough room on the transfer ring. The old code would unconditionally queue this too-large transfer, and over write the beginning of the transfer. This would mean the cycle bit was unchanged in those overwritten transfers, causing the hardware to think it didn't own the TRBs, and the host would seem to hang. Now drivers may see submit_urb() fail with -ENOMEM if the transfers are too big to fit on the ring. Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Cc: stable <stable@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b520b37c0f36..407d33fb5e84 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -242,10 +242,27 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
242 int i; 242 int i;
243 union xhci_trb *enq = ring->enqueue; 243 union xhci_trb *enq = ring->enqueue;
244 struct xhci_segment *enq_seg = ring->enq_seg; 244 struct xhci_segment *enq_seg = ring->enq_seg;
245 struct xhci_segment *cur_seg;
246 unsigned int left_on_ring;
245 247
246 /* Check if ring is empty */ 248 /* Check if ring is empty */
247 if (enq == ring->dequeue) 249 if (enq == ring->dequeue) {
250 /* Can't use link trbs */
251 left_on_ring = TRBS_PER_SEGMENT - 1;
252 for (cur_seg = enq_seg->next; cur_seg != enq_seg;
253 cur_seg = cur_seg->next)
254 left_on_ring += TRBS_PER_SEGMENT - 1;
255
256 /* Always need one TRB free in the ring. */
257 left_on_ring -= 1;
258 if (num_trbs > left_on_ring) {
259 xhci_warn(xhci, "Not enough room on ring; "
260 "need %u TRBs, %u TRBs left\n",
261 num_trbs, left_on_ring);
262 return 0;
263 }
248 return 1; 264 return 1;
265 }
249 /* Make sure there's an extra empty TRB available */ 266 /* Make sure there's an extra empty TRB available */
250 for (i = 0; i <= num_trbs; ++i) { 267 for (i = 0; i <= num_trbs; ++i) {
251 if (enq == ring->dequeue) 268 if (enq == ring->dequeue)