* [PATCH 00/11] usb: xhci: decouple allocation and initialization
@ 2025-04-11 9:11 Niklas Neronin
2025-04-11 9:11 ` [PATCH 01/11] usb: xhci: relocate pre-allocation initialization Niklas Neronin
` (10 more replies)
0 siblings, 11 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Currently, after hibernation (S4 state), the xhci driver frees all its
memory and reallocates it from scratch, which is inefficient. Instead, much
of the memory can be simply re-initialized.
The proposed changes begin the process by decoupling initialization code
from memory allocation code. Specifically, the initialization code is moved
from xhci_mem_init() into separate functions, which are then called from
xhci_init().
By implementing these changes, future patches will be able to call the
initialization functions directly after hibernation, thereby improving
efficiency and enhancing code structure.
Niklas Neronin (11):
usb: xhci: relocate pre-allocation initialization
usb: xhci: move device slot enabling register write
usb: xhci: move command ring pointer write
usb: xhci: refactor xhci_set_cmd_ring_deq()
usb: xhci: move DCBAA pointer write
usb: xhci: move doorbell array pointer assignment
usb: xhci: move enabling of USB 3 device notifications
usb: xhci: remove error handling from xhci_add_interrupter()
usb: xhci: move initialization of the primary interrupter
usb: xhci: add individual allocation checks in xhci_mem_init()
usb: xhci: cleanup xhci_mem_init()
drivers/usb/host/xhci-caps.h | 4 +-
drivers/usb/host/xhci-mem.c | 164 +++++++++--------------------------
drivers/usb/host/xhci.c | 126 ++++++++++++++++++++++-----
drivers/usb/host/xhci.h | 12 +--
4 files changed, 155 insertions(+), 151 deletions(-)
--
2.47.2
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 01/11] usb: xhci: relocate pre-allocation initialization
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 02/11] usb: xhci: move device slot enabling register write Niklas Neronin
` (9 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Move pre-allocation initialization from xhci_mem_init() to xhci_init().
This change is part of an ongoing effort to separate initialization from
allocation within the xhci driver. By doing so, it will enable future
patches to re-initialize xhci driver memory without the necessity of fully
recreating it.
Additionally, compliance mode recovery initialization has been adjusted to
only occur after successful memory allocation.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 28 ----------------------------
drivers/usb/host/xhci.c | 29 ++++++++++++++++++++++++++---
2 files changed, 26 insertions(+), 31 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d698095fc88d..eb07445687bb 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2371,22 +2371,6 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs,
}
EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter);
-static void xhci_hcd_page_size(struct xhci_hcd *xhci)
-{
- u32 page_size;
-
- page_size = readl(&xhci->op_regs->page_size) & XHCI_PAGE_SIZE_MASK;
- if (!is_power_of_2(page_size)) {
- xhci_warn(xhci, "Invalid page size register = 0x%x\n", page_size);
- /* Fallback to 4K page size, since that's common */
- page_size = 1;
- }
-
- xhci->page_size = page_size << 12;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK",
- xhci->page_size >> 10);
-}
-
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
{
struct xhci_interrupter *ir;
@@ -2395,15 +2379,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
unsigned int val, val2;
u64 val_64;
u32 temp;
- int i;
-
- INIT_LIST_HEAD(&xhci->cmd_list);
-
- /* init command timeout work */
- INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);
- init_completion(&xhci->cmd_ring_stop_completion);
-
- xhci_hcd_page_size(xhci);
/*
* Program the Number of Device Slots Enabled field in the CONFIG
@@ -2515,9 +2490,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
- for (i = 0; i < MAX_HC_SLOTS; i++)
- xhci->devs[i] = NULL;
-
if (scratchpad_alloc(xhci, flags))
goto fail;
if (xhci_setup_port_arrays(xhci, flags))
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 0452b8d65832..abc5115a2839 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -460,6 +460,21 @@ static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci)
return (xhci->port_status_u0 == ((1 << xhci->usb3_rhub.num_ports) - 1));
}
+static void xhci_hcd_page_size(struct xhci_hcd *xhci)
+{
+ u32 page_size;
+
+ page_size = readl(&xhci->op_regs->page_size) & XHCI_PAGE_SIZE_MASK;
+ if (!is_power_of_2(page_size)) {
+ xhci_warn(xhci, "Invalid page size register = 0x%x\n", page_size);
+ /* Fallback to 4K page size, since that's common */
+ page_size = 1;
+ }
+
+ xhci->page_size = page_size << 12;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "HCD page size set to %iK",
+ xhci->page_size >> 10);
+}
/*
* Initialize memory for HCD and xHC (one-time init).
@@ -473,11 +488,18 @@ static int xhci_init(struct usb_hcd *hcd)
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int retval;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_init");
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Starting %s", __func__);
spin_lock_init(&xhci->lock);
+ INIT_LIST_HEAD(&xhci->cmd_list);
+ INIT_DELAYED_WORK(&xhci->cmd_timer, xhci_handle_command_timeout);
+ init_completion(&xhci->cmd_ring_stop_completion);
+ xhci_hcd_page_size(xhci);
+ memset(xhci->devs, 0, MAX_HC_SLOTS * sizeof(*xhci->devs));
+
retval = xhci_mem_init(xhci, GFP_KERNEL);
- xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_init");
+ if (retval)
+ return retval;
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
@@ -485,7 +507,8 @@ static int xhci_init(struct usb_hcd *hcd)
compliance_mode_recovery_timer_init(xhci);
}
- return retval;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished %s", __func__);
+ return 0;
}
/*-------------------------------------------------------------------------*/
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 02/11] usb: xhci: move device slot enabling register write
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
2025-04-11 9:11 ` [PATCH 01/11] usb: xhci: relocate pre-allocation initialization Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 03/11] usb: xhci: move command ring pointer write Niklas Neronin
` (8 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Refactor the setting of the Number of Device Slots Enabled field into a
separate function, relocating it to xhci_init().
The xHCI driver consistently sets the number of enabled device slots to the
maximum value. The new function is named to reflect this behavior.
Remove the "// " prefix from trace messages, as it is unnecessary and
distracting.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 15 +--------------
drivers/usb/host/xhci.c | 21 +++++++++++++++++++++
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index eb07445687bb..5086d6108d3e 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2376,23 +2376,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
struct xhci_interrupter *ir;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
dma_addr_t dma;
- unsigned int val, val2;
+ unsigned int val;
u64 val_64;
u32 temp;
- /*
- * Program the Number of Device Slots Enabled field in the CONFIG
- * register with the max value of slots the HC can handle.
- */
- val = HCS_MAX_SLOTS(readl(&xhci->cap_regs->hcs_params1));
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// xHC can handle at most %d device slots.", val);
- val2 = readl(&xhci->op_regs->config_reg);
- val |= (val2 & ~HCS_SLOTS_MASK);
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Setting Max device slots reg = 0x%x.", val);
- writel(val, &xhci->op_regs->config_reg);
-
/*
* xHCI section 5.4.6 - Device Context array must be
* "physically contiguous and 64-byte (cache line) aligned".
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index abc5115a2839..1e4850542a2e 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -476,6 +476,24 @@ static void xhci_hcd_page_size(struct xhci_hcd *xhci)
xhci->page_size >> 10);
}
+static void xhci_enable_max_dev_slots(struct xhci_hcd *xhci)
+{
+ u32 config_reg;
+ u32 max_slots;
+
+ max_slots = HCS_MAX_SLOTS(xhci->hcs_params1);
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xHC can handle at most %d device slots",
+ max_slots);
+
+ config_reg = readl(&xhci->op_regs->config_reg);
+ config_reg &= ~HCS_SLOTS_MASK;
+ config_reg |= max_slots;
+
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Setting Max device slots reg = 0x%x",
+ config_reg);
+ writel(config_reg, &xhci->op_regs->config_reg);
+}
+
/*
* Initialize memory for HCD and xHC (one-time init).
*
@@ -501,6 +519,9 @@ static int xhci_init(struct usb_hcd *hcd)
if (retval)
return retval;
+ /* Set the Number of Device Slots Enabled to the maximum supported value */
+ xhci_enable_max_dev_slots(xhci);
+
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 03/11] usb: xhci: move command ring pointer write
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
2025-04-11 9:11 ` [PATCH 01/11] usb: xhci: relocate pre-allocation initialization Niklas Neronin
2025-04-11 9:11 ` [PATCH 02/11] usb: xhci: move device slot enabling register write Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 04/11] usb: xhci: refactor xhci_set_cmd_ring_deq() Niklas Neronin
` (7 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Move command ring pointer write from xhci_mem_init() to xhci_init(),
and utilize the xhci_set_cmd_ring_deq() function.
The xhci_set_cmd_ring_deq() function is nearly identical to the Command
Ring Control register code in xhci_mem_init(). The only notable change is
the use of:
xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, xhci->cmd_ring->dequeue)
instead of:
xhci->cmd_ring->first_seg->dma
but they are effectively the same in this context. The former represents
the exact position of the dequeue pointer, while the latter is the first
DMA in the first segment. Before use, the dequeue pointer is at the first
DMA in the first segment.
The xhci_set_cmd_ring_deq() function is moved without modification, except
for (long unsigned long) -> (unsigned long long) due to checkpatch.pl.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 10 ----------
drivers/usb/host/xhci.c | 37 ++++++++++++++++++++-----------------
2 files changed, 20 insertions(+), 27 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 5086d6108d3e..47b804aa328d 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2377,7 +2377,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
dma_addr_t dma;
unsigned int val;
- u64 val_64;
u32 temp;
/*
@@ -2440,15 +2439,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "First segment DMA is 0x%pad",
&xhci->cmd_ring->first_seg->dma);
- /* Set the address in the Command Ring Control register */
- val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
- val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
- (xhci->cmd_ring->first_seg->dma & (u64) ~CMD_RING_RSVD_BITS) |
- xhci->cmd_ring->cycle_state;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Setting command ring address to 0x%016llx", val_64);
- xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
-
/* Reserve one command ring TRB for disabling LPM.
* Since the USB core grabs the shared usb_bus bandwidth mutex before
* disabling LPM, we only need to reserve one TRB for all devices.
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 1e4850542a2e..278bd32d7b55 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -494,6 +494,23 @@ static void xhci_enable_max_dev_slots(struct xhci_hcd *xhci)
writel(config_reg, &xhci->op_regs->config_reg);
}
+static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
+{
+ u64 val_64;
+
+ /* step 2: initialize command ring buffer */
+ val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+ val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
+ (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
+ xhci->cmd_ring->dequeue) &
+ (u64) ~CMD_RING_RSVD_BITS) |
+ xhci->cmd_ring->cycle_state;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+ "// Setting command ring address to 0x%llx",
+ (unsigned long long) val_64);
+ xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+}
+
/*
* Initialize memory for HCD and xHC (one-time init).
*
@@ -522,6 +539,9 @@ static int xhci_init(struct usb_hcd *hcd)
/* Set the Number of Device Slots Enabled to the maximum supported value */
xhci_enable_max_dev_slots(xhci);
+ /* Set the address in the Command Ring Control register */
+ xhci_set_cmd_ring_deq(xhci);
+
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
@@ -792,23 +812,6 @@ static void xhci_restore_registers(struct xhci_hcd *xhci)
}
}
-static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
-{
- u64 val_64;
-
- /* step 2: initialize command ring buffer */
- val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
- val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
- (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
- xhci->cmd_ring->dequeue) &
- (u64) ~CMD_RING_RSVD_BITS) |
- xhci->cmd_ring->cycle_state;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Setting command ring address to 0x%llx",
- (long unsigned long) val_64);
- xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
-}
-
/*
* The whole command ring must be cleared to zero when we suspend the host.
*
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 04/11] usb: xhci: refactor xhci_set_cmd_ring_deq()
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (2 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 03/11] usb: xhci: move command ring pointer write Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 05/11] usb: xhci: move DCBAA pointer write Niklas Neronin
` (6 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Refactor xhci_set_cmd_ring_deq() making the code more understandable by
using more descriptive constants and separating operations logically.
- Remove 'CMD_RING_RSVD_BITS' the macro is misleading, the reserved bits
are 5:4, yet the mask is for bits 5:0.
- Introduce masks 'CMD_RING_PTR_MASK' and 'CMD_RING_CYCLE' to clearly
define the bits for the Command Ring pointer and Command Ring Cycle.
- Simplifying the process of setting the command ring address by separating
the DMA address calculation and the Command Ring Control register (crcr)
updates.
- Remove the "// " prefix from trace messages, as it is unnecessary and
distracting.
Note: In the current implementation, the cycle bit is not cleared before
applying the OR operation. Although this hasn't caused issues so far
because the bit is '0' before reaching this function, the bit is now
cleared before being set to prevent potential future problems and simplify
the process.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci.c | 26 ++++++++++++++------------
drivers/usb/host/xhci.h | 8 ++++----
2 files changed, 18 insertions(+), 16 deletions(-)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 278bd32d7b55..5f630e74b323 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -496,19 +496,21 @@ static void xhci_enable_max_dev_slots(struct xhci_hcd *xhci)
static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
{
- u64 val_64;
+ dma_addr_t deq_dma;
+ u64 crcr;
- /* step 2: initialize command ring buffer */
- val_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
- val_64 = (val_64 & (u64) CMD_RING_RSVD_BITS) |
- (xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
- xhci->cmd_ring->dequeue) &
- (u64) ~CMD_RING_RSVD_BITS) |
- xhci->cmd_ring->cycle_state;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Setting command ring address to 0x%llx",
- (unsigned long long) val_64);
- xhci_write_64(xhci, val_64, &xhci->op_regs->cmd_ring);
+ deq_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, xhci->cmd_ring->dequeue);
+ deq_dma &= CMD_RING_PTR_MASK;
+
+ crcr = xhci_read_64(xhci, &xhci->op_regs->cmd_ring);
+ crcr &= ~CMD_RING_PTR_MASK;
+ crcr |= deq_dma;
+
+ crcr &= ~CMD_RING_CYCLE;
+ crcr |= xhci->cmd_ring->cycle_state;
+
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Setting command ring address to 0x%llx", crcr);
+ xhci_write_64(xhci, crcr, &xhci->op_regs->cmd_ring);
}
/*
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 37860f1e3aba..38058006f79b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -191,16 +191,16 @@ struct xhci_op_regs {
#define DEV_NOTE_FWAKE ENABLE_DEV_NOTE(1)
/* CRCR - Command Ring Control Register - cmd_ring bitmasks */
-/* bit 0 is the command ring cycle state */
+/* bit 0 - Cycle bit indicates the ownership of the command ring */
+#define CMD_RING_CYCLE (1 << 0)
/* stop ring operation after completion of the currently executing command */
#define CMD_RING_PAUSE (1 << 1)
/* stop ring immediately - abort the currently executing command */
#define CMD_RING_ABORT (1 << 2)
/* true: command ring is running */
#define CMD_RING_RUNNING (1 << 3)
-/* bits 4:5 reserved and should be preserved */
-/* Command Ring pointer - bit mask for the lower 32 bits. */
-#define CMD_RING_RSVD_BITS (0x3f)
+/* bits 63:6 - Command Ring pointer */
+#define CMD_RING_PTR_MASK GENMASK_ULL(63, 6)
/* CONFIG - Configure Register - config_reg bitmasks */
/* bits 0:7 - maximum number of device slots enabled (NumSlotsEn) */
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 05/11] usb: xhci: move DCBAA pointer write
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (3 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 04/11] usb: xhci: refactor xhci_set_cmd_ring_deq() Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 15:05 ` Sergey Shtylyov
2025-04-11 9:11 ` [PATCH 06/11] usb: xhci: move doorbell array pointer assignment Niklas Neronin
` (5 subsequent siblings)
10 siblings, 1 reply; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Move the Device Context Base Address Array (DCBAA) pointer write from
xhci_mem_init() to xhci_init(). This is part of the ongoing effort to
separate allocation and initialization.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 1 -
drivers/usb/host/xhci.c | 3 +++
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 47b804aa328d..4e6289d9a89a 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2391,7 +2391,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"// Device context base array address = 0x%pad (DMA), %p (virt)",
&xhci->dcbaa->dma, xhci->dcbaa);
- xhci_write_64(xhci, dma, &xhci->op_regs->dcbaa_ptr);
/*
* Initialize the ring segment pool. The ring must be a contiguous
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 5f630e74b323..431c922b3f2d 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -544,6 +544,9 @@ static int xhci_init(struct usb_hcd *hcd)
/* Set the address in the Command Ring Control register */
xhci_set_cmd_ring_deq(xhci);
+ /* Set Device Context Base Address pointer */
+ xhci_write_64(xhci, xhci->dcbaa->dma, &xhci->op_regs->dcbaa_ptr);
+
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 06/11] usb: xhci: move doorbell array pointer assignment
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (4 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 05/11] usb: xhci: move DCBAA pointer write Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 07/11] usb: xhci: move enabling of USB 3 device notifications Niklas Neronin
` (4 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Move the assignment of the doorbell array pointer from xhci_mem_init()
to xhci_init(). The assignment now utilizes the newly introduced
xhci_set_doorbell_ptr() function.
Doorbell Array Offset mask (DBOFF_MASK) is updated to directly specify its
bit range as 31:2, rather than using inverted reserved bits 1:0.
This change simplifies the mask representation, making it more intuitive
and easier to understand.
Remove the "// " prefix from trace messages, as it is unnecessary and
distracting.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-caps.h | 4 ++--
drivers/usb/host/xhci-mem.c | 8 --------
drivers/usb/host/xhci.c | 13 +++++++++++++
3 files changed, 15 insertions(+), 10 deletions(-)
diff --git a/drivers/usb/host/xhci-caps.h b/drivers/usb/host/xhci-caps.h
index f6b9a00a0ab9..4b8ff4815644 100644
--- a/drivers/usb/host/xhci-caps.h
+++ b/drivers/usb/host/xhci-caps.h
@@ -62,8 +62,8 @@
#define CTX_SIZE(_hcc) (HCC_64BYTE_CONTEXT(_hcc) ? 64 : 32)
-/* db_off bitmask - bits 0:1 reserved */
-#define DBOFF_MASK (~0x3)
+/* db_off bitmask - bits 31:2 Doorbell Array Offset */
+#define DBOFF_MASK (0xfffffffc)
/* run_regs_off bitmask - bits 0:4 reserved */
#define RTSOFF_MASK (~0x1f)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 4e6289d9a89a..7525713f0774 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2376,7 +2376,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
struct xhci_interrupter *ir;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
dma_addr_t dma;
- unsigned int val;
u32 temp;
/*
@@ -2444,13 +2443,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
*/
xhci->cmd_ring_reserved_trbs++;
- val = readl(&xhci->cap_regs->db_off);
- val &= DBOFF_MASK;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Doorbell array is located at offset 0x%x from cap regs base addr",
- val);
- xhci->dba = (void __iomem *) xhci->cap_regs + val;
-
/* Allocate and set up primary interrupter 0 with an event ring. */
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
"Allocating primary event ring");
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 431c922b3f2d..e5e5a50d9617 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -513,6 +513,16 @@ static void xhci_set_cmd_ring_deq(struct xhci_hcd *xhci)
xhci_write_64(xhci, crcr, &xhci->op_regs->cmd_ring);
}
+static void xhci_set_doorbell_ptr(struct xhci_hcd *xhci)
+{
+ u32 offset;
+
+ offset = readl(&xhci->cap_regs->db_off) & DBOFF_MASK;
+ xhci->dba = (void __iomem *)xhci->cap_regs + offset;
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init,
+ "Doorbell array is located at offset 0x%x from cap regs base addr", offset);
+}
+
/*
* Initialize memory for HCD and xHC (one-time init).
*
@@ -547,6 +557,9 @@ static int xhci_init(struct usb_hcd *hcd)
/* Set Device Context Base Address pointer */
xhci_write_64(xhci, xhci->dcbaa->dma, &xhci->op_regs->dcbaa_ptr);
+ /* Set Doorbell array pointer */
+ xhci_set_doorbell_ptr(xhci);
+
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 07/11] usb: xhci: move enabling of USB 3 device notifications
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (5 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 06/11] usb: xhci: move doorbell array pointer assignment Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 08/11] usb: xhci: remove error handling from xhci_add_interrupter() Niklas Neronin
` (3 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Relocated the enabling of USB 3.0 device notifications from xhci_mem_init()
to xhci_init(). Introduced xhci_set_dev_notifications() function to handle
the notification settings.
Simplify 'DEV_NOTE_FWAKE' masks by directly using the 'ENABLE_DEV_NOTE'
value (1 << 1) instead of using the 'ENABLE_DEV_NOTE' macro.
Macro 'ENABLE_DEV_NOTE' is removed.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 10 ----------
drivers/usb/host/xhci.c | 17 +++++++++++++++++
drivers/usb/host/xhci.h | 3 +--
3 files changed, 18 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 7525713f0774..1b05704a1852 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2376,7 +2376,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
struct xhci_interrupter *ir;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
dma_addr_t dma;
- u32 temp;
/*
* xHCI section 5.4.6 - Device Context array must be
@@ -2463,15 +2462,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
if (xhci_setup_port_arrays(xhci, flags))
goto fail;
- /* Enable USB 3.0 device notifications for function remote wake, which
- * is necessary for allowing USB 3.0 devices to do remote wakeup from
- * U3 (device suspend).
- */
- temp = readl(&xhci->op_regs->dev_notification);
- temp &= ~DEV_NOTE_MASK;
- temp |= DEV_NOTE_FWAKE;
- writel(temp, &xhci->op_regs->dev_notification);
-
return 0;
fail:
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e5e5a50d9617..8fe217cdf80f 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -523,6 +523,20 @@ static void xhci_set_doorbell_ptr(struct xhci_hcd *xhci)
"Doorbell array is located at offset 0x%x from cap regs base addr", offset);
}
+/*
+ * Enable USB 3.0 device notifications for function remote wake, which is necessary
+ * for allowing USB 3.0 devices to do remote wakeup from U3 (device suspend).
+ */
+static void xhci_set_dev_notifications(struct xhci_hcd *xhci)
+{
+ u32 dev_notf;
+
+ dev_notf = readl(&xhci->op_regs->dev_notification);
+ dev_notf &= ~DEV_NOTE_MASK;
+ dev_notf |= DEV_NOTE_FWAKE;
+ writel(dev_notf, &xhci->op_regs->dev_notification);
+}
+
/*
* Initialize memory for HCD and xHC (one-time init).
*
@@ -560,6 +574,9 @@ static int xhci_init(struct usb_hcd *hcd)
/* Set Doorbell array pointer */
xhci_set_doorbell_ptr(xhci);
+ /* Set USB 3.0 device notifications for function remote wake */
+ xhci_set_dev_notifications(xhci);
+
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 38058006f79b..b8e6ce888032 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -184,11 +184,10 @@ struct xhci_op_regs {
* notification type that matches a bit set in this bit field.
*/
#define DEV_NOTE_MASK (0xffff)
-#define ENABLE_DEV_NOTE(x) (1 << (x))
/* Most of the device notification types should only be used for debug.
* SW does need to pay attention to function wake notifications.
*/
-#define DEV_NOTE_FWAKE ENABLE_DEV_NOTE(1)
+#define DEV_NOTE_FWAKE (1 << 1)
/* CRCR - Command Ring Control Register - cmd_ring bitmasks */
/* bit 0 - Cycle bit indicates the ownership of the command ring */
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 08/11] usb: xhci: remove error handling from xhci_add_interrupter()
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (6 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 07/11] usb: xhci: move enabling of USB 3 device notifications Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 09/11] usb: xhci: move initialization of the primary interrupter Niklas Neronin
` (2 subsequent siblings)
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Remove redundant error handling from xhci_add_interrupter() instead of
trying to accommodate them in future changes.
======== Reasoning for the removal ========
Function xhci_add_interrupter() is invoked in two scenarios:
Primary Interrupter Setup (ID 0):
The maximum number of interrupters is always greater than zero, and the
primary interrupter is always allocated as part of the driver's
initialization process. In case of failure, the xHCI driver errors and
exits.
Secondary Interrupter Creation (ID >= 1):
The interrupter is pre-allocated, and an empty slot is identified before
invoking xhci_add_interrupter().
In both cases, the existing error handling within xhci_add_interrupter() is
redundant and unnecessary.
Upcoming Changes:
In the subsequent commit, interrupter initialization will move from
xhci_mem_init() to xhci_init(). This change is necessary to facilitate
the ability to restart the xHCI driver without re-allocating memory.
As a result, the allocated interrupter must be stored in the interrupters
pointer array before initialization.
Consequently, xhci_create_secondary_interrupter() would need to handle
pointer removal for allocated 'interrupters' array upon failure, although
xhci_add_interrupter() will never fail.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 24 +++++-------------------
1 file changed, 5 insertions(+), 19 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 1b05704a1852..ce632a288c41 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2282,24 +2282,13 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
return ir;
}
-static int
+static void
xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
unsigned int intr_num)
{
u64 erst_base;
u32 erst_size;
- if (intr_num >= xhci->max_interrupters) {
- xhci_warn(xhci, "Can't add interrupter %d, max interrupters %d\n",
- intr_num, xhci->max_interrupters);
- return -EINVAL;
- }
-
- if (xhci->interrupters[intr_num]) {
- xhci_warn(xhci, "Interrupter %d\n already set up", intr_num);
- return -EINVAL;
- }
-
xhci->interrupters[intr_num] = ir;
ir->intr_num = intr_num;
ir->ir_set = &xhci->run_regs->ir_set[intr_num];
@@ -2320,8 +2309,6 @@ xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
/* Set the event ring dequeue address of this interrupter */
xhci_set_hc_event_deq(xhci, ir);
-
- return 0;
}
struct xhci_interrupter *
@@ -2331,7 +2318,7 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs,
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_interrupter *ir;
unsigned int i;
- int err = -ENOSPC;
+ int err;
if (!xhci->interrupters || xhci->max_interrupters <= 1)
return NULL;
@@ -2345,14 +2332,14 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs,
/* Find available secondary interrupter, interrupter 0 is reserved for primary */
for (i = 1; i < xhci->max_interrupters; i++) {
if (xhci->interrupters[i] == NULL) {
- err = xhci_add_interrupter(xhci, ir, i);
+ xhci_add_interrupter(xhci, ir, i);
break;
}
}
spin_unlock_irq(&xhci->lock);
- if (err) {
+ if (i == xhci->max_interrupters) {
xhci_warn(xhci, "Failed to add secondary interrupter, max interrupters %d\n",
xhci->max_interrupters);
xhci_free_interrupter(xhci, ir);
@@ -2452,8 +2439,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
if (!ir)
goto fail;
- if (xhci_add_interrupter(xhci, ir, 0))
- goto fail;
+ xhci_add_interrupter(xhci, ir, 0);
ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 09/11] usb: xhci: move initialization of the primary interrupter
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (7 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 08/11] usb: xhci: remove error handling from xhci_add_interrupter() Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 10/11] usb: xhci: add individual allocation checks in xhci_mem_init() Niklas Neronin
2025-04-11 9:11 ` [PATCH 11/11] usb: xhci: cleanup xhci_mem_init() Niklas Neronin
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Move the primary interrupter (0) initialization from xhci_mem_init() to
xhci_init(). This change requires us to save the allocated interrupter
somewhere before initialization. Therefore, store it in the 'interrupters'
array and rework xhci_add_interrupter() to retrieve the interrupter from
the array.
This is part of the ongoing effort to separate allocation and
initialization.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 19 +++++++------------
drivers/usb/host/xhci.c | 4 ++++
drivers/usb/host/xhci.h | 1 +
3 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index ce632a288c41..2d1f320e5fd6 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2282,14 +2282,13 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
return ir;
}
-static void
-xhci_add_interrupter(struct xhci_hcd *xhci, struct xhci_interrupter *ir,
- unsigned int intr_num)
+void xhci_add_interrupter(struct xhci_hcd *xhci, unsigned int intr_num)
{
+ struct xhci_interrupter *ir;
u64 erst_base;
u32 erst_size;
- xhci->interrupters[intr_num] = ir;
+ ir = xhci->interrupters[intr_num];
ir->intr_num = intr_num;
ir->ir_set = &xhci->run_regs->ir_set[intr_num];
@@ -2332,7 +2331,8 @@ xhci_create_secondary_interrupter(struct usb_hcd *hcd, unsigned int segs,
/* Find available secondary interrupter, interrupter 0 is reserved for primary */
for (i = 1; i < xhci->max_interrupters; i++) {
if (xhci->interrupters[i] == NULL) {
- xhci_add_interrupter(xhci, ir, i);
+ xhci->interrupters[i] = ir;
+ xhci_add_interrupter(xhci, i);
break;
}
}
@@ -2360,7 +2360,6 @@ EXPORT_SYMBOL_GPL(xhci_create_secondary_interrupter);
int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
{
- struct xhci_interrupter *ir;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
dma_addr_t dma;
@@ -2435,14 +2434,10 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci->interrupters = kcalloc_node(xhci->max_interrupters, sizeof(*xhci->interrupters),
flags, dev_to_node(dev));
- ir = xhci_alloc_interrupter(xhci, 0, flags);
- if (!ir)
+ xhci->interrupters[0] = xhci_alloc_interrupter(xhci, 0, flags);
+ if (!xhci->interrupters[0])
goto fail;
- xhci_add_interrupter(xhci, ir, 0);
-
- ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
-
if (scratchpad_alloc(xhci, flags))
goto fail;
if (xhci_setup_port_arrays(xhci, flags))
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 8fe217cdf80f..c7380ebdb680 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -577,6 +577,10 @@ static int xhci_init(struct usb_hcd *hcd)
/* Set USB 3.0 device notifications for function remote wake */
xhci_set_dev_notifications(xhci);
+ /* Initialize the Primary interrupter */
+ xhci_add_interrupter(xhci, 0);
+ xhci->interrupters[0]->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
+
/* Initializing Compliance Mode Recovery Data If Needed */
if (xhci_compliance_mode_recovery_timer_quirk_check()) {
xhci->quirks |= XHCI_COMP_MODE_QUIRK;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index b8e6ce888032..4c32ad36c493 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1934,6 +1934,7 @@ unsigned int count_trbs(u64 addr, u64 len);
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);
+void xhci_add_interrupter(struct xhci_hcd *xhci, unsigned int intr_num);
/* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 10/11] usb: xhci: add individual allocation checks in xhci_mem_init()
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (8 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 09/11] usb: xhci: move initialization of the primary interrupter Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
2025-04-11 9:11 ` [PATCH 11/11] usb: xhci: cleanup xhci_mem_init() Niklas Neronin
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Break up the existing multi-allocation checks into individual checks.
Add missing allocation check for 'xhci->interrupters'.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 2d1f320e5fd6..a45d96a5ef5f 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2390,11 +2390,13 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
else
xhci->segment_pool = dma_pool_create("xHCI ring segments", dev,
TRB_SEGMENT_SIZE, TRB_SEGMENT_SIZE, xhci->page_size);
+ if (!xhci->segment_pool)
+ goto fail;
/* See Table 46 and Note on Figure 55 */
xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
2112, 64, xhci->page_size);
- if (!xhci->segment_pool || !xhci->device_pool)
+ if (!xhci->device_pool)
goto fail;
/* Linear stream context arrays don't have any boundary restrictions,
@@ -2403,6 +2405,9 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci->small_streams_pool =
dma_pool_create("xHCI 256 byte stream ctx arrays",
dev, SMALL_STREAM_ARRAY_SIZE, 16, 0);
+ if (!xhci->small_streams_pool)
+ goto fail;
+
xhci->medium_streams_pool =
dma_pool_create("xHCI 1KB stream ctx arrays",
dev, MEDIUM_STREAM_ARRAY_SIZE, 16, 0);
@@ -2410,7 +2415,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
* will be allocated with dma_alloc_coherent()
*/
- if (!xhci->small_streams_pool || !xhci->medium_streams_pool)
+ if (!xhci->medium_streams_pool)
goto fail;
/* Set up the command ring to have one segments for now. */
@@ -2433,6 +2438,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
"Allocating primary event ring");
xhci->interrupters = kcalloc_node(xhci->max_interrupters, sizeof(*xhci->interrupters),
flags, dev_to_node(dev));
+ if (!xhci->interrupters)
+ goto fail;
xhci->interrupters[0] = xhci_alloc_interrupter(xhci, 0, flags);
if (!xhci->interrupters[0])
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 11/11] usb: xhci: cleanup xhci_mem_init()
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
` (9 preceding siblings ...)
2025-04-11 9:11 ` [PATCH 10/11] usb: xhci: add individual allocation checks in xhci_mem_init() Niklas Neronin
@ 2025-04-11 9:11 ` Niklas Neronin
10 siblings, 0 replies; 13+ messages in thread
From: Niklas Neronin @ 2025-04-11 9:11 UTC (permalink / raw)
To: mathias.nyman; +Cc: linux-usb, Niklas Neronin
Cleanup indentation, spacing and comment formats.
Remove the "// " prefix from trace messages, as it is unnecessary and
distracting.
Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
---
drivers/usb/host/xhci-mem.c | 46 ++++++++++++++++++-------------------
1 file changed, 23 insertions(+), 23 deletions(-)
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index a45d96a5ef5f..1066c5d8ad83 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2367,14 +2367,14 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
* xHCI section 5.4.6 - Device Context array must be
* "physically contiguous and 64-byte (cache line) aligned".
*/
- xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma,
- flags);
+ xhci->dcbaa = dma_alloc_coherent(dev, sizeof(*xhci->dcbaa), &dma, flags);
if (!xhci->dcbaa)
goto fail;
+
xhci->dcbaa->dma = dma;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "// Device context base array address = 0x%pad (DMA), %p (virt)",
- &xhci->dcbaa->dma, xhci->dcbaa);
+ "Device context base array address = 0x%pad (DMA), %p (virt)",
+ &xhci->dcbaa->dma, xhci->dcbaa);
/*
* Initialize the ring segment pool. The ring must be a contiguous
@@ -2394,27 +2394,26 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
goto fail;
/* See Table 46 and Note on Figure 55 */
- xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev,
- 2112, 64, xhci->page_size);
+ xhci->device_pool = dma_pool_create("xHCI input/output contexts", dev, 2112, 64,
+ xhci->page_size);
if (!xhci->device_pool)
goto fail;
- /* Linear stream context arrays don't have any boundary restrictions,
+ /*
+ * Linear stream context arrays don't have any boundary restrictions,
* and only need to be 16-byte aligned.
*/
- xhci->small_streams_pool =
- dma_pool_create("xHCI 256 byte stream ctx arrays",
- dev, SMALL_STREAM_ARRAY_SIZE, 16, 0);
+ xhci->small_streams_pool = dma_pool_create("xHCI 256 byte stream ctx arrays",
+ dev, SMALL_STREAM_ARRAY_SIZE, 16, 0);
if (!xhci->small_streams_pool)
goto fail;
- xhci->medium_streams_pool =
- dma_pool_create("xHCI 1KB stream ctx arrays",
- dev, MEDIUM_STREAM_ARRAY_SIZE, 16, 0);
- /* Any stream context array bigger than MEDIUM_STREAM_ARRAY_SIZE
- * will be allocated with dma_alloc_coherent()
+ /*
+ * Any stream context array bigger than MEDIUM_STREAM_ARRAY_SIZE will be
+ * allocated with dma_alloc_coherent().
*/
-
+ xhci->medium_streams_pool = dma_pool_create("xHCI 1KB stream ctx arrays",
+ dev, MEDIUM_STREAM_ARRAY_SIZE, 16, 0);
if (!xhci->medium_streams_pool)
goto fail;
@@ -2422,20 +2421,20 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
xhci->cmd_ring = xhci_ring_alloc(xhci, 1, TYPE_COMMAND, 0, flags);
if (!xhci->cmd_ring)
goto fail;
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "Allocated command ring at %p", xhci->cmd_ring);
- xhci_dbg_trace(xhci, trace_xhci_dbg_init, "First segment DMA is 0x%pad",
- &xhci->cmd_ring->first_seg->dma);
- /* Reserve one command ring TRB for disabling LPM.
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Allocated command ring at %p", xhci->cmd_ring);
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "First segment DMA is 0x%pad",
+ &xhci->cmd_ring->first_seg->dma);
+
+ /*
+ * Reserve one command ring TRB for disabling LPM.
* Since the USB core grabs the shared usb_bus bandwidth mutex before
* disabling LPM, we only need to reserve one TRB for all devices.
*/
xhci->cmd_ring_reserved_trbs++;
/* Allocate and set up primary interrupter 0 with an event ring. */
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "Allocating primary event ring");
+ xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Allocating primary event ring");
xhci->interrupters = kcalloc_node(xhci->max_interrupters, sizeof(*xhci->interrupters),
flags, dev_to_node(dev));
if (!xhci->interrupters)
@@ -2447,6 +2446,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
if (scratchpad_alloc(xhci, flags))
goto fail;
+
if (xhci_setup_port_arrays(xhci, flags))
goto fail;
--
2.47.2
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 05/11] usb: xhci: move DCBAA pointer write
2025-04-11 9:11 ` [PATCH 05/11] usb: xhci: move DCBAA pointer write Niklas Neronin
@ 2025-04-11 15:05 ` Sergey Shtylyov
0 siblings, 0 replies; 13+ messages in thread
From: Sergey Shtylyov @ 2025-04-11 15:05 UTC (permalink / raw)
To: Niklas Neronin, mathias.nyman; +Cc: linux-usb
On 4/11/25 12:11 PM, Niklas Neronin wrote:
> Move the Device Context Base Address Array (DCBAA) pointer write from
> xhci_mem_init() to xhci_init(). This is part of the ongoing effort to
> separate allocation and initialization.
>
> Signed-off-by: Niklas Neronin <niklas.neronin@linux.intel.com>
[...]
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index 5f630e74b323..431c922b3f2d 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -544,6 +544,9 @@ static int xhci_init(struct usb_hcd *hcd)
> /* Set the address in the Command Ring Control register */
> xhci_set_cmd_ring_deq(xhci);
>
> + /* Set Device Context Base Address pointer */
"Array" missing here?
> + xhci_write_64(xhci, xhci->dcbaa->dma, &xhci->op_regs->dcbaa_ptr);
> +
> /* Initializing Compliance Mode Recovery Data If Needed */
> if (xhci_compliance_mode_recovery_timer_quirk_check()) {
> xhci->quirks |= XHCI_COMP_MODE_QUIRK;
MBR, Sergey
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2025-04-11 15:05 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-11 9:11 [PATCH 00/11] usb: xhci: decouple allocation and initialization Niklas Neronin
2025-04-11 9:11 ` [PATCH 01/11] usb: xhci: relocate pre-allocation initialization Niklas Neronin
2025-04-11 9:11 ` [PATCH 02/11] usb: xhci: move device slot enabling register write Niklas Neronin
2025-04-11 9:11 ` [PATCH 03/11] usb: xhci: move command ring pointer write Niklas Neronin
2025-04-11 9:11 ` [PATCH 04/11] usb: xhci: refactor xhci_set_cmd_ring_deq() Niklas Neronin
2025-04-11 9:11 ` [PATCH 05/11] usb: xhci: move DCBAA pointer write Niklas Neronin
2025-04-11 15:05 ` Sergey Shtylyov
2025-04-11 9:11 ` [PATCH 06/11] usb: xhci: move doorbell array pointer assignment Niklas Neronin
2025-04-11 9:11 ` [PATCH 07/11] usb: xhci: move enabling of USB 3 device notifications Niklas Neronin
2025-04-11 9:11 ` [PATCH 08/11] usb: xhci: remove error handling from xhci_add_interrupter() Niklas Neronin
2025-04-11 9:11 ` [PATCH 09/11] usb: xhci: move initialization of the primary interrupter Niklas Neronin
2025-04-11 9:11 ` [PATCH 10/11] usb: xhci: add individual allocation checks in xhci_mem_init() Niklas Neronin
2025-04-11 9:11 ` [PATCH 11/11] usb: xhci: cleanup xhci_mem_init() Niklas Neronin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.