aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core')
-rw-r--r--drivers/usb/core/driver.c8
-rw-r--r--drivers/usb/core/endpoint.c1
-rw-r--r--drivers/usb/core/hcd-pci.c127
-rw-r--r--drivers/usb/core/hub.c1
-rw-r--r--drivers/usb/core/message.c1
5 files changed, 137 insertions, 1 deletions
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 60a45f1e3a67..f2f055eb6831 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -1022,6 +1022,14 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg)
1022 goto done; 1022 goto done;
1023 } 1023 }
1024 1024
1025 /* Non-root devices on a full/low-speed bus must wait for their
1026 * companion high-speed root hub, in case a handoff is needed.
1027 */
1028 if (!(msg.event & PM_EVENT_AUTO) && udev->parent &&
1029 udev->bus->hs_companion)
1030 device_pm_wait_for_dev(&udev->dev,
1031 &udev->bus->hs_companion->root_hub->dev);
1032
1025 if (udev->quirks & USB_QUIRK_RESET_RESUME) 1033 if (udev->quirks & USB_QUIRK_RESET_RESUME)
1026 udev->reset_resume = 1; 1034 udev->reset_resume = 1;
1027 1035
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index fdfaa7885515..d26b9ea981f9 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -186,6 +186,7 @@ int usb_create_ep_devs(struct device *parent,
186 ep_dev->dev.parent = parent; 186 ep_dev->dev.parent = parent;
187 ep_dev->dev.release = ep_device_release; 187 ep_dev->dev.release = ep_device_release;
188 dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress); 188 dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress);
189 device_enable_async_suspend(&ep_dev->dev);
189 190
190 retval = device_register(&ep_dev->dev); 191 retval = device_register(&ep_dev->dev);
191 if (retval) 192 if (retval)
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 2dcf906df569..15286533c15a 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -19,6 +19,7 @@
19#include <linux/kernel.h> 19#include <linux/kernel.h>
20#include <linux/module.h> 20#include <linux/module.h>
21#include <linux/pci.h> 21#include <linux/pci.h>
22#include <linux/pm_runtime.h>
22#include <linux/usb.h> 23#include <linux/usb.h>
23 24
24#include <asm/io.h> 25#include <asm/io.h>
@@ -37,6 +38,122 @@
37 38
38/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ 39/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
39 40
41#ifdef CONFIG_PM_SLEEP
42
43/* Coordinate handoffs between EHCI and companion controllers
44 * during system resume
45 */
46
47static DEFINE_MUTEX(companions_mutex);
48
49#define CL_UHCI PCI_CLASS_SERIAL_USB_UHCI
50#define CL_OHCI PCI_CLASS_SERIAL_USB_OHCI
51#define CL_EHCI PCI_CLASS_SERIAL_USB_EHCI
52
53enum companion_action {
54 SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS
55};
56
57static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd,
58 enum companion_action action)
59{
60 struct pci_dev *companion;
61 struct usb_hcd *companion_hcd;
62 unsigned int slot = PCI_SLOT(pdev->devfn);
63
64 /* Iterate through other PCI functions in the same slot.
65 * If pdev is OHCI or UHCI then we are looking for EHCI, and
66 * vice versa.
67 */
68 companion = NULL;
69 for (;;) {
70 companion = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, companion);
71 if (!companion)
72 break;
73 if (companion->bus != pdev->bus ||
74 PCI_SLOT(companion->devfn) != slot)
75 continue;
76
77 companion_hcd = pci_get_drvdata(companion);
78 if (!companion_hcd)
79 continue;
80
81 /* For SET_HS_COMPANION, store a pointer to the EHCI bus in
82 * the OHCI/UHCI companion bus structure.
83 * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
84 * in the OHCI/UHCI companion bus structure.
85 * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
86 * companion controllers have fully resumed.
87 */
88
89 if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
90 companion->class == CL_EHCI) {
91 /* action must be SET_HS_COMPANION */
92 dev_dbg(&companion->dev, "HS companion for %s\n",
93 dev_name(&pdev->dev));
94 hcd->self.hs_companion = &companion_hcd->self;
95
96 } else if (pdev->class == CL_EHCI &&
97 (companion->class == CL_OHCI ||
98 companion->class == CL_UHCI)) {
99 switch (action) {
100 case SET_HS_COMPANION:
101 dev_dbg(&pdev->dev, "HS companion for %s\n",
102 dev_name(&companion->dev));
103 companion_hcd->self.hs_companion = &hcd->self;
104 break;
105 case CLEAR_HS_COMPANION:
106 companion_hcd->self.hs_companion = NULL;
107 break;
108 case WAIT_FOR_COMPANIONS:
109 device_pm_wait_for_dev(&pdev->dev,
110 &companion->dev);
111 break;
112 }
113 }
114 }
115}
116
117static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
118{
119 mutex_lock(&companions_mutex);
120 dev_set_drvdata(&pdev->dev, hcd);
121 companion_common(pdev, hcd, SET_HS_COMPANION);
122 mutex_unlock(&companions_mutex);
123}
124
125static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd)
126{
127 mutex_lock(&companions_mutex);
128 dev_set_drvdata(&pdev->dev, NULL);
129
130 /* If pdev is OHCI or UHCI, just clear its hs_companion pointer */
131 if (pdev->class == CL_OHCI || pdev->class == CL_UHCI)
132 hcd->self.hs_companion = NULL;
133
134 /* Otherwise search for companion buses and clear their pointers */
135 else
136 companion_common(pdev, hcd, CLEAR_HS_COMPANION);
137 mutex_unlock(&companions_mutex);
138}
139
140static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd)
141{
142 /* Only EHCI controllers need to wait.
143 * No locking is needed because a controller cannot be resumed
144 * while one of its companions is getting unbound.
145 */
146 if (pdev->class == CL_EHCI)
147 companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
148}
149
150#else /* !CONFIG_PM_SLEEP */
151
152static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
153static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {}
154static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {}
155
156#endif /* !CONFIG_PM_SLEEP */
40 157
41/*-------------------------------------------------------------------------*/ 158/*-------------------------------------------------------------------------*/
42 159
@@ -123,7 +240,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
123 if (region == PCI_ROM_RESOURCE) { 240 if (region == PCI_ROM_RESOURCE) {
124 dev_dbg(&dev->dev, "no i/o regions available\n"); 241 dev_dbg(&dev->dev, "no i/o regions available\n");
125 retval = -EBUSY; 242 retval = -EBUSY;
126 goto err1; 243 goto err2;
127 } 244 }
128 } 245 }
129 246
@@ -132,6 +249,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
132 retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); 249 retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED);
133 if (retval != 0) 250 if (retval != 0)
134 goto err4; 251 goto err4;
252 set_hs_companion(dev, hcd);
135 return retval; 253 return retval;
136 254
137 err4: 255 err4:
@@ -142,6 +260,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
142 } else 260 } else
143 release_region(hcd->rsrc_start, hcd->rsrc_len); 261 release_region(hcd->rsrc_start, hcd->rsrc_len);
144 err2: 262 err2:
263 clear_hs_companion(dev, hcd);
145 usb_put_hcd(hcd); 264 usb_put_hcd(hcd);
146 err1: 265 err1:
147 pci_disable_device(dev); 266 pci_disable_device(dev);
@@ -180,6 +299,7 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
180 } else { 299 } else {
181 release_region(hcd->rsrc_start, hcd->rsrc_len); 300 release_region(hcd->rsrc_start, hcd->rsrc_len);
182 } 301 }
302 clear_hs_companion(dev, hcd);
183 usb_put_hcd(hcd); 303 usb_put_hcd(hcd);
184 pci_disable_device(dev); 304 pci_disable_device(dev);
185} 305}
@@ -344,6 +464,11 @@ static int resume_common(struct device *dev, bool hibernated)
344 clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); 464 clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags);
345 465
346 if (hcd->driver->pci_resume) { 466 if (hcd->driver->pci_resume) {
467 /* This call should be made only during system resume,
468 * not during runtime resume.
469 */
470 wait_for_companions(pci_dev, hcd);
471
347 retval = hcd->driver->pci_resume(hcd, hibernated); 472 retval = hcd->driver->pci_resume(hcd, hibernated);
348 if (retval) { 473 if (retval) {
349 dev_err(dev, "PCI post-resume error %d!\n", retval); 474 dev_err(dev, "PCI post-resume error %d!\n", retval);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 35cc8b9ba1f5..20ecb4cec8de 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -1817,6 +1817,7 @@ int usb_new_device(struct usb_device *udev)
1817 /* Tell the world! */ 1817 /* Tell the world! */
1818 announce_device(udev); 1818 announce_device(udev);
1819 1819
1820 device_enable_async_suspend(&udev->dev);
1820 /* Register the device. The device driver is responsible 1821 /* Register the device. The device driver is responsible
1821 * for configuring the device and invoking the add-device 1822 * for configuring the device and invoking the add-device
1822 * notifier chain (used by usbfs and possibly others). 1823 * notifier chain (used by usbfs and possibly others).
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 9bc95fec793f..df73574a9cc9 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1867,6 +1867,7 @@ free_interfaces:
1867 "adding %s (config #%d, interface %d)\n", 1867 "adding %s (config #%d, interface %d)\n",
1868 dev_name(&intf->dev), configuration, 1868 dev_name(&intf->dev), configuration,
1869 intf->cur_altsetting->desc.bInterfaceNumber); 1869 intf->cur_altsetting->desc.bInterfaceNumber);
1870 device_enable_async_suspend(&intf->dev);
1870 ret = device_add(&intf->dev); 1871 ret = device_add(&intf->dev);
1871 if (ret != 0) { 1872 if (ret != 0) {
1872 dev_err(&dev->dev, "device_add(%s) --> %d\n", 1873 dev_err(&dev->dev, "device_add(%s) --> %d\n",