summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorHemant Kumar <hemantk@codeaurora.org>2016-10-03 11:32:10 -0700
committerHemant Kumar <hemantk@codeaurora.org>2016-10-06 10:47:24 -0700
commit20caa4fd629eb30220ef6c4973802123ecd8a01a (patch)
treeb7320912d42ad3a655d00474d083da291404058b /include/linux
parent0b3886773c113fe0ad5748d8f5a9d1648fafdee2 (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.h2
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);