avoid using list_for_each_entry_safe when closing endpoints to prevent potential infinite loop
list_for_each_entry_safe is only safe when the current entry is being removed. If other entries in the list could potentially be removed it can result in an infinite loop. Because usbh_lld_ep_close blocks on each urb during iteration, it may give up its lock on the system and allow an interrupt to remove a different urb from the list, resulting in an infinite loop when the thread resumes.
This commit is contained in:
parent
ca79ff2e87
commit
40769f9bd3
|
@ -594,9 +594,10 @@ void usbh_lld_ep_open(usbh_ep_t *ep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void usbh_lld_ep_close(usbh_ep_t *ep) {
|
void usbh_lld_ep_close(usbh_ep_t *ep) {
|
||||||
usbh_urb_t *urb, *tmp;
|
usbh_urb_t *urb;
|
||||||
uinfof("\t%s: Closing EP...", ep->name);
|
uinfof("\t%s: Closing EP...", ep->name);
|
||||||
list_for_each_entry_safe(urb, usbh_urb_t, tmp, &ep->urb_list, node) {
|
while (!list_empty(&ep->urb_list)) {
|
||||||
|
urb = list_first_entry(&ep->urb_list, usbh_urb_t, node);
|
||||||
uinfof("\t%s: Abort URB, USBH_URBSTATUS_DISCONNECTED", ep->name);
|
uinfof("\t%s: Abort URB, USBH_URBSTATUS_DISCONNECTED", ep->name);
|
||||||
_usbh_urb_abort_and_waitS(urb, USBH_URBSTATUS_DISCONNECTED);
|
_usbh_urb_abort_and_waitS(urb, USBH_URBSTATUS_DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue