@@ -580,6 +580,9 @@ static void record_transfer_result(struct usb_device *udev,
case COMP_SHORT_TX:
udev->status = 0;
break;
+ case COMP_TX_ERR:
+ udev->status = USB_ST_CRC_ERR;
+ break;
case COMP_STALL:
udev->status = USB_ST_STALLED;
break;
@@ -979,6 +982,10 @@ int xhci_ctrl_tx(struct usb_device *udev,
unsigned long pipe,
reset_ep(udev, ep_index);
return -EPIPE;
}
+ if (udev->status == USB_ST_CRC_ERR ) {
+ reset_ep(udev, ep_index);
+ return -EAGAIN;
+ }
/* Invalidate buffer to make it available to usb-core */
if (length > 0) {
@@ -1156,6 +1156,7 @@ static int _xhci_submit_control_msg(struct
usb_device *udev, unsigned long pipe,
{
struct xhci_ctrl *ctrl = xhci_get_ctrl(udev);
int ret = 0;
+ int soft_reset_attempt = SOFT_RESET_ATTEMPTS;
if (usb_pipetype(pipe) != PIPE_CONTROL) {
printf("non-control pipe (type=%lu)", usb_pipetype(pipe));
@@ -1178,7 +1179,16 @@ static int _xhci_submit_control_msg(struct
usb_device *udev, unsigned long pipe,
}
}
- return xhci_ctrl_tx(udev, pipe, setup, length, buffer);
+ while(soft_reset_attempt > 0)
+ {
+ ret = xhci_ctrl_tx(udev, pipe, setup, length, buffer);
+ if (ret == -EAGAIN)
+ soft_reset_attempt--;
+ else
+ return ret;
+ }
+ printf("control transfer is unsuccessful after %d attempts\n",
SOFT_RESET_ATTEMPTS);
+ return ret;
}
static int xhci_lowlevel_init(struct xhci_ctrl *ctrl)
@@ -33,6 +33,8 @@
/* Section 5.3.3 - MaxPorts */
#define MAX_HC_PORTS 255
+#define SOFT_RESET_ATTEMPTS 3
+
/* Up to 16 ms to halt an HC */
#define XHCI_MAX_HALT_USEC (16*1000)