[RFC PATCH 12/20] xhci: introduce struct xhci_ring_pointer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Consolidate ring pointer tracking variables into their own type.  This
simplifies the calling convention of some routines and allows for the
later introduction of integer ring index variables.

Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---
 drivers/usb/host/xhci-dbg.c  |    8 +
 drivers/usb/host/xhci-mem.c  |   26 ++--
 drivers/usb/host/xhci-ring.c |  306 +++++++++++++++++++-----------------------
 drivers/usb/host/xhci.c      |   32 ++--
 drivers/usb/host/xhci.h      |   55 +++++---
 5 files changed, 201 insertions(+), 226 deletions(-)

diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 19a6037257c3..f1230629978c 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -330,12 +330,12 @@ void xhci_dbg_ring_ptrs(struct xhci_hcd *xhci, struct xhci_ring *ring)
 {
 	dma_addr_t dma;
 
-	dma = xhci_trb_virt_to_dma(ring->deq_seg, xhci_ring_dequeue(ring));
+	dma = xhci_trb_virt_to_dma(&ring->deq);
 	xhci_dbg(xhci, "Ring deq = %p (virt), %pad (dma)\n",
 			xhci_ring_dequeue(ring), &dma);
 	xhci_dbg(xhci, "Ring deq updated %u times\n",
 			ring->deq_updates);
-	dma = xhci_trb_virt_to_dma(ring->enq_seg, xhci_ring_enqueue(ring));
+	dma = xhci_trb_virt_to_dma(&ring->enq);
 	xhci_dbg(xhci, "Ring enq = %p (virt), %pad (dma)\n",
 			xhci_ring_enqueue(ring), &dma);
 	xhci_dbg(xhci, "Ring enq updated %u times\n",
@@ -379,7 +379,7 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
 			ring = ep->stream_info->stream_rings[i];
 			xhci_dbg(xhci, "Dev %d endpoint %d stream ID %d:\n",
 				slot_id, ep_index, i);
-			xhci_debug_segment(xhci, ring->deq_seg);
+			xhci_debug_segment(xhci, ring->deq.seg);
 		}
 	} else {
 		ring = ep->ring;
@@ -387,7 +387,7 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
 			return;
 		xhci_dbg(xhci, "Dev %d endpoint ring %d:\n",
 				slot_id, ep_index);
-		xhci_debug_segment(xhci, ring->deq_seg);
+		xhci_debug_segment(xhci, ring->deq.seg);
 	}
 }
 
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index e0b459441807..452aa75a096c 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -107,7 +107,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
 
 	new_tail = list_last_entry(segments, typeof(*new_tail), list);
 	new_head = list_first_entry(segments, typeof(*new_head), list);
-	insert_head = ring->enq_seg;
+	insert_head = ring->enq.seg;
 	insert_next = xhci_segment_next(ring, insert_head);
 
 	/* link them physically */
@@ -259,12 +259,12 @@ static void xhci_initialize_ring_info(struct xhci_ring *ring,
 					unsigned int cycle_state)
 {
 	struct xhci_segment *first_seg = xhci_ring_first_seg(ring);
+	struct xhci_ring_pointer enq = { first_seg, first_seg->trbs };
 
 	/* The ring is empty, so the enqueue pointer == dequeue pointer */
-	xhci_ring_set_enqueue(ring, first_seg->trbs);
-	ring->enq_seg = first_seg;
-	xhci_ring_set_dequeue(ring, xhci_ring_enqueue(ring));
-	ring->deq_seg = first_seg;
+	xhci_ring_set_enqueue(ring, &enq);
+	xhci_ring_set_dequeue(ring, &enq);
+
 	/* The ring is initialized to 0. The producer must write 1 to the cycle
 	 * bit to handover ownership of the TRB, so PCS = 1.  The consumer must
 	 * compare CCS to the cycle bit to check ownership, so CCS = 1.
@@ -753,7 +753,7 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
 	dma_addr_t addr;
 
 	ep_ctx->ep_info &= cpu_to_le32(~(EP_MAXPSTREAMS_MASK | EP_HAS_LSA));
-	addr = xhci_trb_virt_to_dma(ring->deq_seg, xhci_ring_dequeue(ring));
+	addr = xhci_trb_virt_to_dma(&ring->deq);
 	ep_ctx->deq  = cpu_to_le64(addr | ep->ring->cycle_state);
 }
 
@@ -1015,8 +1015,7 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
 	 * configured device has reset, so all control transfers should have
 	 * been completed or cancelled before the reset.
 	 */
-	ep0_ctx->deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring->enq_seg,
-				xhci_ring_enqueue(ep_ring))
+	ep0_ctx->deq = cpu_to_le64(xhci_trb_virt_to_dma(&ep_ring->enq)
 			| ep_ring->cycle_state);
 }
 
