From a5022829821b27e00790f8fe2fd9cd8090a47e36 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 10 Sep 2012 12:44:11 +0200 Subject: [PATCH] ehci: Don't process too much frames in 1 timer tick (v2) The Linux ehci isoc scheduling code fills the entire schedule ahead of time minus 80 frames. If we make a large jump in where we are in the schedule, ie 40 frames, then the scheduler all of a sudden will only have 40 frames left to work in, causing it to fail packet submissions with error -27 (-EFBIG). Changes in v2: -Don't hardcode a maximum number of frames to process in one tick, instead: -Process a minimum number of frames to ensure we do eventually catch up -Stop (after the minimum number) when the guest has requested an irq Signed-off-by: Hans de Goede Signed-off-by: Gerd Hoffmann (cherry picked from commit 8f74ed1e43263293301031a10e440549bab19a6e) Signed-off-by: Michael Roth --- hw/usb/hcd-ehci.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c index 54273d7..017a01d 100644 --- a/hw/usb/hcd-ehci.c +++ b/hw/usb/hcd-ehci.c @@ -139,6 +139,7 @@ #define NB_PORTS 6 // Number of downstream ports #define BUFF_SIZE 5*4096 // Max bytes to transfer per transaction #define MAX_QH 100 // Max allowable queue heads in a chain +#define MIN_FR_PER_TICK 3 // Min frames to process when catching up /* Internal periodic / asynchronous schedule state machine states */ @@ -2448,6 +2449,19 @@ static void ehci_frame_timer(void *opaque) } for (i = 0; i < frames; i++) { + /* + * If we're running behind schedule, we should not catch up + * too fast, as that will make some guests unhappy: + * 1) We must process a minimum of MIN_FR_PER_TICK frames, + * otherwise we will never catch up + * 2) Process frames until the guest has requested an irq (IOC) + */ + if (i >= MIN_FR_PER_TICK) { + ehci_commit_irq(ehci); + if ((ehci->usbsts & USBINTR_MASK) & ehci->usbintr) { + break; + } + } ehci_update_frindex(ehci, 1); ehci_advance_periodic_state(ehci); ehci->last_run_ns += FRAME_TIMER_NS; -- 1.8.0.2