FAILED: patch "[PATCH] xhci: dbc: decouple endpoint allocation from initialization" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x 220a0ffde02f962c13bc752b01aa570b8c65a37b
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025091707-blip-kilometer-4c4c@gregkh' --subject-prefix 'PATCH 6.12.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 220a0ffde02f962c13bc752b01aa570b8c65a37b Mon Sep 17 00:00:00 2001
From: Mathias Nyman <[email protected]>
Date: Tue, 2 Sep 2025 13:53:04 +0300
Subject: [PATCH] xhci: dbc: decouple endpoint allocation from initialization
Decouple allocation of endpoint ring buffer from initialization of the buffer, and initialization of endpoint context parts from from the rest of the contexts.
It allows driver to clear up and reinitialize endpoint rings after disconnect without reallocating everything.
This is a prerequisite for the next patch that prevents the transfer ring from filling up with cancelled (no-op) TRBs if a debug cable is reconnected several times without transferring anything.
drivers/usb/host/xhci-dbgcap.c +46 -25
@@ -101,13 +101,34 @@ static u32 xhci_dbc_populate_strings(struct dbc_str_descs *strings)return string_length; } +static void xhci_dbc_init_ep_contexts (struct xhci_dbc *dbc) +{ +struct xhci_ep_ctx *ep_ctx; +unsigned int max_burst; +dma_addr_t deq; + + max_burst =DBC_CTRL_MAXBURST (readl (&dbc->regs->control)); + +/* Populate bulk out endpoint context: */ + ep_ctx =dbc_bulkout_ctx (dbc); + deq =dbc_bulkout_enq (dbc); + ep_ctx->ep_info =0 ; + ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_OUT_EP ,1024 , max_burst); + ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_out->cycle_state); + +/* Populate bulk in endpoint context: */ + ep_ctx =dbc_bulkin_ctx (dbc); + deq =dbc_bulkin_enq (dbc); + ep_ctx->ep_info =0 ; + ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_IN_EP ,1024 , max_burst); + ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_in->cycle_state); +} +static void xhci_dbc_init_contexts (struct xhci_dbc *dbc,u32 string_length) {struct dbc_info_context *info; -struct xhci_ep_ctx *ep_ctx;u32 dev_info; -dma_addr_t deq, dma; -unsigned int max_burst; +dma_addr_t dma;if (!dbc)return ;
@@ -121,20 +142,8 @@ static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) info->serial =cpu_to_le64 (dma +DBC_MAX_STRING_LENGTH *3 ); info->length =cpu_to_le32 (string_length); -/* Populate bulk out endpoint context: */ - ep_ctx =dbc_bulkout_ctx (dbc); - max_burst =DBC_CTRL_MAXBURST (readl (&dbc->regs->control)); - deq =dbc_bulkout_enq (dbc); - ep_ctx->ep_info =0 ; - ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_OUT_EP ,1024 , max_burst); - ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_out->cycle_state); - -/* Populate bulk in endpoint context: */ - ep_ctx =dbc_bulkin_ctx (dbc); - deq =dbc_bulkin_enq (dbc); - ep_ctx->ep_info =0 ; - ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_IN_EP ,1024 , max_burst); - ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_in->cycle_state); +/* Populate bulk in and out endpoint contexts: */ +xhci_dbc_init_ep_contexts (dbc);/* Set DbC context and info registers: */ lo_hi_writeq (dbc->ctx->dma, &dbc->regs->dccp);
@@ -436,6 +445,23 @@ dbc_alloc_ctx(struct device *dev, gfp_t flags)return ctx; } +static void xhci_dbc_ring_init (struct xhci_ring *ring) +{ +struct xhci_segment *seg = ring->first_seg; + +/* clear all trbs on ring in case of old ring */ +memset (seg->trbs,0 ,TRB_SEGMENT_SIZE ); + +/* Only event ring does not use link TRB */ +if (ring->type !=TYPE_EVENT ) { +union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT -1 ]; + + trb->link.segment_ptr =cpu_to_le64 (ring->first_seg->dma); + trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); + } +xhci_initialize_ring_info (ring); +} +static struct xhci_ring *xhci_dbc_ring_alloc (struct device *dev,enum xhci_ring_type type,gfp_t flags) {
@@ -464,15 +490,10 @@ xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) seg->dma = dma; -/* Only event ring does not use link TRB */ -if (type !=TYPE_EVENT ) { -union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT -1 ]; - - trb->link.segment_ptr =cpu_to_le64 (dma); - trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); - }INIT_LIST_HEAD (&ring->td_list); -xhci_initialize_ring_info (ring); + +xhci_dbc_ring_init (ring); +return ring; dma_fail:kfree (seg);
Sasha Levin
maintainerPATCH 1/3 usb: xhci: introduce macro for ring segment list iteration
From: Niklas Neronin <[email protected]>
[ 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.
Stable-dep-of: 220a0ffde02f ("xhci: dbc: decouple endpoint allocation from initialization")
--- drivers/usb/host/xhci-debugfs.c | 5 +---- drivers/usb/host/xhci-mem.c | 24 +++++++----------------- drivers/usb/host/xhci.c | 20 ++++++++------------ drivers/usb/host/xhci.h | 3 +++ 4 files changed, 19 insertions(+), 33 deletions(-)
drivers/usb/host/xhci-debugfs.c +1 -4
@@ -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 ; }
drivers/usb/host/xhci-mem.c +7 -17
@@ -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; }
drivers/usb/host/xhci.c +8 -12
@@ -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 );/*
drivers/usb/host/xhci.h +3 -0
@@ -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 */
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 2/3 usb: xhci: remove option to change a default ring's TRB cycle bit
From: Niklas Neronin <[email protected]>
[ Upstream commit e1b0fa863907a61e86acc19ce2d0633941907c8e ]
The TRB cycle bit indicates TRB ownership by the Host Controller (HC) or Host Controller Driver (HCD). New rings are initialized with 'cycle_state' equal to one, and all its TRBs' cycle bits are set to zero. When handling ring expansion, set the source ring cycle bits to the same value as the destination ring.
Move the cycle bit setting from xhci_segment_alloc() to xhci_link_rings(), and remove the 'cycle_state' argument from xhci_initialize_ring_info(). The xhci_segment_alloc() function uses kzalloc_node() to allocate segments, ensuring that all TRB cycle bits are initialized to zero.
Stable-dep-of: 220a0ffde02f ("xhci: dbc: decouple endpoint allocation from initialization")
--- drivers/usb/host/xhci-dbgcap.c | 2 +- drivers/usb/host/xhci-mem.c | 50 ++++++++++++++++------------------ drivers/usb/host/xhci.c | 2 +- drivers/usb/host/xhci.h | 6 ++-- 4 files changed, 27 insertions(+), 33 deletions(-)
drivers/usb/host/xhci-dbgcap.c +1 -1
@@ -471,7 +471,7 @@ xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); }INIT_LIST_HEAD (&ring->td_list); -xhci_initialize_ring_info (ring,1 ); +xhci_initialize_ring_info (ring);return ring; dma_fail:kfree (seg);
drivers/usb/host/xhci-mem.c +23 -27
158 lines not on this page · raw message
drivers/usb/host/xhci.c +1 -1
@@ -769,7 +769,7 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci) seg->trbs[TRBS_PER_SEGMENT -1 ].link.control &=cpu_to_le32 (~TRB_CYCLE ); } -xhci_initialize_ring_info (ring,1 ); +xhci_initialize_ring_info (ring);/* * Reset the hardware dequeue pointer. * Yes, this will need to be re-written after resume, but we're paranoid
drivers/usb/host/xhci.h +2 -4
@@ -1803,14 +1803,12 @@ void xhci_slot_copy(struct xhci_hcd *xhci,int xhci_endpoint_init (struct xhci_hcd *xhci,struct xhci_virt_device *virt_dev,struct usb_device *udev,struct usb_host_endpoint *ep,gfp_t mem_flags); -struct xhci_ring *xhci_ring_alloc (struct xhci_hcd *xhci, -unsigned int num_segs,unsigned int cycle_state, +struct xhci_ring *xhci_ring_alloc (struct xhci_hcd *xhci,unsigned int num_segs,enum xhci_ring_type type,unsigned int max_packet,gfp_t flags);void xhci_ring_free (struct xhci_hcd *xhci,struct xhci_ring *ring);int xhci_ring_expansion (struct xhci_hcd *xhci,struct xhci_ring *ring,unsigned int num_trbs,gfp_t flags); -void xhci_initialize_ring_info (struct xhci_ring *ring, -unsigned int cycle_state); +void xhci_initialize_ring_info (struct xhci_ring *ring);void xhci_free_endpoint_ring (struct xhci_hcd *xhci,struct xhci_virt_device *virt_dev,unsigned int ep_index);
Signature · 1 line
2.51.0
Sasha Levin
maintainerPATCH 3/3 xhci: dbc: decouple endpoint allocation from initialization
In reply to Sasha LevinFrom: Mathias Nyman <[email protected]>
[ Upstream commit 220a0ffde02f962c13bc752b01aa570b8c65a37b ]
Decouple allocation of endpoint ring buffer from initialization of the buffer, and initialization of endpoint context parts from from the rest of the contexts.
It allows driver to clear up and reinitialize endpoint rings after disconnect without reallocating everything.
This is a prerequisite for the next patch that prevents the transfer ring from filling up with cancelled (no-op) TRBs if a debug cable is reconnected several times without transferring anything.
--- drivers/usb/host/xhci-dbgcap.c | 71 ++++++++++++++++++++++------------ 1 file changed, 46 insertions(+), 25 deletions(-)
drivers/usb/host/xhci-dbgcap.c +46 -25
@@ -101,13 +101,34 @@ static u32 xhci_dbc_populate_strings(struct dbc_str_descs *strings)return string_length; } +static void xhci_dbc_init_ep_contexts (struct xhci_dbc *dbc) +{ +struct xhci_ep_ctx *ep_ctx; +unsigned int max_burst; +dma_addr_t deq; + + max_burst =DBC_CTRL_MAXBURST (readl (&dbc->regs->control)); + +/* Populate bulk out endpoint context: */ + ep_ctx =dbc_bulkout_ctx (dbc); + deq =dbc_bulkout_enq (dbc); + ep_ctx->ep_info =0 ; + ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_OUT_EP ,1024 , max_burst); + ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_out->cycle_state); + +/* Populate bulk in endpoint context: */ + ep_ctx =dbc_bulkin_ctx (dbc); + deq =dbc_bulkin_enq (dbc); + ep_ctx->ep_info =0 ; + ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_IN_EP ,1024 , max_burst); + ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_in->cycle_state); +} +static void xhci_dbc_init_contexts (struct xhci_dbc *dbc,u32 string_length) {struct dbc_info_context *info; -struct xhci_ep_ctx *ep_ctx;u32 dev_info; -dma_addr_t deq, dma; -unsigned int max_burst; +dma_addr_t dma;if (!dbc)return ;
@@ -121,20 +142,8 @@ static void xhci_dbc_init_contexts(struct xhci_dbc *dbc, u32 string_length) info->serial =cpu_to_le64 (dma +DBC_MAX_STRING_LENGTH *3 ); info->length =cpu_to_le32 (string_length); -/* Populate bulk out endpoint context: */ - ep_ctx =dbc_bulkout_ctx (dbc); - max_burst =DBC_CTRL_MAXBURST (readl (&dbc->regs->control)); - deq =dbc_bulkout_enq (dbc); - ep_ctx->ep_info =0 ; - ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_OUT_EP ,1024 , max_burst); - ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_out->cycle_state); - -/* Populate bulk in endpoint context: */ - ep_ctx =dbc_bulkin_ctx (dbc); - deq =dbc_bulkin_enq (dbc); - ep_ctx->ep_info =0 ; - ep_ctx->ep_info2 =dbc_epctx_info2 (BULK_IN_EP ,1024 , max_burst); - ep_ctx->deq =cpu_to_le64 (deq | dbc->ring_in->cycle_state); +/* Populate bulk in and out endpoint contexts: */ +xhci_dbc_init_ep_contexts (dbc);/* Set DbC context and info registers: */ lo_hi_writeq (dbc->ctx->dma, &dbc->regs->dccp);
@@ -435,6 +444,23 @@ dbc_alloc_ctx(struct device *dev, gfp_t flags)return ctx; } +static void xhci_dbc_ring_init (struct xhci_ring *ring) +{ +struct xhci_segment *seg = ring->first_seg; + +/* clear all trbs on ring in case of old ring */ +memset (seg->trbs,0 ,TRB_SEGMENT_SIZE ); + +/* Only event ring does not use link TRB */ +if (ring->type !=TYPE_EVENT ) { +union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT -1 ]; + + trb->link.segment_ptr =cpu_to_le64 (ring->first_seg->dma); + trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); + } +xhci_initialize_ring_info (ring); +} +static struct xhci_ring *xhci_dbc_ring_alloc (struct device *dev,enum xhci_ring_type type,gfp_t flags) {
@@ -463,15 +489,10 @@ xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags) seg->dma = dma; -/* Only event ring does not use link TRB */ -if (type !=TYPE_EVENT ) { -union xhci_trb *trb = &seg->trbs[TRBS_PER_SEGMENT -1 ]; - - trb->link.segment_ptr =cpu_to_le64 (dma); - trb->link.control =cpu_to_le32 (LINK_TOGGLE |TRB_TYPE (TRB_LINK )); - }INIT_LIST_HEAD (&ring->td_list); -xhci_initialize_ring_info (ring); + +xhci_dbc_ring_init (ring); +return ring; dma_fail:kfree (seg);
Signature · 1 line
2.51.0