@@ -1859,11 +1858,13 @@ static int xhci_test_trb_in_td(struct xhci_hcd *xhci,
 	unsigned long long start_dma;
 	unsigned long long end_dma;
 	struct xhci_segment *seg;
+	struct xhci_ring_pointer start_rp = { input_seg, start_trb };
+	struct xhci_ring_pointer end_rp = { input_seg, end_trb };
 
-	start_dma = xhci_trb_virt_to_dma(input_seg, start_trb);
-	end_dma = xhci_trb_virt_to_dma(input_seg, end_trb);
+	start_dma = xhci_trb_virt_to_dma(&start_rp);
+	end_dma = xhci_trb_virt_to_dma(&end_rp);
 
-	seg = trb_in_td(input_ring, input_seg, start_trb, end_trb, input_dma);
+	seg = trb_in_td(input_ring, &start_rp, end_trb, input_dma);
 	if (seg != result_seg) {
 		xhci_warn(xhci, "WARN: %s TRB math test %d failed!\n",
 				test_name, test_number);
@@ -2021,8 +2022,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
 	u64 temp;
 	dma_addr_t deq;
 
-	deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
-			xhci_ring_dequeue(xhci->event_ring));
+	deq = xhci_trb_virt_to_dma(&xhci->event_ring->deq);
 	if (deq == 0 && !in_interrupt())
 		xhci_warn(xhci, "WARN something wrong with SW event ring "
 				"dequeue ptr.\n");
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 01e6685738ff..d364f504c1fd 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -73,10 +73,11 @@
  * Returns zero if the TRB isn't in this segment, otherwise it returns the DMA
  * address of the TRB.
  */
-dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
-		union xhci_trb *trb)
+dma_addr_t xhci_trb_virt_to_dma(struct xhci_ring_pointer *rp)
 {
 	unsigned long segment_offset;
+	union xhci_trb *trb = rp->ptr;
+	struct xhci_segment *seg = rp->seg;
 
 	if (!seg || !trb || trb < seg->trbs)
 		return 0;
@@ -91,16 +92,16 @@ dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg,
  * or was the previous TRB the last TRB on the last segment in the ERST?
  */
 static bool event_last_trb_ring(struct xhci_ring *ring,
-		struct xhci_segment *seg, union xhci_trb *trb)
+		struct xhci_ring_pointer *rp)
 {
-	return (trb == &seg->trbs[TRBS_PER_SEGMENT]) &&
-		(seg == xhci_ring_last_seg(ring));
+	return (rp->ptr == &rp->seg->trbs[TRBS_PER_SEGMENT]) &&
+		(rp->seg == xhci_ring_last_seg(ring));
 }
 
 static bool ep_last_trb_ring(struct xhci_ring *ring,
-		struct xhci_segment *seg, union xhci_trb *trb)
+		struct xhci_ring_pointer *rp)
 {
-	return le32_to_cpu(trb->link.control) & LINK_TOGGLE;
+	return le32_to_cpu(rp->ptr->link.control) & LINK_TOGGLE;
 }
 
 
