diff options
-rw-r--r-- | drivers/pci/pcie/aspm.c | 71 |
1 files changed, 38 insertions, 33 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 419f1f3697c0..fdb3b7da7383 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -41,9 +41,10 @@ struct pcie_link_state { | |||
41 | struct list_head link; | 41 | struct list_head link; |
42 | 42 | ||
43 | /* ASPM state */ | 43 | /* ASPM state */ |
44 | unsigned int support_state; | 44 | u32 aspm_support:2; /* Supported ASPM state */ |
45 | unsigned int enabled_state; | 45 | u32 aspm_enabled:2; /* Enabled ASPM state */ |
46 | unsigned int bios_aspm_state; | 46 | u32 aspm_default:2; /* Default ASPM state by BIOS */ |
47 | |||
47 | /* upstream component */ | 48 | /* upstream component */ |
48 | unsigned int l0s_upper_latency; | 49 | unsigned int l0s_upper_latency; |
49 | unsigned int l1_upper_latency; | 50 | unsigned int l1_upper_latency; |
@@ -88,9 +89,9 @@ static int policy_to_aspm_state(struct pci_dev *pdev) | |||
88 | return 0; | 89 | return 0; |
89 | case POLICY_POWERSAVE: | 90 | case POLICY_POWERSAVE: |
90 | /* Enable ASPM L0s/L1 */ | 91 | /* Enable ASPM L0s/L1 */ |
91 | return PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1; | 92 | return PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1; |
92 | case POLICY_DEFAULT: | 93 | case POLICY_DEFAULT: |
93 | return link_state->bios_aspm_state; | 94 | return link_state->aspm_default; |
94 | } | 95 | } |
95 | return 0; | 96 | return 0; |
96 | } | 97 | } |
@@ -311,6 +312,7 @@ static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state, | |||
311 | u32 reg32; | 312 | u32 reg32; |
312 | unsigned int latency; | 313 | unsigned int latency; |
313 | 314 | ||
315 | *l0s = *l1 = *enabled = 0; | ||
314 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 316 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
315 | pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); | 317 | pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); |
316 | *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; | 318 | *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; |
@@ -333,26 +335,29 @@ static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state, | |||
333 | static void pcie_aspm_cap_init(struct pci_dev *pdev) | 335 | static void pcie_aspm_cap_init(struct pci_dev *pdev) |
334 | { | 336 | { |
335 | struct pci_dev *child_dev; | 337 | struct pci_dev *child_dev; |
336 | u32 state, tmp; | 338 | u32 support, l0s, l1, enabled; |
337 | struct pcie_link_state *link_state = pdev->link_state; | 339 | struct pcie_link_state *link_state = pdev->link_state; |
338 | 340 | ||
339 | /* upstream component states */ | 341 | /* upstream component states */ |
340 | pcie_aspm_get_cap_device(pdev, &link_state->support_state, | 342 | pcie_aspm_get_cap_device(pdev, &support, &l0s, &l1, &enabled); |
341 | &link_state->l0s_upper_latency, | 343 | link_state->aspm_support = support; |
342 | &link_state->l1_upper_latency, | 344 | link_state->l0s_upper_latency = l0s; |
343 | &link_state->enabled_state); | 345 | link_state->l1_upper_latency = l1; |
346 | link_state->aspm_enabled = enabled; | ||
347 | |||
344 | /* downstream component states, all functions have the same setting */ | 348 | /* downstream component states, all functions have the same setting */ |
345 | child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev, | 349 | child_dev = list_entry(pdev->subordinate->devices.next, struct pci_dev, |
346 | bus_list); | 350 | bus_list); |
347 | pcie_aspm_get_cap_device(child_dev, &state, | 351 | pcie_aspm_get_cap_device(child_dev, &support, &l0s, &l1, &enabled); |
348 | &link_state->l0s_down_latency, | 352 | link_state->aspm_support &= support; |
349 | &link_state->l1_down_latency, | 353 | link_state->l0s_down_latency = l0s; |
350 | &tmp); | 354 | link_state->l1_down_latency = l1; |
351 | link_state->support_state &= state; | 355 | |
352 | if (!link_state->support_state) | 356 | if (!link_state->aspm_support) |
353 | return; | 357 | return; |
354 | link_state->enabled_state &= link_state->support_state; | 358 | |
355 | link_state->bios_aspm_state = link_state->enabled_state; | 359 | link_state->aspm_enabled &= link_state->aspm_support; |
360 | link_state->aspm_default = link_state->aspm_enabled; | ||
356 | 361 | ||
357 | /* ENDPOINT states*/ | 362 | /* ENDPOINT states*/ |
358 | list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) { | 363 | list_for_each_entry(child_dev, &pdev->subordinate->devices, bus_list) { |
@@ -371,7 +376,7 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) | |||
371 | latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; | 376 | latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; |
372 | latency = calc_L0S_latency(latency, 1); | 377 | latency = calc_L0S_latency(latency, 1); |
373 | ep_state->l0s_acceptable_latency = latency; | 378 | ep_state->l0s_acceptable_latency = latency; |
374 | if (link_state->support_state & PCIE_LINK_STATE_L1) { | 379 | if (link_state->aspm_support & PCIE_LINK_STATE_L1) { |
375 | latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; | 380 | latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; |
376 | latency = calc_L1_latency(latency, 1); | 381 | latency = calc_L1_latency(latency, 1); |
377 | ep_state->l1_acceptable_latency = latency; | 382 | ep_state->l1_acceptable_latency = latency; |
@@ -389,7 +394,7 @@ static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev, | |||
389 | 394 | ||
390 | parent_dev = pdev->bus->self; | 395 | parent_dev = pdev->bus->self; |
391 | link_state = parent_dev->link_state; | 396 | link_state = parent_dev->link_state; |
392 | state &= link_state->support_state; | 397 | state &= link_state->aspm_support; |
393 | if (state == 0) | 398 | if (state == 0) |
394 | return 0; | 399 | return 0; |
395 | ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)]; | 400 | ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)]; |
@@ -519,7 +524,7 @@ static void __pcie_aspm_config_link(struct pci_dev *pdev, unsigned int state) | |||
519 | if (!(state & PCIE_LINK_STATE_L1)) | 524 | if (!(state & PCIE_LINK_STATE_L1)) |
520 | __pcie_aspm_config_one_dev(pdev, state); | 525 | __pcie_aspm_config_one_dev(pdev, state); |
521 | 526 | ||
522 | link_state->enabled_state = state; | 527 | link_state->aspm_enabled = state; |
523 | } | 528 | } |
524 | 529 | ||
525 | static struct pcie_link_state *get_root_port_link(struct pcie_link_state *link) | 530 | static struct pcie_link_state *get_root_port_link(struct pcie_link_state *link) |
@@ -550,7 +555,7 @@ static void __pcie_aspm_configure_link_state(struct pci_dev *pdev, | |||
550 | /* check root port link too in case it hasn't children */ | 555 | /* check root port link too in case it hasn't children */ |
551 | state = pcie_aspm_check_state(root_port_link->pdev, state); | 556 | state = pcie_aspm_check_state(root_port_link->pdev, state); |
552 | 557 | ||
553 | if (link_state->enabled_state == state) | 558 | if (link_state->aspm_enabled == state) |
554 | return; | 559 | return; |
555 | 560 | ||
556 | /* | 561 | /* |
@@ -675,10 +680,11 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
675 | pcie_aspm_configure_common_clock(pdev); | 680 | pcie_aspm_configure_common_clock(pdev); |
676 | pcie_aspm_cap_init(pdev); | 681 | pcie_aspm_cap_init(pdev); |
677 | } else { | 682 | } else { |
678 | link_state->enabled_state = PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1; | 683 | link_state->aspm_enabled = |
679 | link_state->bios_aspm_state = 0; | 684 | (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); |
685 | link_state->aspm_default = 0; | ||
680 | /* Set support state to 0, so we will disable ASPM later */ | 686 | /* Set support state to 0, so we will disable ASPM later */ |
681 | link_state->support_state = 0; | 687 | link_state->aspm_support = 0; |
682 | } | 688 | } |
683 | 689 | ||
684 | link_state->pdev = pdev; | 690 | link_state->pdev = pdev; |
@@ -690,7 +696,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
690 | * initialization will config the whole hierarchy. but we must | 696 | * initialization will config the whole hierarchy. but we must |
691 | * make sure BIOS doesn't set unsupported link state | 697 | * make sure BIOS doesn't set unsupported link state |
692 | **/ | 698 | **/ |
693 | state = pcie_aspm_check_state(pdev, link_state->bios_aspm_state); | 699 | state = pcie_aspm_check_state(pdev, link_state->aspm_default); |
694 | __pcie_aspm_config_link(pdev, state); | 700 | __pcie_aspm_config_link(pdev, state); |
695 | } else | 701 | } else |
696 | __pcie_aspm_configure_link_state(pdev, | 702 | __pcie_aspm_configure_link_state(pdev, |
@@ -753,7 +759,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) | |||
753 | * devices changed PM state, we should recheck if latency meets all | 759 | * devices changed PM state, we should recheck if latency meets all |
754 | * functions' requirement | 760 | * functions' requirement |
755 | */ | 761 | */ |
756 | pcie_aspm_configure_link_state(pdev, link_state->enabled_state); | 762 | pcie_aspm_configure_link_state(pdev, link_state->aspm_enabled); |
757 | } | 763 | } |
758 | 764 | ||
759 | /* | 765 | /* |
@@ -776,12 +782,11 @@ void pci_disable_link_state(struct pci_dev *pdev, int state) | |||
776 | down_read(&pci_bus_sem); | 782 | down_read(&pci_bus_sem); |
777 | mutex_lock(&aspm_lock); | 783 | mutex_lock(&aspm_lock); |
778 | link_state = parent->link_state; | 784 | link_state = parent->link_state; |
779 | link_state->support_state &= | 785 | link_state->aspm_support &= ~state; |
780 | ~(state & (PCIE_LINK_STATE_L0S|PCIE_LINK_STATE_L1)); | ||
781 | if (state & PCIE_LINK_STATE_CLKPM) | 786 | if (state & PCIE_LINK_STATE_CLKPM) |
782 | link_state->clk_pm_capable = 0; | 787 | link_state->clk_pm_capable = 0; |
783 | 788 | ||
784 | __pcie_aspm_configure_link_state(parent, link_state->enabled_state); | 789 | __pcie_aspm_configure_link_state(parent, link_state->aspm_enabled); |
785 | if (!link_state->clk_pm_capable && link_state->clk_pm_enabled) | 790 | if (!link_state->clk_pm_capable && link_state->clk_pm_enabled) |
786 | pcie_set_clock_pm(parent, 0); | 791 | pcie_set_clock_pm(parent, 0); |
787 | mutex_unlock(&aspm_lock); | 792 | mutex_unlock(&aspm_lock); |
@@ -842,7 +847,7 @@ static ssize_t link_state_show(struct device *dev, | |||
842 | struct pci_dev *pci_device = to_pci_dev(dev); | 847 | struct pci_dev *pci_device = to_pci_dev(dev); |
843 | struct pcie_link_state *link_state = pci_device->link_state; | 848 | struct pcie_link_state *link_state = pci_device->link_state; |
844 | 849 | ||
845 | return sprintf(buf, "%d\n", link_state->enabled_state); | 850 | return sprintf(buf, "%d\n", link_state->aspm_enabled); |
846 | } | 851 | } |
847 | 852 | ||
848 | static ssize_t link_state_store(struct device *dev, | 853 | static ssize_t link_state_store(struct device *dev, |
@@ -908,7 +913,7 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) | |||
908 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) | 913 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) |
909 | return; | 914 | return; |
910 | 915 | ||
911 | if (link_state->support_state) | 916 | if (link_state->aspm_support) |
912 | sysfs_add_file_to_group(&pdev->dev.kobj, | 917 | sysfs_add_file_to_group(&pdev->dev.kobj, |
913 | &dev_attr_link_state.attr, power_group); | 918 | &dev_attr_link_state.attr, power_group); |
914 | if (link_state->clk_pm_capable) | 919 | if (link_state->clk_pm_capable) |
@@ -924,7 +929,7 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
924 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) | 929 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) |
925 | return; | 930 | return; |
926 | 931 | ||
927 | if (link_state->support_state) | 932 | if (link_state->aspm_support) |
928 | sysfs_remove_file_from_group(&pdev->dev.kobj, | 933 | sysfs_remove_file_from_group(&pdev->dev.kobj, |
929 | &dev_attr_link_state.attr, power_group); | 934 | &dev_attr_link_state.attr, power_group); |
930 | if (link_state->clk_pm_capable) | 935 | if (link_state->clk_pm_capable) |