[RFC PATCH 05/20] xhci: prepare for mid-segment link-trbs

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

 



Break the assumption that link-trbs are always located at the end of a
segment.  Introduce ->link to struct xhci_segment and use that every
place that looks up the link-trb for a segment.  This is meant to be
functionally equivalent to the existing driver and is just a search and
replace for hard coded "link at the end" assumption.

Signed-off-by: Dan Williams <dan.j.williams@xxxxxxxxx>
---
 drivers/usb/host/xhci-mem.c  |   17 +++++++----------
 drivers/usb/host/xhci-ring.c |    7 ++-----
 drivers/usb/host/xhci.c      |   12 ++++++++----
 drivers/usb/host/xhci.h      |    1 +
 4 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1d05dc9e1928..1eda6166b30f 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -115,11 +115,11 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
 		return;
 	prev->next = next;
 	if (type != TYPE_EVENT) {
-		prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
-			cpu_to_le64(next->dma);
+		prev->link = &prev->trbs[TRBS_PER_SEGMENT-1];
+		prev->link->link.segment_ptr = cpu_to_le64(next->dma);
 
 		/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
-		val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
+		val = le32_to_cpu(prev->link->link.control);
 		val &= ~TRB_TYPE_BITMASK;
 		val |= TRB_TYPE(TRB_LINK);
 		/* Always set the chain bit with 0.95 hardware */
@@ -128,7 +128,7 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
 				(type == TYPE_ISOC &&
 				 (xhci->quirks & XHCI_AMD_0x96_HOST)))
 			val |= TRB_CHAIN;
-		prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
+		prev->link->link.control = cpu_to_le32(val);
 	}
 }
 
@@ -152,10 +152,8 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
 	ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
 
 	if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
-		ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
-			&= ~cpu_to_le32(LINK_TOGGLE);
-		last->trbs[TRBS_PER_SEGMENT-1].link.control
-			|= cpu_to_le32(LINK_TOGGLE);
+		ring->last_seg->link->link.control &= ~cpu_to_le32(LINK_TOGGLE);
+		last->link->link.control |= cpu_to_le32(LINK_TOGGLE);
 		ring->last_seg = last;
 	}
 }
@@ -395,8 +393,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
 	/* Only event ring does not use link TRB */
 	if (type != TYPE_EVENT) {
 		/* See section 4.9.2.1 and 6.4.4.1 */
-		ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
-			cpu_to_le32(LINK_TOGGLE);
+		ring->last_seg->link->link.control |= cpu_to_le32(LINK_TOGGLE);
 	}
 	xhci_initialize_ring_info(ring, cycle_state);
 	return ring;
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 0efbbf0b6233..ae436cb7e06d 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -374,12 +374,10 @@ static struct xhci_segment *find_trb_seg(
 		union xhci_trb	*trb, int *cycle_state)
 {
 	struct xhci_segment *cur_seg = start_seg;
-	struct xhci_generic_trb *generic_trb;
 
 	while (cur_seg->trbs > trb ||
 			&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
-		generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
-		if (generic_trb->field[3] & cpu_to_le32(LINK_TOGGLE))
+		if (cur_seg->link->link.control & cpu_to_le32(LINK_TOGGLE))
 			*cycle_state ^= 0x1;
 		cur_seg = cur_seg->next;
 		if (cur_seg == start_seg)
@@ -1735,8 +1733,7 @@ struct xhci_segment *trb_in_td(struct xhci_segment *start_seg,
 		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->trbs[TRBS_PER_SEGMENT - 1]);
+		end_seg_dma = xhci_trb_virt_to_dma(cur_seg, cur_seg->link);
 		/* 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);
 
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1d3dc014b477..0b05f67fde5b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -820,10 +820,14 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
 	ring = xhci->cmd_ring;
 	seg = ring->deq_seg;
 	do {
-		memset(seg->trbs, 0,
-			sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
-		seg->trbs[TRBS_PER_SEGMENT - 1].link.control &=
-			cpu_to_le32(~TRB_CYCLE);
+		/* clear all but the link-trb */
+		memset(seg->trbs, 0, (seg->link - seg->trbs)
+		       * sizeof(union xhci_trb));
+		/* note: 0-length memset if the link is at the end */
+		memset(seg->link + 1, 0, (TRBS_PER_SEGMENT
+		       - (seg->link - seg->trbs) - 1)
+		       * sizeof(union xhci_trb));
+		seg->link->link.control &= cpu_to_le32(~TRB_CYCLE);
 		seg = seg->next;
 	} while (seg != ring->deq_seg);
 
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 1a60e8498a55..35345b32509d 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1279,6 +1279,7 @@ union xhci_trb {
 struct xhci_segment {
 	union xhci_trb		*trbs;
 	/* private to HCD */
+	union xhci_trb		*link;
 	struct xhci_segment	*next;
 	dma_addr_t		dma;
 	struct device		*dev;

--
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