aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hcd.c')
-rw-r--r--drivers/usb/core/hcd.c44
1 files changed, 29 insertions, 15 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 975d7c1288e3..94d22551fc1b 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1878,23 +1878,10 @@ rescan:
1878 /* kick hcd */ 1878 /* kick hcd */
1879 unlink1(hcd, urb, -ESHUTDOWN); 1879 unlink1(hcd, urb, -ESHUTDOWN);
1880 dev_dbg (hcd->self.controller, 1880 dev_dbg (hcd->self.controller,
1881 "shutdown urb %pK ep%d%s%s\n", 1881 "shutdown urb %pK ep%d%s-%s\n",
1882 urb, usb_endpoint_num(&ep->desc), 1882 urb, usb_endpoint_num(&ep->desc),
1883 is_in ? "in" : "out", 1883 is_in ? "in" : "out",
1884 ({ char *s; 1884 usb_ep_type_string(usb_endpoint_type(&ep->desc)));
1885
1886 switch (usb_endpoint_type(&ep->desc)) {
1887 case USB_ENDPOINT_XFER_CONTROL:
1888 s = ""; break;
1889 case USB_ENDPOINT_XFER_BULK:
1890 s = "-bulk"; break;
1891 case USB_ENDPOINT_XFER_INT:
1892 s = "-intr"; break;
1893 default:
1894 s = "-iso"; break;
1895 };
1896 s;
1897 }));
1898 usb_put_urb (urb); 1885 usb_put_urb (urb);
1899 1886
1900 /* list contents may have changed */ 1887 /* list contents may have changed */
@@ -2448,6 +2435,19 @@ EXPORT_SYMBOL_GPL(usb_hcd_irq);
2448 2435
2449/*-------------------------------------------------------------------------*/ 2436/*-------------------------------------------------------------------------*/
2450 2437
2438/* Workqueue routine for when the root-hub has died. */
2439static void hcd_died_work(struct work_struct *work)
2440{
2441 struct usb_hcd *hcd = container_of(work, struct usb_hcd, died_work);
2442 static char *env[] = {
2443 "ERROR=DEAD",
2444 NULL
2445 };
2446
2447 /* Notify user space that the host controller has died */
2448 kobject_uevent_env(&hcd->self.root_hub->dev.kobj, KOBJ_OFFLINE, env);
2449}
2450
2451/** 2451/**
2452 * usb_hc_died - report abnormal shutdown of a host controller (bus glue) 2452 * usb_hc_died - report abnormal shutdown of a host controller (bus glue)
2453 * @hcd: pointer to the HCD representing the controller 2453 * @hcd: pointer to the HCD representing the controller
@@ -2488,6 +2488,13 @@ void usb_hc_died (struct usb_hcd *hcd)
2488 usb_kick_hub_wq(hcd->self.root_hub); 2488 usb_kick_hub_wq(hcd->self.root_hub);
2489 } 2489 }
2490 } 2490 }
2491
2492 /* Handle the case where this function gets called with a shared HCD */
2493 if (usb_hcd_is_primary_hcd(hcd))
2494 schedule_work(&hcd->died_work);
2495 else
2496 schedule_work(&hcd->primary_hcd->died_work);
2497
2491 spin_unlock_irqrestore (&hcd_root_hub_lock, flags); 2498 spin_unlock_irqrestore (&hcd_root_hub_lock, flags);
2492 /* Make sure that the other roothub is also deallocated. */ 2499 /* Make sure that the other roothub is also deallocated. */
2493} 2500}
@@ -2555,6 +2562,8 @@ struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
2555 INIT_WORK(&hcd->wakeup_work, hcd_resume_work); 2562 INIT_WORK(&hcd->wakeup_work, hcd_resume_work);
2556#endif 2563#endif
2557 2564
2565 INIT_WORK(&hcd->died_work, hcd_died_work);
2566
2558 hcd->driver = driver; 2567 hcd->driver = driver;
2559 hcd->speed = driver->flags & HCD_MASK; 2568 hcd->speed = driver->flags & HCD_MASK;
2560 hcd->product_desc = (driver->product_desc) ? driver->product_desc : 2569 hcd->product_desc = (driver->product_desc) ? driver->product_desc :
@@ -2908,6 +2917,7 @@ error_create_attr_group:
2908#ifdef CONFIG_PM 2917#ifdef CONFIG_PM
2909 cancel_work_sync(&hcd->wakeup_work); 2918 cancel_work_sync(&hcd->wakeup_work);
2910#endif 2919#endif
2920 cancel_work_sync(&hcd->died_work);
2911 mutex_lock(&usb_bus_idr_lock); 2921 mutex_lock(&usb_bus_idr_lock);
2912 usb_disconnect(&rhdev); /* Sets rhdev to NULL */ 2922 usb_disconnect(&rhdev); /* Sets rhdev to NULL */
2913 mutex_unlock(&usb_bus_idr_lock); 2923 mutex_unlock(&usb_bus_idr_lock);
@@ -2968,6 +2978,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
2968#ifdef CONFIG_PM 2978#ifdef CONFIG_PM
2969 cancel_work_sync(&hcd->wakeup_work); 2979 cancel_work_sync(&hcd->wakeup_work);
2970#endif 2980#endif
2981 cancel_work_sync(&hcd->died_work);
2971 2982
2972 mutex_lock(&usb_bus_idr_lock); 2983 mutex_lock(&usb_bus_idr_lock);
2973 usb_disconnect(&rhdev); /* Sets rhdev to NULL */ 2984 usb_disconnect(&rhdev); /* Sets rhdev to NULL */
@@ -3020,6 +3031,9 @@ usb_hcd_platform_shutdown(struct platform_device *dev)
3020{ 3031{
3021 struct usb_hcd *hcd = platform_get_drvdata(dev); 3032 struct usb_hcd *hcd = platform_get_drvdata(dev);
3022 3033
3034 /* No need for pm_runtime_put(), we're shutting down */
3035 pm_runtime_get_sync(&dev->dev);
3036
3023 if (hcd->driver->shutdown) 3037 if (hcd->driver->shutdown)
3024 hcd->driver->shutdown(hcd); 3038 hcd->driver->shutdown(hcd);
3025} 3039}