diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-03-31 07:53:43 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-31 07:53:43 -0400 |
commit | 7bee946358c3cb957d4aa648fc5ab3cad0b232d0 (patch) | |
tree | 693061ebde2abc35ecc846e5084630d7225aaaff /drivers/pci/pci.c | |
parent | d820ac4c2fa881079e6b689d2098adce337558ae (diff) | |
parent | 15f7176eb1cccec0a332541285ee752b935c1c85 (diff) |
Merge branch 'linus' into locking-for-linus
Conflicts:
lib/Kconfig.debug
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 142 |
1 files changed, 65 insertions, 77 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 6d6120007af4..0195066251e5 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,12 +434,15 @@ 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; |
443 | 441 | ||
442 | /* Check if we're already there */ | ||
443 | if (dev->current_state == state) | ||
444 | return 0; | ||
445 | |||
444 | if (!dev->pm_cap) | 446 | if (!dev->pm_cap) |
445 | return -EIO; | 447 | return -EIO; |
446 | 448 | ||
@@ -451,10 +453,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
451 | * Can enter D0 from any state, but if we can only go deeper | 453 | * Can enter D0 from any state, but if we can only go deeper |
452 | * to sleep if we're already in a low power state | 454 | * to sleep if we're already in a low power state |
453 | */ | 455 | */ |
454 | if (dev->current_state == state) { | 456 | if (state != PCI_D0 && dev->current_state <= PCI_D3cold |
455 | /* we're already there */ | ||
456 | return 0; | ||
457 | } else if (state != PCI_D0 && dev->current_state <= PCI_D3cold | ||
458 | && dev->current_state > state) { | 457 | && dev->current_state > state) { |
459 | dev_err(&dev->dev, "invalid power transition " | 458 | dev_err(&dev->dev, "invalid power transition " |
460 | "(from state %d to %d)\n", dev->current_state, state); | 459 | "(from state %d to %d)\n", dev->current_state, state); |
@@ -481,10 +480,8 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
481 | break; | 480 | break; |
482 | case PCI_UNKNOWN: /* Boot-up */ | 481 | case PCI_UNKNOWN: /* Boot-up */ |
483 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot | 482 | if ((pmcsr & PCI_PM_CTRL_STATE_MASK) == PCI_D3hot |
484 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) { | 483 | && !(pmcsr & PCI_PM_CTRL_NO_SOFT_RESET)) |
485 | need_restore = true; | 484 | need_restore = true; |
486 | wait = true; | ||
487 | } | ||
488 | /* Fall-through: force to D0 */ | 485 | /* Fall-through: force to D0 */ |
489 | default: | 486 | default: |
490 | pmcsr = 0; | 487 | pmcsr = 0; |
@@ -494,9 +491,6 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
494 | /* enter specified state */ | 491 | /* enter specified state */ |
495 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); | 492 | pci_write_config_word(dev, dev->pm_cap + PCI_PM_CTRL, pmcsr); |
496 | 493 | ||
497 | if (!wait) | ||
498 | return 0; | ||
499 | |||
500 | /* Mandatory power management transition delays */ | 494 | /* Mandatory power management transition delays */ |
501 | /* see PCI PM 1.1 5.6.1 table 18 */ | 495 | /* see PCI PM 1.1 5.6.1 table 18 */ |
502 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) | 496 | if (state == PCI_D3hot || dev->current_state == PCI_D3hot) |
@@ -521,7 +515,7 @@ pci_raw_set_power_state(struct pci_dev *dev, pci_power_t state, bool wait) | |||
521 | if (need_restore) | 515 | if (need_restore) |
522 | pci_restore_bars(dev); | 516 | pci_restore_bars(dev); |
523 | 517 | ||
524 | if (wait && dev->bus->self) | 518 | if (dev->bus->self) |
525 | pcie_aspm_pm_state_change(dev->bus->self); | 519 | pcie_aspm_pm_state_change(dev->bus->self); |
526 | 520 | ||
527 | return 0; | 521 | return 0; |
@@ -546,6 +540,53 @@ void pci_update_current_state(struct pci_dev *dev, pci_power_t state) | |||
546 | } | 540 | } |
547 | 541 | ||
548 | /** | 542 | /** |
543 | * pci_platform_power_transition - Use platform to change device power state | ||
544 | * @dev: PCI device to handle. | ||
545 | * @state: State to put the device into. | ||
546 | */ | ||
547 | static int pci_platform_power_transition(struct pci_dev *dev, pci_power_t state) | ||
548 | { | ||
549 | int error; | ||
550 | |||
551 | if (platform_pci_power_manageable(dev)) { | ||
552 | error = platform_pci_set_power_state(dev, state); | ||
553 | if (!error) | ||
554 | pci_update_current_state(dev, state); | ||
555 | } else { | ||
556 | error = -ENODEV; | ||
557 | /* Fall back to PCI_D0 if native PM is not supported */ | ||
558 | pci_update_current_state(dev, PCI_D0); | ||
559 | } | ||
560 | |||
561 | return error; | ||
562 | } | ||
563 | |||
564 | /** | ||
565 | * __pci_start_power_transition - Start power transition of a PCI device | ||
566 | * @dev: PCI device to handle. | ||
567 | * @state: State to put the device into. | ||
568 | */ | ||
569 | static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state) | ||
570 | { | ||
571 | if (state == PCI_D0) | ||
572 | pci_platform_power_transition(dev, PCI_D0); | ||
573 | } | ||
574 | |||
575 | /** | ||
576 | * __pci_complete_power_transition - Complete power transition of a PCI device | ||
577 | * @dev: PCI device to handle. | ||
578 | * @state: State to put the device into. | ||
579 | * | ||
580 | * This function should not be called directly by device drivers. | ||
581 | */ | ||
582 | int __pci_complete_power_transition(struct pci_dev *dev, pci_power_t state) | ||
583 | { | ||
584 | return state > PCI_D0 ? | ||
585 | pci_platform_power_transition(dev, state) : -EINVAL; | ||
586 | } | ||
587 | EXPORT_SYMBOL_GPL(__pci_complete_power_transition); | ||
588 | |||
589 | /** | ||
549 | * pci_set_power_state - Set the power state of a PCI device | 590 | * pci_set_power_state - Set the power state of a PCI device |
550 | * @dev: PCI device to handle. | 591 | * @dev: PCI device to handle. |
551 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. | 592 | * @state: PCI power state (D0, D1, D2, D3hot) to put the device into. |
@@ -577,30 +618,21 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
577 | */ | 618 | */ |
578 | return 0; | 619 | return 0; |
579 | 620 | ||
580 | if (state == PCI_D0 && platform_pci_power_manageable(dev)) { | 621 | /* Check if we're already there */ |
581 | /* | 622 | if (dev->current_state == state) |
582 | * Allow the platform to change the state, for example via ACPI | 623 | return 0; |
583 | * _PR0, _PS0 and some such, but do not trust it. | 624 | |
584 | */ | 625 | __pci_start_power_transition(dev, state); |
585 | int ret = platform_pci_set_power_state(dev, PCI_D0); | 626 | |
586 | if (!ret) | ||
587 | pci_update_current_state(dev, PCI_D0); | ||
588 | } | ||
589 | /* This device is quirked not to be put into D3, so | 627 | /* This device is quirked not to be put into D3, so |
590 | don't put it in D3 */ | 628 | don't put it in D3 */ |
591 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) | 629 | if (state == PCI_D3hot && (dev->dev_flags & PCI_DEV_FLAGS_NO_D3)) |
592 | return 0; | 630 | return 0; |
593 | 631 | ||
594 | error = pci_raw_set_power_state(dev, state, true); | 632 | error = pci_raw_set_power_state(dev, state); |
595 | 633 | ||
596 | if (state > PCI_D0 && platform_pci_power_manageable(dev)) { | 634 | if (!__pci_complete_power_transition(dev, state)) |
597 | /* Allow the platform to finalize the transition */ | 635 | error = 0; |
598 | int ret = platform_pci_set_power_state(dev, state); | ||
599 | if (!ret) { | ||
600 | pci_update_current_state(dev, state); | ||
601 | error = 0; | ||
602 | } | ||
603 | } | ||
604 | 636 | ||
605 | return error; | 637 | return error; |
606 | } | 638 | } |
@@ -1231,7 +1263,7 @@ int pci_prepare_to_sleep(struct pci_dev *dev) | |||
1231 | if (target_state == PCI_POWER_ERROR) | 1263 | if (target_state == PCI_POWER_ERROR) |
1232 | return -EIO; | 1264 | return -EIO; |
1233 | 1265 | ||
1234 | pci_enable_wake(dev, target_state, true); | 1266 | pci_enable_wake(dev, target_state, device_may_wakeup(&dev->dev)); |
1235 | 1267 | ||
1236 | error = pci_set_power_state(dev, target_state); | 1268 | error = pci_set_power_state(dev, target_state); |
1237 | 1269 | ||
@@ -1381,50 +1413,6 @@ void pci_allocate_cap_save_buffers(struct pci_dev *dev) | |||
1381 | } | 1413 | } |
1382 | 1414 | ||
1383 | /** | 1415 | /** |
1384 | * pci_restore_standard_config - restore standard config registers of PCI device | ||
1385 | * @dev: PCI device to handle | ||
1386 | * | ||
1387 | * This function assumes that the device's configuration space is accessible. | ||
1388 | * If the device needs to be powered up, the function will wait for it to | ||
1389 | * change the state. | ||
1390 | */ | ||
1391 | int pci_restore_standard_config(struct pci_dev *dev) | ||
1392 | { | ||
1393 | pci_power_t prev_state; | ||
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 | |||
1406 | /* | ||
1407 | * This assumes that we won't get a bus in B2 or B3 from the BIOS, but | ||
1408 | * we've made this assumption forever and it appears to be universally | ||
1409 | * satisfied. | ||
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 | } | ||
1420 | |||
1421 | pci_update_current_state(dev, PCI_D0); | ||
1422 | |||
1423 | Restore: | ||
1424 | return dev->state_saved ? pci_restore_state(dev) : 0; | ||
1425 | } | ||
1426 | |||
1427 | /** | ||
1428 | * pci_enable_ari - enable ARI forwarding if hardware support it | 1416 | * pci_enable_ari - enable ARI forwarding if hardware support it |
1429 | * @dev: the PCI device | 1417 | * @dev: the PCI device |
1430 | */ | 1418 | */ |