This is an automated email from the ASF dual-hosted git repository. xiaoxiang781216 pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 8f88d7327592011ef44a06dacb24af06251eb337 Author: Justin Hammond <[email protected]> AuthorDate: Sun Aug 16 17:10:58 2026 +0800 drivers/usbhost: Set the xHCI interrupter moderation interval. The interval was left at its reset value of 4000, a millisecond, which is how long the controller waits after an event before reporting it. Every completion paid that, and mass storage spends three transfers on a request. Set it to 160, which is 40us, as Linux does. Zero puts no bound on how often a controller may interrupt: a keyboard on an interrupt endpoint then takes them continuously and occupies a processor. Measured on a DWC3 with a USB 2.0 drive, doorbell to interrupt 986-1021us before and 13-56us after: reading 1MiB before after 512 byte blocks 166 KB/s 775 KB/s 32 KiB blocks 10666 KB/s 18618 KB/s mounting a FAT32 volume: 92.7s before, 21.1s after Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond <[email protected]> --- drivers/usbhost/usbhost_xhci.c | 4 ++++ drivers/usbhost/usbhost_xhci.h | 11 +++++++++++ 2 files changed, 15 insertions(+) diff --git a/drivers/usbhost/usbhost_xhci.c b/drivers/usbhost/usbhost_xhci.c index ed417a92a52..2c3d3ad559a 100644 --- a/drivers/usbhost/usbhost_xhci.c +++ b/drivers/usbhost/usbhost_xhci.c @@ -1141,6 +1141,10 @@ static int xhci_ctrl_start(FAR struct usbhost_xhci_s *priv) xhci_oper_putreg_8b(priv, XHCI_CRCR, up_addrenv_va_to_pa(priv->cmd.ring) | XHCI_CRCR_RCS); + /* Do not sit on completions; see XHCI_IMOD_INTERVAL */ + + xhci_runt_putreg(priv, XHCI_IMOD(0), XHCI_IMOD_DEFAULT); + /* Enable interrupts */ regval = xhci_runt_getreg(priv, XHCI_IMAN(0)); diff --git a/drivers/usbhost/usbhost_xhci.h b/drivers/usbhost/usbhost_xhci.h index 8f940f8a82c..2fc2aa207ad 100644 --- a/drivers/usbhost/usbhost_xhci.h +++ b/drivers/usbhost/usbhost_xhci.h @@ -315,6 +315,17 @@ #define XHCI_IMOD_IMODI_SHIFT (0) /* Bits 0-15: Interrupt Moderation Interval */ #define XHCI_IMOD_IMODC_SHIFT (16) /* Bits 16-31: Interrupt Moderation Counter */ +/* What to set the moderation interval to, in 250ns units. + * + * The reset default is 4000, a millisecond, which is far too long to wait + * to be told a transfer finished. Zero is too short: it puts no bound on + * how often a controller may interrupt, and a polled device such as a + * keyboard on an interrupt endpoint will then occupy a processor. 160 is + * 40us, which is what Linux uses. + */ + +#define XHCI_IMOD_DEFAULT (160) + /* Event Ring Segment Table Size */ #define XHCI_ERSTS_MASK (0xffff) /* Bit 0-15: Event Ring Segment Table Size */
