remove qh with iaad

This commit is contained in:
sakumisu
2024-05-08 17:17:35 +08:00
parent d0f79ff668
commit 8ecbd32483

View File

@@ -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;