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