xhci: refactor out TRBS_PER_SEGMENT define in runtime code
authorJonathan Bell <jonathan@raspberrypi.com>
Mon, 13 Dec 2021 15:05:56 +0000 (15:05 +0000)
committerDom Cobley <popcornmix@gmail.com>
Mon, 21 Mar 2022 16:04:33 +0000 (16:04 +0000)
In anticipation of adjusting the number of utilised TRBs in a ring
segment, add trbs_per_seg to struct xhci_ring and use this instead
of a compile-time define.

Signed-off-by: Jonathan Bell <jonathan@raspberrypi.com>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index df84bfa..eb802f2 100644 (file)
@@ -98,6 +98,7 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
  */
 static void xhci_link_segments(struct xhci_segment *prev,
                               struct xhci_segment *next,
+                              unsigned int trbs_per_seg,
                               enum xhci_ring_type type, bool chain_links)
 {
        u32 val;
@@ -106,16 +107,16 @@ static void xhci_link_segments(struct xhci_segment *prev,
                return;
        prev->next = next;
        if (type != TYPE_EVENT) {
-               prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
+               prev->trbs[trbs_per_seg - 1].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->trbs[trbs_per_seg - 1].link.control);
                val &= ~TRB_TYPE_BITMASK;
                val |= TRB_TYPE(TRB_LINK);
                if (chain_links)
                        val |= TRB_CHAIN;
-               prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
+               prev->trbs[trbs_per_seg - 1].link.control = cpu_to_le32(val);
        }
 }
 
@@ -139,15 +140,17 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
                          (xhci->quirks & XHCI_AMD_0x96_HOST)));
 
        next = ring->enq_seg->next;
-       xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
-       xhci_link_segments(last, next, ring->type, chain_links);
+       xhci_link_segments(ring->enq_seg, first, ring->trbs_per_seg,
+                          ring->type, chain_links);
+       xhci_link_segments(last, next, ring->trbs_per_seg,
+                          ring->type, chain_links);
        ring->num_segs += num_segs;
-       ring->num_trbs_free += (TRBS_PER_SEGMENT - 1) * num_segs;
+       ring->num_trbs_free += (ring->trbs_per_seg - 1) * num_segs;
 
        if (ring->type != TYPE_EVENT && ring->enq_seg == ring->last_seg) {
-               ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
+               ring->last_seg->trbs[ring->trbs_per_seg - 1].link.control
                        &= ~cpu_to_le32(LINK_TOGGLE);
-               last->trbs[TRBS_PER_SEGMENT-1].link.control
+               last->trbs[ring->trbs_per_seg - 1].link.control
                        |= cpu_to_le32(LINK_TOGGLE);
                ring->last_seg = last;
        }
@@ -314,14 +317,15 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
         * Each segment has a link TRB, and leave an extra TRB for SW
         * accounting purpose
         */
-       ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
+       ring->num_trbs_free = ring->num_segs * (ring->trbs_per_seg - 1) - 1;
 }
 
 /* Allocate segments and link them for a ring */
 static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
                struct xhci_segment **first, struct xhci_segment **last,
-               unsigned int num_segs, unsigned int cycle_state,
-               enum xhci_ring_type type, unsigned int max_packet, gfp_t flags)
+               unsigned int num_segs, unsigned int trbs_per_seg,
+               unsigned int cycle_state, enum xhci_ring_type type,
+               unsigned int max_packet, gfp_t flags)
 {
        struct xhci_segment *prev;
        bool chain_links;
@@ -350,12 +354,12 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
                        }
                        return -ENOMEM;
                }
-               xhci_link_segments(prev, next, type, chain_links);
+               xhci_link_segments(prev, next, trbs_per_seg, type, chain_links);
 
                prev = next;
                num_segs--;
        }
-       xhci_link_segments(prev, *first, type, chain_links);
+       xhci_link_segments(prev, *first, trbs_per_seg, type, chain_links);
        *last = prev;
 
        return 0;
@@ -387,16 +391,17 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
        if (num_segs == 0)
                return ring;
 
+       ring->trbs_per_seg = TRBS_PER_SEGMENT;
        ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg,
-                       &ring->last_seg, num_segs, cycle_state, type,
-                       max_packet, flags);
+                       &ring->last_seg, num_segs, ring->trbs_per_seg,
+                       cycle_state, type, max_packet, flags);
        if (ret)
                goto fail;
 
        /* 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 |=
+               ring->last_seg->trbs[ring->trbs_per_seg - 1].link.control |=
                        cpu_to_le32(LINK_TOGGLE);
        }
        xhci_initialize_ring_info(ring, cycle_state);
@@ -429,16 +434,15 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
        unsigned int            num_segs_needed;
        int                     ret;
 
-       num_segs_needed = (num_trbs + (TRBS_PER_SEGMENT - 1) - 1) /
-                               (TRBS_PER_SEGMENT - 1);
-
+       num_segs_needed = (num_trbs + (ring->trbs_per_seg - 1) - 1) /
+                               (ring->trbs_per_seg - 1);
        /* Allocate number of segments we needed, or double the ring size */
        num_segs = ring->num_segs > num_segs_needed ?
                        ring->num_segs : num_segs_needed;
 
        ret = xhci_alloc_segments_for_ring(xhci, &first, &last,
-                       num_segs, ring->cycle_state, ring->type,
-                       ring->bounce_buf_len, flags);
+                       num_segs, ring->trbs_per_seg, ring->cycle_state,
+                       ring->type, ring->bounce_buf_len, flags);
        if (ret)
                return -ENOMEM;
 
