diff options
| -rw-r--r-- | drivers/acpi/pci_root.c | 11 | ||||
| -rw-r--r-- | drivers/pci/pci.c | 6 | ||||
| -rw-r--r-- | drivers/pci/pcie/aspm.c | 33 | ||||
| -rw-r--r-- | drivers/pci/pcie/portdrv_core.c | 5 | ||||
| -rw-r--r-- | include/linux/pci-aspm.h | 4 | ||||
| -rw-r--r-- | include/linux/pci.h | 7 |
6 files changed, 55 insertions, 11 deletions
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 85249395623..f911a2f8cc3 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
| 33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
| 34 | #include <linux/pci-acpi.h> | 34 | #include <linux/pci-acpi.h> |
| 35 | #include <linux/pci-aspm.h> | ||
| 35 | #include <linux/acpi.h> | 36 | #include <linux/acpi.h> |
| 36 | #include <linux/slab.h> | 37 | #include <linux/slab.h> |
| 37 | #include <acpi/acpi_bus.h> | 38 | #include <acpi/acpi_bus.h> |
| @@ -564,7 +565,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 564 | /* Indicate support for various _OSC capabilities. */ | 565 | /* Indicate support for various _OSC capabilities. */ |
| 565 | if (pci_ext_cfg_avail(root->bus->self)) | 566 | if (pci_ext_cfg_avail(root->bus->self)) |
| 566 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; | 567 | flags |= OSC_EXT_PCI_CONFIG_SUPPORT; |
| 567 | if (pcie_aspm_enabled()) | 568 | if (pcie_aspm_support_enabled()) |
| 568 | flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | | 569 | flags |= OSC_ACTIVE_STATE_PWR_SUPPORT | |
| 569 | OSC_CLOCK_PWR_CAPABILITY_SUPPORT; | 570 | OSC_CLOCK_PWR_CAPABILITY_SUPPORT; |
| 570 | if (pci_msi_enabled()) | 571 | if (pci_msi_enabled()) |
| @@ -591,12 +592,16 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device) | |||
| 591 | 592 | ||
| 592 | status = acpi_pci_osc_control_set(device->handle, &flags, | 593 | status = acpi_pci_osc_control_set(device->handle, &flags, |
| 593 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); | 594 | OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL); |
| 594 | if (ACPI_SUCCESS(status)) | 595 | if (ACPI_SUCCESS(status)) { |
| 595 | dev_info(root->bus->bridge, | 596 | dev_info(root->bus->bridge, |
| 596 | "ACPI _OSC control (0x%02x) granted\n", flags); | 597 | "ACPI _OSC control (0x%02x) granted\n", flags); |
| 597 | else | 598 | } else { |
| 598 | dev_dbg(root->bus->bridge, | 599 | dev_dbg(root->bus->bridge, |
| 599 | "ACPI _OSC request failed (code %d)\n", status); | 600 | "ACPI _OSC request failed (code %d)\n", status); |
| 601 | printk(KERN_INFO "Unable to assume _OSC PCIe control. " | ||
| 602 | "Disabling ASPM\n"); | ||
| 603 | pcie_no_aspm(); | ||
| 604 | } | ||
| 600 | } | 605 | } |
| 601 | 606 | ||
| 602 | pci_acpi_add_bus_pm_notifier(device, root->bus); | 607 | pci_acpi_add_bus_pm_notifier(device, root->bus); |
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index b714d787bdd..2472e7177b4 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c | |||
| @@ -740,6 +740,12 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state) | |||
| 740 | 740 | ||
| 741 | if (!__pci_complete_power_transition(dev, state)) | 741 | if (!__pci_complete_power_transition(dev, state)) |
| 742 | error = 0; | 742 | error = 0; |
| 743 | /* | ||
| 744 | * When aspm_policy is "powersave" this call ensures | ||
| 745 | * that ASPM is configured. | ||
| 746 | */ | ||
| 747 | if (!error && dev->bus->self) | ||
| 748 | pcie_aspm_powersave_config_link(dev->bus->self); | ||
| 743 | 749 | ||
| 744 | return error; | 750 | return error; |
| 745 | } | 751 | } |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 3188cd96b33..eee09f756ec 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
| @@ -69,6 +69,7 @@ struct pcie_link_state { | |||
| 69 | }; | 69 | }; |
| 70 | 70 | ||
| 71 | static int aspm_disabled, aspm_force, aspm_clear_state; | 71 | static int aspm_disabled, aspm_force, aspm_clear_state; |
| 72 | static bool aspm_support_enabled = true; | ||
| 72 | static DEFINE_MUTEX(aspm_lock); | 73 | static DEFINE_MUTEX(aspm_lock); |
| 73 | static LIST_HEAD(link_list); | 74 | static LIST_HEAD(link_list); |
| 74 | 75 | ||
| @@ -707,6 +708,28 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) | |||
| 707 | up_read(&pci_bus_sem); | 708 | up_read(&pci_bus_sem); |
| 708 | } | 709 | } |
| 709 | 710 | ||
| 711 | void pcie_aspm_powersave_config_link(struct pci_dev *pdev) | ||
| 712 | { | ||
| 713 | struct pcie_link_state *link = pdev->link_state; | ||
| 714 | |||
| 715 | if (aspm_disabled || !pci_is_pcie(pdev) || !link) | ||
| 716 | return; | ||
| 717 | |||
| 718 | if (aspm_policy != POLICY_POWERSAVE) | ||
| 719 | return; | ||
| 720 | |||
| 721 | if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && | ||
| 722 | (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) | ||
| 723 | return; | ||
| 724 | |||
| 725 | down_read(&pci_bus_sem); | ||
| 726 | mutex_lock(&aspm_lock); | ||
| 727 | pcie_config_aspm_path(link); | ||
| 728 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); | ||
| 729 | mutex_unlock(&aspm_lock); | ||
| 730 | up_read(&pci_bus_sem); | ||
| 731 | } | ||
| 732 | |||
| 710 | /* | 733 | /* |
| 711 | * pci_disable_link_state - disable pci device's link state, so the link will | 734 | * pci_disable_link_state - disable pci device's link state, so the link will |
| 712 | * never enter specific states | 735 | * never enter specific states |
| @@ -747,6 +770,8 @@ static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) | |||
| 747 | int i; | 770 | int i; |
| 748 | struct pcie_link_state *link; | 771 | struct pcie_link_state *link; |
| 749 | 772 | ||
| 773 | if (aspm_disabled) | ||
| 774 | return -EPERM; | ||
| 750 | for (i = 0; i < ARRAY_SIZE(policy_str); i++) | 775 | for (i = 0; i < ARRAY_SIZE(policy_str); i++) |
| 751 | if (!strncmp(val, policy_str[i], strlen(policy_str[i]))) | 776 | if (!strncmp(val, policy_str[i], strlen(policy_str[i]))) |
| 752 | break; | 777 | break; |
| @@ -801,6 +826,8 @@ static ssize_t link_state_store(struct device *dev, | |||
| 801 | struct pcie_link_state *link, *root = pdev->link_state->root; | 826 | struct pcie_link_state *link, *root = pdev->link_state->root; |
| 802 | u32 val = buf[0] - '0', state = 0; | 827 | u32 val = buf[0] - '0', state = 0; |
| 803 | 828 | ||
| 829 | if (aspm_disabled) | ||
| 830 | return -EPERM; | ||
| 804 | if (n < 1 || val > 3) | 831 | if (n < 1 || val > 3) |
| 805 | return -EINVAL; | 832 | return -EINVAL; |
| 806 | 833 | ||
| @@ -896,6 +923,7 @@ static int __init pcie_aspm_disable(char *str) | |||
| 896 | { | 923 | { |
| 897 | if (!strcmp(str, "off")) { | 924 | if (!strcmp(str, "off")) { |
| 898 | aspm_disabled = 1; | 925 | aspm_disabled = 1; |
| 926 | aspm_support_enabled = false; | ||
| 899 | printk(KERN_INFO "PCIe ASPM is disabled\n"); | 927 | printk(KERN_INFO "PCIe ASPM is disabled\n"); |
| 900 | } else if (!strcmp(str, "force")) { | 928 | } else if (!strcmp(str, "force")) { |
| 901 | aspm_force = 1; | 929 | aspm_force = 1; |
| @@ -930,3 +958,8 @@ int pcie_aspm_enabled(void) | |||
| 930 | } | 958 | } |
| 931 | EXPORT_SYMBOL(pcie_aspm_enabled); | 959 | EXPORT_SYMBOL(pcie_aspm_enabled); |
| 932 | 960 | ||
| 961 | bool pcie_aspm_support_enabled(void) | ||
| 962 | { | ||
| 963 | return aspm_support_enabled; | ||
| 964 | } | ||
| 965 | EXPORT_SYMBOL(pcie_aspm_support_enabled); | ||
diff --git a/drivers/pci/pcie/portdrv_core.c b/drivers/pci/pcie/portdrv_core.c index 5130d0d2239..595654a1a6a 100644 --- a/drivers/pci/pcie/portdrv_core.c +++ b/drivers/pci/pcie/portdrv_core.c | |||
| @@ -15,7 +15,6 @@ | |||
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/pcieport_if.h> | 16 | #include <linux/pcieport_if.h> |
| 17 | #include <linux/aer.h> | 17 | #include <linux/aer.h> |
| 18 | #include <linux/pci-aspm.h> | ||
| 19 | 18 | ||
| 20 | #include "../pci.h" | 19 | #include "../pci.h" |
| 21 | #include "portdrv.h" | 20 | #include "portdrv.h" |
| @@ -356,10 +355,8 @@ int pcie_port_device_register(struct pci_dev *dev) | |||
| 356 | 355 | ||
| 357 | /* Get and check PCI Express port services */ | 356 | /* Get and check PCI Express port services */ |
| 358 | capabilities = get_port_device_capability(dev); | 357 | capabilities = get_port_device_capability(dev); |
| 359 | if (!capabilities) { | 358 | if (!capabilities) |
| 360 | pcie_no_aspm(); | ||
| 361 | return 0; | 359 | return 0; |
| 362 | } | ||
| 363 | 360 | ||
| 364 | pci_set_master(dev); | 361 | pci_set_master(dev); |
| 365 | /* | 362 | /* |
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h index ce6810512c6..67cb3ae3801 100644 --- a/include/linux/pci-aspm.h +++ b/include/linux/pci-aspm.h | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | extern void pcie_aspm_init_link_state(struct pci_dev *pdev); | 26 | extern void pcie_aspm_init_link_state(struct pci_dev *pdev); |
| 27 | extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); | 27 | extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); |
| 28 | extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); | 28 | extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); |
| 29 | extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev); | ||
| 29 | extern void pci_disable_link_state(struct pci_dev *pdev, int state); | 30 | extern void pci_disable_link_state(struct pci_dev *pdev, int state); |
| 30 | extern void pcie_clear_aspm(void); | 31 | extern void pcie_clear_aspm(void); |
| 31 | extern void pcie_no_aspm(void); | 32 | extern void pcie_no_aspm(void); |
| @@ -39,6 +40,9 @@ static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev) | |||
| 39 | static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) | 40 | static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev) |
| 40 | { | 41 | { |
| 41 | } | 42 | } |
| 43 | static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev) | ||
| 44 | { | ||
| 45 | } | ||
| 42 | static inline void pci_disable_link_state(struct pci_dev *pdev, int state) | 46 | static inline void pci_disable_link_state(struct pci_dev *pdev, int state) |
| 43 | { | 47 | { |
| 44 | } | 48 | } |
diff --git a/include/linux/pci.h b/include/linux/pci.h index 16c9f2e6197..96f70d7e058 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h | |||
| @@ -1002,12 +1002,11 @@ extern bool pcie_ports_auto; | |||
| 1002 | #endif | 1002 | #endif |
| 1003 | 1003 | ||
| 1004 | #ifndef CONFIG_PCIEASPM | 1004 | #ifndef CONFIG_PCIEASPM |
| 1005 | static inline int pcie_aspm_enabled(void) | 1005 | static inline int pcie_aspm_enabled(void) { return 0; } |
| 1006 | { | 1006 | static inline bool pcie_aspm_support_enabled(void) { return false; } |
| 1007 | return 0; | ||
| 1008 | } | ||
| 1009 | #else | 1007 | #else |
| 1010 | extern int pcie_aspm_enabled(void); | 1008 | extern int pcie_aspm_enabled(void); |
| 1009 | extern bool pcie_aspm_support_enabled(void); | ||
| 1011 | #endif | 1010 | #endif |
| 1012 | 1011 | ||
| 1013 | #ifdef CONFIG_PCIEAER | 1012 | #ifdef CONFIG_PCIEAER |
