aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-ring.c
diff options
context:
space:
mode:
authorAndiry Xu <andiry.xu@amd.com>2012-03-05 04:49:40 -0500
committerSarah Sharp <sarah.a.sharp@linux.intel.com>2012-03-13 12:30:44 -0400
commit085deb16845ee0b25385274b39c70cc07e6e4140 (patch)
tree7e08185fde1567ba14095f4bebe7a9c5c7fd1d36 /drivers/usb/host/xhci-ring.c
parent2fdcd47b6980f4e26a97811a17f5be7cb919ef90 (diff)
xHCI: check enqueue pointer advance into dequeue seg
When a urb is submitted to xHCI driver, check if queueing the urb will make the enqueue pointer advance into dequeue seg and expand the ring if it occurs. This is to guarantee the safety of ring expansion. Signed-off-by: Andiry Xu <andiry.xu@amd.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Tested-by: Paul Zimmerman <Paul.Zimmerman@synopsys.com>
Diffstat (limited to 'drivers/usb/host/xhci-ring.c')
-rw-r--r--drivers/usb/host/xhci-ring.c25
1 files changed, 13 insertions, 12 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 4194f348e3a7..6bd9d53062eb 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -249,16 +249,24 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
249} 249}
250 250
251/* 251/*
252 * Check to see if there's room to enqueue num_trbs on the ring. See rules 252 * Check to see if there's room to enqueue num_trbs on the ring and make sure
253 * above. 253 * enqueue pointer will not advance into dequeue segment. See rules above.
254 */ 254 */
255static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, 255static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
256 unsigned int num_trbs) 256 unsigned int num_trbs)
257{ 257{
258 if (ring->num_trbs_free >= num_trbs) 258 int num_trbs_in_deq_seg;
259 return 1;
260 259
261 return 0; 260 if (ring->num_trbs_free < num_trbs)
261 return 0;
262
263 if (ring->type != TYPE_COMMAND && ring->type != TYPE_EVENT) {
264 num_trbs_in_deq_seg = ring->dequeue - ring->deq_seg->trbs;
265 if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg)
266 return 0;
267 }
268
269 return 1;
262} 270}
263 271
264/* Ring the host controller doorbell after placing a command on the ring */ 272/* Ring the host controller doorbell after placing a command on the ring */
@@ -2529,13 +2537,6 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
2529 return -ENOMEM; 2537 return -ENOMEM;
2530 } 2538 }
2531 2539
2532 if (ep_ring->enq_seg == ep_ring->deq_seg &&
2533 ep_ring->dequeue > ep_ring->enqueue) {
2534 xhci_err(xhci, "Can not expand the ring while dequeue "
2535 "pointer has not passed the link TRB\n");
2536 return -ENOMEM;
2537 }
2538
2539 xhci_dbg(xhci, "ERROR no room on ep ring, " 2540 xhci_dbg(xhci, "ERROR no room on ep ring, "
2540 "try ring expansion\n"); 2541 "try ring expansion\n");
2541 num_trbs_needed = num_trbs - ep_ring->num_trbs_free; 2542 num_trbs_needed = num_trbs - ep_ring->num_trbs_free;