diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-03-16 17:40:08 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2009-03-30 15:46:55 -0400 |
commit | f00a20ef46b1795c495869163a9a7333f899713a (patch) | |
tree | c5992f03dc67c1492ac06d0191024e4676f6cc5f /drivers/pci/pci.c | |
parent | 57ef80266e14ecc363380268fedc64e519047b4a (diff) |
PCI PM: Use pci_set_power_state during early resume
Once we have allowed timer interrupts to be enabled during the early
phase of resuming devices, we are now able to use the generic
pci_set_power_state() to put PCI devices into D0 at that time. Then,
the platform-specific PM code will have a chance to handle devices
that don't implement the native PCI PM or that require some
additional, platform-specific operations to be carried out to power
them up. Also, by doing this we can simplify the code quite a bit.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Acked-by: Ingo Molnar <mingo@elte.hu>
Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 48 |
1 files changed, 9 insertions, 39 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6d6120007af4..3acb1da296d5 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
@@ -426,7 +426,6 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
426 | * given PCI device | 426 | * given PCI device |
427 | * @dev: PCI device to handle. | 427 | * @dev: PCI device to handle. |
428 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | 428 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. |
429 | * @wait: If 'true', wait for the device to change its power state | ||
430 | * | 429 | * |
431 | * RETURN VALUE: | 430 | * RETURN VALUE: |
432 | * -EINVAL if the requested state is invalid. | 431 | * -EINVAL if the requested state is invalid. |
@@ -435,8 +434,7 @@ static inline int platform_pci_sleep_wake(struct pci_dev *dev, bool enable) | |||
435 | * 0 if device already is in the requested state. | 434 | * 0 if device already is in the requested state. |
436 | * 0 if device's power state has been successfully changed. | 435 | * 0 if device's power state has been successfully changed. |
437 | */ | 436 | */ |
438 | static int | 437 | static int pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state) |
439 | pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | ||
440 | { | 438 | { |
441 | u16 pmcsr; | 439 | u16 pmcsr; |
442 | bool need_restore = false; | 440 | bool need_restore = false; |
@@ -481,10 +479,8 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
481 | break; | 479 | break; |
482 | case PCI_UNKNOWN: /* Boot-up */ | 480 | case PCI_UNKNOWN: /* Boot-up */ |
483 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot | 481 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot |
484 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) { | 482 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) |
485 | need_restore = true; | 483 | need_restore = true; |
486 | wait = true; | ||
487 | } | ||
488 | /* Fall-through: force to D0 */ | 484 | /* Fall-through: force to D0 */ |
489 | default: | 485 | default: |
490 | pmcsr = 0; | 486 | pmcsr = 0; |
@@ -494,9 +490,6 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
494 | /* enter specified state */ | 490 | /* enter specified state */ |
495 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); | 491 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); |
496 | 492 | ||
497 | if (!wait) | ||
498 | return 0; | ||
499 | |||
500 | /* Mandatory power management transition delays */ | 493 | /* Mandatory power management transition delays */ |
501 | /* see PCI PM 1.1 5.6.1 table 18 */ | 494 | /* see PCI PM 1.1 5.6.1 table 18 */ |
502 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) | 495 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) |
@@ -521,7 +514,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
521 | if (need_restore) | 514 | if (need_restore) |
522 | pci_restore_bars(dev); | 515 | pci_restore_bars(dev); |
523 | 516 | ||
524 | if (wait && dev->bus->self) | 517 | if (dev->bus->self) |
525 | pcie_aspm_pm_state_change(dev->bus->self); | 518 | pcie_aspm_pm_state_change(dev->bus->self); |
526 | 519 | ||
527 | return 0; | 520 | return 0; |
@@ -591,7 +584,7 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
591 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) | 584 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) |
592 | return 0; | 585 | return 0; |
593 | 586 | ||
594 | error = pci_raw_set_power_state(dev, state, true); | 587 | error = pci_raw_set_power_state(dev, state); |
595 | 588 | ||
596 | if (state > PCI_D0 && platform_pci_power_manageable(dev)) { | 589 | if (state > PCI_D0 && platform_pci_power_manageable(dev)) { |
597 | /* Allow the platform to finalize the transition */ | 590 | /* Allow the platform to finalize the transition */ |
@@ -1390,37 +1383,14 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) | |||
1390 | */ | 1383 | */ |
1391 | int pci_restore_standard_config(struct pci_dev *dev) | 1384 | int pci_restore_standard_config(struct pci_dev *dev) |
1392 | { | 1385 | { |
1393 | pci_power_t prev_state; | 1386 | pci_update_current_state(dev, PCI_UNKNOWN); |
1394 | int error; | ||
1395 | |||
1396 | pci_update_current_state(dev, PCI_D0); | ||
1397 | |||
1398 | prev_state = dev->current_state; | ||
1399 | if (prev_state == PCI_D0) | ||
1400 | goto Restore; | ||
1401 | |||
1402 | error = pci_raw_set_power_state(dev, PCI_D0, false); | ||
1403 | if (error) | ||
1404 | return error; | ||
1405 | 1387 | ||
1406 | /* | 1388 | if (dev->current_state != PCI_D0) { |
1407 | * This assumes that we won't get a bus in B2 or B3 from the BIOS, but | 1389 | int error = pci_set_power_state(dev, PCI_D0); |
1408 | * we've made this assumption forever and it appears to be universally | 1390 | if (error) |
1409 | * satisfied. | 1391 | return error; |
1410 | */ | ||
1411 | switch(prev_state) { | ||
1412 | case PCI_D3cold: | ||
1413 | case PCI_D3hot: | ||
1414 | mdelay(pci_pm_d3_delay); | ||
1415 | break; | ||
1416 | case PCI_D2: | ||
1417 | udelay(PCI_PM_D2_DELAY); | ||
1418 | break; | ||
1419 | } | 1392 | } |
1420 | 1393 | ||
1421 | pci_update_current_state(dev, PCI_D0); | ||
1422 | |||
1423 | Restore: | ||
1424 | return dev->state_saved ? pci_restore_state(dev) : 0; | 1394 | return dev->state_saved ? pci_restore_state(dev) : 0; |
1425 | } | 1395 | } |
1426 | 1396 | ||