dcavalca / rpms / qemu

Forked from rpms/qemu a year ago
Clone

Blame 0360-ehci-Don-t-process-too-much-frames-in-1-timer-tick.patch

c8dfc6
From d2901e4798cb106d5b265aa4e3ae05c06bf2bd1c Mon Sep 17 00:00:00 2001
c8dfc6
From: Hans de Goede <hdegoede@redhat.com>
c8dfc6
Date: Thu, 6 Sep 2012 17:10:48 +0200
c8dfc6
Subject: [PATCH 360/366] ehci: Don't process too much frames in 1 timer tick
c8dfc6
c8dfc6
The Linux ehci isoc scheduling code fills the entire schedule ahead of
c8dfc6
time minus 80 frames. If we make a large jump in where we are in the
c8dfc6
schedule, ie 40 frames, then the scheduler all of a sudden will only have
c8dfc6
40 frames left to work in, causing it to fail packet submissions
c8dfc6
with error -27 (-EFBIG).
c8dfc6
c8dfc6
Note at first I had MAX_FR_PER_TICK set to 8, which works well with newer
c8dfc6
Linux guest kernels, but not with older ones (such as the RHEL-6 kernel).
c8dfc6
c8dfc6
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
c8dfc6
---
c8dfc6
 hw/usb/hcd-ehci.c | 9 +++++++++
c8dfc6
 1 file changed, 9 insertions(+)
c8dfc6
c8dfc6
diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
c8dfc6
index 30d2b56..5398544 100644
c8dfc6
--- a/hw/usb/hcd-ehci.c
c8dfc6
+++ b/hw/usb/hcd-ehci.c
c8dfc6
@@ -140,6 +140,7 @@
c8dfc6
 #define NB_PORTS         6        // Number of downstream ports
c8dfc6
 #define BUFF_SIZE        5*4096   // Max bytes to transfer per transaction
c8dfc6
 #define MAX_QH           100      // Max allowable queue heads in a chain
c8dfc6
+#define MAX_FR_PER_TICK  4        /* Max frames to process in one timer tick */
c8dfc6
 
c8dfc6
 /*  Internal periodic / asynchronous schedule state machine states
c8dfc6
  */
c8dfc6
@@ -2460,6 +2461,14 @@ static void ehci_frame_timer(void *opaque)
c8dfc6
             DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
c8dfc6
         }
c8dfc6
 
c8dfc6
+        /*
c8dfc6
+         * Processing too much frames at once causes the Linux EHCI isoc
c8dfc6
+         * scheduling code to fail packet re-submissions with -EFBIG.
c8dfc6
+         */
c8dfc6
+        if (frames > MAX_FR_PER_TICK) {
c8dfc6
+            frames = MAX_FR_PER_TICK;
c8dfc6
+        }
c8dfc6
+
c8dfc6
         for (i = 0; i < frames; i++) {
c8dfc6
             ehci_update_frindex(ehci, 1);
c8dfc6
             ehci_advance_periodic_state(ehci);
c8dfc6
-- 
c8dfc6
1.7.12
c8dfc6