* [RFC PATCH v1 0/3] usb: early: xhci-dbc: Handle out-of-bound
@ 2026-06-04 14:41 Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 1/3] usb: early: xhci-dbc: Track early_ioremap size separately Umang Jain
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Umang Jain @ 2026-06-04 14:41 UTC (permalink / raw)
To: Greg Kroah-Hartman, Lucas De Marchi
Cc: Mathias Nyman, linux-usb, linux-kernel, kernel-dev, Umang Jain
Small series to handle xhci-xdbc caps if the offset and out-of-bounds
for fixed time boot mappings. Previous discussion is at [1].
However, RFC because it doesn't completely work for me. Patch 3/3
WIP, makes it partially work (xdbc being recognized at host side)
but still something is OFF. 3/3 might contain a clue which we can
probably discuss in reviews.
[1]: https://lore.kernel.org/linux-usb/ab199e7a-c0d4-4150-bbcc-9ab8b18f0725@linux.intel.com/
Umang Jain (3):
usb: early: xhci-dbc: Track early_ioremap size separately
early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability
WIP: early: xhci-xdbc: Map lower and with 0 offset to partially work
drivers/usb/early/xhci-dbc.c | 77 ++++++++++++++++++++++++++++--------
drivers/usb/early/xhci-dbc.h | 1 +
2 files changed, 61 insertions(+), 17 deletions(-)
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH v1 1/3] usb: early: xhci-dbc: Track early_ioremap size separately
2026-06-04 14:41 [RFC PATCH v1 0/3] usb: early: xhci-dbc: Handle out-of-bound Umang Jain
@ 2026-06-04 14:41 ` Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 2/3] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 3/3] WIP: early: xhci-xdbc: Map lower and with 0 offset to partially work Umang Jain
2 siblings, 0 replies; 5+ messages in thread
From: Umang Jain @ 2026-06-04 14:41 UTC (permalink / raw)
To: Greg Kroah-Hartman, Lucas De Marchi
Cc: Mathias Nyman, linux-usb, linux-kernel, kernel-dev, Umang Jain
early_ioremap() only allows to map a fixed number of boot time mappings,
hence, the mapped size should be tracked separately from the PCIe base
address and size.
Signed-off-by: Umang Jain <uajain@igalia.com>
---
drivers/usb/early/xhci-dbc.c | 13 +++++++------
drivers/usb/early/xhci-dbc.h | 1 +
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
index 41118bba9197..8ce362a90910 100644
--- a/drivers/usb/early/xhci-dbc.c
+++ b/drivers/usb/early/xhci-dbc.c
@@ -86,6 +86,7 @@ static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
xdbc.xhci_start = val64;
xdbc.xhci_length = sz64;
base = early_ioremap(val64, sz64);
+ xdbc.xhci_base_length = sz64;
return base;
}
@@ -643,9 +644,9 @@ int __init early_xdbc_parse_parameter(char *s, int keep_early)
offset = xhci_find_next_ext_cap(xdbc.xhci_base, 0, XHCI_EXT_CAPS_DEBUG);
if (!offset) {
pr_notice("xhci host doesn't support debug capability\n");
- early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
+ early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
xdbc.xhci_base = NULL;
- xdbc.xhci_length = 0;
+ xdbc.xhci_base_length = 0;
return -ENODEV;
}
@@ -682,9 +683,9 @@ int __init early_xdbc_setup_hardware(void)
xdbc.table_base = NULL;
xdbc.out_buf = NULL;
- early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
+ early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
xdbc.xhci_base = NULL;
- xdbc.xhci_length = 0;
+ xdbc.xhci_base_length = 0;
}
return ret;
@@ -987,7 +988,7 @@ static int __init xdbc_init(void)
}
raw_spin_lock_irqsave(&xdbc.lock, flags);
- early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
+ early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
xdbc.xhci_base = base;
offset = xhci_find_next_ext_cap(xdbc.xhci_base, 0, XHCI_EXT_CAPS_DEBUG);
xdbc.xdbc_reg = (struct xdbc_regs __iomem *)(xdbc.xhci_base + offset);
@@ -1004,7 +1005,7 @@ static int __init xdbc_init(void)
memblock_phys_free(xdbc.table_dma, PAGE_SIZE);
memblock_phys_free(xdbc.out_dma, PAGE_SIZE);
writel(0, &xdbc.xdbc_reg->control);
- early_iounmap(xdbc.xhci_base, xdbc.xhci_length);
+ early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
return ret;
}
diff --git a/drivers/usb/early/xhci-dbc.h b/drivers/usb/early/xhci-dbc.h
index 8b4d71de45fc..e2aefb796084 100644
--- a/drivers/usb/early/xhci-dbc.h
+++ b/drivers/usb/early/xhci-dbc.h
@@ -144,6 +144,7 @@ struct xdbc_state {
u32 dev;
u32 func;
void __iomem *xhci_base;
+ size_t xhci_base_length;
u64 xhci_start;
size_t xhci_length;
int port_number;
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH v1 2/3] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability
2026-06-04 14:41 [RFC PATCH v1 0/3] usb: early: xhci-dbc: Handle out-of-bound Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 1/3] usb: early: xhci-dbc: Track early_ioremap size separately Umang Jain
@ 2026-06-04 14:41 ` Umang Jain
2026-06-05 18:16 ` Mathias Nyman
2026-06-04 14:41 ` [RFC PATCH v1 3/3] WIP: early: xhci-xdbc: Map lower and with 0 offset to partially work Umang Jain
2 siblings, 1 reply; 5+ messages in thread
From: Umang Jain @ 2026-06-04 14:41 UTC (permalink / raw)
To: Greg Kroah-Hartman, Lucas De Marchi
Cc: Mathias Nyman, linux-usb, linux-kernel, kernel-dev, Umang Jain
Currently, the early xhci-dbc assumes that the extended capability
can be mapped within the fixed boot time mappings dictated by
NR_FIX_BTMAPS.
This patch iterates over the PCI BAR address size to find and map
xhci-xdbc capability which could be out-of-bounds otherwise,
in xdbc_map_pci_mmio(). The iterations map the maximum allowed
boot time mappings (fixmap size) at a time and search for xhci-xdbc
capability offset, till the end of the bar address size.
Signed-off-by: Umang Jain <uajain@igalia.com>
---
drivers/usb/early/xhci-dbc.c | 47 +++++++++++++++++++++++++++++++++---
1 file changed, 44 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
index 8ce362a90910..1f6a129d4b5d 100644
--- a/drivers/usb/early/xhci-dbc.c
+++ b/drivers/usb/early/xhci-dbc.c
@@ -35,10 +35,13 @@ static bool early_console_keep;
static inline void xdbc_trace(const char *fmt, ...) { }
#endif /* XDBC_TRACE */
+#define XDBC_MAPPING_SIZE 56
+
static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
{
- u64 val64, sz64, mask64;
+ u64 val64, sz64, mask64, fixmap_size, mapped_size;
void __iomem *base;
+ int offset;
u32 val, sz;
u8 byte;
@@ -85,8 +88,46 @@ static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
xdbc.xhci_start = val64;
xdbc.xhci_length = sz64;
- base = early_ioremap(val64, sz64);
- xdbc.xhci_base_length = sz64;
+
+ fixmap_size = NR_FIX_BTMAPS << PAGE_SHIFT;
+ if (sz64 < fixmap_size) {
+ xdbc.xhci_base_length = sz64;
+ return early_ioremap(val64, sz64);
+ }
+
+ /*
+ * Base address size is greater than fixed size boot mappings,
+ * hence iterate over the region one fixmap_size at a time.
+ */
+ base = early_ioremap(val64, fixmap_size);
+ offset = xhci_find_next_ext_cap(base, 0, 0);
+ mapped_size = fixmap_size;
+
+ while (mapped_size <= sz64) {
+ val = readl(base + offset);
+ if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_DEBUG) {
+ if (offset + XDBC_MAPPING_SIZE > fixmap_size) {
+ early_iounmap(base, fixmap_size);
+ base = early_ioremap(val64 + offset, XDBC_MAPPING_SIZE);
+ }
+ break;
+ }
+
+ /*
+ * Find offset to next xhci-ext capability, remap if the offset
+ * is out of bounds of the already mapped region.
+ */
+ offset = xhci_find_next_ext_cap(base, offset, 0);
+ if (!offset) {
+ early_iounmap(base, fixmap_size);
+ base = early_ioremap(val64 + mapped_size, fixmap_size);
+ mapped_size += fixmap_size;
+
+ offset = xhci_find_next_ext_cap(base, 0, 0);
+ }
+ }
+
+ xdbc.xhci_base_length = fixmap_size;
return base;
}
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [RFC PATCH v1 3/3] WIP: early: xhci-xdbc: Map lower and with 0 offset to partially work
2026-06-04 14:41 [RFC PATCH v1 0/3] usb: early: xhci-dbc: Handle out-of-bound Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 1/3] usb: early: xhci-dbc: Track early_ioremap size separately Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 2/3] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability Umang Jain
@ 2026-06-04 14:41 ` Umang Jain
2 siblings, 0 replies; 5+ messages in thread
From: Umang Jain @ 2026-06-04 14:41 UTC (permalink / raw)
To: Greg Kroah-Hartman, Lucas De Marchi
Cc: Mathias Nyman, linux-usb, linux-kernel, kernel-dev, Umang Jain
Map the area slightly lower than max fixmap. Detect the offset of xhci
xdbc cap and remap it again, so that the offset becomes 0.
----
>> This is investigation patch to get early xdbc attached to host
>> successfully. Without this, the xdbc doesn't attach to host.
on host:
[180056.895751] usb usb4-port2: attempt power cycle
[180059.049494] usb 4-2: Device not responding to setup address.
[180059.262513] usb 4-2: Device not responding to setup address.
[180059.463201] usb 4-2: device not accepting address 81, error -71
[180059.651391] usb 4-2: Device not responding to setup address.
[180059.862171] usb 4-2: Device not responding to setup address.
[180060.065072] usb 4-2: device not accepting address 82, error -71
on target:
[ 5.779884] xhci_dbc:xdbc_start: waiting for device configuration timed out
[ 5.779891] xhci_dbc:early_xdbc_setup_hardware: failed to setup the connection to host
----
This patches atleast makes the target attach to xhci host at
/dev/ttyUSB0. It's meant to debug and discuss the core issue as a
"clue".
Signed-off-by: Umang Jain <uajain@igalia.com>
---
drivers/usb/early/xhci-dbc.c | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
index 1f6a129d4b5d..b2bde2e8f85f 100644
--- a/drivers/usb/early/xhci-dbc.c
+++ b/drivers/usb/early/xhci-dbc.c
@@ -95,6 +95,9 @@ static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
return early_ioremap(val64, sz64);
}
+ /* Do not fill all fixed page slots in one go. */
+ fixmap_size = fixmap_size / 2;
+
/*
* Base address size is greater than fixed size boot mappings,
* hence iterate over the region one fixmap_size at a time.
@@ -110,6 +113,14 @@ static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
early_iounmap(base, fixmap_size);
base = early_ioremap(val64 + offset, XDBC_MAPPING_SIZE);
}
+
+ pr_notice("Found CAPS_DEBUG: mapped size: %llu, \
+ fixmap_size: %llu, offset: %d, page_size:%d\n",
+ mapped_size, fixmap_size, offset, 1 << PAGE_SHIFT);
+
+ early_iounmap(base, fixmap_size);
+ base = early_ioremap(val64+offset, fixmap_size);
+
break;
}
@@ -681,17 +692,7 @@ int __init early_xdbc_parse_parameter(char *s, int keep_early)
if (!xdbc.xhci_base)
return -EINVAL;
- /* Locate DbC registers: */
- offset = xhci_find_next_ext_cap(xdbc.xhci_base, 0, XHCI_EXT_CAPS_DEBUG);
- if (!offset) {
- pr_notice("xhci host doesn't support debug capability\n");
- early_iounmap(xdbc.xhci_base, xdbc.xhci_base_length);
- xdbc.xhci_base = NULL;
- xdbc.xhci_base_length = 0;
-
- return -ENODEV;
- }
- xdbc.xdbc_reg = (struct xdbc_regs __iomem *)(xdbc.xhci_base + offset);
+ xdbc.xdbc_reg = (struct xdbc_regs __iomem *)(xdbc.xhci_base);
return 0;
}
--
2.53.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH v1 2/3] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability
2026-06-04 14:41 ` [RFC PATCH v1 2/3] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability Umang Jain
@ 2026-06-05 18:16 ` Mathias Nyman
0 siblings, 0 replies; 5+ messages in thread
From: Mathias Nyman @ 2026-06-05 18:16 UTC (permalink / raw)
To: Umang Jain, Greg Kroah-Hartman, Lucas De Marchi
Cc: linux-usb, linux-kernel, kernel-dev
Hi
On 6/4/26 17:41, Umang Jain wrote:
> Currently, the early xhci-dbc assumes that the extended capability
> can be mapped within the fixed boot time mappings dictated by
> NR_FIX_BTMAPS.
>
> This patch iterates over the PCI BAR address size to find and map
> xhci-xdbc capability which could be out-of-bounds otherwise,
> in xdbc_map_pci_mmio(). The iterations map the maximum allowed
> boot time mappings (fixmap size) at a time and search for xhci-xdbc
> capability offset, till the end of the bar address size.
>
Patch 1/3 can probably be merged into this one.
> Signed-off-by: Umang Jain <uajain@igalia.com>
> ---
> drivers/usb/early/xhci-dbc.c | 47 +++++++++++++++++++++++++++++++++---
> 1 file changed, 44 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c
> index 8ce362a90910..1f6a129d4b5d 100644
> --- a/drivers/usb/early/xhci-dbc.c
> +++ b/drivers/usb/early/xhci-dbc.c
> @@ -35,10 +35,13 @@ static bool early_console_keep;
> static inline void xdbc_trace(const char *fmt, ...) { }
> #endif /* XDBC_TRACE */
>
> +#define XDBC_MAPPING_SIZE 56
> +
I know spec says 56 bytes, but when looking at the Debug capability structure
in xhci section 7.6.8. it looks like 64 bytes.
> static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
> {
> - u64 val64, sz64, mask64;
> + u64 val64, sz64, mask64, fixmap_size, mapped_size;
> void __iomem *base;
> + int offset;
> u32 val, sz;
> u8 byte;
>
> @@ -85,8 +88,46 @@ static void __iomem * __init xdbc_map_pci_mmio(u32 bus, u32 dev, u32 func)
>
> xdbc.xhci_start = val64;
> xdbc.xhci_length = sz64;
> - base = early_ioremap(val64, sz64);
> - xdbc.xhci_base_length = sz64;
> +
> + fixmap_size = NR_FIX_BTMAPS << PAGE_SHIFT;
> + if (sz64 < fixmap_size) {
> + xdbc.xhci_base_length = sz64;
> + return early_ioremap(val64, sz64);
> + }
> +
> + /*
> + * Base address size is greater than fixed size boot mappings,
> + * hence iterate over the region one fixmap_size at a time.
> + */
> + base = early_ioremap(val64, fixmap_size);
> + offset = xhci_find_next_ext_cap(base, 0, 0);
> + mapped_size = fixmap_size;
> +
> + while (mapped_size <= sz64) {
> + val = readl(base + offset);
> + if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_DEBUG) {
> + if (offset + XDBC_MAPPING_SIZE > fixmap_size) {
> + early_iounmap(base, fixmap_size);
> + base = early_ioremap(val64 + offset, XDBC_MAPPING_SIZE);
Took a closer look and it turns out we do sometimes need to touch registers in other
extended capabilities. Mainly BIOS handoff in XHCI_EXT_CAPS_LEGACY and port reset in
XHCI_EXT_CAPS_PROTOCOL
In the case where xHC size is larger than early_ioremap() allows I would just
early_ioremap() maximum allowed size once, starting from xdbc.xhci_start.
Then walk the extended capabilities list ensuring DbC and the other needed capabilities
are inside this maximum allowed size.
early_iounmap() and fail if not.
This way we can also access the normal xHC host registers in case we need to reset the
controller, or ensure the 'controller not ready' bit is clear.
Thanks
Mathias
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-06-05 18:16 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-04 14:41 [RFC PATCH v1 0/3] usb: early: xhci-dbc: Handle out-of-bound Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 1/3] usb: early: xhci-dbc: Track early_ioremap size separately Umang Jain
2026-06-04 14:41 ` [RFC PATCH v1 2/3] early: usb: xhci-dbc: Handle out of bounds xhci-xdbc capability Umang Jain
2026-06-05 18:16 ` Mathias Nyman
2026-06-04 14:41 ` [RFC PATCH v1 3/3] WIP: early: xhci-xdbc: Map lower and with 0 offset to partially work Umang Jain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®