usb: dwc2: host: kill remaining urbs using -ECONNRESET status
On a disconnect, dwc2 will kill all remaining urbs from qh list. urbs are given back to hcd with -ETIMEDOUT status. Some usb device driver, like mass storage, will unlink all urbs using usb_hcd_unlink_urb when receiving a negative status different from -ECONNRESET. The following flow will then happen: dwc2_hcd_disconnect() -> dwc2_kill_all_urbs() try to kill first pending urb. -> dwc2_host_complete(-ETIMEDOUT) -> usb_hcd_giveback_urb(-ETIMEDOUT) -> sg_complete() -> usb_unlink_urb() -> usb_put_dev(urb->dev) -> dwc2_kill_all_urbs() try to kill next pending urb. -> dwc2_host_complete(-ETIMEDOUT) -> usb_hcd_giveback_urb(-ETIMEDOUT) -> NULL pointer dereferencing because urb->dev has been freed for all urbs of this device. The root cause of this NULL pointer is to call call usb_unlink_urb() while we are killing all urbs. To avoid this return urb with -ECONNRESET status This issue usually happens while removing mass storage device during transfer. Signed-off-by: Gregory Herrero <gregory.herrero@intel.com> Signed-off-by: Mian Yousaf Kaukab <yousaf.kaukab@intel.com> Tested-by: Robert Baldyga <r.baldyga@samsung.com> Tested-by: Dinh Nguyen <dinguyen@opensource.altera.com> Tested-by: John Youn <johnyoun@synopsys.com> Acked-by: John Youn <johnyoun@synopsys.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
parent
dd81dd7c81
commit
2e84da6e34
@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg *hsotg,
|
||||
list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
|
||||
list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
|
||||
qtd_list_entry) {
|
||||
dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
|
||||
dwc2_host_complete(hsotg, qtd, -ECONNRESET);
|
||||
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user