mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 03:59:52 +00:00
usb-ehci: Fix cerr tracking
cerr should only be decremented on errors which cause XactErr to be set, and when that happens the failing transaction should be retried until cerr reaches 0 and only then should USBSTS_ERRINT be set (and inactive cleared and USBSTS_INT set if requested). Since we don't have any hardware level errors (and in case of redirection the real hardware has already retried), re-trying makes no sense, so immediately set cerr to 0 on errors which set XactErr. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
2763cbc751
commit
dd54cfe0bc
@ -1291,7 +1291,7 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
|
|||||||
|
|
||||||
static void ehci_execute_complete(EHCIQueue *q)
|
static void ehci_execute_complete(EHCIQueue *q)
|
||||||
{
|
{
|
||||||
int c_err, reload;
|
int reload;
|
||||||
|
|
||||||
assert(q->async != EHCI_ASYNC_INFLIGHT);
|
assert(q->async != EHCI_ASYNC_INFLIGHT);
|
||||||
q->async = EHCI_ASYNC_NONE;
|
q->async = EHCI_ASYNC_NONE;
|
||||||
@ -1300,15 +1300,10 @@ static void ehci_execute_complete(EHCIQueue *q)
|
|||||||
q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
|
q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
|
||||||
|
|
||||||
if (q->usb_status < 0) {
|
if (q->usb_status < 0) {
|
||||||
err:
|
|
||||||
/* TO-DO: put this is in a function that can be invoked below as well */
|
|
||||||
c_err = get_field(q->qh.token, QTD_TOKEN_CERR);
|
|
||||||
c_err--;
|
|
||||||
set_field(&q->qh.token, c_err, QTD_TOKEN_CERR);
|
|
||||||
|
|
||||||
switch(q->usb_status) {
|
switch(q->usb_status) {
|
||||||
case USB_RET_NODEV:
|
case USB_RET_NODEV:
|
||||||
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
|
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
|
||||||
|
set_field(&q->qh.token, 0, QTD_TOKEN_CERR);
|
||||||
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
||||||
break;
|
break;
|
||||||
case USB_RET_STALL:
|
case USB_RET_STALL:
|
||||||
@ -1336,15 +1331,13 @@ err:
|
|||||||
assert(0);
|
assert(0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
|
||||||
|
q->usb_status = USB_RET_BABBLE;
|
||||||
|
q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
|
||||||
|
ehci_record_interrupt(q->ehci, USBSTS_ERRINT);
|
||||||
} else {
|
} else {
|
||||||
// DPRINTF("Short packet condition\n");
|
|
||||||
// TODO check 4.12 for splits
|
// TODO check 4.12 for splits
|
||||||
|
|
||||||
if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
|
|
||||||
q->usb_status = USB_RET_BABBLE;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (q->tbytes && q->pid == USB_TOKEN_IN) {
|
if (q->tbytes && q->pid == USB_TOKEN_IN) {
|
||||||
q->tbytes -= q->usb_status;
|
q->tbytes -= q->usb_status;
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user