From 9a0ffde0537136c97c82fb76a004c7e1322e069b Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Thu, 14 May 2020 14:49:10 -0700 Subject: devices: usb: ignore busy flag in interrupter This works around an issue where the xhci controller hangs from the guest's point of view, with the guest kernel eventually timing out and disabling the controller. The xHCI spec says that the EHB (Event Handler Busy) bit should be cleared before signalling another interrupt. This bit is set by the controller before triggering an interrupt, and it is meant to be cleared by the guest (via write-1-to-clear) when it is done handling the interrupt. However, it seems that there is a race going on between the clearing and setting of this bit. Removing the check seems to avoid the issue, since we never get into the state where we think EHB is set but the guest thinks it is clear (where no further interrupts would be triggered). This will potentially trigger more interrupts than strictly necessary, but the Linux kernel xhci driver handles interrupts with no events available gracefully. BUG=chromium:1082930 TEST=`while adb shell echo hi; do : ; done` for 8+ hours without hangs Change-Id: I3c08f0c5675be10d8e46f73714d684f7ba3a3903 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2202745 Reviewed-by: Dylan Reid Tested-by: kokoro Commit-Queue: Daniel Verkamp --- devices/src/usb/xhci/interrupter.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'devices') diff --git a/devices/src/usb/xhci/interrupter.rs b/devices/src/usb/xhci/interrupter.rs index 6366050..cf79fd8 100644 --- a/devices/src/usb/xhci/interrupter.rs +++ b/devices/src/usb/xhci/interrupter.rs @@ -187,7 +187,8 @@ impl Interrupter { } fn interrupt_if_needed(&mut self) -> Result<()> { - if self.enabled && !self.event_ring.is_empty() && !self.event_handler_busy { + // TODO(dverkamp): re-add !self.event_handler_busy after solving https://crbug.com/1082930 + if self.enabled && !self.event_ring.is_empty() { self.interrupt()?; } Ok(()) -- cgit 1.4.1