Blame 0617-xhci-rework-interrupt-handling.patch

5544c1
From 3bf435b656390f75ce8b8990f7484efb162472c9 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
5544c1
index d2e6ee6..1857f42 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;
c8dfc6
-- 
5544c1
1.7.12.1
c8dfc6