Hi Kirill,
On 13/7/26 13:16, Kirill A. Korinsky wrote:
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);
Per your description we are missing to clear ERDP_EHB?
@@ -592,6 +592,7 @@ static void xhci_intr_raise(XHCIState *xhci, int v)
}
if (xhci->intr_raise) {
if (xhci->intr_raise(xhci, v, true)) {
+ xhci->intr[v].erdp_low &= ~ERDP_EHB;
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)) {