aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/pci-acpi.c1
-rw-r--r--drivers/pci/pcie/aspm.c21
-rw-r--r--include/linux/pci-aspm.h5
3 files changed, 22 insertions, 5 deletions
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 24e19c594e57..d7ea699b8ddc 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -399,6 +399,7 @@ static int __init acpi_pci_init(void)
399 399
400 if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) { 400 if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
401 printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n"); 401 printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
402 pcie_clear_aspm();
402 pcie_no_aspm(); 403 pcie_no_aspm();
403 } 404 }
404 405
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 71222814c1ec..3188cd96b338 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; 71static int aspm_disabled, aspm_force, aspm_clear_state;
72static DEFINE_MUTEX(aspm_lock); 72static DEFINE_MUTEX(aspm_lock);
73static LIST_HEAD(link_list); 73static LIST_HEAD(link_list);
74 74
@@ -139,7 +139,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable)
139{ 139{
140 /* Don't enable Clock PM if the link is not Clock PM capable */ 140 /* Don't enable Clock PM if the link is not Clock PM capable */
141 if (!link->clkpm_capable && enable) 141 if (!link->clkpm_capable && enable)
142 return; 142 enable = 0;
143 /* Need nothing if the specified equals to current state */ 143 /* Need nothing if the specified equals to current state */
144 if (link->clkpm_enabled == enable) 144 if (link->clkpm_enabled == enable)
145 return; 145 return;
@@ -498,6 +498,10 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
498 struct pci_dev *child; 498 struct pci_dev *child;
499 int pos; 499 int pos;
500 u32 reg32; 500 u32 reg32;
501
502 if (aspm_clear_state)
503 return -EINVAL;
504
501 /* 505 /*
502 * Some functions in a slot might not all be PCIe functions, 506 * Some functions in a slot might not all be PCIe functions,
503 * very strange. Disable ASPM for the whole slot 507 * very strange. Disable ASPM for the whole slot
@@ -563,12 +567,15 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
563 struct pcie_link_state *link; 567 struct pcie_link_state *link;
564 int blacklist = !!pcie_aspm_sanity_check(pdev); 568 int blacklist = !!pcie_aspm_sanity_check(pdev);
565 569
566 if (aspm_disabled || !pci_is_pcie(pdev) || pdev->link_state) 570 if (!pci_is_pcie(pdev) || pdev->link_state)
567 return; 571 return;
568 if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && 572 if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
569 pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) 573 pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
570 return; 574 return;
571 575
576 if (aspm_disabled && !aspm_clear_state)
577 return;
578
572 /* VIA has a strange chipset, root port is under a bridge */ 579 /* VIA has a strange chipset, root port is under a bridge */
573 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && 580 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
574 pdev->bus->self) 581 pdev->bus->self)
@@ -641,7 +648,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
641 struct pci_dev *parent = pdev->bus->self; 648 struct pci_dev *parent = pdev->bus->self;
642 struct pcie_link_state *link, *root, *parent_link; 649 struct pcie_link_state *link, *root, *parent_link;
643 650
644 if (aspm_disabled || !pci_is_pcie(pdev) || 651 if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) ||
645 !parent || !parent->link_state) 652 !parent || !parent->link_state)
646 return; 653 return;
647 if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && 654 if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
@@ -899,6 +906,12 @@ static int __init pcie_aspm_disable(char *str)
899 906
900__setup("pcie_aspm=", pcie_aspm_disable); 907__setup("pcie_aspm=", pcie_aspm_disable);
901 908
909void pcie_clear_aspm(void)
910{
911 if (!aspm_force)
912 aspm_clear_state = 1;
913}
914
902void pcie_no_aspm(void) 915void pcie_no_aspm(void)
903{ 916{
904 if (!aspm_force) 917 if (!aspm_force)
diff --git a/include/linux/pci-aspm.h b/include/linux/pci-aspm.h
index 91ba0b338b47..ce6810512c66 100644
--- a/include/linux/pci-aspm.h
+++ b/include/linux/pci-aspm.h
@@ -27,6 +27,7 @@ extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
27extern void pcie_aspm_exit_link_state(struct pci_dev *pdev); 27extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
28extern void pcie_aspm_pm_state_change(struct pci_dev *pdev); 28extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
29extern void pci_disable_link_state(struct pci_dev *pdev, int state); 29extern void pci_disable_link_state(struct pci_dev *pdev, int state);
30extern void pcie_clear_aspm(void);
30extern void pcie_no_aspm(void); 31extern void pcie_no_aspm(void);
31#else 32#else
32static inline void pcie_aspm_init_link_state(struct pci_dev *pdev) 33static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
@@ -41,7 +42,9 @@ static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
41static inline void pci_disable_link_state(struct pci_dev *pdev, int state) 42static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
42{ 43{
43} 44}
44 45static inline void pcie_clear_aspm(void)
46{
47}
45static inline void pcie_no_aspm(void) 48static inline void pcie_no_aspm(void)
46{ 49{
47} 50}