@@ -108,16 +109,14 @@ static bool ep_last_trb_ring(struct xhci_ring *ring,
  * segment?  I.e. would the updated event TRB pointer step off the end of the
  * event seg?
  */
-static bool event_last_trb(struct xhci_ring *ring, struct xhci_segment *seg,
-		union xhci_trb *trb)
+static bool event_last_trb(struct xhci_ring *ring, struct xhci_ring_pointer *rp)
 {
-	return trb == &seg->trbs[TRBS_PER_SEGMENT];
+	return rp->ptr == &rp->seg->trbs[TRBS_PER_SEGMENT];
 }
 
-static bool ep_last_trb(struct xhci_ring *ring, struct xhci_segment *seg,
-		union xhci_trb *trb)
+static bool ep_last_trb(struct xhci_ring *ring, struct xhci_ring_pointer *rp)
 {
-	return TRB_TYPE_LINK_LE32(trb->link.control);
+	return TRB_TYPE_LINK_LE32(rp->ptr->link.control);
 }
 
 static int enqueue_is_link_trb(struct xhci_ring *ring)
@@ -130,15 +129,12 @@ static int enqueue_is_link_trb(struct xhci_ring *ring)
  * TRB is in a new segment.  This does not skip over link TRBs, and it does not
  * effect the ring dequeue or enqueue pointers.
  */
-static void next_trb(struct xhci_ring *ring, struct xhci_segment **seg,
-		union xhci_trb **trb)
+static void next_trb(struct xhci_ring *ring, struct xhci_ring_pointer *rp)
 {
-	if (ring->ops->last_trb(ring, *seg, *trb)) {
-		*seg = xhci_segment_next(ring, *seg);
-		*trb = ((*seg)->trbs);
-	} else {
-		(*trb)++;
-	}
+	if (ring->ops->last_trb(ring, rp))
+		xhci_ring_pointer_advance_seg(ring, rp);
+	else
+		xhci_ring_pointer_advance(rp);
 }
 
 /*
@@ -148,11 +144,10 @@ static void next_trb(struct xhci_ring *ring, struct xhci_segment **seg,
 static void event_inc_deq(struct xhci_ring *ring)
 {
 	ring->deq_updates++;
-	xhci_ring_set_dequeue(ring, xhci_ring_dequeue(ring) + 1);
+	xhci_ring_pointer_advance(&ring->deq);
 
-	if (ring->ops->last_trb(ring, ring->deq_seg, xhci_ring_dequeue(ring))) {
-		ring->deq_seg = xhci_segment_next(ring, ring->deq_seg);
-		xhci_ring_set_dequeue(ring, ring->deq_seg->trbs);
+	if (ring->ops->last_trb(ring, &ring->deq)) {
+		xhci_ring_pointer_advance_seg(ring, &ring->deq);
 		ring->cycle_state ^= 1;
 	}
 }
@@ -161,21 +156,16 @@ static void ep_inc_deq(struct xhci_ring *ring)
 {
 	ring->deq_updates++;
 
-	if (!ring->ops->last_trb(ring, ring->deq_seg, xhci_ring_dequeue(ring)))
+	if (!ring->ops->last_trb(ring, &ring->deq))
 		ring->num_trbs_free++;
 
 	do {
 		/* Update the dequeue pointer further if that was a link TRB */
-		if (ring->ops->last_trb(ring, ring->deq_seg,
-					xhci_ring_dequeue(ring))) {
-			ring->deq_seg = xhci_segment_next(ring, ring->deq_seg);
-			xhci_ring_set_dequeue(ring, ring->deq_seg->trbs);
-		} else {
-			xhci_ring_set_dequeue(ring,
-					xhci_ring_dequeue(ring) + 1);
-		}
-	} while (ring->ops->last_trb(ring, ring->deq_seg,
-				xhci_ring_dequeue(ring)));
+		if (ring->ops->last_trb(ring, &ring->deq))
+			xhci_ring_pointer_advance_seg(ring, &ring->deq);
+		else
+			xhci_ring_pointer_advance(&ring->deq);
+	} while (ring->ops->last_trb(ring, &ring->deq));
 }
 
 /*
@@ -184,13 +174,13 @@ static void ep_inc_deq(struct xhci_ring *ring)
  */
 static void advance_enq(struct xhci_ring *ring, u32 chain, bool do_carry_chain)
 {
-	union xhci_trb *next = xhci_ring_enqueue(ring);
-
 	/*
 	 * Update the enqueue pointer further if we're now pointing to a
 	 * link TRB
 	 */
-	while (ring->ops->last_trb(ring, ring->enq_seg, next)) {
+	while (ring->ops->last_trb(ring, &ring->enq)) {
+		union xhci_trb *next = xhci_ring_enqueue(ring);
+
 		if (do_carry_chain) {
 			next->link.control &= cpu_to_le32(~TRB_CHAIN);
 			next->link.control |= cpu_to_le32(chain);
@@ -203,11 +193,9 @@ static void advance_enq(struct xhci_ring *ring, u32 chain, bool do_carry_chain)
 		next->link.control ^= cpu_to_le32(TRB_CYCLE);
 
 		/* Toggle the cycle bit after the last ring segment. */
-		if (ring->ops->last_trb_ring(ring, ring->enq_seg, next))
+		if (ring->ops->last_trb_ring(ring, &ring->enq))
 			ring->cycle_state ^= 1;
-		ring->enq_seg = xhci_segment_next(ring, ring->enq_seg);
-		xhci_ring_set_enqueue(ring, ring->enq_seg->trbs);
-		next = xhci_ring_enqueue(ring);
+		xhci_ring_pointer_advance_seg(ring, &ring->enq);
 	}
 }
 
@@ -232,7 +220,7 @@ static void common_inc_enq(struct xhci_ring *ring, bool more_trbs_coming,
 	u32 chain = le32_to_cpu(enqueue->generic.field[3]) & TRB_CHAIN;
 
 	ring->num_trbs_free--;
-	xhci_ring_set_enqueue(ring, enqueue + 1);
+	xhci_ring_pointer_advance(&ring->enq);
 	ring->enq_updates++;
 
 	/*
@@ -267,17 +255,15 @@ static void chain_quirk_inc_enq(struct xhci_ring *ring, bool more_trbs_coming)
  */
 static void event_inc_enq(struct xhci_ring *ring, bool unused)
 {
-	xhci_ring_set_enqueue(ring, xhci_ring_enqueue(ring) + 1);
+	xhci_ring_pointer_advance(&ring->enq);
 	ring->enq_updates++;
 
 	/*
 	 * Fix up the enqueue pointer if we're at the end of an event
 	 * ring segment (which doesn't have link TRBS)
 	 */
-	if (ring->ops->last_trb(ring, ring->enq_seg, xhci_ring_enqueue(ring))) {
-		ring->enq_seg = xhci_segment_next(ring, ring->enq_seg);
-		xhci_ring_set_enqueue(ring, ring->enq_seg->trbs);
-	}
+	if (ring->ops->last_trb(ring, &ring->enq))
+		xhci_ring_pointer_advance_seg(ring, &ring->enq);
 }
 
 static bool do_carry_chain(struct xhci_hcd *xhci, struct xhci_ring *ring)
@@ -418,7 +404,7 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring,
 
 	if (!ring->is_command && !xhci_is_event_ring(ring)) {
 		num_trbs_in_deq_seg = xhci_ring_dequeue(ring)
-			- ring->deq_seg->trbs;
+			- ring->deq.seg->trbs;
 		if (ring->num_trbs_free < num_trbs + num_trbs_in_deq_seg)
 			return 0;
 	}
@@ -528,17 +514,17 @@ static void ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
  * bit set, then we will toggle the value pointed at by cycle_state.
  */
 static struct xhci_segment *find_trb_seg(struct xhci_ring *ring,
-		struct xhci_segment *start_seg,
-		union xhci_trb	*trb, int *cycle_state)
+		struct xhci_ring_pointer *start_rp, int *cycle_state)
 {
-	struct xhci_segment *cur_seg = start_seg;
+	struct xhci_segment *cur_seg = start_rp->seg;
+	union xhci_trb *trb = start_rp->ptr;
 
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
 		if (cur_seg->link->link.control & cpu_to_le32(LINK_TOGGLE))
 			*cycle_state ^= 0x1;
 		cur_seg = xhci_segment_next(ring, cur_seg);
-		if (cur_seg == start_seg)
+		if (cur_seg == start_rp->seg)
 			/* Looped over the entire list.  Oops! */
 			return NULL;
 	}
@@ -615,9 +601,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	struct xhci_virt_device *dev = xhci->devs[slot_id];
 	struct xhci_virt_ep *ep = &dev->eps[ep_index];
 	struct xhci_generic_trb *trb;
+	dma_addr_t addr, hw_dequeue;
 	struct xhci_ring *ep_ring;
-	dma_addr_t addr;
-	u64 hw_dequeue;
 
 	ep_ring = xhci_triad_to_transfer_ring(xhci, slot_id,
 			ep_index, stream_id);
@@ -643,13 +628,11 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	}
 
 	/* Find virtual address and segment of hardware dequeue pointer */
-	state->new_deq_seg = ep_ring->deq_seg;
-	state->new_deq_ptr = xhci_ring_dequeue(ep_ring);
-	while (xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr)
-			!= (dma_addr_t)(hw_dequeue & ~0xf)) {
-		next_trb(ep_ring, &state->new_deq_seg,
-					&state->new_deq_ptr);
-		if (state->new_deq_ptr == xhci_ring_dequeue(ep_ring)) {
+	state->new_deq = ep_ring->deq;
+	state->new_cycle_state = hw_dequeue & 0x1;
+	while (xhci_trb_virt_to_dma(&state->new_deq) != (hw_dequeue & ~0xf)) {
+		next_trb(ep_ring, &state->new_deq);
+		if (state->new_deq.ptr == xhci_ring_dequeue(ep_ring)) {
 			WARN_ON(1);
 			return;
 		}
@@ -662,25 +645,25 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 	 */
 	state->new_cycle_state = hw_dequeue & 0x1;
 	if (list_is_singular(&ep_ring->segments) &&
-			cur_td->last_trb < state->new_deq_ptr)
+			cur_td->last_trb < state->new_deq.ptr)
 		state->new_cycle_state ^= 0x1;
 
-	state->new_deq_ptr = cur_td->last_trb;
+	state->new_deq.ptr = cur_td->last_trb;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"Finding segment containing last TRB in TD.");
-	state->new_deq_seg = find_trb_seg(ep_ring, state->new_deq_seg,
-			state->new_deq_ptr, &state->new_cycle_state);
-	if (!state->new_deq_seg) {
+	state->new_deq.seg = find_trb_seg(ep_ring, &state->new_deq,
+			&state->new_cycle_state);
+	if (!state->new_deq.seg) {
 		WARN_ON(1);
 		return;
 	}
 
 	/* Increment to find next TRB after last_trb. Cycle if appropriate. */
-	trb = &state->new_deq_ptr->generic;
+	trb = &state->new_deq.ptr->generic;
 	if (TRB_TYPE_LINK_LE32(trb->field[3]) &&
 	    (trb->field[3] & cpu_to_le32(LINK_TOGGLE)))
 		state->new_cycle_state ^= 0x1;
-	next_trb(ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
+	next_trb(ep_ring, &state->new_deq);
 
 	/* Don't update the ring cycle state for the producer (us). */
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
@@ -688,8 +671,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"New dequeue segment = %p (virtual)",
-			state->new_deq_seg);
-	addr = xhci_trb_virt_to_dma(state->new_deq_seg, state->new_deq_ptr);
+			state->new_deq.seg);
+	addr = xhci_trb_virt_to_dma(&state->new_deq);
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"New dequeue pointer = 0x%llx (DMA)",
 			(unsigned long long) addr);
