Commit 085deb16 authored by Andiry Xu's avatar Andiry Xu Committed by Sarah Sharp

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: default avatarAndiry Xu <andiry.xu@amd.com>
Signed-off-by: default avatarSarah Sharp <sarah.a.sharp@linux.intel.com>
Tested-by: default avatarPaul Zimmerman <Paul.Zimmerman@synopsys.com>
parent 2fdcd47b
...@@ -249,16 +249,24 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, ...@@ -249,16 +249,24 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
} }
/* /*
* Check to see if there's room to enqueue num_trbs on the ring. See rules * Check to see if there's room to enqueue num_trbs on the ring and make sure
* above. * enqueue pointer will not advance into dequeue segment. See rules above.
*/ */
static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_trbs) unsigned int num_trbs)
{ {
if (ring->num_trbs_free >= num_trbs) int num_trbs_in_deq_seg;
return 1;
return 0; if (ring->num_trbs_free < num_trbs)
return 0;
if (ring->type != TYPE_COMMAND && ring->type != TYPE_EVENT) {
num_trbs_in_deq_seg = ring->dequeue - ring->deq_seg->trbs;
if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg)
return 0;
}
return 1;
} }
/* Ring the host controller doorbell after placing a command on the ring */ /* 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,13 +2537,6 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
return -ENOMEM; return -ENOMEM;
} }
if (ep_ring->enq_seg == ep_ring->deq_seg &&
ep_ring->dequeue > ep_ring->enqueue) {
xhci_err(xhci, "Can not expand the ring while dequeue "
"pointer has not passed the link TRB\n");
return -ENOMEM;
}
xhci_dbg(xhci, "ERROR no room on ep ring, " xhci_dbg(xhci, "ERROR no room on ep ring, "
"try ring expansion\n"); "try ring expansion\n");
num_trbs_needed = num_trbs - ep_ring->num_trbs_free; num_trbs_needed = num_trbs - ep_ring->num_trbs_free;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment