dect
/
linux-2.6
Archived
13
0
Fork 0

PCI ASPM: cleanup __pcie_aspm_check_state_one

Clean up and simplify __pcie_aspm_check_state_one().

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:
Kenji Kaneshige 2009-05-13 12:19:00 +09:00 committed by Jesse Barnes
parent 8d349ace9a
commit f7ea3d7fc0
1 changed files with 25 additions and 42 deletions

View File

@ -370,56 +370,39 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
}
}
static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev,
unsigned int state)
/**
* __pcie_aspm_check_state_one - check latency for endpoint device.
* @endpoint: pointer to the struct pci_dev of endpoint device
*
* TBD: The latency from the endpoint to root complex vary per switch's
* upstream link state above the device. Here we just do a simple check
* which assumes all links above the device can be in L1 state, that
* is we just consider the worst case. If switch's upstream link can't
* be put into L0S/L1, then our check is too strictly.
*/
static u32 __pcie_aspm_check_state_one(struct pci_dev *endpoint, u32 state)
{
struct pci_dev *parent_dev, *tmp_dev;
unsigned int l1_latency = 0;
struct pcie_link_state *link_state;
u32 l1_switch_latency = 0;
struct aspm_latency *acceptable;
struct pcie_link_state *link;
parent_dev = pdev->bus->self;
link_state = parent_dev->link_state;
state &= link_state->aspm_support;
if (state == 0)
return 0;
acceptable = &link_state->acceptable[PCI_FUNC(pdev->devfn)];
link = endpoint->bus->self->link_state;
state &= link->aspm_support;
acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)];
/*
* Check latency for endpoint device.
* TBD: The latency from the endpoint to root complex vary per
* switch's upstream link state above the device. Here we just do a
* simple check which assumes all links above the device can be in L1
* state, that is we just consider the worst case. If switch's upstream
* link can't be put into L0S/L1, then our check is too strictly.
*/
tmp_dev = pdev;
while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
parent_dev = tmp_dev->bus->self;
link_state = parent_dev->link_state;
while (link && state) {
if ((state & PCIE_LINK_STATE_L0S) &&
(link_state->latency.l0s > acceptable->l0s))
(link->latency.l0s > acceptable->l0s))
state &= ~PCIE_LINK_STATE_L0S;
if ((state & PCIE_LINK_STATE_L1) &&
(link_state->latency.l1 + l1_latency > acceptable->l1))
(link->latency.l1 + l1_switch_latency > acceptable->l1))
state &= ~PCIE_LINK_STATE_L1;
if (!parent_dev->bus->self) /* parent_dev is a root port */
break;
else {
/*
* parent_dev is the downstream port of a switch, make
* tmp_dev the upstream port of the switch
*/
tmp_dev = parent_dev->bus->self;
/*
* every switch on the path to root complex need 1 more
* microsecond for L1. Spec doesn't mention L0S.
*/
if (state & PCIE_LINK_STATE_L1)
l1_latency += 1000;
}
link = link->parent;
/*
* Every switch on the path to root complex need 1
* more microsecond for L1. Spec doesn't mention L0s.
*/
l1_switch_latency += 1000;
}
return state;
}