summary refs log tree commit diff stats
path: root/hw/usb/hcd-xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/usb/hcd-xhci.c')
-rw-r--r--hw/usb/hcd-xhci.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 54b3901c8c..f3f95796ba 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -54,6 +54,8 @@
 #define ER_FULL_HACK
 
 #define TRB_LINK_LIMIT  4
+#define COMMAND_LIMIT   256
+#define TRANSFER_LIMIT  256
 
 #define LEN_CAP         0x40
 #define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
@@ -1032,6 +1034,7 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
             return type;
         } else {
             if (++link_cnt > TRB_LINK_LIMIT) {
+                trace_usb_xhci_enforced_limit("trb-link");
                 return 0;
             }
             ring->dequeue = xhci_mask64(trb->parameter);
@@ -2150,6 +2153,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
     XHCIRing *ring;
     USBEndpoint *ep = NULL;
     uint64_t mfindex;
+    unsigned int count = 0;
     int length;
     int i;
 
@@ -2262,6 +2266,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)
             epctx->retry = xfer;
             break;
         }
+        if (count++ > TRANSFER_LIMIT) {
+            trace_usb_xhci_enforced_limit("transfers");
+            break;
+        }
     }
     epctx->kick_active--;
 
@@ -2734,7 +2742,7 @@ static void xhci_process_commands(XHCIState *xhci)
     TRBType type;
     XHCIEvent event = {ER_COMMAND_COMPLETE, CC_SUCCESS};
     dma_addr_t addr;
-    unsigned int i, slotid = 0;
+    unsigned int i, slotid = 0, count = 0;
 
     DPRINTF("xhci_process_commands()\n");
     if (!xhci_running(xhci)) {
@@ -2848,6 +2856,11 @@ static void xhci_process_commands(XHCIState *xhci)
         }
         event.slotid = slotid;
         xhci_event(xhci, &event, 0);
+
+        if (count++ > COMMAND_LIMIT) {
+            trace_usb_xhci_enforced_limit("commands");
+            return;
+        }
     }
 }