aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorJohn Youn <John.Youn@synopsys.com>2010-05-10 18:33:00 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-05-20 16:21:44 -0400
commit6c12db90f19727c76990e7f4801c67a148b30111 (patch)
treeae2454143dac5970376cfeb10af008fa03eef7d7 /drivers/usb
parentb0608690c2deafbca32b45196672bfd74006cf61 (diff)
USB: xhci: Transfer ring link TRB activation change.
Change transfer ring behavior to not follow/activate link TRBs until active TRBs are queued after it. This change affects the behavior when a TD ends just before a link TRB. Signed-off-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-ring.c71
1 files changed, 58 insertions, 13 deletions
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 15f02e88f329..803f6810e996 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -112,6 +112,12 @@ static inline int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
112 return (trb->link.control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK); 112 return (trb->link.control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK);
113} 113}
114 114
115static inline int enqueue_is_link_trb(struct xhci_ring *ring)
116{
117 struct xhci_link_trb *link = &ring->enqueue->link;
118 return ((link->control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK));
119}
120
115/* Updates trb to point to the next TRB in the ring, and updates seg if the next 121/* Updates trb to point to the next TRB in the ring, and updates seg if the next
116 * TRB is in a new segment. This does not skip over link TRBs, and it does not 122 * TRB is in a new segment. This does not skip over link TRBs, and it does not
117 * effect the ring dequeue or enqueue pointers. 123 * effect the ring dequeue or enqueue pointers.
@@ -193,20 +199,15 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer
193 while (last_trb(xhci, ring, ring->enq_seg, next)) { 199 while (last_trb(xhci, ring, ring->enq_seg, next)) {
194 if (!consumer) { 200 if (!consumer) {
195 if (ring != xhci->event_ring) { 201 if (ring != xhci->event_ring) {
196 /* If we're not dealing with 0.95 hardware, 202 if (chain) {
197 * carry over the chain bit of the previous TRB 203 next->link.control |= TRB_CHAIN;
198 * (which may mean the chain bit is cleared). 204
199 */ 205 /* Give this link TRB to the hardware */
200 if (!xhci_link_trb_quirk(xhci)) { 206 wmb();
201 next->link.control &= ~TRB_CHAIN; 207 next->link.control ^= TRB_CYCLE;
202 next->link.control |= chain; 208 } else {
209 break;
203 } 210 }
204 /* Give this link TRB to the hardware */
205 wmb();
206 if (next->link.control & TRB_CYCLE)
207 next->link.control &= (u32) ~TRB_CYCLE;
208 else
209 next->link.control |= (u32) TRB_CYCLE;
210 } 211 }
211 /* Toggle the cycle bit after the last ring segment. */ 212 /* Toggle the cycle bit after the last ring segment. */
212 if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) { 213 if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -245,6 +246,13 @@ static int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
245 struct xhci_segment *cur_seg; 246 struct xhci_segment *cur_seg;
246 unsigned int left_on_ring; 247 unsigned int left_on_ring;
247 248
249 /* If we are currently pointing to a link TRB, advance the
250 * enqueue pointer before checking for space */
251 while (last_trb(xhci, ring, enq_seg, enq)) {
252 enq_seg = enq_seg->next;
253 enq = enq_seg->trbs;
254 }
255
248 /* Check if ring is empty */ 256 /* Check if ring is empty */
249 if (enq == ring->dequeue) { 257 if (enq == ring->dequeue) {
250 /* Can't use link trbs */ 258 /* Can't use link trbs */
@@ -1728,6 +1736,43 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
1728 xhci_err(xhci, "ERROR no room on ep ring\n"); 1736 xhci_err(xhci, "ERROR no room on ep ring\n");
1729 return -ENOMEM; 1737 return -ENOMEM;
1730 } 1738 }
1739
1740 if (enqueue_is_link_trb(ep_ring)) {
1741 struct xhci_ring *ring = ep_ring;
1742 union xhci_trb *next;
1743 unsigned long long addr;
1744
1745 xhci_dbg(xhci, "prepare_ring: pointing to link trb\n");
1746 next = ring->enqueue;
1747
1748 while (last_trb(xhci, ring, ring->enq_seg, next)) {
1749
1750 /* If we're not dealing with 0.95 hardware,
1751 * clear the chain bit.
1752 */
1753 if (!xhci_link_trb_quirk(xhci))
1754 next->link.control &= ~TRB_CHAIN;
1755 else
1756 next->link.control |= TRB_CHAIN;
1757
1758 wmb();
1759 next->link.control ^= (u32) TRB_CYCLE;
1760
1761 /* Toggle the cycle bit after the last ring segment. */
1762 if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
1763 ring->cycle_state = (ring->cycle_state ? 0 : 1);
1764 if (!in_interrupt()) {
1765 xhci_dbg(xhci, "queue_trb: Toggle cycle "
1766 "state for ring %p = %i\n",
1767 ring, (unsigned int)ring->cycle_state);
1768 }
1769 }
1770 ring->enq_seg = ring->enq_seg->next;
1771 ring->enqueue = ring->enq_seg->trbs;
1772 next = ring->enqueue;
1773 }
1774 }
1775
1731 return 0; 1776 return 0;
1732} 1777}
1733 1778