diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-10-24 18:31:07 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2012-10-25 09:08:10 +0200 |
commit | a89e255b0cbe7c5b56348201e1c0f6d427c98fc8 (patch) | |
tree | 4f64268e2336b482a15440676396b4d6557cbe0e /hw/usb/hcd-uhci.c | |
parent | 2f2ee2689ffe8a784a86bf10fb946772748632c7 (diff) |
uhci: Don't retry on error
Since we are either dealing with emulated devices, where retrying is
not going to help, or with redirected devices where the host OS will
have already retried, don't bother retrying on failed transfers.
Also move some common/indentical code out of all the error cases
into the generic error path.
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.c | 62 |
1 files changed, 19 insertions, 43 deletions
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c index 82dd5c2358..eecd291f3d 100644 --- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -696,10 +696,6 @@ static USBDevice *uhci_find_device(UHCIState *s, uint8_t addr) static void uhci_async_complete(USBPort *port, USBPacket *packet); static void uhci_process_frame(UHCIState *s); -/* return -1 if fatal error (frame must be stopped) - 0 if TD successful - 1 if TD unsuccessful or inactive -*/ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask) { int len = 0, max_len, err, ret; @@ -742,60 +738,40 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_ out: switch(ret) { + case USB_RET_NAK: + td->ctrl |= TD_CTRL_NAK; + return TD_RESULT_NEXT_QH; + case USB_RET_STALL: td->ctrl |= TD_CTRL_STALL; - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; - } - uhci_update_irq(s); trace_usb_uhci_packet_complete_stall(async->queue->token, async->td); - return TD_RESULT_NEXT_QH; + err = TD_RESULT_NEXT_QH; + break; case USB_RET_BABBLE: td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) { - *int_mask |= 0x01; - } - uhci_update_irq(s); /* frame interrupted */ trace_usb_uhci_packet_complete_babble(async->queue->token, async->td); - return TD_RESULT_STOP_FRAME; - - case USB_RET_NAK: - td->ctrl |= TD_CTRL_NAK; - if (pid == USB_TOKEN_SETUP) - break; - return TD_RESULT_NEXT_QH; + err = TD_RESULT_STOP_FRAME; + break; case USB_RET_IOERROR: case USB_RET_NODEV: default: - break; + td->ctrl |= TD_CTRL_TIMEOUT; + td->ctrl &= ~(3 << TD_CTRL_ERROR_SHIFT); + trace_usb_uhci_packet_complete_error(async->queue->token, async->td); + err = TD_RESULT_NEXT_QH; + break; } - /* Retry the TD if error count is not zero */ - - td->ctrl |= TD_CTRL_TIMEOUT; - err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3; - if (err != 0) { - err--; - if (err == 0) { - td->ctrl &= ~TD_CTRL_ACTIVE; - s->status |= UHCI_STS_USBERR; - if (td->ctrl & TD_CTRL_IOC) - *int_mask |= 0x01; - uhci_update_irq(s); - trace_usb_uhci_packet_complete_error(async->queue->token, - async->td); - } + td->ctrl &= ~TD_CTRL_ACTIVE; + s->status |= UHCI_STS_USBERR; + if (td->ctrl & TD_CTRL_IOC) { + *int_mask |= 0x01; } - td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) | - (err << TD_CTRL_ERROR_SHIFT); - return TD_RESULT_NEXT_QH; + uhci_update_irq(s); + return err; } static int uhci_handle_td(UHCIState *s, uint32_t addr, UHCI_TD *td, |