aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorKenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>2009-05-12 23:18:22 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-06-18 17:02:15 -0400
commit8d349ace9a5c2a8404bcf4a371fe170480ffbebb (patch)
tree6495378f6b3255752cd04af22e653ece36c7d8b7 /drivers
parent5aa63583cbec27482c6f1d761a0509f59b7969a8 (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/pci/pcie/aspm.c142
1 files changed, 75 insertions, 67 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 9eaaf95f65a2..68a4d4b15f9f 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -126,7 +126,7 @@ static void pcie_set_clock_pm(struct pcie_link_state *link, int enable)
126 link->clkpm_enabled = !!enable; 126 link->clkpm_enabled = !!enable;
127} 127}
128 128
129static void pcie_check_clock_pm(struct pcie_link_state *link, int blacklist) 129static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist)
130{ 130{
131 int pos, capable = 1, enabled = 1; 131 int pos, capable = 1, enabled = 1;
132 u32 reg32; 132 u32 reg32;
@@ -151,13 +151,7 @@ static void pcie_check_clock_pm(struct pcie_link_state *link, int blacklist)
151 } 151 }
152 link->clkpm_enabled = enabled; 152 link->clkpm_enabled = enabled;
153 link->clkpm_default = enabled; 153 link->clkpm_default = enabled;
154 if (!blacklist) { 154 link->clkpm_capable = (blacklist) ? 0 : capable;
155 link->clkpm_capable = capable;
156 pcie_set_clock_pm(link, policy_to_clkpm_state(link));
157 } else {
158 link->clkpm_capable = 0;
159 pcie_set_clock_pm(link, 0);
160 }
161} 155}
162 156
163static bool pcie_aspm_downstream_has_switch(struct pcie_link_state *link) 157static 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,
314 *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1); 308 *enabled = reg16 & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1);
315} 309}
316 310
317static void pcie_aspm_cap_init(struct pcie_link_state *link) 311static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist)
318{ 312{
319 u32 support, l0s, l1, enabled; 313 u32 support, l0s, l1, enabled;
320 struct pci_dev *child, *parent = link->pdev; 314 struct pci_dev *child, *parent = link->pdev;
321 struct pci_bus *linkbus = parent->subordinate; 315 struct pci_bus *linkbus = parent->subordinate;
322 316
317 if (blacklist) {
318 /* Set support state to 0, so we will disable ASPM later */
319 link->aspm_support = 0;
320 link->aspm_default = 0;
321 link->aspm_enabled = PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1;
322 return;
323 }
324
325 /* Configure common clock before checking latencies */
326 pcie_aspm_configure_common_clock(link);
327
323 /* upstream component states */ 328 /* upstream component states */
324 pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled); 329 pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled);
325 link->aspm_support = support; 330 link->aspm_support = support;
@@ -590,6 +595,42 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev)
590 return 0; 595 return 0;
591} 596}
592 597
598static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev)
599{
600 struct pcie_link_state *link;
601 int blacklist = !!pcie_aspm_sanity_check(pdev);
602
603 link = kzalloc(sizeof(*link), GFP_KERNEL);
604 if (!link)
605 return NULL;
606 INIT_LIST_HEAD(&link->sibling);
607 INIT_LIST_HEAD(&link->children);
608 INIT_LIST_HEAD(&link->link);
609 link->pdev = pdev;
610 link->has_switch = pcie_aspm_downstream_has_switch(link);
611 if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) {
612 struct pcie_link_state *parent;
613 parent = pdev->bus->parent->self->link_state;
614 if (!parent) {
615 kfree(link);
616 return NULL;
617 }
618 link->parent = parent;
619 list_add(&link->link, &parent->children);
620 }
621 list_add(&link->sibling, &link_list);
622
623 pdev->link_state = link;
624
625 /* Check ASPM capability */
626 pcie_aspm_cap_init(link, blacklist);
627
628 /* Check Clock PM capability */
629 pcie_clkpm_cap_init(link, blacklist);
630
631 return link;
632}
633
593/* 634/*
594 * pcie_aspm_init_link_state: Initiate PCI express link state. 635 * pcie_aspm_init_link_state: Initiate PCI express link state.
595 * It is called after the pcie and its children devices are scaned. 636 * 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)
597 */ 638 */
598void pcie_aspm_init_link_state(struct pci_dev *pdev) 639void pcie_aspm_init_link_state(struct pci_dev *pdev)
599{ 640{
600 unsigned int state; 641 u32 state;
601 struct pcie_link_state *link_state; 642 struct pcie_link_state *link;
602 int error = 0;
603 int blacklist;
604 643
605 if (aspm_disabled || !pdev->is_pcie || pdev->link_state) 644 if (aspm_disabled || !pdev->is_pcie || pdev->link_state)
606 return; 645 return;
607 if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && 646 if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT &&
608 pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) 647 pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)
609 return; 648 return;
649
610 /* VIA has a strange chipset, root port is under a bridge */ 650 /* VIA has a strange chipset, root port is under a bridge */
611 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && 651 if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT &&
612 pdev->bus->self) 652 pdev->bus->self)
613 return; 653 return;
654
614 down_read(&pci_bus_sem); 655 down_read(&pci_bus_sem);
615 if (list_empty(&pdev->subordinate->devices)) 656 if (list_empty(&pdev->subordinate->devices))
616 goto out; 657 goto out;
617 658
618 blacklist = !!pcie_aspm_sanity_check(pdev);
619
620 mutex_lock(&aspm_lock); 659 mutex_lock(&aspm_lock);
621 660 link = pcie_aspm_setup_link_state(pdev);
622 link_state = kzalloc(sizeof(*link_state), GFP_KERNEL); 661 if (!link)
623 if (!link_state) 662 goto unlock;
624 goto unlock_out; 663 /*
625 664 * Setup initial ASPM state
626 INIT_LIST_HEAD(&link_state->children); 665 *
627 INIT_LIST_HEAD(&link_state->link); 666 * If link has switch, delay the link config. The leaf link
628 if (pdev->bus->self) {/* this is a switch */ 667 * initialization will config the whole hierarchy. But we must
629 struct pcie_link_state *parent_link_state; 668 * make sure BIOS doesn't set unsupported link state.
630 669 */
631 parent_link_state = pdev->bus->parent->self->link_state; 670 if (link->has_switch) {
632 if (!parent_link_state) { 671 state = pcie_aspm_check_state(link, link->aspm_default);
633 kfree(link_state); 672 __pcie_aspm_config_link(link, state);
634 goto unlock_out;
635 }
636 list_add(&link_state->link, &parent_link_state->children);
637 link_state->parent = parent_link_state;
638 }
639 link_state->pdev = pdev;
640 link_state->has_switch = pcie_aspm_downstream_has_switch(link_state);
641 pdev->link_state = link_state;
642
643 if (!blacklist) {
644 pcie_aspm_configure_common_clock(link_state);
645 pcie_aspm_cap_init(link_state);
646 } else { 673 } else {
647 link_state->aspm_enabled = 674 state = policy_to_aspm_state(link);
648 (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); 675 __pcie_aspm_configure_link_state(link, state);
649 link_state->aspm_default = 0;
650 /* Set support state to 0, so we will disable ASPM later */
651 link_state->aspm_support = 0;
652 } 676 }
653 677
654 list_add(&link_state->sibling, &link_list); 678 /* Setup initial Clock PM state */
655 679 state = (link->clkpm_capable) ? policy_to_clkpm_state(link) : 0;
656 if (link_state->has_switch) { 680 pcie_set_clock_pm(link, state);
657 /* 681unlock:
658 * If link has switch, delay the link config. The leaf link
659 * initialization will config the whole hierarchy. but we must
660 * make sure BIOS doesn't set unsupported link state
661 **/
662 state = pcie_aspm_check_state(link_state,
663 link_state->aspm_default);
664 __pcie_aspm_config_link(link_state, state);
665 } else
666 __pcie_aspm_configure_link_state(link_state,
667 policy_to_aspm_state(link_state));
668
669 pcie_check_clock_pm(link_state, blacklist);
670
671unlock_out:
672 if (error)
673 free_link_state(link_state);
674 mutex_unlock(&aspm_lock); 682 mutex_unlock(&aspm_lock);
675out: 683out:
676 up_read(&pci_bus_sem); 684 up_read(&pci_bus_sem);