aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/pcie
diff options
context:
space:
mode:
authorNaga Chumbalkar <nagananda.chumbalkar@hp.com>2011-03-20 23:29:14 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2011-03-21 12:40:57 -0400
commitbbfa306a1e5d9618231aa0de3d52a8eb1219d0c3 (patch)
tree8228863e124a9733eefb30845e6a2d01617de69e /drivers/pci/pcie
parent1a680b7c325882188865f05b9a88d32f75f26495 (diff)
PCI: Changing ASPM policy, via /sys, to POWERSAVE could cause NMIs
v3 -> v2: Modified the text that describes the problem v2 -> v1: Returned -EPERM v1 : http://marc.info/?l=linux-pci&m=130013194803727&w=2 For servers whose hardware cannot handle ASPM the BIOS ought to set the FADT bit shown below: In Sec 5.2.9.3 (IA-PC Boot Arch. Flags) of ACPI4.0a Specification, please see Table 5-11: PCIe ASPM Controls: If set, indicates to OSPM that it must not enable OPSM ASPM control on this platform. However there are shipping servers whose BIOS did not set this bit. (An example is the HP ProLiant DL385 G6. A Maintenance BIOS will fix that). For such servers even if a call is made via pci_no_aspm(), based on _OSC support in the BIOS, it may be too late because the ASPM code may have already allocated and filled its "link_list". So if a user sets the ASPM "policy" to "powersave" via /sys then pcie_aspm_set_policy() will run through the "link_list" and re-configure ASPM policy on devices that advertise ASPM L0s/L1 capability: # echo powersave > /sys/module/pcie_aspm/parameters/policy # cat /sys/module/pcie_aspm/parameters/policy default performance [powersave] That can cause NMIs since the hardware doesn't play well with ASPM: [ 1651.906015] NMI: PCI system error (SERR) for reason b1 on CPU 0. [ 1651.906015] Dazed and confused, but trying to continue Ideally, the BIOS should have set that FADT bit in the first place but we could be more robust - especially given the fact that Windows doesn't cause NMIs in the above scenario. There should be a sanity check to not allow a user to modify ASPM policy when aspm_disabled is set. Signed-off-by: Naga Chumbalkar <nagananda.chumbalkar@hp.com> Acked-by: Rafael J. Wysocki <rjw@sisk.pl> Cc: Matthew Garrett <mjg59@srcf.ucam.org> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/pcie')
-rw-r--r--drivers/pci/pcie/aspm.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index e61b82e611c2..eee09f756ec9 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -770,6 +770,8 @@ static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
770 int i; 770 int i;
771 struct pcie_link_state *link; 771 struct pcie_link_state *link;
772 772
773 if (aspm_disabled)
774 return -EPERM;
773 for (i = 0; i < ARRAY_SIZE(policy_str); i++) 775 for (i = 0; i < ARRAY_SIZE(policy_str); i++)
774 if (!strncmp(val, policy_str[i], strlen(policy_str[i]))) 776 if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
775 break; 777 break;
@@ -824,6 +826,8 @@ static ssize_t link_state_store(struct device *dev,
824 struct pcie_link_state *link, *root = pdev->link_state->root; 826 struct pcie_link_state *link, *root = pdev->link_state->root;
825 u32 val = buf[0] - '0', state = 0; 827 u32 val = buf[0] - '0', state = 0;
826 828
829 if (aspm_disabled)
830 return -EPERM;
827 if (n < 1 || val > 3) 831 if (n < 1 || val > 3)
828 return -EINVAL; 832 return -EINVAL;
829 833