diff --git a/port/ehci/usb_hc_ehci.c b/port/ehci/usb_hc_ehci.c index d93fefcf..ec6f2d7f 100644 --- a/port/ehci/usb_hc_ehci.c +++ b/port/ehci/usb_hc_ehci.c @@ -1208,6 +1208,7 @@ int usbh_kill_urb(struct usbh_urb *urb) struct ehci_qh_hw *qh; struct usbh_bus *bus; size_t flags; + bool remove_in_iaad = false; if (!urb || !urb->hport || !urb->hcpriv || !urb->hport->bus) { return -USB_ERR_INVAL; @@ -1229,6 +1230,7 @@ int usbh_kill_urb(struct usbh_urb *urb) qh = EHCI_ADDR2QH(g_async_qh_head[bus->hcd.hcd_id].hw.hlp); while ((qh != &g_async_qh_head[bus->hcd.hcd_id]) && qh) { if (qh->urb == urb) { + remove_in_iaad = true; ehci_kill_qh(bus, &g_async_qh_head[bus->hcd.hcd_id], qh); } qh = EHCI_ADDR2QH(qh->hw.hlp); @@ -1263,6 +1265,19 @@ int usbh_kill_urb(struct usbh_urb *urb) ehci_qh_free(bus, qh); } + if (remove_in_iaad) { + volatile uint32_t timeout = 0; + EHCI_HCOR->usbcmd |= EHCI_USBCMD_IAAD; + while (!(EHCI_HCOR->usbsts & EHCI_USBSTS_IAA)) { + usb_osal_msleep(1); + timeout++; + if (timeout > 100) { + usb_osal_leave_critical_section(flags); + return -USB_ERR_TIMEOUT; + } + } + } + usb_osal_leave_critical_section(flags); return 0;