@@ -1811,7 +1815,7 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
        for (val = 0; val < evt_ring->num_segs; val++) {
                entry = &erst->entries[val];
                entry->seg_addr = cpu_to_le64(seg->dma);
-               entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
+               entry->seg_size = cpu_to_le32(evt_ring->trbs_per_seg);
                entry->rsvd = 0;
                seg = seg->next;
        }
index 96e1a18..ee756ed 100644 (file)
@@ -90,15 +90,16 @@ static bool trb_is_link(union xhci_trb *trb)
        return TRB_TYPE_LINK_LE32(trb->link.control);
 }
 
-static bool last_trb_on_seg(struct xhci_segment *seg, union xhci_trb *trb)
+static bool last_trb_on_seg(struct xhci_segment *seg,
+                           unsigned int trbs_per_seg, union xhci_trb *trb)
 {
-       return trb == &seg->trbs[TRBS_PER_SEGMENT - 1];
+       return trb == &seg->trbs[trbs_per_seg - 1];
 }
 
 static bool last_trb_on_ring(struct xhci_ring *ring,
                        struct xhci_segment *seg, union xhci_trb *trb)
 {
-       return last_trb_on_seg(seg, trb) && (seg->next == ring->first_seg);
+       return last_trb_on_seg(seg, ring->trbs_per_seg, trb) && (seg->next == ring->first_seg);
 }
 
 static bool link_trb_toggles_cycle(union xhci_trb *trb)
@@ -161,7 +162,8 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
 
        /* event ring doesn't have link trbs, check for last trb */
        if (ring->type == TYPE_EVENT) {
-               if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
+               if (!last_trb_on_seg(ring->deq_seg, ring->trbs_per_seg,
+                                    ring->dequeue)) {
                        ring->dequeue++;
                        goto out;
                }
@@ -174,7 +176,8 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
 
        /* All other rings have link trbs */
        if (!trb_is_link(ring->dequeue)) {
-               if (last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
+               if (last_trb_on_seg(ring->deq_seg, ring->trbs_per_seg,
+                   ring->dequeue)) {
                        xhci_warn(xhci, "Missing link TRB at end of segment\n");
                } else {
                        ring->dequeue++;
@@ -225,7 +228,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
        if (!trb_is_link(ring->enqueue))
                ring->num_trbs_free--;
 
-       if (last_trb_on_seg(ring->enq_seg, ring->enqueue)) {
+       if (last_trb_on_seg(ring->enq_seg, ring->trbs_per_seg, ring->enqueue)) {
                xhci_err(xhci, "Tried to move enqueue past ring segment\n");
                return;
        }
@@ -3153,7 +3156,7 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
         * that clears the EHB.
         */
        while (xhci_handle_event(xhci) > 0) {
-               if (event_loop++ < TRBS_PER_SEGMENT / 2)
+               if (event_loop++ < xhci->event_ring->trbs_per_seg / 2)
                        continue;
                xhci_update_erst_dequeue(xhci, event_ring_deq);
 
@@ -3294,7 +3297,8 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
                }
        }
 
-       if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->enqueue)) {
+       if (last_trb_on_seg(ep_ring->enq_seg, ep_ring->trbs_per_seg,
+           ep_ring->enqueue)) {
                xhci_warn(xhci, "Missing link TRB at end of ring segment\n");
                return -EINVAL;
        }
index 2e482d4..45dfdcd 100644 (file)
@@ -857,8 +857,8 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
        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 &=
+                       sizeof(union xhci_trb) * (ring->trbs_per_seg - 1));
+               seg->trbs[ring->trbs_per_seg - 1].link.control &=
                        cpu_to_le32(~TRB_CYCLE);
                seg = seg->next;
        } while (seg != ring->deq_seg);
@@ -869,7 +869,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
        ring->enq_seg = ring->deq_seg;
        ring->enqueue = ring->dequeue;
 
-       ring->num_trbs_free = ring->num_segs * (TRBS_PER_SEGMENT - 1) - 1;
+       ring->num_trbs_free = ring->num_segs * (ring->trbs_per_seg - 1) - 1;
        /*
         * Ring is now zeroed, so the HW should look for change of ownership
         * when the cycle bit is set to 1.
index 19c2e6a..41ddff3 100644 (file)
@@ -1632,6 +1632,7 @@ struct xhci_ring {
        unsigned int            num_trbs_free;
        unsigned int            num_trbs_free_temp;
        unsigned int            bounce_buf_len;
+       unsigned int            trbs_per_seg;
        enum xhci_ring_type     type;
        bool                    last_td_was_short;
        struct radix_tree_root  *trb_address_map;