diff options
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 3188cd96b338..eee09f756ec9 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); | ||