forked from Minki/linux
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes/pci-2.6: PCI: Disable ASPM when _OSC control is not granted for PCIe services PCI: Changing ASPM policy, via /sys, to POWERSAVE could cause NMIs PCI: PCIe links may not get configured for ASPM under POWERSAVE mode PCI/ACPI: Report ASPM support to BIOS if not disabled from command line
This commit is contained in:
commit
5aafdea448
@ -32,6 +32,7 @@
|
|||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/pci.h>
|
#include <linux/pci.h>
|
||||||
#include <linux/pci-acpi.h>
|
#include <linux/pci-acpi.h>
|
||||||
|
#include <linux/pci-aspm.h>
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <acpi/acpi_bus.h>
|
#include <acpi/acpi_bus.h>
|
||||||
@ -564,7 +565,7 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|||||||
/* Indicate support for various _OSC capabilities. */
|
/* Indicate support for various _OSC capabilities. */
|
||||||
if (pci_ext_cfg_avail(root->bus->self))
|
if (pci_ext_cfg_avail(root->bus->self))
|
||||||
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
|
flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
|
||||||
if (pcie_aspm_enabled())
|
if (pcie_aspm_support_enabled())
|
||||||
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
|
flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
|
||||||
OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
|
OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
|
||||||
if (pci_msi_enabled())
|
if (pci_msi_enabled())
|
||||||
@ -591,12 +592,16 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
|
|||||||
|
|
||||||
status = acpi_pci_osc_control_set(device->handle, &flags,
|
status = acpi_pci_osc_control_set(device->handle, &flags,
|
||||||
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
|
OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
|
||||||
if (ACPI_SUCCESS(status))
|
if (ACPI_SUCCESS(status)) {
|
||||||
dev_info(root->bus->bridge,
|
dev_info(root->bus->bridge,
|
||||||
"ACPI _OSC control (0x%02x) granted\n", flags);
|
"ACPI _OSC control (0x%02x) granted\n", flags);
|
||||||
else
|
} else {
|
||||||
dev_dbg(root->bus->bridge,
|
dev_dbg(root->bus->bridge,
|
||||||
"ACPI _OSC request failed (code %d)\n", status);
|
"ACPI _OSC request failed (code %d)\n", status);
|
||||||
|
printk(KERN_INFO "Unable to assume _OSC PCIe control. "
|
||||||
|
"Disabling ASPM\n");
|
||||||
|
pcie_no_aspm();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_acpi_add_bus_pm_notifier(device, root->bus);
|
pci_acpi_add_bus_pm_notifier(device, root->bus);
|
||||||
|
@ -740,6 +740,12 @@ int pci_set_power_state(struct pci_dev *dev, pci_power_t state)
|
|||||||
|
|
||||||
if (!__pci_complete_power_transition(dev, state))
|
if (!__pci_complete_power_transition(dev, state))
|
||||||
error = 0;
|
error = 0;
|
||||||
|
/*
|
||||||
|
* When aspm_policy is "powersave" this call ensures
|
||||||
|
* that ASPM is configured.
|
||||||
|
*/
|
||||||
|
if (!error && dev->bus->self)
|
||||||
|
pcie_aspm_powersave_config_link(dev->bus->self);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ struct pcie_link_state {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static int aspm_disabled, aspm_force, aspm_clear_state;
|
static int aspm_disabled, aspm_force, aspm_clear_state;
|
||||||
|
static bool aspm_support_enabled = true;
|
||||||
static DEFINE_MUTEX(aspm_lock);
|
static DEFINE_MUTEX(aspm_lock);
|
||||||
static LIST_HEAD(link_list);
|
static LIST_HEAD(link_list);
|
||||||
|
|
||||||
@ -707,6 +708,28 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev)
|
|||||||
up_read(&pci_bus_sem);
|
up_read(&pci_bus_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
struct pcie_link_state *link = pdev->link_state;
|
||||||
|
|
||||||
|
if (aspm_disabled || !pci_is_pcie(pdev) || !link)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (aspm_policy != POLICY_POWERSAVE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
|
||||||
|
(pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
|
||||||
|
return;
|
||||||
|
|
||||||
|
down_read(&pci_bus_sem);
|
||||||
|
mutex_lock(&aspm_lock);
|
||||||
|
pcie_config_aspm_path(link);
|
||||||
|
pcie_set_clkpm(link, policy_to_clkpm_state(link));
|
||||||
|
mutex_unlock(&aspm_lock);
|
||||||
|
up_read(&pci_bus_sem);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* pci_disable_link_state - disable pci device's link state, so the link will
|
* pci_disable_link_state - disable pci device's link state, so the link will
|
||||||
* never enter specific states
|
* never enter specific states
|
||||||
@ -747,6 +770,8 @@ static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
|
|||||||
int i;
|
int i;
|
||||||
struct pcie_link_state *link;
|
struct pcie_link_state *link;
|
||||||
|
|
||||||
|
if (aspm_disabled)
|
||||||
|
return -EPERM;
|
||||||
for (i = 0; i < ARRAY_SIZE(policy_str); i++)
|
for (i = 0; i < ARRAY_SIZE(policy_str); i++)
|
||||||
if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
|
if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
|
||||||
break;
|
break;
|
||||||
@ -801,6 +826,8 @@ static ssize_t link_state_store(struct device *dev,
|
|||||||
struct pcie_link_state *link, *root = pdev->link_state->root;
|
struct pcie_link_state *link, *root = pdev->link_state->root;
|
||||||
u32 val = buf[0] - '0', state = 0;
|
u32 val = buf[0] - '0', state = 0;
|
||||||
|
|
||||||
|
if (aspm_disabled)
|
||||||
|
return -EPERM;
|
||||||
if (n < 1 || val > 3)
|
if (n < 1 || val > 3)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
@ -896,6 +923,7 @@ static int __init pcie_aspm_disable(char *str)
|
|||||||
{
|
{
|
||||||
if (!strcmp(str, "off")) {
|
if (!strcmp(str, "off")) {
|
||||||
aspm_disabled = 1;
|
aspm_disabled = 1;
|
||||||
|
aspm_support_enabled = false;
|
||||||
printk(KERN_INFO "PCIe ASPM is disabled\n");
|
printk(KERN_INFO "PCIe ASPM is disabled\n");
|
||||||
} else if (!strcmp(str, "force")) {
|
} else if (!strcmp(str, "force")) {
|
||||||
aspm_force = 1;
|
aspm_force = 1;
|
||||||
@ -930,3 +958,8 @@ int pcie_aspm_enabled(void)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(pcie_aspm_enabled);
|
EXPORT_SYMBOL(pcie_aspm_enabled);
|
||||||
|
|
||||||
|
bool pcie_aspm_support_enabled(void)
|
||||||
|
{
|
||||||
|
return aspm_support_enabled;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(pcie_aspm_support_enabled);
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/pcieport_if.h>
|
#include <linux/pcieport_if.h>
|
||||||
#include <linux/aer.h>
|
#include <linux/aer.h>
|
||||||
#include <linux/pci-aspm.h>
|
|
||||||
|
|
||||||
#include "../pci.h"
|
#include "../pci.h"
|
||||||
#include "portdrv.h"
|
#include "portdrv.h"
|
||||||
@ -356,10 +355,8 @@ int pcie_port_device_register(struct pci_dev *dev)
|
|||||||
|
|
||||||
/* Get and check PCI Express port services */
|
/* Get and check PCI Express port services */
|
||||||
capabilities = get_port_device_capability(dev);
|
capabilities = get_port_device_capability(dev);
|
||||||
if (!capabilities) {
|
if (!capabilities)
|
||||||
pcie_no_aspm();
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
pci_set_master(dev);
|
pci_set_master(dev);
|
||||||
/*
|
/*
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
|
extern void pcie_aspm_init_link_state(struct pci_dev *pdev);
|
||||||
extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
|
extern void pcie_aspm_exit_link_state(struct pci_dev *pdev);
|
||||||
extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
|
extern void pcie_aspm_pm_state_change(struct pci_dev *pdev);
|
||||||
|
extern void pcie_aspm_powersave_config_link(struct pci_dev *pdev);
|
||||||
extern void pci_disable_link_state(struct pci_dev *pdev, int state);
|
extern void pci_disable_link_state(struct pci_dev *pdev, int state);
|
||||||
extern void pcie_clear_aspm(void);
|
extern void pcie_clear_aspm(void);
|
||||||
extern void pcie_no_aspm(void);
|
extern void pcie_no_aspm(void);
|
||||||
@ -39,6 +40,9 @@ static inline void pcie_aspm_exit_link_state(struct pci_dev *pdev)
|
|||||||
static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
|
static inline void pcie_aspm_pm_state_change(struct pci_dev *pdev)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static inline void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
|
||||||
|
{
|
||||||
|
}
|
||||||
static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
|
static inline void pci_disable_link_state(struct pci_dev *pdev, int state)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -1002,12 +1002,11 @@ extern bool pcie_ports_auto;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CONFIG_PCIEASPM
|
#ifndef CONFIG_PCIEASPM
|
||||||
static inline int pcie_aspm_enabled(void)
|
static inline int pcie_aspm_enabled(void) { return 0; }
|
||||||
{
|
static inline bool pcie_aspm_support_enabled(void) { return false; }
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#else
|
#else
|
||||||
extern int pcie_aspm_enabled(void);
|
extern int pcie_aspm_enabled(void);
|
||||||
|
extern bool pcie_aspm_support_enabled(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_PCIEAER
|
#ifdef CONFIG_PCIEAER
|
||||||
|
Loading…
Reference in New Issue
Block a user