@@ -702,12 +685,12 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
 static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 		struct xhci_td *cur_td, bool flip_cycle)
 {
-	struct xhci_segment *cur_seg;
-	union xhci_trb *cur_trb;
+	struct xhci_ring_pointer cur_rp = { cur_td->start_seg,
+		cur_td->first_trb };
+
+	for (; true; next_trb(ep_ring, &cur_rp)) {
+		union xhci_trb *cur_trb = cur_rp.ptr;
 
-	for (cur_seg = cur_td->start_seg, cur_trb = cur_td->first_trb;
-			true;
-			next_trb(ep_ring, &cur_seg, &cur_trb)) {
 		if (TRB_TYPE_LINK_LE32(cur_trb->generic.field[3])) {
 			/* Unchain any chained Link TRBs, but
 			 * leave the pointers intact.
@@ -725,9 +708,9 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 					"Address = %p (0x%llx dma); "
 					"in seg %p (0x%llx dma)",
 					cur_trb,
-					(unsigned long long)xhci_trb_virt_to_dma(cur_seg, cur_trb),
-					cur_seg,
-					(unsigned long long)cur_seg->dma);
+					(unsigned long long)xhci_trb_virt_to_dma(&cur_rp),
+					cur_rp.seg,
+					(unsigned long long)cur_rp.seg->dma);
 		} else {
 			cur_trb->generic.field[0] = 0;
 			cur_trb->generic.field[1] = 0;
@@ -744,7 +727,7 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 			xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 					"TRB to noop at offset 0x%llx",
 					(unsigned long long)
-					xhci_trb_virt_to_dma(cur_seg, cur_trb));
+					xhci_trb_virt_to_dma(&cur_rp));
 		}
 		if (cur_trb == cur_td->last_trb)
 			break;
@@ -754,8 +737,7 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
 static int queue_set_tr_deq(struct xhci_hcd *xhci,
 		struct xhci_command *cmd, int slot_id,
 		unsigned int ep_index, unsigned int stream_id,
-		struct xhci_segment *deq_seg,
-		union xhci_trb *deq_ptr, u32 cycle_state);
+		struct xhci_ring_pointer *rp, u32 cycle_state);
 
 void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
 		struct xhci_command *cmd,
@@ -768,15 +750,13 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci,
 	xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), "
 			"new deq ptr = %p (0x%llx dma), new cycle = %u",
-			deq_state->new_deq_seg,
-			(unsigned long long)deq_state->new_deq_seg->dma,
-			deq_state->new_deq_ptr,
-			(unsigned long long)xhci_trb_virt_to_dma(deq_state->new_deq_seg, deq_state->new_deq_ptr),
+			deq_state->new_deq.seg,
+			(unsigned long long)deq_state->new_deq.seg->dma,
+			deq_state->new_deq.ptr,
+			(unsigned long long)xhci_trb_virt_to_dma(&deq_state->new_deq),
 			deq_state->new_cycle_state);
 	queue_set_tr_deq(xhci, cmd, slot_id, ep_index, stream_id,
-			deq_state->new_deq_seg,
-			deq_state->new_deq_ptr,
-			(u32) deq_state->new_cycle_state);
+			&deq_state->new_deq, deq_state->new_cycle_state);
 	/* Stop the TD queueing code from ringing the doorbell until
 	 * this command completes.  The HC won't set the dequeue pointer
 	 * if the ring is running, and ringing the doorbell starts the
@@ -875,11 +855,14 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
 	 * if another Stop Endpoint command completes
 	 */
 	list_for_each(entry, &ep->cancelled_td_list) {
+		struct xhci_ring_pointer td_rp;
+
 		cur_td = list_entry(entry, struct xhci_td, cancelled_td_list);
+		td_rp.seg = cur_td->start_seg;
+		td_rp.ptr = cur_td->first_trb;
 		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 				"Removing canceled TD starting at 0x%llx (dma).",
-				(unsigned long long)xhci_trb_virt_to_dma(
-					cur_td->start_seg, cur_td->first_trb));
+				(unsigned long long)xhci_trb_virt_to_dma(&td_rp));
 		ep_ring = xhci_urb_to_transfer_ring(xhci, cur_td->urb);
 		if (!ep_ring) {
 			/* This shouldn't happen unless a driver is mucking
@@ -921,7 +904,7 @@ remove_finished_td:
 	xhci_stop_watchdog_timer_in_irq(xhci, ep);
 
 	/* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
-	if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
+	if (deq_state.new_deq.ptr && deq_state.new_deq.seg) {
 		struct xhci_command *command;
 		command = xhci_alloc_command(xhci, false, false, GFP_ATOMIC);
 		xhci_queue_new_dequeue_state(xhci, command,
@@ -1126,23 +1109,18 @@ static void update_ring_for_set_deq_completion(struct xhci_hcd *xhci,
 	 * the dequeue pointer one segment further, or we'll jump off
 	 * the segment into la-la-land.
 	 */
-	if (ep_ring->ops->last_trb(ep_ring, ep_ring->deq_seg, dequeue_temp)) {
-		ep_ring->deq_seg = xhci_segment_next(ep_ring, ep_ring->deq_seg);
-		xhci_ring_set_dequeue(ep_ring, ep_ring->deq_seg->trbs);
-	}
+	if (ep_ring->ops->last_trb(ep_ring, &ep_ring->deq))
+		xhci_ring_pointer_advance_seg(ep_ring, &ep_ring->deq);
 
-	while (xhci_ring_dequeue(ep_ring) != ep->queued_deq_ptr) {
+	while (xhci_ring_dequeue(ep_ring) != ep->queued_deq.ptr) {
 		/* We have more usable TRBs */
 		ep_ring->num_trbs_free++;
-		xhci_ring_set_dequeue(ep_ring, xhci_ring_dequeue(ep_ring) + 1);
-		if (ep_ring->ops->last_trb(ep_ring, ep_ring->deq_seg,
-				xhci_ring_dequeue(ep_ring))) {
+		xhci_ring_pointer_advance(&ep_ring->deq);
+		if (ep_ring->ops->last_trb(ep_ring, &ep_ring->deq)) {
 			if (xhci_ring_dequeue(ep_ring) ==
-					dev->eps[ep_index].queued_deq_ptr)
+					dev->eps[ep_index].queued_deq.ptr)
 				break;
-			ep_ring->deq_seg = xhci_segment_next(ep_ring,
-					ep_ring->deq_seg);
-			xhci_ring_set_dequeue(ep_ring, ep_ring->deq_seg->trbs);
+			xhci_ring_pointer_advance_seg(ep_ring, &ep_ring->deq);
 		}
 		if (xhci_ring_dequeue(ep_ring) == dequeue_temp) {
 			revert = true;
@@ -1236,8 +1214,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
 		}
 		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 			"Successful Set TR Deq Ptr cmd, deq = @%08llx", deq);
-		if (xhci_trb_virt_to_dma(ep->queued_deq_seg,
-					 ep->queued_deq_ptr) == deq) {
+		if (xhci_trb_virt_to_dma(&ep->queued_deq) == deq) {
 			/* Update the ring's dequeue segment and dequeue pointer
 			 * to reflect the new position.
 			 */
@@ -1246,13 +1223,13 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
 		} else {
 			xhci_warn(xhci, "Mismatch between completed Set TR Deq Ptr command & xHCI internal state.\n");
 			xhci_warn(xhci, "ep deq seg = %p, deq ptr = %p\n",
-				  ep->queued_deq_seg, ep->queued_deq_ptr);
+				  ep->queued_deq.seg, ep->queued_deq.ptr);
 		}
 	}
 
 	dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING;
-	dev->eps[ep_index].queued_deq_seg = NULL;
-	dev->eps[ep_index].queued_deq_ptr = NULL;
+	dev->eps[ep_index].queued_deq.seg = NULL;
+	dev->eps[ep_index].queued_deq.ptr = NULL;
 	/* Restart any rings with pending URBs */
 	ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
 }
@@ -1509,9 +1486,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 	u32 cmd_type;
 
 	cmd_dma = le64_to_cpu(event->cmd_trb);
-	cmd_trb = xhci_ring_dequeue(xhci->cmd_ring);
-	cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
-			cmd_trb);
+	cmd_dequeue_dma = xhci_trb_virt_to_dma(&xhci->cmd_ring->deq);
 	/* Is the command ring deq ptr out of sync with the deq seg ptr? */
 	if (cmd_dequeue_dma == 0) {
 		xhci->error_bitmask |= 1 << 4;
@@ -1533,6 +1508,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
 
 	del_timer(&xhci->cmd_timer);
 
+	cmd_trb = xhci_ring_dequeue(xhci->cmd_ring);
 	trace_xhci_cmd_completion(cmd_trb, (struct xhci_generic_trb *) event);
 
 	cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
@@ -1877,51 +1853,48 @@ cleanup:
  * returns 0.
  */
 struct xhci_segment *trb_in_td(struct xhci_ring *ring,
-		struct xhci_segment *start_seg,
-		union xhci_trb	*start_trb,
-		union xhci_trb	*end_trb,
-		dma_addr_t	suspect_dma)
+		struct xhci_ring_pointer *start_rp,
+		union xhci_trb *end_trb, dma_addr_t suspect_dma)
 {
-	dma_addr_t start_dma;
-	dma_addr_t end_seg_dma;
-	dma_addr_t end_trb_dma;
-	struct xhci_segment *cur_seg;
-
-	start_dma = xhci_trb_virt_to_dma(start_seg, start_trb);
-	cur_seg = start_seg;
+	struct xhci_ring_pointer cur_rp = *start_rp;
 
 	do {
+		dma_addr_t start_dma = xhci_trb_virt_to_dma(&cur_rp);
+		dma_addr_t end_seg_dma, end_trb_dma;
+
 		if (start_dma == 0)
 			return NULL;
 		/* 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, cur_seg->link);
+		cur_rp.ptr = cur_rp.seg->link;
+		end_seg_dma = xhci_trb_virt_to_dma(&cur_rp);
+
 		/* 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);
+		cur_rp.ptr = end_trb;
+		end_trb_dma = xhci_trb_virt_to_dma(&cur_rp);
 
 		if (end_trb_dma > 0) {
 			/* The end TRB is in this segment, so suspect should be here */
 			if (start_dma <= end_trb_dma) {
 				if (suspect_dma >= start_dma && suspect_dma <= end_trb_dma)
-					return cur_seg;
+					return cur_rp.seg;
 			} else {
 				/* Case for one segment with
 				 * a TD wrapped around to the top
 				 */
 				if ((suspect_dma >= start_dma &&
 							suspect_dma <= end_seg_dma) ||
-						(suspect_dma >= cur_seg->dma &&
+						(suspect_dma >= cur_rp.seg->dma &&
 						 suspect_dma <= end_trb_dma))
-					return cur_seg;
+					return cur_rp.seg;
 			}
 			return NULL;
 		} else {
 			/* Might still be somewhere in this segment */
 			if (suspect_dma >= start_dma && suspect_dma <= end_seg_dma)
-				return cur_seg;
+				return cur_rp.seg;
 		}
-		cur_seg = xhci_segment_next(ring, cur_seg);
-		start_dma = xhci_trb_virt_to_dma(cur_seg, &cur_seg->trbs[0]);
-	} while (cur_seg != start_seg);
+		xhci_ring_pointer_advance_seg(ring, &cur_rp);
+	} while (cur_rp.seg != start_rp->seg);
 
 	return NULL;
 }
@@ -2212,8 +2185,6 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
 	struct urb_priv *urb_priv;
 	int idx;
 	int len = 0;
-	union xhci_trb *cur_trb;
-	struct xhci_segment *cur_seg;
 	struct usb_iso_packet_descriptor *frame;
 	u32 trb_comp_code;
 	bool skip_td = false;
@@ -2264,14 +2235,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
 		frame->actual_length = frame->length;
 		td->urb->actual_length += frame->length;
 	} else {
-		for (cur_trb = xhci_ring_dequeue(ep_ring),
-		     cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
-		     next_trb(ep_ring, &cur_seg, &cur_trb)) {
-			if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) &&
-			    !TRB_TYPE_LINK_LE32(cur_trb->generic.field[3]))
-				len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
+		struct xhci_ring_pointer rp = ep_ring->deq;
+
+		for (; rp.ptr != event_trb; next_trb(ep_ring, &rp)) {
+			if (!TRB_TYPE_NOOP_LE32(rp.ptr->generic.field[3]) &&
+			    !TRB_TYPE_LINK_LE32(rp.ptr->generic.field[3]))
+				len += TRB_LEN(le32_to_cpu(rp.ptr->generic.field[2]));
 		}
