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)) {


Reply via email to