PCI ASPM: cleanup initialization
Clean up ASPM initialization by refactoring some functionality, renaming functions, and moving things around. Acked-by: Shaohua Li <shaohua.li@intel.com> Signed-off-by: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com> Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
This commit is contained in:
parent
5aa63583cb
commit
8d349ace9a
|
@ -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)
|
||||||
}
|
}
|
||||||
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,
|
||||||
*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)
|
||||||
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)
|
||||||
*/
|
*/
|
||||||
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);
|
||||||
|
|
Loading…
Reference in New Issue