-		len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+		len += TRB_LEN(le32_to_cpu(rp.ptr->generic.field[2])) -
 			EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 
 		if (trb_comp_code != COMP_STOP_INVAL) {
@@ -2319,8 +2290,6 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
 	struct xhci_virt_ep *ep, int *status)
 {
 	struct xhci_ring *ep_ring;
-	union xhci_trb *cur_trb;
-	struct xhci_segment *cur_seg;
 	u32 trb_comp_code;
 
 	ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
@@ -2393,25 +2362,24 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
 				*status = 0;
 		}
 	} else {
+		struct xhci_ring_pointer rp = ep_ring->deq;
+
 		/* Slow path - walk the list, starting from the dequeue
 		 * pointer, to get the actual length transferred.
 		 */
 		td->urb->actual_length = 0;
-		for (cur_trb = xhci_ring_dequeue(ep_ring),
-				cur_seg = ep_ring->deq_seg;
-				cur_trb != event_trb;
-				next_trb(ep_ring, &cur_seg, &cur_trb)) {
-			if (!TRB_TYPE_NOOP_LE32(cur_trb->generic.field[3]) &&
-			    !TRB_TYPE_LINK_LE32(cur_trb->generic.field[3]))
+		for (; rp.ptr != event_trb; next_trb(ep_ring, &rp)) {
+			if (!TRB_TYPE_NOOP_LE32(rp.ptr->generic.field[3]) &&
+			    !TRB_TYPE_LINK_LE32(rp.ptr->generic.field[3]))
 				td->urb->actual_length +=
-					TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
+					TRB_LEN(le32_to_cpu(rp.ptr->generic.field[2]));
 		}
 		/* If the ring didn't stop on a Link or No-op TRB, add
 		 * in the actual bytes transferred from the Normal TRB
 		 */
 		if (trb_comp_code != COMP_STOP_INVAL)
 			td->urb->actual_length +=
-				TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+				TRB_LEN(le32_to_cpu(rp.ptr->generic.field[2])) -
 				EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 	}
 
@@ -2452,14 +2420,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 		xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
 		xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
 			 (unsigned long long) xhci_trb_virt_to_dma(
-				 xhci->event_ring->deq_seg,
-				 xhci_ring_dequeue(xhci->event_ring)),
+				 &xhci->event_ring->deq),
 			 lower_32_bits(le64_to_cpu(event->buffer)),
 			 upper_32_bits(le64_to_cpu(event->buffer)),
 			 le32_to_cpu(event->transfer_len),
 			 le32_to_cpu(event->flags));
 		xhci_dbg(xhci, "Event ring:\n");
-		xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
+		xhci_debug_segment(xhci, xhci->event_ring->deq.seg);
 		return -ENODEV;
 	}
 
@@ -2475,14 +2442,13 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 				"or incorrect stream ring\n");
 		xhci_err(xhci, "@%016llx %08x %08x %08x %08x\n",
 			 (unsigned long long) xhci_trb_virt_to_dma(
-				 xhci->event_ring->deq_seg,
-				 xhci_ring_dequeue(xhci->event_ring)),
+				 &xhci->event_ring->deq),
 			 lower_32_bits(le64_to_cpu(event->buffer)),
 			 upper_32_bits(le64_to_cpu(event->buffer)),
 			 le32_to_cpu(event->transfer_len),
 			 le32_to_cpu(event->flags));
 		xhci_dbg(xhci, "Event ring:\n");
-		xhci_debug_segment(xhci, xhci->event_ring->deq_seg);
+		xhci_debug_segment(xhci, xhci->event_ring->deq.seg);
 		return -ENODEV;
 	}
 
@@ -2631,8 +2597,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
 			td_num--;
 
 		/* Is this a TRB in the currently executing TD? */
-		event_seg = trb_in_td(ep_ring, ep_ring->deq_seg,
-				xhci_ring_dequeue(ep_ring), td->last_trb,
+		event_seg = trb_in_td(ep_ring, &ep_ring->deq, td->last_trb,
 				event_dma);
 
 		/*
@@ -2910,8 +2875,7 @@ hw_died:
 	temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
 	/* If necessary, update the HW's version of the event ring deq ptr. */
 	if (event_ring_deq != xhci_ring_dequeue(xhci->event_ring)) {
-		deq = xhci_trb_virt_to_dma(xhci->event_ring->deq_seg,
-				xhci_ring_dequeue(xhci->event_ring));
+		deq = xhci_trb_virt_to_dma(&xhci->event_ring->deq);
 		if (deq == 0)
 			xhci_warn(xhci, "WARN something wrong with SW event "
 					"ring dequeue ptr.\n");
@@ -3060,7 +3024,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
 	td->urb = urb;
 	/* Add this TD to the tail of the endpoint ring's TD list */
 	list_add_tail(&td->td_list, &ep_ring->td_list);
-	td->start_seg = ep_ring->enq_seg;
+	td->start_seg = ep_ring->enq.seg;
 	td->first_trb = xhci_ring_enqueue(ep_ring);
 
 	urb_priv->td[td_index] = td;
@@ -3710,6 +3674,7 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
 	int start_cycle;
 	u32 field, length_field;
 	int running_total, trb_buff_len, td_len, td_remain_len, ret;
+	struct xhci_ring_pointer rp;
 	u64 start_addr, addr;
 	int i, j;
 	bool more_trbs_coming;
@@ -3870,8 +3835,9 @@ cleanup:
 	td_to_noop(xhci, ep_ring, urb_priv->td[0], true);
 
 	/* Reset the ring enqueue back to the first TRB and its cycle bit. */
-	xhci_ring_set_enqueue(ep_ring, urb_priv->td[0]->first_trb);
-	ep_ring->enq_seg = urb_priv->td[0]->start_seg;
+	rp.seg = urb_priv->td[0]->start_seg;
+	rp.ptr = urb_priv->td[0]->first_trb;
+	xhci_ring_set_enqueue(ep_ring, &rp);
 	ep_ring->cycle_state = start_cycle;
 	ep_ring->num_trbs_free = ep_ring->num_trbs_free_temp;
 	usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
@@ -4070,8 +4036,7 @@ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, struct xhci_command *cmd,
 static int queue_set_tr_deq(struct xhci_hcd *xhci, struct xhci_command *cmd,
 			int slot_id,
 			unsigned int ep_index, unsigned int stream_id,
-			struct xhci_segment *deq_seg,
-			union xhci_trb *deq_ptr, u32 cycle_state)
+			struct xhci_ring_pointer *rp, u32 cycle_state)
 {
 	dma_addr_t addr;
 	u32 trb_slot_id = SLOT_ID_FOR_TRB(slot_id);
@@ -4081,11 +4046,11 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, struct xhci_command *cmd,
 	u32 type = TRB_TYPE(TRB_SET_DEQ);
 	struct xhci_virt_ep *ep;
 
-	addr = xhci_trb_virt_to_dma(deq_seg, deq_ptr);
+	addr = xhci_trb_virt_to_dma(rp);
 	if (addr == 0) {
 		xhci_warn(xhci, "WARN Cannot submit Set TR Deq Ptr\n");
 		xhci_warn(xhci, "WARN deq seg = %p, deq pt = %p\n",
-				deq_seg, deq_ptr);
+				rp->seg, rp->ptr);
 		return 0;
 	}
 	ep = &xhci->devs[slot_id]->eps[ep_index];
@@ -4094,8 +4059,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, struct xhci_command *cmd,
 		xhci_warn(xhci, "A Set TR Deq Ptr command is pending.\n");
 		return 0;
 	}
