aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/core/hcd.c2
-rw-r--r--drivers/usb/core/hub.c32
-rw-r--r--drivers/usb/core/usb.c4
3 files changed, 26 insertions, 12 deletions
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index e277258df382..8969e42434b9 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -1681,7 +1681,7 @@ void usb_remove_hcd(struct usb_hcd *hcd)
1681 spin_unlock_irq (&hcd_root_hub_lock); 1681 spin_unlock_irq (&hcd_root_hub_lock);
1682 1682
1683#ifdef CONFIG_PM 1683#ifdef CONFIG_PM
1684 flush_workqueue(ksuspend_usb_wq); 1684 cancel_work_sync(&hcd->wakeup_work);
1685#endif 1685#endif
1686 1686
1687 mutex_lock(&usb_bus_list_lock); 1687 mutex_lock(&usb_bus_list_lock);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index caaa46f2dec7..24f10a19dbdb 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1158,6 +1158,30 @@ static void release_address(struct usb_device *udev)
1158 } 1158 }
1159} 1159}
1160 1160
1161#ifdef CONFIG_USB_SUSPEND
1162
1163static void usb_stop_pm(struct usb_device *udev)
1164{
1165 /* Synchronize with the ksuspend thread to prevent any more
1166 * autosuspend requests from being submitted, and decrement
1167 * the parent's count of unsuspended children.
1168 */
1169 usb_pm_lock(udev);
1170 if (udev->parent && !udev->discon_suspended)
1171 usb_autosuspend_device(udev->parent);
1172 usb_pm_unlock(udev);
1173
1174 /* Stop any autosuspend requests already submitted */
1175 cancel_rearming_delayed_work(&udev->autosuspend);
1176}
1177
1178#else
1179
1180static inline void usb_stop_pm(struct usb_device *udev)
1181{ }
1182
1183#endif
1184
1161/** 1185/**
1162 * usb_disconnect - disconnect a device (usbcore-internal) 1186 * usb_disconnect - disconnect a device (usbcore-internal)
1163 * @pdev: pointer to device being disconnected 1187 * @pdev: pointer to device being disconnected
@@ -1224,13 +1248,7 @@ void usb_disconnect(struct usb_device **pdev)
1224 *pdev = NULL; 1248 *pdev = NULL;
1225 spin_unlock_irq(&device_state_lock); 1249 spin_unlock_irq(&device_state_lock);
1226 1250
1227 /* Decrement the parent's count of unsuspended children */ 1251 usb_stop_pm(udev);
1228 if (udev->parent) {
1229 usb_pm_lock(udev);
1230 if (!udev->discon_suspended)
1231 usb_autosuspend_device(udev->parent);
1232 usb_pm_unlock(udev);
1233 }
1234 1252
1235 put_device(&udev->dev); 1253 put_device(&udev->dev);
1236} 1254}
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 80627b6a2bf9..4a6299bd0047 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -184,10 +184,6 @@ static void usb_release_dev(struct device *dev)
184 184
185 udev = to_usb_device(dev); 185 udev = to_usb_device(dev);
186 186
187#ifdef CONFIG_USB_SUSPEND
188 cancel_delayed_work(&udev->autosuspend);
189 flush_workqueue(ksuspend_usb_wq);
190#endif
191 usb_destroy_configuration(udev); 187 usb_destroy_configuration(udev);
192 usb_put_hcd(bus_to_hcd(udev->bus)); 188 usb_put_hcd(bus_to_hcd(udev->bus));
193 kfree(udev->product); 189 kfree(udev->product);