]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: xhci: remove legacy 'num_trbs_free' tracking
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Wed, 3 Jun 2026 09:11:19 +0000 (12:11 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 3 Jun 2026 17:23:28 +0000 (19:23 +0200)
Keeping track of free TRBs in a ring by adding and subtracting each time
a enqueue or dequeue pointer is modified has proven to be buggy and
complicated, especially over long periods of time.
The xhci driver has already moved to calculating free TRBs dynamically
based on ring size and the enqueue/dequeue positions.

The DbC path is the last user of 'num_trbs_free'. Rather than maintaining
two separate accounting mechanisms, remove the field entirely and switch
DbC to use xhci_num_trbs_free(). Since 'num_trbs_free' undercounts by one,
and xhci_num_trbs_free() does not, the check for sufficient free TRBs is
adjusted.

Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Link: https://patch.msgid.link/20260603091132.1110849-3-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-dbgcap.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h

index 7e6f7d72f03ee4a1015026125ca350fb4d776418..6a9f73fecb737357ee3077a04ca2eb0eed59dcb0 100644 (file)
@@ -275,7 +275,6 @@ xhci_dbc_queue_trb(struct xhci_ring *ring, u32 field1,
        trace_xhci_dbc_gadget_ep_queue(ring, &trb->generic,
                                       xhci_trb_virt_to_dma(ring->enq_seg,
                                                            ring->enqueue));
-       ring->num_trbs_free--;
        next = ++(ring->enqueue);
        if (TRB_TYPE_LINK_LE32(next->link.control)) {
                next->link.control ^= cpu_to_le32(TRB_CYCLE);
@@ -296,7 +295,7 @@ static int xhci_dbc_queue_bulk_tx(struct dbc_ep *dep,
 
        num_trbs = count_trbs(req->dma, req->length);
        WARN_ON(num_trbs != 1);
-       if (ring->num_trbs_free < num_trbs)
+       if (xhci_num_trbs_free(ring) <= num_trbs)
                return -EBUSY;
 
        addr    = req->dma;
@@ -796,7 +795,6 @@ static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event)
                }
                if (r->status == -COMP_STALL_ERROR) {
                        dev_warn(dbc->dev, "Give back stale stalled req\n");
-                       ring->num_trbs_free++;
                        xhci_dbc_giveback(r, 0);
                }
        }
@@ -861,7 +859,6 @@ static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event)
                break;
        }
 
-       ring->num_trbs_free++;
        req->actual = req->length - remain_length;
        xhci_dbc_giveback(req, status);
 }
index 997fe90f54e5c2f889d75b264a8a47cbf677cb3a..289461c06bf952eac19f420269796b1004be9dfb 100644 (file)
@@ -324,12 +324,6 @@ void xhci_initialize_ring_info(struct xhci_ring *ring)
         * handling ring expansion, set the cycle state equal to the old ring.
         */
        ring->cycle_state = 1;
-
-       /*
-        * 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;
 }
 EXPORT_SYMBOL_GPL(xhci_initialize_ring_info);
 
index e47e644b296eab7d6dc2454ffc24ccd006422572..f62db238276dee4affcaebf51d9c0652424e0795 100644 (file)
@@ -340,7 +340,7 @@ static bool trb_in_td(struct xhci_td *td, dma_addr_t suspect_dma)
  * Only for transfer and command rings where driver is the producer, not for
  * event rings.
  */
-static unsigned int xhci_num_trbs_free(struct xhci_ring *ring)
+unsigned int xhci_num_trbs_free(struct xhci_ring *ring)
 {
        struct xhci_segment *enq_seg = ring->enq_seg;
        union xhci_trb *enq = ring->enqueue;
index aeecd301f20707117d35b680e9f243458530e219..e73c498449e8db2722d85d1937d25fc97c35d568 100644 (file)
@@ -1376,7 +1376,6 @@ struct xhci_ring {
        u32                     cycle_state;
        unsigned int            stream_id;
        unsigned int            num_segs;
-       unsigned int            num_trbs_free; /* used only by xhci DbC */
        unsigned int            bounce_buf_len;
        enum xhci_ring_type     type;
        u32                     old_trb_comp_code;
@@ -1955,6 +1954,7 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
 void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
 void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
 unsigned int count_trbs(u64 addr, u64 len);
+unsigned int xhci_num_trbs_free(struct xhci_ring *ring);
 int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
                            int suspend, gfp_t gfp_flags);
 void xhci_process_cancelled_tds(struct xhci_virt_ep *ep);