]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: xhci: introduce macro for ring segment list iteration
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Wed, 17 Sep 2025 12:39:06 +0000 (08:39 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 25 Sep 2025 09:13:50 +0000 (11:13 +0200)
[ Upstream commit 3f970bd06c5295e742ef4f9cf7808a3cb74a6816 ]

Add macro to streamline and standardize the iteration over ring
segment list.

xhci_for_each_ring_seg(): Iterates over the entire ring segment list.

The xhci_free_segments_for_ring() function's while loop has not been
updated to use the new macro. This function has some underlying issues,
and as a result, it will be handled separately in a future patch.

Suggested-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://lore.kernel.org/r/20241106101459.775897-11-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: a5c98e8b1398 ("xhci: dbc: Fix full DbC transfer ring after several reconnects")
Signed-off-by: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-debugfs.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h

index f8ba15e7c225c2a079ae31c74c93a3ddc82a08ee..570210e8a8e874af5725bff52c0998f1d2a73489 100644 (file)
@@ -214,14 +214,11 @@ static void xhci_ring_dump_segment(struct seq_file *s,
 
 static int xhci_ring_trb_show(struct seq_file *s, void *unused)
 {
-       int                     i;
        struct xhci_ring        *ring = *(struct xhci_ring **)s->private;
        struct xhci_segment     *seg = ring->first_seg;
 
-       for (i = 0; i < ring->num_segs; i++) {
+       xhci_for_each_ring_seg(ring->first_seg, seg)
                xhci_ring_dump_segment(s, seg);
-               seg = seg->next;
-       }
 
        return 0;
 }
index 91b47f9573cd7e77f16c0ba71593a125e0fdd099..f0ed38da6a0c892687ae581614601b0c5f51a921 100644 (file)
@@ -224,7 +224,6 @@ static int xhci_update_stream_segment_mapping(
                struct radix_tree_root *trb_address_map,
                struct xhci_ring *ring,
                struct xhci_segment *first_seg,
-               struct xhci_segment *last_seg,
                gfp_t mem_flags)
 {
        struct xhci_segment *seg;
@@ -234,28 +233,22 @@ static int xhci_update_stream_segment_mapping(
        if (WARN_ON_ONCE(trb_address_map == NULL))
                return 0;
 
-       seg = first_seg;
-       do {
+       xhci_for_each_ring_seg(first_seg, seg) {
                ret = xhci_insert_segment_mapping(trb_address_map,
                                ring, seg, mem_flags);
                if (ret)
                        goto remove_streams;
-               if (seg == last_seg)
-                       return 0;
-               seg = seg->next;
-       } while (seg != first_seg);
+       }
 
        return 0;
 
 remove_streams:
        failed_seg = seg;
-       seg = first_seg;
-       do {
+       xhci_for_each_ring_seg(first_seg, seg) {
                xhci_remove_segment_mapping(trb_address_map, seg);
                if (seg == failed_seg)
                        return ret;
-               seg = seg->next;
-       } while (seg != first_seg);
+       }
 
        return ret;
 }
@@ -267,17 +260,14 @@ static void xhci_remove_stream_mapping(struct xhci_ring *ring)
        if (WARN_ON_ONCE(ring->trb_address_map == NULL))
                return;
 
-       seg = ring->first_seg;
-       do {
+       xhci_for_each_ring_seg(ring->first_seg, seg)
                xhci_remove_segment_mapping(ring->trb_address_map, seg);
-               seg = seg->next;
-       } while (seg != ring->first_seg);
 }
 
 static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
 {
        return xhci_update_stream_segment_mapping(ring->trb_address_map, ring,
-                       ring->first_seg, ring->last_seg, mem_flags);
+                       ring->first_seg, mem_flags);
 }
 
 /* XXX: Do we need the hcd structure in all these functions? */
@@ -438,7 +428,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
 
        if (ring->type == TYPE_STREAM) {
                ret = xhci_update_stream_segment_mapping(ring->trb_address_map,
-                                               ring, first, last, flags);
+                                               ring, first, flags);
                if (ret)
                        goto free_segments;
        }
index d5bcd5475b72b133ce9ca96fb5fbc0f842052467..abbf89e82d01a34d73b344004651d5c5c5663402 100644 (file)
@@ -41,15 +41,15 @@ MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default");
 
 static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
 {
-       struct xhci_segment *seg = ring->first_seg;
+       struct xhci_segment *seg;
 
        if (!td || !td->start_seg)
                return false;
-       do {
+
+       xhci_for_each_ring_seg(ring->first_seg, seg) {
                if (seg == td->start_seg)
                        return true;
-               seg = seg->next;
-       } while (seg && seg != ring->first_seg);
+       }
 
        return false;
 }
@@ -764,14 +764,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
        struct xhci_segment *seg;
 
        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);
-               seg = seg->next;
-       } while (seg != ring->deq_seg);
+       xhci_for_each_ring_seg(ring->deq_seg, seg) {
+               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);
+       }
 
        xhci_initialize_ring_info(ring, 1);
        /*
index 67ee2e04994330999ea177a328d220989c3b422f..b4fa8e7e43763971a766520cabfe3a7cad8ec931 100644 (file)
@@ -1263,6 +1263,9 @@ static inline const char *xhci_trb_type_string(u8 type)
 #define AVOID_BEI_INTERVAL_MIN 8
 #define AVOID_BEI_INTERVAL_MAX 32
 
+#define xhci_for_each_ring_seg(head, seg) \
+       for (seg = head; seg != NULL; seg = (seg->next != head ? seg->next : NULL))
+
 struct xhci_segment {
        union xhci_trb          *trbs;
        /* private to HCD */