From 20caa4fd629eb30220ef6c4973802123ecd8a01a Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Mon, 3 Oct 2016 11:32:10 -0700 Subject: 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 --- include/linux/usb/hcd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') 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); -- cgit v1.2.3