]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: xhci: move link chain bit quirk checks into one helper function.
authorNiklas Neronin <niklas.neronin@linux.intel.com>
Thu, 8 Jan 2026 08:49:26 +0000 (00:49 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 19 Jan 2026 12:12:01 +0000 (13:12 +0100)
commit 7476a2215c07703db5e95efaa3fc5b9f957b9417 upstream.

Older 0.95 xHCI hosts and some other specific newer hosts require the
chain bit to be set for Link TRBs even if the link TRB is not in the
middle of a transfer descriptor (TD).

move the checks for all those cases  into one xhci_link_chain_quirk()
function to clean up and avoid code duplication.

No functional changes.

[skip renaming chain_links flag, reword commit message -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/20240626124835.1023046-10-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
[Shivani: Modified to apply on v5.10.y-v6.1.y]
Signed-off-by: Shivani Agarwal <shivani.agarwal@broadcom.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.h

index e681c0dd9fbfe7c3c73a979be8be7e67f9f80a9e..7220c3a55ddefb2450672ce37071a9ee5aedccb8 100644 (file)
@@ -133,10 +133,7 @@ static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
        if (!ring || !first || !last)
                return;
 
-       /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
-       chain_links = !!(xhci_link_trb_quirk(xhci) ||
-                        (ring->type == TYPE_ISOC &&
-                         (xhci->quirks & XHCI_AMD_0x96_HOST)));
+       chain_links = xhci_link_chain_quirk(xhci, ring->type);
 
        next = ring->enq_seg->next;
        xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
@@ -326,10 +323,7 @@ static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
        struct xhci_segment *prev;
        bool chain_links;
 
-       /* Set chain bit for 0.95 hosts, and for isoc rings on AMD 0.96 host */
-       chain_links = !!(xhci_link_trb_quirk(xhci) ||
-                        (type == TYPE_ISOC &&
-                         (xhci->quirks & XHCI_AMD_0x96_HOST)));
+       chain_links = xhci_link_chain_quirk(xhci, type);
 
        prev = xhci_segment_alloc(xhci, cycle_state, max_packet, flags);
        if (!prev)
index bf2787bb04eaf0cc41cacc77a91f3452e3740e77..a337e1fda33dbfdc58d3ff342f8a6d48298f5202 100644 (file)
@@ -230,9 +230,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
                 * AMD 0.96 host, carry over the chain bit of the previous TRB
                 * (which may mean the chain bit is cleared).
                 */
-               if (!(ring->type == TYPE_ISOC &&
-                     (xhci->quirks & XHCI_AMD_0x96_HOST)) &&
-                   !xhci_link_trb_quirk(xhci)) {
+               if (!xhci_link_chain_quirk(xhci, ring->type)) {
                        next->link.control &= cpu_to_le32(~TRB_CHAIN);
                        next->link.control |= cpu_to_le32(chain);
                }
@@ -3138,9 +3136,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
                /* If we're not dealing with 0.95 hardware or isoc rings
                 * on AMD 0.96 host, clear the chain bit.
                 */
-               if (!xhci_link_trb_quirk(xhci) &&
-                   !(ep_ring->type == TYPE_ISOC &&
-                     (xhci->quirks & XHCI_AMD_0x96_HOST)))
+               if (!xhci_link_chain_quirk(xhci, ep_ring->type))
                        ep_ring->enqueue->link.control &=
                                cpu_to_le32(~TRB_CHAIN);
                else
index 6bb1ddc3918c6bc522631a15de7c8f8ce6345d4e..337706210ca6f61310d0b9663859159f1de02e03 100644 (file)
@@ -1998,9 +1998,12 @@ static inline void xhci_write_64(struct xhci_hcd *xhci,
        lo_hi_writeq(val, regs);
 }
 
-static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci)
+
+/* Link TRB chain should always be set on 0.95 hosts, and AMD 0.96 ISOC rings */
+static inline bool xhci_link_chain_quirk(struct xhci_hcd *xhci, enum xhci_ring_type type)
 {
-       return xhci->quirks & XHCI_LINK_TRB_QUIRK;
+       return (xhci->quirks & XHCI_LINK_TRB_QUIRK) ||
+              (type == TYPE_ISOC && (xhci->quirks & XHCI_AMD_0x96_HOST));
 }
 
 /* xHCI debugging */