diff options
Diffstat (limited to 'drivers/usb/core/hcd-pci.c')
-rw-r--r-- | drivers/usb/core/hcd-pci.c | 117 |
1 files changed, 27 insertions, 90 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 507741ed4482..c54fc40458b1 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -128,7 +128,6 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | pci_set_master(dev); | 130 | pci_set_master(dev); |
131 | device_set_wakeup_enable(&dev->dev, 1); | ||
132 | 131 | ||
133 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); | 132 | retval = usb_add_hcd(hcd, dev->irq, IRQF_DISABLED | IRQF_SHARED); |
134 | if (retval != 0) | 133 | if (retval != 0) |
@@ -201,6 +200,7 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
201 | struct usb_hcd *hcd = pci_get_drvdata(dev); | 200 | struct usb_hcd *hcd = pci_get_drvdata(dev); |
202 | int retval = 0; | 201 | int retval = 0; |
203 | int wake, w; | 202 | int wake, w; |
203 | int has_pci_pm; | ||
204 | 204 | ||
205 | /* Root hub suspend should have stopped all downstream traffic, | 205 | /* Root hub suspend should have stopped all downstream traffic, |
206 | * and all bus master traffic. And done so for both the interface | 206 | * and all bus master traffic. And done so for both the interface |
@@ -230,6 +230,15 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
230 | 230 | ||
231 | synchronize_irq(dev->irq); | 231 | synchronize_irq(dev->irq); |
232 | 232 | ||
233 | /* Downstream ports from this root hub should already be quiesced, so | ||
234 | * there will be no DMA activity. Now we can shut down the upstream | ||
235 | * link (except maybe for PME# resume signaling) and enter some PCI | ||
236 | * low power state, if the hardware allows. | ||
237 | */ | ||
238 | pci_disable_device(dev); | ||
239 | |||
240 | pci_save_state(dev); | ||
241 | |||
233 | /* Don't fail on error to enable wakeup. We rely on pci code | 242 | /* Don't fail on error to enable wakeup. We rely on pci code |
234 | * to reject requests the hardware can't implement, rather | 243 | * to reject requests the hardware can't implement, rather |
235 | * than coding the same thing. | 244 | * than coding the same thing. |
@@ -241,35 +250,6 @@ int usb_hcd_pci_suspend(struct pci_dev *dev, pm_message_t message) | |||
241 | wake = w; | 250 | wake = w; |
242 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); | 251 | dev_dbg(&dev->dev, "wakeup: %d\n", wake); |
243 | 252 | ||
244 | /* Downstream ports from this root hub should already be quiesced, so | ||
245 | * there will be no DMA activity. Now we can shut down the upstream | ||
246 | * link (except maybe for PME# resume signaling) and enter some PCI | ||
247 | * low power state, if the hardware allows. | ||
248 | */ | ||
249 | pci_disable_device(dev); | ||
250 | done: | ||
251 | return retval; | ||
252 | } | ||
253 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); | ||
254 | |||
255 | /** | ||
256 | * usb_hcd_pci_suspend_late - suspend a PCI-based HCD after IRQs are disabled | ||
257 | * @dev: USB Host Controller being suspended | ||
258 | * @message: Power Management message describing this state transition | ||
259 | * | ||
260 | * Store this function in the HCD's struct pci_driver as .suspend_late. | ||
261 | */ | ||
262 | int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | ||
263 | { | ||
264 | int retval = 0; | ||
265 | int has_pci_pm; | ||
266 | |||
267 | /* We might already be suspended (runtime PM -- not yet written) */ | ||
268 | if (dev->current_state != PCI_D0) | ||
269 | goto done; | ||
270 | |||
271 | pci_save_state(dev); | ||
272 | |||
273 | /* Don't change state if we don't need to */ | 253 | /* Don't change state if we don't need to */ |
274 | if (message.event == PM_EVENT_FREEZE || | 254 | if (message.event == PM_EVENT_FREEZE || |
275 | message.event == PM_EVENT_PRETHAW) { | 255 | message.event == PM_EVENT_PRETHAW) { |
@@ -315,7 +295,7 @@ int usb_hcd_pci_suspend_late(struct pci_dev *dev, pm_message_t message) | |||
315 | done: | 295 | done: |
316 | return retval; | 296 | return retval; |
317 | } | 297 | } |
318 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); | 298 | EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend); |
319 | 299 | ||
320 | /** | 300 | /** |
321 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled | 301 | * usb_hcd_pci_resume_early - resume a PCI-based HCD before IRQs are enabled |
@@ -325,65 +305,8 @@ EXPORT_SYMBOL_GPL(usb_hcd_pci_suspend_late); | |||
325 | */ | 305 | */ |
326 | int usb_hcd_pci_resume_early(struct pci_dev *dev) | 306 | int usb_hcd_pci_resume_early(struct pci_dev *dev) |
327 | { | 307 | { |
328 | int retval = 0; | 308 | pci_restore_state(dev); |
329 | pci_power_t state = dev->current_state; | 309 | return 0; |
330 | |||
331 | #ifdef CONFIG_PPC_PMAC | ||
332 | /* Reenable ASIC clocks for USB */ | ||
333 | if (machine_is(powermac)) { | ||
334 | struct device_node *of_node; | ||
335 | |||
336 | of_node = pci_device_to_OF_node(dev); | ||
337 | if (of_node) | ||
338 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
339 | of_node, 0, 1); | ||
340 | } | ||
341 | #endif | ||
342 | |||
343 | /* NOTE: chip docs cover clean "real suspend" cases (what Linux | ||
344 | * calls "standby", "suspend to RAM", and so on). There are also | ||
345 | * dirty cases when swsusp fakes a suspend in "shutdown" mode. | ||
346 | */ | ||
347 | if (state != PCI_D0) { | ||
348 | #ifdef DEBUG | ||
349 | int pci_pm; | ||
350 | u16 pmcr; | ||
351 | |||
352 | pci_pm = pci_find_capability(dev, PCI_CAP_ID_PM); | ||
353 | pci_read_config_word(dev, pci_pm + PCI_PM_CTRL, &pmcr); | ||
354 | pmcr &= PCI_PM_CTRL_STATE_MASK; | ||
355 | if (pmcr) { | ||
356 | /* Clean case: power to USB and to HC registers was | ||
357 | * maintained; remote wakeup is easy. | ||
358 | */ | ||
359 | dev_dbg(&dev->dev, "resume from PCI D%d\n", pmcr); | ||
360 | } else { | ||
361 | /* Clean: HC lost Vcc power, D0 uninitialized | ||
362 | * + Vaux may have preserved port and transceiver | ||
363 | * state ... for remote wakeup from D3cold | ||
364 | * + or not; HCD must reinit + re-enumerate | ||
365 | * | ||
366 | * Dirty: D0 semi-initialized cases with swsusp | ||
367 | * + after BIOS init | ||
368 | * + after Linux init (HCD statically linked) | ||
369 | */ | ||
370 | dev_dbg(&dev->dev, "resume from previous PCI D%d\n", | ||
371 | state); | ||
372 | } | ||
373 | #endif | ||
374 | |||
375 | retval = pci_set_power_state(dev, PCI_D0); | ||
376 | } else { | ||
377 | /* Same basic cases: clean (powered/not), dirty */ | ||
378 | dev_dbg(&dev->dev, "PCI legacy resume\n"); | ||
379 | } | ||
380 | |||
381 | if (retval < 0) | ||
382 | dev_err(&dev->dev, "can't resume: %d\n", retval); | ||
383 | else | ||
384 | pci_restore_state(dev); | ||
385 | |||
386 | return retval; | ||
387 | } | 310 | } |
388 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); | 311 | EXPORT_SYMBOL_GPL(usb_hcd_pci_resume_early); |
389 | 312 | ||
@@ -398,6 +321,18 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
398 | struct usb_hcd *hcd; | 321 | struct usb_hcd *hcd; |
399 | int retval; | 322 | int retval; |
400 | 323 | ||
324 | #ifdef CONFIG_PPC_PMAC | ||
325 | /* Reenable ASIC clocks for USB */ | ||
326 | if (machine_is(powermac)) { | ||
327 | struct device_node *of_node; | ||
328 | |||
329 | of_node = pci_device_to_OF_node(dev); | ||
330 | if (of_node) | ||
331 | pmac_call_feature(PMAC_FTR_USB_ENABLE, | ||
332 | of_node, 0, 1); | ||
333 | } | ||
334 | #endif | ||
335 | |||
401 | hcd = pci_get_drvdata(dev); | 336 | hcd = pci_get_drvdata(dev); |
402 | if (hcd->state != HC_STATE_SUSPENDED) { | 337 | if (hcd->state != HC_STATE_SUSPENDED) { |
403 | dev_dbg(hcd->self.controller, | 338 | dev_dbg(hcd->self.controller, |
@@ -405,6 +340,8 @@ int usb_hcd_pci_resume(struct pci_dev *dev) | |||
405 | return 0; | 340 | return 0; |
406 | } | 341 | } |
407 | 342 | ||
343 | pci_enable_wake(dev, PCI_D0, false); | ||
344 | |||
408 | retval = pci_enable_device(dev); | 345 | retval = pci_enable_device(dev); |
409 | if (retval < 0) { | 346 | if (retval < 0) { |
410 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", | 347 | dev_err(&dev->dev, "can't re-enable after resume, %d!\n", |