Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 283324
b: refs/heads/master
c: 10f6dc7
h: refs/heads/master
v: v3
  • Loading branch information
Matthew Garrett authored and Jesse Barnes committed Jan 6, 2012
1 parent 199c108 commit 0452231
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 25 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cfa4d8cc56853ec945956d182ecb4c99102b110a
refs/heads/master: 10f6dc7eede9a8895626e9c1b4f2c3b75fbf2850
7 changes: 7 additions & 0 deletions trunk/drivers/acpi/pci_root.c
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,13 @@ static int __devinit acpi_pci_root_add(struct acpi_device *device)
if (ACPI_SUCCESS(status)) {
dev_info(root->bus->bridge,
"ACPI _OSC control (0x%02x) granted\n", flags);
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
/*
* We have ASPM control, but the FADT indicates
* that it's unsupported. Clear it.
*/
pcie_clear_aspm(root->bus);
}
} else {
dev_info(root->bus->bridge,
"ACPI _OSC request failed (%s), "
Expand Down
1 change: 0 additions & 1 deletion trunk/drivers/pci/pci-acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,6 @@ static int __init acpi_pci_init(void)

if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
printk(KERN_INFO"ACPI FADT declares the system doesn't support PCIe ASPM, so disable it\n");
pcie_clear_aspm();
pcie_no_aspm();
}

Expand Down
58 changes: 37 additions & 21 deletions trunk/drivers/pci/pcie/aspm.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct pcie_link_state {
struct aspm_latency acceptable[8];
};

static int aspm_disabled, aspm_force, aspm_clear_state;
static int aspm_disabled, aspm_force;
static bool aspm_support_enabled = true;
static DEFINE_MUTEX(aspm_lock);
static LIST_HEAD(link_list);
Expand Down Expand Up @@ -500,9 +500,6 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
int pos;
u32 reg32;

if (aspm_clear_state)
return -EINVAL;

/*
* Some functions in a slot might not all be PCIe functions,
* very strange. Disable ASPM for the whole slot
Expand Down Expand Up @@ -574,9 +571,6 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
return;

if (aspm_disabled && !aspm_clear_state)
return;

/* VIA has a strange chipset, root port is under a bridge */
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
pdev->bus->self)
Expand Down Expand Up @@ -608,7 +602,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev)
* the BIOS's expectation, we'll do so once pci_enable_device() is
* called.
*/
if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) {
if (aspm_policy != POLICY_POWERSAVE) {
pcie_config_aspm_path(link);
pcie_set_clkpm(link, policy_to_clkpm_state(link));
}
Expand Down Expand Up @@ -649,8 +643,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link, *root, *parent_link;

if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) ||
!parent || !parent->link_state)
if (!pci_is_pcie(pdev) || !parent || !parent->link_state)
return;
if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
(parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
Expand Down Expand Up @@ -734,13 +727,18 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
* pci_disable_link_state - disable pci device's link state, so the link will
* never enter specific states
*/
static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)
static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem,
bool force)
{
struct pci_dev *parent = pdev->bus->self;
struct pcie_link_state *link;

if (aspm_disabled || !pci_is_pcie(pdev))
if (aspm_disabled && !force)
return;

if (!pci_is_pcie(pdev))
return;

if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT ||
pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM)
parent = pdev;
Expand Down Expand Up @@ -768,16 +766,31 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem)

void pci_disable_link_state_locked(struct pci_dev *pdev, int state)
{
__pci_disable_link_state(pdev, state, false);
__pci_disable_link_state(pdev, state, false, false);
}
EXPORT_SYMBOL(pci_disable_link_state_locked);

void pci_disable_link_state(struct pci_dev *pdev, int state)
{
__pci_disable_link_state(pdev, state, true);
__pci_disable_link_state(pdev, state, true, false);
}
EXPORT_SYMBOL(pci_disable_link_state);

void pcie_clear_aspm(struct pci_bus *bus)
{
struct pci_dev *child;

/*
* Clear any ASPM setup that the firmware has carried out on this bus
*/
list_for_each_entry(child, &bus->devices, bus_list) {
__pci_disable_link_state(child, PCIE_LINK_STATE_L0S |
PCIE_LINK_STATE_L1 |
PCIE_LINK_STATE_CLKPM,
false, true);
}
}

static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp)
{
int i;
Expand Down Expand Up @@ -935,6 +948,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev)
static int __init pcie_aspm_disable(char *str)
{
if (!strcmp(str, "off")) {
aspm_policy = POLICY_DEFAULT;
aspm_disabled = 1;
aspm_support_enabled = false;
printk(KERN_INFO "PCIe ASPM is disabled\n");
Expand All @@ -947,16 +961,18 @@ static int __init pcie_aspm_disable(char *str)

__setup("pcie_aspm=", pcie_aspm_disable);

void pcie_clear_aspm(void)
{
if (!aspm_force)
aspm_clear_state = 1;
}

void pcie_no_aspm(void)
{
if (!aspm_force)
/*
* Disabling ASPM is intended to prevent the kernel from modifying
* existing hardware state, not to clear existing state. To that end:
* (a) set policy to POLICY_DEFAULT in order to avoid changing state
* (b) prevent userspace from changing policy
*/
if (!aspm_force) {
aspm_policy = POLICY_DEFAULT;
aspm_disabled = 1;
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions trunk/include/linux/pci-aspm.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ 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_locked(struct pci_dev *pdev, int state);
extern void pcie_clear_aspm(void);
extern void pcie_clear_aspm(struct pci_bus *bus);
extern void pcie_no_aspm(void);
#else
static inline void pcie_aspm_init_link_state(struct pci_dev *pdev)
Expand All @@ -47,7 +47,7 @@ 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 pcie_clear_aspm(void)
static inline void pcie_clear_aspm(struct pci_bus *bus)
{
}
static inline void pcie_no_aspm(void)
Expand Down

0 comments on commit 0452231

Please sign in to comment.