usb: xhci: utilize 'xhci_free_segments_for_ring()' for freeing segments
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Thu, 29 Feb 2024 14:14:34 +0000 (16:14 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 2 Mar 2024 19:25:27 +0000 (20:25 +0100)
Refactor the code to improve readability by using
'xhci_free_segments_for_ring()' function for freeing ring segments.
This replaces the custom while loop previously used within
'xhci_ring_expansion()' and 'xhci_alloc_segments_for_ring()'.

Slightly modify 'xhci_free_segments_for_ring()' to handle lists
which do not loop. This makes it possible to use it in error
paths of 'xhci_alloc_segments_for_ring()'.

This change also prepares for switching the custom xhci linked segment
list into to more standard list.h lists.

[minor commit message rewording -Mathias]

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/20240229141438.619372-6-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-mem.c

index c4b3e425bd1914eb2c20d1d7cd896f7794898935..69dd866698833e990bf22097f89d165af65d2ba2 100644 (file)
@@ -84,7 +84,7 @@ static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
        struct xhci_segment *seg;
 
        seg = first->next;
-       while (seg != first) {
+       while (seg && seg != first) {
                struct xhci_segment *next = seg->next;
                xhci_segment_free(xhci, seg);
                seg = next;
@@ -351,17 +351,10 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
 
                next = xhci_segment_alloc(xhci, cycle_state, max_packet, num,
                                          flags);
-               if (!next) {
-                       prev = *first;
-                       while (prev) {
-                               next = prev->next;
-                               xhci_segment_free(xhci, prev);
-                               prev = next;
-                       }
-                       return -ENOMEM;
-               }
-               xhci_link_segments(prev, next, type, chain_links);
+               if (!next)
+                       goto free_segments;
 
+               xhci_link_segments(prev, next, type, chain_links);
                prev = next;
                num++;
        }
@@ -369,6 +362,10 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
        *last = prev;
 
        return 0;
+
+free_segments:
+       xhci_free_segments_for_ring(xhci, *first);
+       return -ENOMEM;
 }
 
 /*
@@ -444,19 +441,11 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
        if (ret)
                return -ENOMEM;
 
-       if (ring->type == TYPE_STREAM)
+       if (ring->type == TYPE_STREAM) {
                ret = xhci_update_stream_segment_mapping(ring->trb_address_map,
                                                ring, first, last, flags);
-       if (ret) {
-               struct xhci_segment *next;
-               do {
-                       next = first->next;
-                       xhci_segment_free(xhci, first);
-                       if (first == last)
-                               break;
-                       first = next;
-               } while (true);
-               return ret;
+               if (ret)
+                       goto free_segments;
        }
 
        xhci_link_rings(xhci, ring, first, last, num_new_segs);
@@ -466,6 +455,10 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
                        ring->num_segs);
 
        return 0;
+
+free_segments:
+       xhci_free_segments_for_ring(xhci, first);
+       return ret;
 }
 
 struct xhci_container_ctx *xhci_alloc_container_ctx(struct xhci_hcd *xhci,