yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
218e99
From e25b1bfc8a6b74bf8474fe8d8e927abd1cacaa4f Mon Sep 17 00:00:00 2001
218e99
From: Gerd Hoffmann <kraxel@redhat.com>
218e99
Date: Thu, 12 Sep 2013 09:39:30 +0200
218e99
Subject: [PATCH 02/25] xhci: emulate intr endpoint intervals correctly
218e99
218e99
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
218e99
Message-id: <1378978772-21612-3-git-send-email-kraxel@redhat.com>
218e99
Patchwork-id: 54337
218e99
O-Subject: [RHEL-7 qemu-kvm PATCH 2/4] xhci: emulate intr endpoint intervals correctly
218e99
Bugzilla: 1001604
218e99
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
218e99
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
218e99
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
218e99
Respect the interval for interrupt endpoints, so we don't finish
218e99
transfers as fast as possible but at the rate configured by the guest.
218e99
218e99
Fixes guest deadlocks triggered by interrupt storms.
218e99
218e99
Cc:
218e99
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
218e99
(cherry picked from commit 4d7a81c06f5f17e019a2d3a18300500bd64f6f40)
218e99
---
218e99
 hw/usb/hcd-xhci.c | 44 +++++++++++++++++++++++++++++++++++++-------
218e99
 1 file changed, 37 insertions(+), 7 deletions(-)
218e99
218e99
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
---
218e99
 hw/usb/hcd-xhci.c |   44 +++++++++++++++++++++++++++++++++++++-------
218e99
 1 files changed, 37 insertions(+), 7 deletions(-)
218e99
218e99
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
218e99
index 55bcfc4..ccf7cc5 100644
218e99
--- a/hw/usb/hcd-xhci.c
218e99
+++ b/hw/usb/hcd-xhci.c
218e99
@@ -355,6 +355,7 @@ typedef struct XHCITransfer {
218e99
     unsigned int streamid;
218e99
     bool in_xfer;
218e99
     bool iso_xfer;
218e99
+    bool timed_xfer;
218e99
 
218e99
     unsigned int trb_count;
218e99
     unsigned int trb_alloced;
218e99
@@ -1787,6 +1788,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
218e99
 
218e99
     xfer->in_xfer = bmRequestType & USB_DIR_IN;
218e99
     xfer->iso_xfer = false;
218e99
+    xfer->timed_xfer = false;
218e99
 
218e99
     if (xhci_setup_packet(xfer) < 0) {
218e99
         return -1;
218e99
@@ -1802,6 +1804,17 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
218e99
     return 0;
218e99
 }
218e99
 
218e99
+static void xhci_calc_intr_kick(XHCIState *xhci, XHCITransfer *xfer,
218e99
+                                XHCIEPContext *epctx, uint64_t mfindex)
218e99
+{
218e99
+    uint64_t asap = ((mfindex + epctx->interval - 1) &
218e99
+                     ~(epctx->interval-1));
218e99
+    uint64_t kick = epctx->mfindex_last + epctx->interval;
218e99
+
218e99
+    assert(epctx->interval != 0);
218e99
+    xfer->mfindex_kick = MAX(asap, kick);
218e99
+}
218e99
+
218e99
 static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
218e99
                                XHCIEPContext *epctx, uint64_t mfindex)
218e99
 {
218e99
@@ -1824,8 +1837,8 @@ static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
218e99
     }
218e99
 }
218e99
 
218e99
-static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
218e99
-                                XHCIEPContext *epctx, uint64_t mfindex)
218e99
+static void xhci_check_intr_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
218e99
+                                     XHCIEPContext *epctx, uint64_t mfindex)
218e99
 {
218e99
     if (xfer->mfindex_kick > mfindex) {
218e99
         qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock) +
218e99
@@ -1850,18 +1863,30 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
218e99
     switch(epctx->type) {
218e99
     case ET_INTR_OUT:
218e99
     case ET_INTR_IN:
218e99
+        xfer->pkts = 0;
218e99
+        xfer->iso_xfer = false;
218e99
+        xfer->timed_xfer = true;
218e99
+        mfindex = xhci_mfindex_get(xhci);
218e99
+        xhci_calc_intr_kick(xhci, xfer, epctx, mfindex);
218e99
+        xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
218e99
+        if (xfer->running_retry) {
218e99
+            return -1;
218e99
+        }
218e99
+        break;
218e99
     case ET_BULK_OUT:
218e99
     case ET_BULK_IN:
218e99
         xfer->pkts = 0;
218e99
         xfer->iso_xfer = false;
218e99
+        xfer->timed_xfer = false;
218e99
         break;
218e99
     case ET_ISO_OUT:
218e99
     case ET_ISO_IN:
218e99
         xfer->pkts = 1;
218e99
         xfer->iso_xfer = true;
218e99
+        xfer->timed_xfer = true;
218e99
         mfindex = xhci_mfindex_get(xhci);
218e99
         xhci_calc_iso_kick(xhci, xfer, epctx, mfindex);
218e99
-        xhci_check_iso_kick(xhci, xfer, epctx, mfindex);
218e99
+        xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
218e99
         if (xfer->running_retry) {
218e99
             return -1;
218e99
         }
218e99
@@ -1922,13 +1947,18 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
218e99
 
218e99
         trace_usb_xhci_xfer_retry(xfer);
218e99
         assert(xfer->running_retry);
218e99
-        if (xfer->iso_xfer) {
218e99
-            /* retry delayed iso transfer */
218e99
+        if (xfer->timed_xfer) {
218e99
+            /* time to kick the transfer? */
218e99
             mfindex = xhci_mfindex_get(xhci);
218e99
-            xhci_check_iso_kick(xhci, xfer, epctx, mfindex);
218e99
+            xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);
218e99
             if (xfer->running_retry) {
218e99
                 return;
218e99
             }
218e99
+            xfer->timed_xfer = 0;
218e99
+            xfer->running_retry = 1;
218e99
+        }
218e99
+        if (xfer->iso_xfer) {
218e99
+            /* retry iso transfer */
218e99
             if (xhci_setup_packet(xfer) < 0) {
218e99
                 return;
218e99
             }
218e99
@@ -2014,7 +2044,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
218e99
                 epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
218e99
                 ep = xfer->packet.ep;
218e99
             } else {
218e99
-                if (!xfer->iso_xfer) {
218e99
+                if (!xfer->timed_xfer) {
218e99
                     fprintf(stderr, "xhci: error firing data transfer\n");
218e99
                 }
218e99
             }
218e99
-- 
218e99
1.7.1
218e99