aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/hcd-uhci.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-12-14 14:35:33 +0100
committerGerd Hoffmann <kraxel@redhat.com>2013-01-07 12:57:24 +0100
commit719c130dcaa3b1269beed71ca9cf6c43a0219b30 (patch)
treec6a59d31d6792547ea88f557b33263b4953b4bf8 /hw/usb/hcd-uhci.c
parent4a9ef2c042207e4eddbd010ccf2e1c8264d8f0d6 (diff)
uhci: Fix 1 ms delay in interrupt reporting to the guest
Re-arrange how we process frames / increase frnum / report pending interrupts, to avoid a 1 ms delay in interrupt reporting to the guest. This increases the packet throughput for cases where the guest submits a single packet, then waits for its completion then re-submits from 500 pkts / sec to 1000 pkts / sec. This impacts for example the use of redirected / virtual usb to serial convertors. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
Diffstat (limited to 'hw/usb/hcd-uhci.c')
-rw-r--r--hw/usb/hcd-uhci.c24
1 files changed, 13 insertions, 11 deletions
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 2af754b5cf..5685b9f3a9 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -1191,17 +1191,7 @@ static void uhci_frame_timer(void *opaque)
return;
}
- /* Complete the previous frame */
- if (s->pending_int_mask) {
- s->status2 |= s->pending_int_mask;
- s->status |= UHCI_STS_USBINT;
- uhci_update_irq(s);
- }
- s->pending_int_mask = 0;
-
- /* Start new frame */
- s->frnum = (s->frnum + 1) & 0x7ff;
-
+ /* Process the current frame */
trace_usb_uhci_frame_start(s->frnum);
uhci_async_validate_begin(s);
@@ -1210,6 +1200,18 @@ static void uhci_frame_timer(void *opaque)
uhci_async_validate_end(s);
+ /* The uhci spec says frnum reflects the frame currently being processed,
+ * and the guest must look at frnum - 1 on interrupt, so inc frnum now */
+ s->frnum = (s->frnum + 1) & 0x7ff;
+
+ /* Complete the previous frame */
+ if (s->pending_int_mask) {
+ s->status2 |= s->pending_int_mask;
+ s->status |= UHCI_STS_USBINT;
+ uhci_update_irq(s);
+ }
+ s->pending_int_mask = 0;
+
qemu_mod_timer(s->frame_timer, s->expire_time);
}