aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/core/hcd-pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/core/hcd-pci.c')
-rw-r--r--drivers/usb/core/hcd-pci.c214
1 files changed, 129 insertions, 85 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c
index 2b487d4797bd..caeb8d6d39fb 100644
--- a/drivers/usb/core/hcd-pci.c
+++ b/drivers/usb/core/hcd-pci.c
@@ -37,119 +37,123 @@
37 37
38/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */ 38/* PCI-based HCs are common, but plenty of non-PCI HCs are used too */
39 39
40#ifdef CONFIG_PM_SLEEP 40/*
41 41 * Coordinate handoffs between EHCI and companion controllers
42/* Coordinate handoffs between EHCI and companion controllers 42 * during EHCI probing and system resume.
43 * during system resume
44 */ 43 */
45 44
46static DEFINE_MUTEX(companions_mutex); 45static DECLARE_RWSEM(companions_rwsem);
47 46
48#define CL_UHCI PCI_CLASS_SERIAL_USB_UHCI 47#define CL_UHCI PCI_CLASS_SERIAL_USB_UHCI
49#define CL_OHCI PCI_CLASS_SERIAL_USB_OHCI 48#define CL_OHCI PCI_CLASS_SERIAL_USB_OHCI
50#define CL_EHCI PCI_CLASS_SERIAL_USB_EHCI 49#define CL_EHCI PCI_CLASS_SERIAL_USB_EHCI
51 50
52enum companion_action { 51static inline int is_ohci_or_uhci(struct pci_dev *pdev)
53 SET_HS_COMPANION, CLEAR_HS_COMPANION, WAIT_FOR_COMPANIONS 52{
54}; 53 return pdev->class == CL_OHCI || pdev->class == CL_UHCI;
54}
55
56typedef void (*companion_fn)(struct pci_dev *pdev, struct usb_hcd *hcd,
57 struct pci_dev *companion, struct usb_hcd *companion_hcd);
55 58
56static void companion_common(struct pci_dev *pdev, struct usb_hcd *hcd, 59/* Iterate over PCI devices in the same slot as pdev and call fn for each */
57 enum companion_action action) 60static void for_each_companion(struct pci_dev *pdev, struct usb_hcd *hcd,
61 companion_fn fn)
58{ 62{
59 struct pci_dev *companion; 63 struct pci_dev *companion;
60 struct usb_hcd *companion_hcd; 64 struct usb_hcd *companion_hcd;
61 unsigned int slot = PCI_SLOT(pdev->devfn); 65 unsigned int slot = PCI_SLOT(pdev->devfn);
62 66
63 /* Iterate through other PCI functions in the same slot. 67 /*
64 * If pdev is OHCI or UHCI then we are looking for EHCI, and 68 * Iterate through other PCI functions in the same slot.
65 * vice versa. 69 * If the function's drvdata isn't set then it isn't bound to
70 * a USB host controller driver, so skip it.
66 */ 71 */
67 companion = NULL; 72 companion = NULL;
68 for_each_pci_dev(companion) { 73 for_each_pci_dev(companion) {
69 if (companion->bus != pdev->bus || 74 if (companion->bus != pdev->bus ||
70 PCI_SLOT(companion->devfn) != slot) 75 PCI_SLOT(companion->devfn) != slot)
71 continue; 76 continue;
72
73 companion_hcd = pci_get_drvdata(companion); 77 companion_hcd = pci_get_drvdata(companion);
74 if (!companion_hcd) 78 if (!companion_hcd)
75 continue; 79 continue;
76 80 fn(pdev, hcd, companion, companion_hcd);
77 /* For SET_HS_COMPANION, store a pointer to the EHCI bus in
78 * the OHCI/UHCI companion bus structure.
79 * For CLEAR_HS_COMPANION, clear the pointer to the EHCI bus
80 * in the OHCI/UHCI companion bus structure.
81 * For WAIT_FOR_COMPANIONS, wait until the OHCI/UHCI
82 * companion controllers have fully resumed.
83 */
84
85 if ((pdev->class == CL_OHCI || pdev->class == CL_UHCI) &&
86 companion->class == CL_EHCI) {
87 /* action must be SET_HS_COMPANION */
88 dev_dbg(&companion->dev, "HS companion for %s\n",
89 dev_name(&pdev->dev));
90 hcd->self.hs_companion = &companion_hcd->self;
91
92 } else if (pdev->class == CL_EHCI &&
93 (companion->class == CL_OHCI ||
94 companion->class == CL_UHCI)) {
95 switch (action) {
96 case SET_HS_COMPANION:
97 dev_dbg(&pdev->dev, "HS companion for %s\n",
98 dev_name(&companion->dev));
99 companion_hcd->self.hs_companion = &hcd->self;
100 break;
101 case CLEAR_HS_COMPANION:
102 companion_hcd->self.hs_companion = NULL;
103 break;
104 case WAIT_FOR_COMPANIONS:
105 device_pm_wait_for_dev(&pdev->dev,
106 &companion->dev);
107 break;
108 }
109 }
110 } 81 }
111} 82}
112 83
113static void set_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd) 84/*
85 * We're about to add an EHCI controller, which will unceremoniously grab
86 * all the port connections away from its companions. To prevent annoying
87 * error messages, lock the companion's root hub and gracefully unconfigure
88 * it beforehand. Leave it locked until the EHCI controller is all set.
89 */
90static void ehci_pre_add(struct pci_dev *pdev, struct usb_hcd *hcd,
91 struct pci_dev *companion, struct usb_hcd *companion_hcd)
114{ 92{
115 mutex_lock(&companions_mutex); 93 struct usb_device *udev;
116 dev_set_drvdata(&pdev->dev, hcd); 94
117 companion_common(pdev, hcd, SET_HS_COMPANION); 95 if (is_ohci_or_uhci(companion)) {
118 mutex_unlock(&companions_mutex); 96 udev = companion_hcd->self.root_hub;
97 usb_lock_device(udev);
98 usb_set_configuration(udev, 0);
99 }
119} 100}
120 101
121static void clear_hs_companion(struct pci_dev *pdev, struct usb_hcd *hcd) 102/*
103 * Adding the EHCI controller has either succeeded or failed. Set the
104 * companion pointer accordingly, and in either case, reconfigure and
105 * unlock the root hub.
106 */
107static void ehci_post_add(struct pci_dev *pdev, struct usb_hcd *hcd,
108 struct pci_dev *companion, struct usb_hcd *companion_hcd)
122{ 109{
123 mutex_lock(&companions_mutex); 110 struct usb_device *udev;
124 dev_set_drvdata(&pdev->dev, NULL);
125 111
126 /* If pdev is OHCI or UHCI, just clear its hs_companion pointer */ 112 if (is_ohci_or_uhci(companion)) {
127 if (pdev->class == CL_OHCI || pdev->class == CL_UHCI) 113 if (dev_get_drvdata(&pdev->dev)) { /* Succeeded */
128 hcd->self.hs_companion = NULL; 114 dev_dbg(&pdev->dev, "HS companion for %s\n",
115 dev_name(&companion->dev));
116 companion_hcd->self.hs_companion = &hcd->self;
117 }
118 udev = companion_hcd->self.root_hub;
119 usb_set_configuration(udev, 1);
120 usb_unlock_device(udev);
121 }
122}
129 123
130 /* Otherwise search for companion buses and clear their pointers */ 124/*
131 else 125 * We just added a non-EHCI controller. Find the EHCI controller to
132 companion_common(pdev, hcd, CLEAR_HS_COMPANION); 126 * which it is a companion, and store a pointer to the bus structure.
133 mutex_unlock(&companions_mutex); 127 */
128static void non_ehci_add(struct pci_dev *pdev, struct usb_hcd *hcd,
129 struct pci_dev *companion, struct usb_hcd *companion_hcd)
130{
131 if (is_ohci_or_uhci(pdev) && companion->class == CL_EHCI) {
132 dev_dbg(&pdev->dev, "FS/LS companion for %s\n",
133 dev_name(&companion->dev));
134 hcd->self.hs_companion = &companion_hcd->self;
135 }
134} 136}
135 137
136static void wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd) 138/* We are removing an EHCI controller. Clear the companions' pointers. */
139static void ehci_remove(struct pci_dev *pdev, struct usb_hcd *hcd,
140 struct pci_dev *companion, struct usb_hcd *companion_hcd)
137{ 141{
138 /* Only EHCI controllers need to wait. 142 if (is_ohci_or_uhci(companion))
139 * No locking is needed because a controller cannot be resumed 143 companion_hcd->self.hs_companion = NULL;
140 * while one of its companions is getting unbound.
141 */
142 if (pdev->class == CL_EHCI)
143 companion_common(pdev, hcd, WAIT_FOR_COMPANIONS);
144} 144}
145 145
146#else /* !CONFIG_PM_SLEEP */ 146#ifdef CONFIG_PM
147 147
148static inline void set_hs_companion(struct pci_dev *d, struct usb_hcd *h) {} 148/* An EHCI controller must wait for its companions before resuming. */
149static inline void clear_hs_companion(struct pci_dev *d, struct usb_hcd *h) {} 149static void ehci_wait_for_companions(struct pci_dev *pdev, struct usb_hcd *hcd,
150static inline void wait_for_companions(struct pci_dev *d, struct usb_hcd *h) {} 150 struct pci_dev *companion, struct usb_hcd *companion_hcd)
151{
152 if (is_ohci_or_uhci(companion))
153 device_pm_wait_for_dev(&pdev->dev, &companion->dev);
154}
151 155
152#endif /* !CONFIG_PM_SLEEP */ 156#endif /* CONFIG_PM */
153 157
154/*-------------------------------------------------------------------------*/ 158/*-------------------------------------------------------------------------*/
155 159
@@ -217,7 +221,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
217 driver->description)) { 221 driver->description)) {
218 dev_dbg(&dev->dev, "controller already in use\n"); 222 dev_dbg(&dev->dev, "controller already in use\n");
219 retval = -EBUSY; 223 retval = -EBUSY;
220 goto clear_companion; 224 goto put_hcd;
221 } 225 }
222 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); 226 hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
223 if (hcd->regs == NULL) { 227 if (hcd->regs == NULL) {
@@ -244,16 +248,35 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
244 if (region == PCI_ROM_RESOURCE) { 248 if (region == PCI_ROM_RESOURCE) {
245 dev_dbg(&dev->dev, "no i/o regions available\n"); 249 dev_dbg(&dev->dev, "no i/o regions available\n");
246 retval = -EBUSY; 250 retval = -EBUSY;
247 goto clear_companion; 251 goto put_hcd;
248 } 252 }
249 } 253 }
250 254
251 pci_set_master(dev); 255 pci_set_master(dev);
252 256
253 retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED); 257 /* Note: dev_set_drvdata must be called while holding the rwsem */
258 if (dev->class == CL_EHCI) {
259 down_write(&companions_rwsem);
260 dev_set_drvdata(&dev->dev, hcd);
261 for_each_companion(dev, hcd, ehci_pre_add);
262 retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
263 if (retval != 0)
264 dev_set_drvdata(&dev->dev, NULL);
265 for_each_companion(dev, hcd, ehci_post_add);
266 up_write(&companions_rwsem);
267 } else {
268 down_read(&companions_rwsem);
269 dev_set_drvdata(&dev->dev, hcd);
270 retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
271 if (retval != 0)
272 dev_set_drvdata(&dev->dev, NULL);
273 else
274 for_each_companion(dev, hcd, non_ehci_add);
275 up_read(&companions_rwsem);
276 }
277
254 if (retval != 0) 278 if (retval != 0)
255 goto unmap_registers; 279 goto unmap_registers;
256 set_hs_companion(dev, hcd);
257 280
258 if (pci_dev_run_wake(dev)) 281 if (pci_dev_run_wake(dev))
259 pm_runtime_put_noidle(&dev->dev); 282 pm_runtime_put_noidle(&dev->dev);
@@ -266,8 +289,7 @@ release_mem_region:
266 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 289 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
267 } else 290 } else
268 release_region(hcd->rsrc_start, hcd->rsrc_len); 291 release_region(hcd->rsrc_start, hcd->rsrc_len);
269clear_companion: 292put_hcd:
270 clear_hs_companion(dev, hcd);
271 usb_put_hcd(hcd); 293 usb_put_hcd(hcd);
272disable_pci: 294disable_pci:
273 pci_disable_device(dev); 295 pci_disable_device(dev);
@@ -310,14 +332,29 @@ void usb_hcd_pci_remove(struct pci_dev *dev)
310 usb_hcd_irq(0, hcd); 332 usb_hcd_irq(0, hcd);
311 local_irq_enable(); 333 local_irq_enable();
312 334
313 usb_remove_hcd(hcd); 335 /* Note: dev_set_drvdata must be called while holding the rwsem */
336 if (dev->class == CL_EHCI) {
337 down_write(&companions_rwsem);
338 for_each_companion(dev, hcd, ehci_remove);
339 usb_remove_hcd(hcd);
340 dev_set_drvdata(&dev->dev, NULL);
341 up_write(&companions_rwsem);
342 } else {
343 /* Not EHCI; just clear the companion pointer */
344 down_read(&companions_rwsem);
345 hcd->self.hs_companion = NULL;
346 usb_remove_hcd(hcd);
347 dev_set_drvdata(&dev->dev, NULL);
348 up_read(&companions_rwsem);
349 }
350
314 if (hcd->driver->flags & HCD_MEMORY) { 351 if (hcd->driver->flags & HCD_MEMORY) {
315 iounmap(hcd->regs); 352 iounmap(hcd->regs);
316 release_mem_region(hcd->rsrc_start, hcd->rsrc_len); 353 release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
317 } else { 354 } else {
318 release_region(hcd->rsrc_start, hcd->rsrc_len); 355 release_region(hcd->rsrc_start, hcd->rsrc_len);
319 } 356 }
320 clear_hs_companion(dev, hcd); 357
321 usb_put_hcd(hcd); 358 usb_put_hcd(hcd);
322 pci_disable_device(dev); 359 pci_disable_device(dev);
323} 360}
@@ -463,8 +500,15 @@ static int resume_common(struct device *dev, int event)
463 pci_set_master(pci_dev); 500 pci_set_master(pci_dev);
464 501
465 if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) { 502 if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {
466 if (event != PM_EVENT_AUTO_RESUME) 503
467 wait_for_companions(pci_dev, hcd); 504 /*
505 * Only EHCI controllers have to wait for their companions.
506 * No locking is needed because PCI controller drivers do not
507 * get unbound during system resume.
508 */
509 if (pci_dev->class == CL_EHCI && event != PM_EVENT_AUTO_RESUME)
510 for_each_companion(pci_dev, hcd,
511 ehci_wait_for_companions);
468 512
469 retval = hcd->driver->pci_resume(hcd, 513 retval = hcd->driver->pci_resume(hcd,
470 event == PM_EVENT_RESTORE); 514 event == PM_EVENT_RESTORE);