summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2024-05-08 17:17:35 +0800
committersakumisu <[email protected]>2024-05-08 17:17:57 +0800
commit8ecbd3248336e6bf3c3dbc212beca7d755a88907 (patch)
tree942dbe89bade9169956c6b7d2a345f746966bd44
parentd0f79ff6689dbc39c15155dafe081116cd050923 (diff)
remove qh with iaad
-rw-r--r--port/ehci/usb_hc_ehci.c15
1 files changed, 15 insertions, 0 deletions
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;