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); }