|
Hans de Goede |
c8dfc6 |
From 03ab86ecf677d777864a3643ec8479037d3f41cd 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
|
|
Hans de Goede |
c8dfc6 |
Subject: [PATCH 347/366] 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
|
|
Hans de Goede |
c8dfc6 |
index 5eae32e..3bac99a 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);
|
|
Hans de Goede |
c8dfc6 |
@@ -2284,6 +2320,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;
|
|
Hans de Goede |
c8dfc6 |
@@ -2592,6 +2629,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
|
|
Hans de Goede |
c8dfc6 |
index 5bc591a..8589ca4 100644
|
|
Hans de Goede |
c8dfc6 |
--- a/trace-events
|
|
Hans de Goede |
c8dfc6 |
+++ b/trace-events
|
|
Hans de Goede |
c8dfc6 |
@@ -313,6 +313,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 |
--
|
|
Hans de Goede |
c8dfc6 |
1.7.12
|
|
Hans de Goede |
c8dfc6 |
|