diff options
Diffstat (limited to 'drivers/pci')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 24 |
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 | ||
34 | struct pcie_link_state { | 34 | struct 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 | ||
489 | static 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 */ |
498 | static void __pcie_aspm_configure_link_state(struct pcie_link_state *link, | 491 | static 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; |