aboutsummaryrefslogtreecommitdiff
path: root/hw/usb/hcd-uhci.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2012-10-24 18:31:07 +0200
committerGerd Hoffmann <kraxel@redhat.com>2012-10-25 09:08:10 +0200
commita89e255b0cbe7c5b56348201e1c0f6d427c98fc8 (patch)
tree4f64268e2336b482a15440676396b4d6557cbe0e /hw/usb/hcd-uhci.c
parent2f2ee2689ffe8a784a86bf10fb946772748632c7 (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.c62
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,