OSDN Git Service

usb: dwc2: host: kill remaining urbs using -ECONNRESET status
authorGregory Herrero <gregory.herrero@intel.com>
Tue, 22 Sep 2015 13:16:53 +0000 (15:16 +0200)
committerFelipe Balbi <balbi@ti.com>
Thu, 1 Oct 2015 17:40:18 +0000 (12:40 -0500)
commit2e84da6e340a652e942c3513703020976b28190b
treece9eed27d1d501e5e40abab15c63039f72dfa4fd
parentdd81dd7c8178c430040dc98c8144d4998ba2f7fb
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>
drivers/usb/dwc2/hcd.c