aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie/aspm.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r--drivers/pci/pcie/aspm.c58
1 files changed, 37 insertions, 21 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index cbfbab18be91..1cfbf228fbb1 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -68,7 +68,7 @@ struct pcie_link_state {
68 struct aspm_latency acceptable[8]; 68 struct aspm_latency acceptable[8];
69}; 69};
70 70
71static int aspm_disabled, aspm_force, aspm_clear_state; 71static int aspm_disabled, aspm_force;
72static bool aspm_support_enabled = true; 72static bool aspm_support_enabled = true;
73static DEFINE_MUTEX(aspm_lock); 73static DEFINE_MUTEX(aspm_lock);
74static LIST_HEAD(link_list); 74static LIST_HEAD(link_list);
@@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
500 int pos; 500 int pos;
501 u32 reg32; 501 u32 reg32;
502 502
503 if (aspm_clear_state)
504 return -EINVAL;
505
506 /* 503 /*
507 * Some functions in a slot might not all be PCIe functions, 504 * Some functions in a slot might not all be PCIe functions,
508 * very strange. Disable ASPM for the whole slot 505 * very strange. Disable ASPM for the whole slot
@@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
574 pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) 571 pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
575 return; 572 return;
576 573
577 if (aspm_disabled && !aspm_clear_state)
578 return;
579
580 /* VIA has a strange chipset, root port is under a bridge */ 574 /* VIA has a strange chipset, root port is under a bridge */
581 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && 575 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
582 pdev->bus->self) 576 pdev->bus->self)
@@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
608 * the BIOS's expectation, we'll do so once pci_enable_device() is 602 * the BIOS's expectation, we'll do so once pci_enable_device() is
609 * called. 603 * called.
610 */ 604 */
611 if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) { 605 if (aspm_policy != POLICY_POWERSAVE) {
612 pcie_config_aspm_path(link); 606 pcie_config_aspm_path(link);
613 pcie_set_clkpm(link, policy_to_clkpm_state(link)); 607 pcie_set_clkpm(link, policy_to_clkpm_state(link));
614 } 608 }
@@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
649 struct pci_dev *parent = pdev->bus->self; 643 struct pci_dev *parent = pdev->bus->self;
650 struct pcie_link_state *link, *root, *parent_link; 644 struct pcie_link_state *link, *root, *parent_link;
651 645
652 if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || 646 if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
653 !parent || !parent->link_state)
654 return; 647 return;
655 if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && 648 if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
656 (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) 649 (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
@@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
734 * pci_disable_link_state - disable pci device's link state, so the link will 727 * pci_disable_link_state - disable pci device's link state, so the link will
735 * never enter specific states 728 * never enter specific states
736 */ 729 */
737static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) 730static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
731 bool force)
738{ 732{
739 struct pci_dev *parent = pdev->bus->self; 733 struct pci_dev *parent = pdev->bus->self;
740 struct pcie_link_state *link; 734 struct pcie_link_state *link;
741 735
742 if (aspm_disabled || !pci_is_pcie(pdev)) 736 if (aspm_disabled && !force)
737 return;
738
739 if (!pci_is_pcie(pdev))
743 return; 740 return;
741
744 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || 742 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
745 pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) 743 pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
746 parent = pdev; 744 parent = pdev;
@@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
768 766
769void pci_disable_link_state_locked(struct pci_dev *pdev, int state) 767void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
770{ 768{
771 __pci_disable_link_state(pdev, state, false); 769 __pci_disable_link_state(pdev, state, false, false);
772} 770}
773EXPORT_SYMBOL(pci_disable_link_state_locked); 771EXPORT_SYMBOL(pci_disable_link_state_locked);
774 772
775void pci_disable_link_state(struct pci_dev *pdev, int state) 773void pci_disable_link_state(struct pci_dev *pdev, int state)
776{ 774{
777 __pci_disable_link_state(pdev, state, true); 775 __pci_disable_link_state(pdev, state, true, false);
778} 776}
779EXPORT_SYMBOL(pci_disable_link_state); 777EXPORT_SYMBOL(pci_disable_link_state);
780 778
779void pcie_clear_aspm(struct pci_bus *bus)
780{
781 struct pci_dev *child;
782
783 /*
784 * Clear any ASPM setup that the firmware has carried out on this bus
785 */
786 list_for_each_entry(child, &bus->devices, bus_list) {
787 __pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
788 PCIE_LINK_STATE_L1 |
789 PCIE_LINK_STATE_CLKPM,
790 false, true);
791 }
792}
793
781static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) 794static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
782{ 795{
783 int i; 796 int i;
@@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
935static int __init pcie_aspm_disable(char *str) 948static int __init pcie_aspm_disable(char *str)
936{ 949{
937 if (!strcmp(str, "off")) { 950 if (!strcmp(str, "off")) {
951 aspm_policy = POLICY_DEFAULT;
938 aspm_disabled = 1; 952 aspm_disabled = 1;
939 aspm_support_enabled = false; 953 aspm_support_enabled = false;
940 printk(KERN_INFO "PCIe ASPM is disabled\n"); 954 printk(KERN_INFO "PCIe ASPM is disabled\n");
@@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str)
947 961
948__setup("pcie_aspm=", pcie_aspm_disable); 962__setup("pcie_aspm=", pcie_aspm_disable);
949 963
950void pcie_clear_aspm(void)
951{
952 if (!aspm_force)
953 aspm_clear_state = 1;
954}
955
956void pcie_no_aspm(void) 964void pcie_no_aspm(void)
957{ 965{
958 if (!aspm_force) 966 /*
967 * Disabling ASPM is intended to prevent the kernel from modifying
968 * existing hardware state, not to clear existing state. To that end:
969 * (a) set policy to POLICY_DEFAULT in order to avoid changing state
970 * (b) prevent userspace from changing policy
971 */
972 if (!aspm_force) {
973 aspm_policy = POLICY_DEFAULT;
959 aspm_disabled = 1; 974 aspm_disabled = 1;
975 }
960} 976}
961 977
962/** 978/**