Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: xhci: limit number of interrupts to 128

The xHCI driver defines only 128 interrupter register slots, yet allows up
to 2047 interrupters. According to the xHCI specification, the maximum
valid number of interrupters is 1024. These mismatches can lead to
out-of-range accesses and excessive memory use.

The Number of Interrupters (MaxIntrs) field occupies bits 18:8 of the
HCSPARAMS1 register, which can yield a value up to 2047, although the
specification limits it to 1024. Cap the value using the 'MAX_HC_INTRS'
macro.

Set 'xhci->max_intrs' to the minimum of the value reported by the
HCSPARAMS1 register and 'MAX_HC_INTRS'. The interrupter register slot
array is defined for 1024 entries, serving only as a structural template
and not increasing memory usage.

Although the xHCI specification allows up to 1024 interrupters, raising
'MAX_HC_INTRS' above 128 provides no practical benefit. The driver only
uses the primary interrupter (0), and secondary interrupters (1+) are
rarely, if ever, used in practice. No reports exist of usage beyond 128.
Therefore, I have limited it to 128.

Summary:
* Interrupter allocations are now limited to 128 from 2047.
* Interrupter Register template slots are set to 1024 from 128.
* Macro 'MAX_HC_INTRS' can be modified to set the interrupter limit.

==== Detailed interrupter explanation ====

There are two relevant components:

Interrupter array:
This holds the software interrupter structures and is allocated by the
xhci driver. The number of interrupters allocated is determined by the
HCSPARAMS1 register field, which specifies the supported interrupter
count.

Interrupter register slots:
This is a template struct used to access the hardware's runtime
registers. It is not allocated by the driver, the hardware defines and
owns this memory region, and the driver only maps it for MMIO access.

Each entry in the interrupter array points to its corresponding
interrupter register slot in the hardware region once that interrupter
is enabled.

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/20251119142417.2820519-18-mathias.nyman@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Niklas Neronin and committed by
Greg Kroah-Hartman
8e9a3a1e 1668263a

+12 -8
+6 -7
drivers/usb/host/xhci.c
··· 250 250 struct iommu_domain *domain; 251 251 int err, i; 252 252 u64 val; 253 - u32 intrs; 254 253 255 254 /* 256 255 * Some Renesas controllers get into a weird state if they are ··· 290 291 if (upper_32_bits(val)) 291 292 xhci_write_64(xhci, 0, &xhci->op_regs->cmd_ring); 292 293 293 - intrs = min_t(u32, xhci->max_interrupters, ARRAY_SIZE(xhci->run_regs->ir_set)); 294 - 295 - for (i = 0; i < intrs; i++) { 294 + for (i = 0; i < xhci->max_interrupters; i++) { 296 295 struct xhci_intr_reg __iomem *ir; 297 296 298 297 ir = &xhci->run_regs->ir_set[i]; ··· 5447 5450 xhci->max_slots = HCS_MAX_SLOTS(hcs_params1); 5448 5451 xhci->max_ports = min(HCS_MAX_PORTS(hcs_params1), MAX_HC_PORTS); 5449 5452 /* xhci-plat or xhci-pci might have set max_interrupters already */ 5450 - if ((!xhci->max_interrupters) || xhci->max_interrupters > HCS_MAX_INTRS(hcs_params1)) 5453 + if (!xhci->max_interrupters) 5454 + xhci->max_interrupters = min(HCS_MAX_INTRS(hcs_params1), MAX_HC_INTRS); 5455 + else if (xhci->max_interrupters > HCS_MAX_INTRS(hcs_params1)) 5451 5456 xhci->max_interrupters = HCS_MAX_INTRS(hcs_params1); 5452 5457 5453 5458 xhci->quirks |= quirks; ··· 5669 5670 BUILD_BUG_ON(sizeof(struct xhci_erst_entry) != 4*32/8); 5670 5671 BUILD_BUG_ON(sizeof(struct xhci_cap_regs) != 8*32/8); 5671 5672 BUILD_BUG_ON(sizeof(struct xhci_intr_reg) != 8*32/8); 5672 - /* xhci_run_regs has eight fields and embeds 128 xhci_intr_regs */ 5673 - BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*128)*32/8); 5673 + /* xhci_run_regs has eight fields and embeds 1024 xhci_intr_regs */ 5674 + BUILD_BUG_ON(sizeof(struct xhci_run_regs) != (8+8*1024)*32/8); 5674 5675 5675 5676 if (usb_disabled()) 5676 5677 return -ENODEV;
+6 -1
drivers/usb/host/xhci.h
··· 39 39 * Valid values are in the range of 1 to 255. 40 40 */ 41 41 #define MAX_HC_PORTS 127 42 + /* 43 + * Max number of Interrupter Register Sets. xHCI specification section 5.3.3 44 + * Valid values are in the range of 1 to 1024. 45 + */ 46 + #define MAX_HC_INTRS 128 42 47 43 48 /* 44 49 * xHCI register interface. ··· 283 278 struct xhci_run_regs { 284 279 __le32 microframe_index; 285 280 __le32 rsvd[7]; 286 - struct xhci_intr_reg ir_set[128]; 281 + struct xhci_intr_reg ir_set[1024]; 287 282 }; 288 283 289 284 /**