929083
From 5901a1ee90fbbddce3f0a17bc6dbb6a215b718a4 Mon Sep 17 00:00:00 2001
c8dfc6
From: Gerd Hoffmann <kraxel@redhat.com>
c8dfc6
Date: Thu, 30 Aug 2012 13:05:10 +0200
5544c1
Subject: [PATCH] xhci: rework interrupt handling
c8dfc6
c8dfc6
Split xhci_irq_update into a function which handles intx updates
c8dfc6
(including lowering the irq line once the guests acks the interrupt)
c8dfc6
and one which is used for raising an irq only.
c8dfc6
c8dfc6
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
c8dfc6
---
c8dfc6
 hw/usb/hcd-xhci.c | 47 +++++++++++++++++++++++++++++++++--------------
c8dfc6
 1 file changed, 33 insertions(+), 14 deletions(-)
c8dfc6
c8dfc6
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
f375e6
index ff74ed9..74a57fe 100644
c8dfc6
--- a/hw/usb/hcd-xhci.c
c8dfc6
+++ b/hw/usb/hcd-xhci.c
c8dfc6
@@ -612,24 +612,43 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
c8dfc6
     return &xhci->ports[index];
c8dfc6
 }
c8dfc6
 
c8dfc6
-static void xhci_irq_update(XHCIState *xhci)
c8dfc6
+static void xhci_intx_update(XHCIState *xhci)
c8dfc6
 {
c8dfc6
     int level = 0;
c8dfc6
 
c8dfc6
-    if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
c8dfc6
+    if (msi_enabled(&xhci->pci_dev)) {
c8dfc6
+        return;
c8dfc6
+    }
c8dfc6
+
c8dfc6
+    if (xhci->iman & IMAN_IP &&
c8dfc6
+        xhci->iman & IMAN_IE &&
c8dfc6
         xhci->usbcmd & USBCMD_INTE) {
c8dfc6
         level = 1;
c8dfc6
     }
c8dfc6
 
c8dfc6
+    trace_usb_xhci_irq_intx(level);
c8dfc6
+    qemu_set_irq(xhci->irq, level);
c8dfc6
+}
c8dfc6
+
c8dfc6
+static void xhci_intr_raise(XHCIState *xhci)
c8dfc6
+{
c8dfc6
+    if (!(xhci->iman & IMAN_IP) ||
c8dfc6
+        !(xhci->iman & IMAN_IE)) {
c8dfc6
+        return;
c8dfc6
+    }
c8dfc6
+
c8dfc6
+    if (!(xhci->usbcmd & USBCMD_INTE)) {
c8dfc6
+        return;
c8dfc6
+    }
c8dfc6
+
c8dfc6
     if (msi_enabled(&xhci->pci_dev)) {
c8dfc6
-        if (level) {
c8dfc6
-            trace_usb_xhci_irq_msi(0);
c8dfc6
-            msi_notify(&xhci->pci_dev, 0);
c8dfc6
-        }
c8dfc6
-    } else {
c8dfc6
-        trace_usb_xhci_irq_intx(level);
c8dfc6
-        qemu_set_irq(xhci->irq, level);
c8dfc6
+        trace_usb_xhci_irq_msi(0);
c8dfc6
+        msi_notify(&xhci->pci_dev, 0);
c8dfc6
+        return;
c8dfc6
     }
c8dfc6
+
c8dfc6
+    trace_usb_xhci_irq_intx(1);
c8dfc6
+    qemu_set_irq(xhci->irq, 1);
c8dfc6
 }
c8dfc6
 
c8dfc6
 static inline int xhci_running(XHCIState *xhci)
c8dfc6
@@ -732,7 +751,7 @@ static void xhci_events_update(XHCIState *xhci)
c8dfc6
         xhci->erdp_low |= ERDP_EHB;
c8dfc6
         xhci->iman |= IMAN_IP;
c8dfc6
         xhci->usbsts |= USBSTS_EINT;
c8dfc6
-        xhci_irq_update(xhci);
c8dfc6
+        xhci_intr_raise(xhci);
c8dfc6
     }
c8dfc6
 
c8dfc6
     if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) {
c8dfc6
@@ -796,7 +815,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event)
c8dfc6
     xhci->iman |= IMAN_IP;
c8dfc6
     xhci->usbsts |= USBSTS_EINT;
c8dfc6
 
c8dfc6
-    xhci_irq_update(xhci);
c8dfc6
+    xhci_intr_raise(xhci);
c8dfc6
 }
c8dfc6
 
c8dfc6
 static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
5544c1
@@ -2479,13 +2498,13 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
c8dfc6
         if (val & USBCMD_HCRST) {
c8dfc6
             xhci_reset(&xhci->pci_dev.qdev);
c8dfc6
         }
c8dfc6
-        xhci_irq_update(xhci);
c8dfc6
+        xhci_intx_update(xhci);
c8dfc6
         break;
c8dfc6
 
c8dfc6
     case 0x04: /* USBSTS */
c8dfc6
         /* these bits are write-1-to-clear */
c8dfc6
         xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
c8dfc6
-        xhci_irq_update(xhci);
c8dfc6
+        xhci_intx_update(xhci);
c8dfc6
         break;
c8dfc6
 
c8dfc6
     case 0x14: /* DNCTRL */
5544c1
@@ -2570,7 +2589,7 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
c8dfc6
         }
c8dfc6
         xhci->iman &= ~IMAN_IE;
c8dfc6
         xhci->iman |= val & IMAN_IE;
c8dfc6
-        xhci_irq_update(xhci);
c8dfc6
+        xhci_intx_update(xhci);
c8dfc6
         break;
c8dfc6
     case 0x24: /* IMOD */
c8dfc6
         xhci->imod = val;