xhci_intr_raise() returned early whenever ERDP.EHB was set; that also skipped IRQ assertion after the guest cleared IMAN.IP while leaving the event handler busy bit asserted.
Track the previous IMAN.IP state and suppress only duplicate raises; when ERDP.EHB remains set after IMAN.IP is cleared, assert the IRQ again so the guest can observe the pending event. Signed-off-by: Kirill A. Korinsky <[email protected]> --- hw/usb/hcd-xhci.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 2cdab3ba0e..ce06d52c36 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -577,12 +577,13 @@ static void xhci_intr_update(XHCIState *xhci, int v) static void xhci_intr_raise(XHCIState *xhci, int v) { bool pending = (xhci->intr[v].erdp_low & ERDP_EHB); + bool was_raised = (xhci->intr[v].iman & IMAN_IP); xhci->intr[v].erdp_low |= ERDP_EHB; xhci->intr[v].iman |= IMAN_IP; xhci->usbsts |= USBSTS_EINT; - if (pending) { + if (pending && was_raised) { return; } if (!(xhci->intr[v].iman & IMAN_IE)) { -- 2.54.0
