aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/pcie/aspm.c24
1 files changed, 11 insertions, 13 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 04b6a3098505..3d27c97e0486 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -33,6 +33,7 @@ struct aspm_latency {
33 33
34struct pcie_link_state { 34struct pcie_link_state {
35 struct pci_dev *pdev; /* Upstream component of the Link */ 35 struct pci_dev *pdev; /* Upstream component of the Link */
36 struct pcie_link_state *root; /* pointer to the root port link */
36 struct pcie_link_state *parent; /* pointer to the parent Link state */ 37 struct pcie_link_state *parent; /* pointer to the parent Link state */
37 struct list_head sibling; /* node in link_list */ 38 struct list_head sibling; /* node in link_list */
38 struct list_head children; /* list of child link states */ 39 struct list_head children; /* list of child link states */
@@ -486,26 +487,17 @@ static void __pcie_aspm_config_link(struct pcie_link_state *link, u32 state)
486 link->aspm_enabled = state; 487 link->aspm_enabled = state;
487} 488}
488 489
489static struct pcie_link_state *get_root_port_link(struct pcie_link_state *link)
490{
491 struct pcie_link_state *root_port_link = link;
492 while (root_port_link->parent)
493 root_port_link = root_port_link->parent;
494 return root_port_link;
495}
496
497/* Check the whole hierarchy, and configure each link in the hierarchy */ 490/* Check the whole hierarchy, and configure each link in the hierarchy */
498static void __pcie_aspm_configure_link_state(struct pcie_link_state *link, 491static void __pcie_aspm_configure_link_state(struct pcie_link_state *link,
499 u32 state) 492 u32 state)
500{ 493{
501 struct pcie_link_state *leaf, *root = get_root_port_link(link); 494 struct pcie_link_state *leaf, *root = link->root;
502 495
503 state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); 496 state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
504 497
505 /* Check all links who have specific root port link */ 498 /* Check all links who have specific root port link */
506 list_for_each_entry(leaf, &link_list, sibling) { 499 list_for_each_entry(leaf, &link_list, sibling) {
507 if (!list_empty(&leaf->children) || 500 if (!list_empty(&leaf->children) || (leaf->root != root))
508 get_root_port_link(leaf) != root)
509 continue; 501 continue;
510 state = pcie_aspm_check_state(leaf, state); 502 state = pcie_aspm_check_state(leaf, state);
511 } 503 }
@@ -519,12 +511,12 @@ static void __pcie_aspm_configure_link_state(struct pcie_link_state *link,
519 **/ 511 **/
520 if (state & PCIE_LINK_STATE_L1) { 512 if (state & PCIE_LINK_STATE_L1) {
521 list_for_each_entry(leaf, &link_list, sibling) { 513 list_for_each_entry(leaf, &link_list, sibling) {
522 if (get_root_port_link(leaf) == root) 514 if (leaf->root == root)
523 __pcie_aspm_config_link(leaf, state); 515 __pcie_aspm_config_link(leaf, state);
524 } 516 }
525 } else { 517 } else {
526 list_for_each_entry_reverse(leaf, &link_list, sibling) { 518 list_for_each_entry_reverse(leaf, &link_list, sibling) {
527 if (get_root_port_link(leaf) == root) 519 if (leaf->root == root)
528 __pcie_aspm_config_link(leaf, state); 520 __pcie_aspm_config_link(leaf, state);
529 } 521 }
530 } 522 }
@@ -600,6 +592,12 @@ static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev)
600 link->parent = parent; 592 link->parent = parent;
601 list_add(&link->link, &parent->children); 593 list_add(&link->link, &parent->children);
602 } 594 }
595 /* Setup a pointer to the root port link */
596 if (!link->parent)
597 link->root = link;
598 else
599 link->root = link->parent->root;
600
603 list_add(&link->sibling, &link_list); 601 list_add(&link->sibling, &link_list);
604 602
605 pdev->link_state = link; 603 pdev->link_state = link;