diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index fdb3b7da7383..88351c242a48 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -26,9 +26,9 @@ #endif #define MODULE_PARAM_PREFIX "pcie_aspm." -struct endpoint_state { - unsigned int l0s_acceptable_latency; - unsigned int l1_acceptable_latency; +struct aspm_latency { + u32 l0s; /* L0s latency (nsec) */ + u32 l1; /* L1 latency (nsec) */ }; struct pcie_link_state { @@ -45,22 +45,19 @@ struct pcie_link_state { u32 aspm_enabled:2; /* Enabled ASPM state */ u32 aspm_default:2; /* Default ASPM state by BIOS */ - /* upstream component */ - unsigned int l0s_upper_latency; - unsigned int l1_upper_latency; - /* downstream component */ - unsigned int l0s_down_latency; - unsigned int l1_down_latency; + /* Latencies */ + struct aspm_latency latency; /* Exit latency */ + /* Clock PM state*/ unsigned int clk_pm_capable; unsigned int clk_pm_enabled; unsigned int bios_clk_state; /* - * A pcie downstream port only has one slot under it, so at most there - * are 8 functions + * Endpoint acceptable latencies. A pcie downstream port only + * has one slot under it, so at most there are 8 functions. */ - struct endpoint_state endpoints[8]; + struct aspm_latency acceptable[8]; }; static int aspm_disabled, aspm_force; @@ -341,8 +338,8 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) /* upstream component states */ pcie_aspm_get_cap_device(pdev, &support, &l0s, &l1, &enabled); link_state->aspm_support = support; - link_state->l0s_upper_latency = l0s; - link_state->l1_upper_latency = l1; + link_state->latency.l0s = l0s; + link_state->latency.l1 = l1; link_state->aspm_enabled = enabled; /* downstream component states, all functions have the same setting */ @@ -350,8 +347,8 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) bus_list); pcie_aspm_get_cap_device(child_dev, &support, &l0s, &l1, &enabled); link_state->aspm_support &= support; - link_state->l0s_down_latency = l0s; - link_state->l1_down_latency = l1; + link_state->latency.l0s = max_t(u32, link_state->latency.l0s, l0s); + link_state->latency.l1 = max_t(u32, link_state->latency.l1, l1); if (!link_state->aspm_support) return; @@ -364,8 +361,8 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) int pos; u32 reg32; unsigned int latency; - struct endpoint_state *ep_state = - &link_state->endpoints[PCI_FUNC(child_dev->devfn)]; + struct aspm_latency *acceptable = + &link_state->acceptable[PCI_FUNC(child_dev->devfn)]; if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT && child_dev->pcie_type != PCI_EXP_TYPE_LEG_END) @@ -375,11 +372,11 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, ®32); latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; latency = calc_L0S_latency(latency, 1); - ep_state->l0s_acceptable_latency = latency; + acceptable->l0s = latency; if (link_state->aspm_support & PCIE_LINK_STATE_L1) { latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; latency = calc_L1_latency(latency, 1); - ep_state->l1_acceptable_latency = latency; + acceptable->l1 = latency; } } } @@ -388,16 +385,16 @@ static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev, unsigned int state) { struct pci_dev *parent_dev, *tmp_dev; - unsigned int latency, l1_latency = 0; + unsigned int l1_latency = 0; struct pcie_link_state *link_state; - struct endpoint_state *ep_state; + struct aspm_latency *acceptable; parent_dev = pdev->bus->self; link_state = parent_dev->link_state; state &= link_state->aspm_support; if (state == 0) return 0; - ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)]; + acceptable = &link_state->acceptable[PCI_FUNC(pdev->devfn)]; /* * Check latency for endpoint device. @@ -411,21 +408,14 @@ static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev, while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { parent_dev = tmp_dev->bus->self; link_state = parent_dev->link_state; - if (state & PCIE_LINK_STATE_L0S) { - latency = max_t(unsigned int, - link_state->l0s_upper_latency, - link_state->l0s_down_latency); - if (latency > ep_state->l0s_acceptable_latency) - state &= ~PCIE_LINK_STATE_L0S; - } - if (state & PCIE_LINK_STATE_L1) { - latency = max_t(unsigned int, - link_state->l1_upper_latency, - link_state->l1_down_latency); - if (latency + l1_latency > - ep_state->l1_acceptable_latency) - state &= ~PCIE_LINK_STATE_L1; - } + if ((state & PCIE_LINK_STATE_L0S) && + (link_state->latency.l0s > acceptable->l0s)) + state &= ~PCIE_LINK_STATE_L0S; + + if ((state & PCIE_LINK_STATE_L1) && + (link_state->latency.l1 + l1_latency > acceptable->l1)) + state &= ~PCIE_LINK_STATE_L1; + if (!parent_dev->bus->self) /* parent_dev is a root port */ break; else { |