diff options
| author | Hemant Kumar <hemantk@codeaurora.org> | 2016-10-03 11:32:10 -0700 |
|---|---|---|
| committer | Hemant Kumar <hemantk@codeaurora.org> | 2016-10-06 10:47:24 -0700 |
| commit | 20caa4fd629eb30220ef6c4973802123ecd8a01a (patch) | |
| tree | b7320912d42ad3a655d00474d083da291404058b /include/linux | |
| parent | 0b3886773c113fe0ad5748d8f5a9d1648fafdee2 (diff) | |
usb: host: Flush hub workqueue before stopping controller
when xhci platform driver is removed with a usb device
connected there is a possibility of race between xhci
platform driver remove context and device disconnect hub
event work context. This results into
use after free: xhci_mem_clean() called from xhci_plat_remove()
freeing the xhci virtual device when a structure member is
being accessed by xhci_alloc_virt_device() after virtual device
allocation as part of connect hub event.
deadlock: Upon device disconnect if stop endpoint command remains
pending xhci_mem_cleanup() frees xhci virtual device which also
frees up endpoint stop_cmd_timer. udev->dev lock is held until
cancelled urb is not given back to class driver. In a different
context xhci platform remove calls usb_disconnect() on children of
root hub which tries to acquire the same udev->dev lock this results
into a dead lock condition.
Fix issues by making sure hub events are flushed before xhci is
stopped.
Change-Id: I86d414bca17464d1dff3346ec668d8b3efec1652
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/usb/hcd.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index 3740366d9fc5..cef429cf3dce 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -502,7 +502,7 @@ extern void usb_hc_died(struct usb_hcd *hcd); extern void usb_hcd_poll_rh_status(struct usb_hcd *hcd); extern void usb_wakeup_notification(struct usb_device *hdev, unsigned int portnum); - +extern void usb_flush_hub_wq(void); extern void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum); extern void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum); |
