Blame 0618-xhci-add-msix-support.patch

5544c1
From b04ba21e22b2df805af8236bc462c5c403fc6ee4 Mon Sep 17 00:00:00 2001
Hans de Goede c8dfc6
From: Gerd Hoffmann <kraxel@redhat.com>
Hans de Goede c8dfc6
Date: Thu, 30 Aug 2012 12:06:59 +0200
5544c1
Subject: [PATCH] xhci: add msix support
Hans de Goede c8dfc6
Hans de Goede c8dfc6
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Hans de Goede c8dfc6
---
Hans de Goede c8dfc6
 hw/usb/hcd-xhci.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++-
Hans de Goede c8dfc6
 trace-events      |  3 +++
Hans de Goede c8dfc6
 2 files changed, 49 insertions(+), 1 deletion(-)
Hans de Goede c8dfc6
Hans de Goede c8dfc6
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
5544c1
index 1857f42..777f903 100644
Hans de Goede c8dfc6
--- a/hw/usb/hcd-xhci.c
Hans de Goede c8dfc6
+++ b/hw/usb/hcd-xhci.c
Hans de Goede c8dfc6
@@ -23,6 +23,7 @@
Hans de Goede c8dfc6
 #include "hw/usb.h"
Hans de Goede c8dfc6
 #include "hw/pci.h"
Hans de Goede c8dfc6
 #include "hw/msi.h"
Hans de Goede c8dfc6
+#include "hw/msix.h"
Hans de Goede c8dfc6
 #include "trace.h"
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 //#define DEBUG_XHCI
Hans de Goede c8dfc6
@@ -59,6 +60,8 @@
Hans de Goede c8dfc6
 #define OFF_OPER        LEN_CAP
Hans de Goede c8dfc6
 #define OFF_RUNTIME     0x1000
Hans de Goede c8dfc6
 #define OFF_DOORBELL    0x2000
Hans de Goede c8dfc6
+#define OFF_MSIX_TABLE  0x3000
Hans de Goede c8dfc6
+#define OFF_MSIX_PBA    0x3800
Hans de Goede c8dfc6
 /* must be power of 2 */
