aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
authorMatthew Garrett <mjg@redhat.com>2010-12-06 14:00:56 -0500
committerJesse Barnes <jbarnes@virtuousgeek.org>2010-12-23 15:53:08 -0500
commit2f671e2dbff6eb5ef4e2600adbec550c13b8fe72 (patch)
treefb5debb042218dcf1cbdf11eb4d8d603208c219f /drivers/pci
parent8d805286968811223cca002134ba3d81244d5313 (diff)
PCI: Disable ASPM if BIOS asks us to
We currently refuse to touch the ASPM registers if the BIOS tells us that ASPM isn't supported. This can cause problems if the BIOS has (for any reason) enabled ASPM on some devices anyway. Change the code such that we explicitly clear ASPM if the FADT indicates that ASPM isn't supported, and make sure we tidy up appropriately on device removal in order to deal with the hotplug case. If ASPM is disabled because the BIOS doesn't hand over control then we won't touch the registers. Signed-off-by: Matthew Garrett <mjg@redhat.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pci-acpi.c1
-rw-r--r--drivers/pci/pcie/aspm.c21
2 files changed, 18 insertions, 4 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)