summaryrefslogtreecommitdiff
path: root/drivers/usb/dwc2/hcd.c
diff options
context:
space:
mode:
authorGregory Herrero <gregory.herrero@intel.com>2015-09-22 15:16:53 +0200
committerFelipe Balbi <balbi@ti.com>2015-10-01 12:40:18 -0500
commit2e84da6e340a652e942c3513703020976b28190b (patch)
treece9eed27d1d501e5e40abab15c63039f72dfa4fd /drivers/usb/dwc2/hcd.c
parentdd81dd7c8178c430040dc98c8144d4998ba2f7fb (diff)
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>
Diffstat (limited to 'drivers/usb/dwc2/hcd.c')
-rw-r--r--drivers/usb/dwc2/hcd.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 397bb7d0d3c8..15a1e62ac902 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -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);
}
}