X-Git-Url: http://pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fpci%2Fpcie%2Faspm.c;h=f82495583e63c123a89a41e23af1b658ac509a62;hb=ffab6cf44e9058fe75a33aa86386b22e616a8f6f;hp=1a5adeb10c95633b4356258d3bf32e556810b7b4;hpb=687fcdf741e4a268c2c7bac8b3734de761bb9719;p=linux-2.6-omap-h63xx.git diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 1a5adeb10c9..f82495583e6 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -16,9 +16,7 @@ #include #include #include -#include -#include -#include +#include #include "../pci.h" #ifdef MODULE_PARAM_PREFIX @@ -269,7 +267,7 @@ static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state, *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; if (*state != PCIE_LINK_STATE_L0S && *state != (PCIE_LINK_STATE_L1|PCIE_LINK_STATE_L0S)) - * state = 0; + *state = 0; if (*state == 0) return; @@ -508,6 +506,23 @@ static void free_link_state(struct pci_dev *pdev) pdev->link_state = NULL; } +static int pcie_aspm_sanity_check(struct pci_dev *pdev) +{ + struct pci_dev *child_dev; + int child_pos; + + /* + * Some functions in a slot might not all be PCIE functions, very + * strange. Disable ASPM for the whole slot + */ + list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) { + child_pos = pci_find_capability(child_dev, PCI_CAP_ID_EXP); + if (!child_pos) + return -EINVAL; + } + return 0; +} + /* * pcie_aspm_init_link_state: Initiate PCI express link state. * It is called after the pcie and its children devices are scaned. @@ -528,6 +543,9 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) if (list_empty(&pdev->subordinate->devices)) goto out; + if (pcie_aspm_sanity_check(pdev)) + goto out; + mutex_lock(&aspm_lock); link_state = kzalloc(sizeof(*link_state), GFP_KERNEL); @@ -619,7 +637,7 @@ void pci_disable_link_state(struct pci_dev *pdev, int state) if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) parent = pdev; - if (!parent) + if (!parent || !parent->link_state) return; down_read(&pci_bus_sem); @@ -754,7 +772,7 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) struct pcie_link_state *link_state = pdev->link_state; if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->support_state) @@ -770,7 +788,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) struct pcie_link_state *link_state = pdev->link_state; if (!pdev->is_pcie || (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && - pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) + pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) return; if (link_state->support_state) @@ -790,12 +808,23 @@ static int __init pcie_aspm_disable(char *str) __setup("pcie_noaspm", pcie_aspm_disable); +#ifdef CONFIG_ACPI +#include +#include +static void pcie_aspm_platform_init(void) +{ + pcie_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT| + OSC_CLOCK_PWR_CAPABILITY_SUPPORT); +} +#else +static inline void pcie_aspm_platform_init(void) { } +#endif + static int __init pcie_aspm_init(void) { if (aspm_disabled) return 0; - pci_osc_support_set(OSC_ACTIVE_STATE_PWR_SUPPORT| - OSC_CLOCK_PWR_CAPABILITY_SUPPORT); + pcie_aspm_platform_init(); return 0; }