Hans de Goede c8dfc6
 #define LEN_REGS        0x4000
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -411,6 +414,7 @@ struct XHCIState {
Hans de Goede c8dfc6
     uint32_t erstba_high;
Hans de Goede c8dfc6
     uint32_t erdp_low;
Hans de Goede c8dfc6
     uint32_t erdp_high;
Hans de Goede c8dfc6
+    bool     msix_used;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     int64_t mfindex_start;
Hans de Goede c8dfc6
     QEMUTimer *mfwrap_timer;
Hans de Goede c8dfc6
@@ -437,6 +441,7 @@ typedef struct XHCIEvRingSeg {
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 enum xhci_flags {
Hans de Goede c8dfc6
     XHCI_FLAG_USE_MSI = 1,
Hans de Goede c8dfc6
+    XHCI_FLAG_USE_MSI_X,
Hans de Goede c8dfc6
 };
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
Hans de Goede c8dfc6
@@ -616,7 +621,8 @@ static void xhci_intx_update(XHCIState *xhci)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     int level = 0;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
-    if (msi_enabled(&xhci->pci_dev)) {
Hans de Goede c8dfc6
+    if (msix_enabled(&xhci->pci_dev) ||
Hans de Goede c8dfc6
+        msi_enabled(&xhci->pci_dev)) {
Hans de Goede c8dfc6
         return;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
@@ -630,6 +636,30 @@ static void xhci_intx_update(XHCIState *xhci)
Hans de Goede c8dfc6
     qemu_set_irq(xhci->irq, level);
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+static void xhci_msix_update(XHCIState *xhci)
Hans de Goede c8dfc6
+{
Hans de Goede c8dfc6
+    bool enabled;
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (!msix_enabled(&xhci->pci_dev)) {
Hans de Goede c8dfc6
+        return;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    enabled = xhci->iman & IMAN_IE;
Hans de Goede c8dfc6
+    if (enabled == xhci->msix_used) {
Hans de Goede c8dfc6
+        return;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
+    if (enabled) {
Hans de Goede c8dfc6
+        trace_usb_xhci_irq_msix_use(0);
Hans de Goede c8dfc6
+        msix_vector_use(&xhci->pci_dev, 0);
Hans de Goede c8dfc6
+        xhci->msix_used = true;
Hans de Goede c8dfc6
+    } else {
Hans de Goede c8dfc6
+        trace_usb_xhci_irq_msix_unuse(0);
Hans de Goede c8dfc6
+        msix_vector_unuse(&xhci->pci_dev, 0);
Hans de Goede c8dfc6
+        xhci->msix_used = false;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+}
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
 static void xhci_intr_raise(XHCIState *xhci)
Hans de Goede c8dfc6
 {
Hans de Goede c8dfc6
     if (!(xhci->iman & IMAN_IP) ||
Hans de Goede c8dfc6
@@ -641,6 +671,12 @@ static void xhci_intr_raise(XHCIState *xhci)
Hans de Goede c8dfc6
         return;
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
+    if (msix_enabled(&xhci->pci_dev)) {
Hans de Goede c8dfc6
+        trace_usb_xhci_irq_msix(0);
Hans de Goede c8dfc6
+        msix_notify(&xhci->pci_dev, 0);
Hans de Goede c8dfc6
+        return;
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
+
Hans de Goede c8dfc6
     if (msi_enabled(&xhci->pci_dev)) {
Hans de Goede c8dfc6
         trace_usb_xhci_irq_msi(0);
Hans de Goede c8dfc6
         msi_notify(&xhci->pci_dev, 0);
5544c1
@@ -2282,6 +2318,7 @@ static void xhci_reset(DeviceState *dev)
Hans de Goede c8dfc6
     xhci->erstba_high = 0;
Hans de Goede c8dfc6
     xhci->erdp_low = 0;
Hans de Goede c8dfc6
     xhci->erdp_high = 0;
Hans de Goede c8dfc6
+    xhci->msix_used = 0;
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     xhci->er_ep_idx = 0;
Hans de Goede c8dfc6
     xhci->er_pcs = 1;
5544c1
@@ -2590,6 +2627,7 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
Hans de Goede c8dfc6
         xhci->iman &= ~IMAN_IE;
Hans de Goede c8dfc6
         xhci->iman |= val & IMAN_IE;
Hans de Goede c8dfc6
         xhci_intx_update(xhci);
Hans de Goede c8dfc6
+        xhci_msix_update(xhci);
Hans de Goede c8dfc6
         break;
Hans de Goede c8dfc6
     case 0x24: /* IMOD */
Hans de Goede c8dfc6
         xhci->imod = val;
Hans de Goede c8dfc6
@@ -2885,6 +2923,12 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
Hans de Goede c8dfc6
     if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) {
Hans de Goede c8dfc6
         msi_init(&xhci->pci_dev, 0x70, MAXINTRS, true, false);
Hans de Goede c8dfc6
     }
Hans de Goede c8dfc6
+    if (xhci->flags & (1 << XHCI_FLAG_USE_MSI_X)) {
Hans de Goede c8dfc6
+        msix_init(&xhci->pci_dev, MAXINTRS,
Hans de Goede c8dfc6
+                  &xhci->mem, 0, OFF_MSIX_TABLE,
Hans de Goede c8dfc6
+                  &xhci->mem, 0, OFF_MSIX_PBA,
Hans de Goede c8dfc6
+                  0x90);
Hans de Goede c8dfc6
+    }
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
     return 0;
Hans de Goede c8dfc6
 }
Hans de Goede c8dfc6
@@ -2896,6 +2940,7 @@ static const VMStateDescription vmstate_xhci = {
Hans de Goede c8dfc6
 
Hans de Goede c8dfc6
 static Property xhci_properties[] = {
Hans de Goede c8dfc6
     DEFINE_PROP_BIT("msi",    XHCIState, flags, XHCI_FLAG_USE_MSI, true),
Hans de Goede c8dfc6
+    DEFINE_PROP_BIT("msix",   XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
Hans de Goede c8dfc6
     DEFINE_PROP_UINT32("p2",  XHCIState, numports_2, 4),
Hans de Goede c8dfc6
     DEFINE_PROP_UINT32("p3",  XHCIState, numports_3, 4),
Hans de Goede c8dfc6
     DEFINE_PROP_END_OF_LIST(),
Hans de Goede c8dfc6
diff --git a/trace-events b/trace-events
5544c1
index d941e78..f86bbda 100644
Hans de Goede c8dfc6
--- a/trace-events
Hans de Goede c8dfc6
+++ b/trace-events
5544c1
@@ -316,6 +316,9 @@ usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
Hans de Goede c8dfc6
 usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
Hans de Goede c8dfc6
 usb_xhci_irq_intx(uint32_t level) "level %d"
Hans de Goede c8dfc6
 usb_xhci_irq_msi(uint32_t nr) "nr %d"
Hans de Goede c8dfc6
+usb_xhci_irq_msix(uint32_t nr) "nr %d"
Hans de Goede c8dfc6
+usb_xhci_irq_msix_use(uint32_t nr) "nr %d"
Hans de Goede c8dfc6
+usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d"
Hans de Goede c8dfc6
 usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
Hans de Goede c8dfc6
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
Hans de Goede c8dfc6
 usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
Hans de Goede c8dfc6
-- 
5544c1
1.7.12.1
Hans de Goede c8dfc6