Commit 8d349ace authored by Kenji Kaneshige's avatar Kenji Kaneshige Committed by Jesse Barnes

PCI ASPM: cleanup initialization

Clean up ASPM initialization by refactoring some functionality, renaming
functions, and moving things around.
Acked-by: default avatarShaohua Li <shaohua.li@intel.com>
Signed-off-by: default avatarKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Signed-off-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
parent 5aa63583
...@@ -126,7 +126,7 @@ static void pcie_set_clock_pm(struct pcie_link_state *link, int enable) ...@@ -126,7 +126,7 @@ static void pcie_set_clock_pm(struct pcie_link_state *link, int enable)
link->clkpm_enabled = !!enable; link->clkpm_enabled = !!enable;
} }
static void pcie_check_clock_pm(struct pcie_link_state *link, int blacklist) static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
{ {
int pos, capable = 1, enabled = 1; int pos, capable = 1, enabled = 1;
u32 reg32; u32 reg32;
...@@ -151,13 +151,7 @@ static void pcie_check_clock_pm(struct pcie_link_state *link, int blacklist) ...@@ -151,13 +151,7 @@ static void pcie_check_clock_pm(struct pcie_link_state *link, int blacklist)
} }
link->clkpm_enabled = enabled; link->clkpm_enabled = enabled;
link->clkpm_default = enabled; link->clkpm_default = enabled;
if (!blacklist) { link->clkpm_capable = (blacklist) ? 0 : capable;
link->clkpm_capable = capable;
pcie_set_clock_pm(link, policy_to_clkpm_state(link));
} else {
link->clkpm_capable = 0;
pcie_set_clock_pm(link, 0);
}
} }
static bool pcie_aspm_downstream_has_switch(struct pcie_link_state *link) static bool pcie_aspm_downstream_has_switch(struct pcie_link_state *link)
...@@ -314,12 +308,23 @@ static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state, ...@@ -314,12 +308,23 @@ static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state,
*enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1); *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
} }
static void pcie_aspm_cap_init(struct pcie_link_state *link) static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
{ {
u32 support, l0s, l1, enabled; u32 support, l0s, l1, enabled;
struct pci_dev *child, *parent = link->pdev; struct pci_dev *child, *parent = link->pdev;
struct pci_bus *linkbus = parent->subordinate; struct pci_bus *linkbus = parent->subordinate;
if (blacklist) {
/* Set support state to 0, so we will disable ASPM later */
link->aspm_support = 0;
link->aspm_default = 0;
link->aspm_enabled = PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1;
return;
}
/* Configure common clock before checking latencies */
pcie_aspm_configure_common_clock(link);
/* upstream component states */ /* upstream component states */
pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled); pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled);
link->aspm_support = support; link->aspm_support = support;
...@@ -590,6 +595,42 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) ...@@ -590,6 +595,42 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
return 0; return 0;
} }
static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev)
{
struct pcie_link_state *link;
int blacklist = !!pcie_aspm_sanity_check(pdev);
link = kzalloc(sizeof(*link), GFP_KERNEL);
if (!link)
return NULL;
INIT_LIST_HEAD(&link->sibling);
INIT_LIST_HEAD(&link->children);
INIT_LIST_HEAD(&link->link);
link->pdev = pdev;
link->has_switch = pcie_aspm_downstream_has_switch(link);
if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) {
struct pcie_link_state *parent;
parent = pdev->bus->parent->self->link_state;
if (!parent) {
kfree(link);
return NULL;
}
link->parent = parent;
list_add(&link->link, &parent->children);
}
list_add(&link->sibling, &link_list);
pdev->link_state = link;
/* Check ASPM capability */
pcie_aspm_cap_init(link, blacklist);
/* Check Clock PM capability */
pcie_clkpm_cap_init(link, blacklist);
return link;
}
/* /*
* pcie_aspm_init_link_state: Initiate PCI express link state. * pcie_aspm_init_link_state: Initiate PCI express link state.
* It is called after the pcie and its children devices are scaned. * It is called after the pcie and its children devices are scaned.
...@@ -597,80 +638,47 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) ...@@ -597,80 +638,47 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
*/ */
void pcie_aspm_init_link_state(struct pci_dev *pdev) void pcie_aspm_init_link_state(struct pci_dev *pdev)
{ {
unsigned int state; u32 state;
struct pcie_link_state *link_state; struct pcie_link_state *link;
int error = 0;
int blacklist;
if (aspm_disabled || !pdev->is_pcie || pdev->link_state) if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
return; return;
if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
return; return;
/* VIA has a strange chipset, root port is under a bridge */ /* VIA has a strange chipset, root port is under a bridge */
if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
pdev->bus->self) pdev->bus->self)
return; return;
down_read(&pci_bus_sem); down_read(&pci_bus_sem);
if (list_empty(&pdev->subordinate->devices)) if (list_empty(&pdev->subordinate->devices))
goto out; goto out;
blacklist = !!pcie_aspm_sanity_check(pdev);
mutex_lock(&aspm_lock); mutex_lock(&aspm_lock);
link = pcie_aspm_setup_link_state(pdev);
link_state = kzalloc(sizeof(*link_state), GFP_KERNEL); if (!link)
if (!link_state) goto unlock;
goto unlock_out; /*
* Setup initial ASPM state
INIT_LIST_HEAD(&link_state->children); *
INIT_LIST_HEAD(&link_state->link); * If link has switch, delay the link config. The leaf link
if (pdev->bus->self) {/* this is a switch */ * initialization will config the whole hierarchy. But we must
struct pcie_link_state *parent_link_state; * make sure BIOS doesn't set unsupported link state.
*/
parent_link_state = pdev->bus->parent->self->link_state; if (link->has_switch) {
if (!parent_link_state) { state = pcie_aspm_check_state(link, link->aspm_default);
kfree(link_state); __pcie_aspm_config_link(link, state);
goto unlock_out;
}
list_add(&link_state->link, &parent_link_state->children);
link_state->parent = parent_link_state;
}
link_state->pdev = pdev;
link_state->has_switch = pcie_aspm_downstream_has_switch(link_state);
pdev->link_state = link_state;
if (!blacklist) {
pcie_aspm_configure_common_clock(link_state);
pcie_aspm_cap_init(link_state);
} else { } else {
link_state->aspm_enabled = state = policy_to_aspm_state(link);
(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); __pcie_aspm_configure_link_state(link, state);
link_state->aspm_default = 0;
/* Set support state to 0, so we will disable ASPM later */
link_state->aspm_support = 0;
} }
list_add(&link_state->sibling, &link_list); /* Setup initial Clock PM state */
state = (link->clkpm_capable) ? policy_to_clkpm_state(link) : 0;
if (link_state->has_switch) { pcie_set_clock_pm(link, state);
/* unlock:
* If link has switch, delay the link config. The leaf link
* initialization will config the whole hierarchy. but we must
* make sure BIOS doesn't set unsupported link state
**/
state = pcie_aspm_check_state(link_state,
link_state->aspm_default);
__pcie_aspm_config_link(link_state, state);
} else
__pcie_aspm_configure_link_state(link_state,
policy_to_aspm_state(link_state));
pcie_check_clock_pm(link_state, blacklist);
unlock_out:
if (error)
free_link_state(link_state);
mutex_unlock(&aspm_lock); mutex_unlock(&aspm_lock);
out: out:
up_read(&pci_bus_sem); up_read(&pci_bus_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment