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.

xhci: Add helper to set an interrupters interrupt moderation interval

Add a helper to set the interrupt moderation interval for an interrupter.
Each interrupter can have its own moderation value.

Hardware has a 16bit register for the moderation value, each step is 250ns.

Helper function imod_interval argument is in nanoseconds.

Values from 0 to 16383750 (250 x 0xffff) are accepted.
0 means no interrupt throttling.

Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: Wesley Cheng <quic_wcheng@quicinc.com>
Link: https://lore.kernel.org/r/20240217001017.29969-3-quic_wcheng@quicinc.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Mathias Nyman and committed by
Greg Kroah-Hartman
ace21625 4f022aad

+18 -7
+18 -7
drivers/usb/host/xhci.c
··· 346 346 return 0; 347 347 } 348 348 349 + /* interrupt moderation interval imod_interval in nanoseconds */ 350 + static int xhci_set_interrupter_moderation(struct xhci_interrupter *ir, 351 + u32 imod_interval) 352 + { 353 + u32 imod; 354 + 355 + if (!ir || !ir->ir_set || imod_interval > U16_MAX * 250) 356 + return -EINVAL; 357 + 358 + imod = readl(&ir->ir_set->irq_control); 359 + imod &= ~ER_IRQ_INTERVAL_MASK; 360 + imod |= (imod_interval / 250) & ER_IRQ_INTERVAL_MASK; 361 + writel(imod, &ir->ir_set->irq_control); 362 + 363 + return 0; 364 + } 365 + 349 366 static void compliance_mode_recovery(struct timer_list *t) 350 367 { 351 368 struct xhci_hcd *xhci; ··· 545 528 */ 546 529 int xhci_run(struct usb_hcd *hcd) 547 530 { 548 - u32 temp; 549 531 u64 temp_64; 550 532 int ret; 551 533 struct xhci_hcd *xhci = hcd_to_xhci(hcd); ··· 567 551 xhci_dbg_trace(xhci, trace_xhci_dbg_init, 568 552 "ERST deq = 64'h%0lx", (long unsigned int) temp_64); 569 553 570 - xhci_dbg_trace(xhci, trace_xhci_dbg_init, 571 - "// Set the interrupt modulation register"); 572 - temp = readl(&ir->ir_set->irq_control); 573 - temp &= ~ER_IRQ_INTERVAL_MASK; 574 - temp |= (xhci->imod_interval / 250) & ER_IRQ_INTERVAL_MASK; 575 - writel(temp, &ir->ir_set->irq_control); 554 + xhci_set_interrupter_moderation(ir, xhci->imod_interval); 576 555 577 556 if (xhci->quirks & XHCI_NEC_HOST) { 578 557 struct xhci_command *command;