-	ep->queued_deq_seg = deq_seg;
-	ep->queued_deq_ptr = deq_ptr;
+	ep->queued_deq = *rp;
 	if (stream_id)
 		trb_sct = SCT_FOR_TRB(SCT_PRI_TR);
 	return queue_command(xhci, cmd,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 0b7b07da21e2..c6ad8a69e206 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -792,11 +792,9 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
 
 	/* step 2: initialize command ring buffer */
 	val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
-	val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
-		(xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
-				      xhci_ring_dequeue(xhci->cmd_ring)) &
-		 (u64) ~CMD_RING_RSVD_BITS) |
-		xhci->cmd_ring->cycle_state;
+	val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS)
+		| (xhci_trb_virt_to_dma(&xhci->cmd_ring->deq)
+		 & (u64) ~CMD_RING_RSVD_BITS) | xhci->cmd_ring->cycle_state;
 	xhci_dbg_trace(xhci, trace_xhci_dbg_init,
 			"// Setting command ring address to 0x%llx",
 			(long unsigned long) val_64);
@@ -816,6 +814,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 {
 	struct xhci_ring *ring = xhci->cmd_ring;
 	struct xhci_segment *first_seg = xhci_ring_first_seg(ring), *seg;
+	struct xhci_ring_pointer enq = { first_seg, first_seg->trbs };
 
 	list_for_each_entry(seg, &ring->segments, list) {
 		/* clear all but the link-trb */
@@ -829,10 +828,8 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 	}
 
 	/* Reset the software enqueue and dequeue pointers */
-	ring->deq_seg = first_seg;
-	xhci_ring_set_dequeue(ring, first_seg->trbs);
-	ring->enq_seg = ring->deq_seg;
-	xhci_ring_set_enqueue(ring, xhci_ring_dequeue(ring));
+	xhci_ring_set_enqueue(ring, &enq);
+	xhci_ring_set_dequeue(ring, &enq);
 
 	ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
 	/*
@@ -1534,15 +1531,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
 
 	urb_priv = urb->hcpriv;
 	i = urb_priv->td_cnt;
-	if (i < urb_priv->length)
+	if (i < urb_priv->length) {
+		struct xhci_ring_pointer td_rp = { urb_priv->td[i]->start_seg,
+			urb_priv->td[i]->first_trb };
+
 		xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
 				"Cancel URB %p, dev %s, ep 0x%x, "
 				"starting at offset 0x%llx",
 				urb, urb->dev->devpath,
 				urb->ep->desc.bEndpointAddress,
-				(unsigned long long) xhci_trb_virt_to_dma(
-					urb_priv->td[i]->start_seg,
-					urb_priv->td[i]->first_trb));
+				(unsigned long long) xhci_trb_virt_to_dma(&td_rp));
+	}
 
 	for (; i < urb_priv->length; i++) {
 		td = urb_priv->td[i];
@@ -2843,14 +2842,13 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
 	xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx,
 			xhci->devs[slot_id]->out_ctx, ep_index);
 	ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
-	addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg,
-			deq_state->new_deq_ptr);
+	addr = xhci_trb_virt_to_dma(&deq_state->new_deq);
 	if (addr == 0) {
 		xhci_warn(xhci, "WARN Cannot submit config ep after "
 				"reset ep command\n");
 		xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n",
-				deq_state->new_deq_seg,
-				deq_state->new_deq_ptr);
+				deq_state->new_deq.seg,
+				deq_state->new_deq.ptr);
 		return;
 	}
 	ep_ctx->deq = cpu_to_le64(addr | deq_state->new_cycle_state);
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index c1b35f802549..c685036cd2a6 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -847,6 +847,11 @@ struct xhci_bw_info {
 #define HS_BW_RESERVED		20
 #define SS_BW_RESERVED		10
 
+struct xhci_ring_pointer {
+	struct xhci_segment *seg;
+	union xhci_trb *ptr;
+};
+
 struct xhci_virt_ep {
 	struct xhci_ring		*ring;
 	/* Related to endpoints that are configured to use stream IDs only */
@@ -876,8 +881,7 @@ struct xhci_virt_ep {
 	 * command.  We'll need to update the ring's dequeue segment and dequeue
 	 * pointer after the command completes.
 	 */
-	struct xhci_segment	*queued_deq_seg;
-	union xhci_trb		*queued_deq_ptr;
+	struct xhci_ring_pointer queued_deq;
 	/*
 	 * Sometimes the xHC can not process isochronous endpoint ring quickly
 	 * enough, and it will miss some isoc tds on the ring and generate
@@ -1306,8 +1310,7 @@ struct xhci_cd {
 };
 
 struct xhci_dequeue_state {
-	struct xhci_segment *new_deq_seg;
-	union xhci_trb *new_deq_ptr;
+	struct xhci_ring_pointer new_deq;
 	int new_cycle_state;
 };
 
@@ -1322,10 +1325,9 @@ enum xhci_ring_type {
 };
 
 struct xhci_ring_ops {
-	bool (*last_trb)(struct xhci_ring *ring, struct xhci_segment *seg,
-			union xhci_trb *trb);
-	bool (*last_trb_ring)(struct xhci_ring *ring, struct xhci_segment *seg,
-			union xhci_trb *trb);
+	bool (*last_trb)(struct xhci_ring *ring, struct xhci_ring_pointer *rp);
+	bool (*last_trb_ring)(struct xhci_ring *ring,
+			struct xhci_ring_pointer *rp);
 	void (*inc_enq)(struct xhci_ring *ring, bool more_trbs_coming);
 	void (*inc_deq)(struct xhci_ring *ring);
 	void (*link_segments)(struct xhci_segment *prev,
@@ -1333,12 +1335,10 @@ struct xhci_ring_ops {
 };
 
 struct xhci_ring {
+	struct xhci_ring_pointer enq;
+	struct xhci_ring_pointer deq;
 	struct list_head	segments;
-	union  xhci_trb		*enq;
-	struct xhci_segment	*enq_seg;
 	unsigned int		enq_updates;
-	union  xhci_trb		*deq;
-	struct xhci_segment	*deq_seg;
 	unsigned int		deq_updates;
 	struct list_head	td_list;
 	/*
@@ -1360,27 +1360,28 @@ struct xhci_ring {
 
 static inline union xhci_trb *xhci_ring_enqueue(struct xhci_ring *ring)
 {
-	return ring->enq;
+	return ring->enq.ptr;
 }
 
 static inline union xhci_trb *xhci_ring_dequeue(struct xhci_ring *ring)
 {
-	return ring->deq;
+	return ring->deq.ptr;
 }
 
 static inline void xhci_ring_set_enqueue(struct xhci_ring *ring,
-	union xhci_trb *enqueue)
+	struct xhci_ring_pointer *rp)
 {
-	ring->enq = enqueue;
+	ring->enq.ptr = rp->ptr;
+	ring->enq.seg = rp->seg ? rp->seg : ring->enq.seg;
 }
 
 static inline void xhci_ring_set_dequeue(struct xhci_ring *ring,
-	union xhci_trb *dequeue)
+	struct xhci_ring_pointer *rp)
 {
-	ring->deq = dequeue;
+	ring->deq.ptr = rp->ptr;
+	ring->deq.seg = rp->seg ? rp->seg : ring->deq.seg;
 }
 
-
 static inline void xhci_ring_inc_deq(struct xhci_ring *ring)
 {
 	ring->ops->inc_deq(ring);
@@ -1405,6 +1406,18 @@ static inline struct xhci_segment *xhci_segment_next(struct xhci_ring *ring,
 		return list_next_entry(seg, list);
 }
 
+static inline void xhci_ring_pointer_advance_seg(struct xhci_ring *ring,
+	struct xhci_ring_pointer *rp)
+{
+	rp->seg = xhci_segment_next(ring, rp->seg);
+	rp->ptr = rp->seg->trbs;
+}
+
+static inline void xhci_ring_pointer_advance(struct xhci_ring_pointer *rp)
+{
+	rp->ptr++;
+}
+
 void xhci_ring_init_type(struct xhci_hcd *xhci, struct xhci_ring *ring,
 		enum xhci_ring_type type);
 bool xhci_is_event_ring(struct xhci_ring *ring);
@@ -1874,9 +1887,9 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev);
 
 /* xHCI ring, segment, TRB, and TD functions */
-dma_addr_t xhci_trb_virt_to_dma(struct xhci_segment *seg, union xhci_trb *trb);
+dma_addr_t xhci_trb_virt_to_dma(struct xhci_ring_pointer *rp);
 struct xhci_segment *trb_in_td(struct xhci_ring *ring,
-		struct xhci_segment *start_seg, union xhci_trb *start_trb,
+		struct xhci_ring_pointer *start_rp,
 		union xhci_trb *end_trb, dma_addr_t suspect_dma);
 int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code);
 void xhci_ring_cmd_db(struct xhci_hcd *xhci);

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux