diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/pci/pcie/aspm.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 211 |
1 files changed, 102 insertions, 109 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b52630b8ead..cbfbab18be9 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -68,7 +68,7 @@ struct pcie_link_state { | |||
68 | struct aspm_latency acceptable[8]; | 68 | struct aspm_latency acceptable[8]; |
69 | }; | 69 | }; |
70 | 70 | ||
71 | static int aspm_disabled, aspm_force; | 71 | static int aspm_disabled, aspm_force, aspm_clear_state; |
72 | static bool aspm_support_enabled = true; | 72 | static bool aspm_support_enabled = true; |
73 | static DEFINE_MUTEX(aspm_lock); | 73 | static DEFINE_MUTEX(aspm_lock); |
74 | static LIST_HEAD(link_list); | 74 | static LIST_HEAD(link_list); |
@@ -76,15 +76,7 @@ static LIST_HEAD(link_list); | |||
76 | #define POLICY_DEFAULT 0 /* BIOS default setting */ | 76 | #define POLICY_DEFAULT 0 /* BIOS default setting */ |
77 | #define POLICY_PERFORMANCE 1 /* high performance */ | 77 | #define POLICY_PERFORMANCE 1 /* high performance */ |
78 | #define POLICY_POWERSAVE 2 /* high power saving */ | 78 | #define POLICY_POWERSAVE 2 /* high power saving */ |
79 | |||
80 | #ifdef CONFIG_PCIEASPM_PERFORMANCE | ||
81 | static int aspm_policy = POLICY_PERFORMANCE; | ||
82 | #elif defined CONFIG_PCIEASPM_POWERSAVE | ||
83 | static int aspm_policy = POLICY_POWERSAVE; | ||
84 | #else | ||
85 | static int aspm_policy; | 79 | static int aspm_policy; |
86 | #endif | ||
87 | |||
88 | static const char *policy_str[] = { | 80 | static const char *policy_str[] = { |
89 | [POLICY_DEFAULT] = "default", | 81 | [POLICY_DEFAULT] = "default", |
90 | [POLICY_PERFORMANCE] = "performance", | 82 | [POLICY_PERFORMANCE] = "performance", |
@@ -125,16 +117,21 @@ static int policy_to_clkpm_state(struct pcie_link_state *link) | |||
125 | 117 | ||
126 | static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) | 118 | static void pcie_set_clkpm_nocheck(struct pcie_link_state *link, int enable) |
127 | { | 119 | { |
120 | int pos; | ||
121 | u16 reg16; | ||
128 | struct pci_dev *child; | 122 | struct pci_dev *child; |
129 | struct pci_bus *linkbus = link->pdev->subordinate; | 123 | struct pci_bus *linkbus = link->pdev->subordinate; |
130 | 124 | ||
131 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 125 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
126 | pos = pci_pcie_cap(child); | ||
127 | if (!pos) | ||
128 | return; | ||
129 | pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); | ||
132 | if (enable) | 130 | if (enable) |
133 | pcie_capability_set_word(child, PCI_EXP_LNKCTL, | 131 | reg16 |= PCI_EXP_LNKCTL_CLKREQ_EN; |
134 | PCI_EXP_LNKCTL_CLKREQ_EN); | ||
135 | else | 132 | else |
136 | pcie_capability_clear_word(child, PCI_EXP_LNKCTL, | 133 | reg16 &= ~PCI_EXP_LNKCTL_CLKREQ_EN; |
137 | PCI_EXP_LNKCTL_CLKREQ_EN); | 134 | pci_write_config_word(child, pos + PCI_EXP_LNKCTL, reg16); |
138 | } | 135 | } |
139 | link->clkpm_enabled = !!enable; | 136 | link->clkpm_enabled = !!enable; |
140 | } | 137 | } |
@@ -152,7 +149,7 @@ static void pcie_set_clkpm(struct pcie_link_state *link, int enable) | |||
152 | 149 | ||
153 | static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | 150 | static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) |
154 | { | 151 | { |
155 | int capable = 1, enabled = 1; | 152 | int pos, capable = 1, enabled = 1; |
156 | u32 reg32; | 153 | u32 reg32; |
157 | u16 reg16; | 154 | u16 reg16; |
158 | struct pci_dev *child; | 155 | struct pci_dev *child; |
@@ -160,13 +157,16 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | |||
160 | 157 | ||
161 | /* All functions should have the same cap and state, take the worst */ | 158 | /* All functions should have the same cap and state, take the worst */ |
162 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 159 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
163 | pcie_capability_read_dword(child, PCI_EXP_LNKCAP, ®32); | 160 | pos = pci_pcie_cap(child); |
161 | if (!pos) | ||
162 | return; | ||
163 | pci_read_config_dword(child, pos + PCI_EXP_LNKCAP, ®32); | ||
164 | if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) { | 164 | if (!(reg32 & PCI_EXP_LNKCAP_CLKPM)) { |
165 | capable = 0; | 165 | capable = 0; |
166 | enabled = 0; | 166 | enabled = 0; |
167 | break; | 167 | break; |
168 | } | 168 | } |
169 | pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); | 169 | pci_read_config_word(child, pos + PCI_EXP_LNKCTL, ®16); |
170 | if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN)) | 170 | if (!(reg16 & PCI_EXP_LNKCTL_CLKREQ_EN)) |
171 | enabled = 0; | 171 | enabled = 0; |
172 | } | 172 | } |
@@ -182,7 +182,7 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | |||
182 | */ | 182 | */ |
183 | static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | 183 | static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) |
184 | { | 184 | { |
185 | int same_clock = 1; | 185 | int ppos, cpos, same_clock = 1; |
186 | u16 reg16, parent_reg, child_reg[8]; | 186 | u16 reg16, parent_reg, child_reg[8]; |
187 | unsigned long start_jiffies; | 187 | unsigned long start_jiffies; |
188 | struct pci_dev *child, *parent = link->pdev; | 188 | struct pci_dev *child, *parent = link->pdev; |
@@ -195,43 +195,46 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | |||
195 | BUG_ON(!pci_is_pcie(child)); | 195 | BUG_ON(!pci_is_pcie(child)); |
196 | 196 | ||
197 | /* Check downstream component if bit Slot Clock Configuration is 1 */ | 197 | /* Check downstream component if bit Slot Clock Configuration is 1 */ |
198 | pcie_capability_read_word(child, PCI_EXP_LNKSTA, ®16); | 198 | cpos = pci_pcie_cap(child); |
199 | pci_read_config_word(child, cpos + PCI_EXP_LNKSTA, ®16); | ||
199 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) | 200 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) |
200 | same_clock = 0; | 201 | same_clock = 0; |
201 | 202 | ||
202 | /* Check upstream component if bit Slot Clock Configuration is 1 */ | 203 | /* Check upstream component if bit Slot Clock Configuration is 1 */ |
203 | pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); | 204 | ppos = pci_pcie_cap(parent); |
205 | pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); | ||
204 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) | 206 | if (!(reg16 & PCI_EXP_LNKSTA_SLC)) |
205 | same_clock = 0; | 207 | same_clock = 0; |
206 | 208 | ||
207 | /* Configure downstream component, all functions */ | 209 | /* Configure downstream component, all functions */ |
208 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 210 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
209 | pcie_capability_read_word(child, PCI_EXP_LNKCTL, ®16); | 211 | cpos = pci_pcie_cap(child); |
212 | pci_read_config_word(child, cpos + PCI_EXP_LNKCTL, ®16); | ||
210 | child_reg[PCI_FUNC(child->devfn)] = reg16; | 213 | child_reg[PCI_FUNC(child->devfn)] = reg16; |
211 | if (same_clock) | 214 | if (same_clock) |
212 | reg16 |= PCI_EXP_LNKCTL_CCC; | 215 | reg16 |= PCI_EXP_LNKCTL_CCC; |
213 | else | 216 | else |
214 | reg16 &= ~PCI_EXP_LNKCTL_CCC; | 217 | reg16 &= ~PCI_EXP_LNKCTL_CCC; |
215 | pcie_capability_write_word(child, PCI_EXP_LNKCTL, reg16); | 218 | pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, reg16); |
216 | } | 219 | } |
217 | 220 | ||
218 | /* Configure upstream component */ | 221 | /* Configure upstream component */ |
219 | pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); | 222 | pci_read_config_word(parent, ppos + PCI_EXP_LNKCTL, ®16); |
220 | parent_reg = reg16; | 223 | parent_reg = reg16; |
221 | if (same_clock) | 224 | if (same_clock) |
222 | reg16 |= PCI_EXP_LNKCTL_CCC; | 225 | reg16 |= PCI_EXP_LNKCTL_CCC; |
223 | else | 226 | else |
224 | reg16 &= ~PCI_EXP_LNKCTL_CCC; | 227 | reg16 &= ~PCI_EXP_LNKCTL_CCC; |
225 | pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); | 228 | pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16); |
226 | 229 | ||
227 | /* Retrain link */ | 230 | /* Retrain link */ |
228 | reg16 |= PCI_EXP_LNKCTL_RL; | 231 | reg16 |= PCI_EXP_LNKCTL_RL; |
229 | pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); | 232 | pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, reg16); |
230 | 233 | ||
231 | /* Wait for link training end. Break out after waiting for timeout */ | 234 | /* Wait for link training end. Break out after waiting for timeout */ |
232 | start_jiffies = jiffies; | 235 | start_jiffies = jiffies; |
233 | for (;;) { | 236 | for (;;) { |
234 | pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); | 237 | pci_read_config_word(parent, ppos + PCI_EXP_LNKSTA, ®16); |
235 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) | 238 | if (!(reg16 & PCI_EXP_LNKSTA_LT)) |
236 | break; | 239 | break; |
237 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) | 240 | if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) |
@@ -242,11 +245,14 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link) | |||
242 | return; | 245 | return; |
243 | 246 | ||
244 | /* Training failed. Restore common clock configurations */ | 247 | /* Training failed. Restore common clock configurations */ |
245 | dev_err(&parent->dev, "ASPM: Could not configure common clock\n"); | 248 | dev_printk(KERN_ERR, &parent->dev, |
246 | list_for_each_entry(child, &linkbus->devices, bus_list) | 249 | "ASPM: Could not configure common clock\n"); |
247 | pcie_capability_write_word(child, PCI_EXP_LNKCTL, | 250 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
248 | child_reg[PCI_FUNC(child->devfn)]); | 251 | cpos = pci_pcie_cap(child); |
249 | pcie_capability_write_word(parent, PCI_EXP_LNKCTL, parent_reg); | 252 | pci_write_config_word(child, cpos + PCI_EXP_LNKCTL, |
253 | child_reg[PCI_FUNC(child->devfn)]); | ||
254 | } | ||
255 | pci_write_config_word(parent, ppos + PCI_EXP_LNKCTL, parent_reg); | ||
250 | } | 256 | } |
251 | 257 | ||
252 | /* Convert L0s latency encoding to ns */ | 258 | /* Convert L0s latency encoding to ns */ |
@@ -291,14 +297,16 @@ struct aspm_register_info { | |||
291 | static void pcie_get_aspm_reg(struct pci_dev *pdev, | 297 | static void pcie_get_aspm_reg(struct pci_dev *pdev, |
292 | struct aspm_register_info *info) | 298 | struct aspm_register_info *info) |
293 | { | 299 | { |
300 | int pos; | ||
294 | u16 reg16; | 301 | u16 reg16; |
295 | u32 reg32; | 302 | u32 reg32; |
296 | 303 | ||
297 | pcie_capability_read_dword(pdev, PCI_EXP_LNKCAP, ®32); | 304 | pos = pci_pcie_cap(pdev); |
305 | pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); | ||
298 | info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; | 306 | info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; |
299 | info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; | 307 | info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; |
300 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; | 308 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; |
301 | pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, ®16); | 309 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); |
302 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; | 310 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; |
303 | } | 311 | } |
304 | 312 | ||
@@ -396,7 +404,7 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
396 | * do ASPM for now. | 404 | * do ASPM for now. |
397 | */ | 405 | */ |
398 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 406 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
399 | if (pci_pcie_type(child) == PCI_EXP_TYPE_PCI_BRIDGE) { | 407 | if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { |
400 | link->aspm_disable = ASPM_STATE_ALL; | 408 | link->aspm_disable = ASPM_STATE_ALL; |
401 | break; | 409 | break; |
402 | } | 410 | } |
@@ -404,15 +412,17 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
404 | 412 | ||
405 | /* Get and check endpoint acceptable latencies */ | 413 | /* Get and check endpoint acceptable latencies */ |
406 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 414 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
415 | int pos; | ||
407 | u32 reg32, encoding; | 416 | u32 reg32, encoding; |
408 | struct aspm_latency *acceptable = | 417 | struct aspm_latency *acceptable = |
409 | &link->acceptable[PCI_FUNC(child->devfn)]; | 418 | &link->acceptable[PCI_FUNC(child->devfn)]; |
410 | 419 | ||
411 | if (pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT && | 420 | if (child->pcie_type != PCI_EXP_TYPE_ENDPOINT && |
412 | pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END) | 421 | child->pcie_type != PCI_EXP_TYPE_LEG_END) |
413 | continue; | 422 | continue; |
414 | 423 | ||
415 | pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); | 424 | pos = pci_pcie_cap(child); |
425 | pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); | ||
416 | /* Calculate endpoint L0s acceptable latency */ | 426 | /* Calculate endpoint L0s acceptable latency */ |
417 | encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; | 427 | encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; |
418 | acceptable->l0s = calc_l0s_acceptable(encoding); | 428 | acceptable->l0s = calc_l0s_acceptable(encoding); |
@@ -426,8 +436,13 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
426 | 436 | ||
427 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) | 437 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) |
428 | { | 438 | { |
429 | pcie_capability_clear_and_set_word(pdev, PCI_EXP_LNKCTL, | 439 | u16 reg16; |
430 | PCI_EXP_LNKCTL_ASPMC, val); | 440 | int pos = pci_pcie_cap(pdev); |
441 | |||
442 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | ||
443 | reg16 &= ~0x3; | ||
444 | reg16 |= val; | ||
445 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); | ||
431 | } | 446 | } |
432 | 447 | ||
433 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) | 448 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) |
@@ -442,12 +457,12 @@ static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) | |||
442 | return; | 457 | return; |
443 | /* Convert ASPM state to upstream/downstream ASPM register state */ | 458 | /* Convert ASPM state to upstream/downstream ASPM register state */ |
444 | if (state & ASPM_STATE_L0S_UP) | 459 | if (state & ASPM_STATE_L0S_UP) |
445 | dwstream |= PCI_EXP_LNKCTL_ASPM_L0S; | 460 | dwstream |= PCIE_LINK_STATE_L0S; |
446 | if (state & ASPM_STATE_L0S_DW) | 461 | if (state & ASPM_STATE_L0S_DW) |
447 | upstream |= PCI_EXP_LNKCTL_ASPM_L0S; | 462 | upstream |= PCIE_LINK_STATE_L0S; |
448 | if (state & ASPM_STATE_L1) { | 463 | if (state & ASPM_STATE_L1) { |
449 | upstream |= PCI_EXP_LNKCTL_ASPM_L1; | 464 | upstream |= PCIE_LINK_STATE_L1; |
450 | dwstream |= PCI_EXP_LNKCTL_ASPM_L1; | 465 | dwstream |= PCIE_LINK_STATE_L1; |
451 | } | 466 | } |
452 | /* | 467 | /* |
453 | * Spec 2.0 suggests all functions should be configured the | 468 | * Spec 2.0 suggests all functions should be configured the |
@@ -482,32 +497,29 @@ static void free_link_state(struct pcie_link_state *link) | |||
482 | static int pcie_aspm_sanity_check(struct pci_dev *pdev) | 497 | static int pcie_aspm_sanity_check(struct pci_dev *pdev) |
483 | { | 498 | { |
484 | struct pci_dev *child; | 499 | struct pci_dev *child; |
500 | int pos; | ||
485 | u32 reg32; | 501 | u32 reg32; |
486 | 502 | ||
503 | if (aspm_clear_state) | ||
504 | return -EINVAL; | ||
505 | |||
487 | /* | 506 | /* |
488 | * Some functions in a slot might not all be PCIe functions, | 507 | * Some functions in a slot might not all be PCIe functions, |
489 | * very strange. Disable ASPM for the whole slot | 508 | * very strange. Disable ASPM for the whole slot |
490 | */ | 509 | */ |
491 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { | 510 | list_for_each_entry(child, &pdev->subordinate->devices, bus_list) { |
492 | if (!pci_is_pcie(child)) | 511 | pos = pci_pcie_cap(child); |
512 | if (!pos) | ||
493 | return -EINVAL; | 513 | return -EINVAL; |
494 | |||
495 | /* | ||
496 | * If ASPM is disabled then we're not going to change | ||
497 | * the BIOS state. It's safe to continue even if it's a | ||
498 | * pre-1.1 device | ||
499 | */ | ||
500 | |||
501 | if (aspm_disabled) | ||
502 | continue; | ||
503 | |||
504 | /* | 514 | /* |
505 | * Disable ASPM for pre-1.1 PCIe device, we follow MS to use | 515 | * Disable ASPM for pre-1.1 PCIe device, we follow MS to use |
506 | * RBER bit to determine if a function is 1.1 version device | 516 | * RBER bit to determine if a function is 1.1 version device |
507 | */ | 517 | */ |
508 | pcie_capability_read_dword(child, PCI_EXP_DEVCAP, ®32); | 518 | pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); |
509 | if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { | 519 | if (!(reg32 & PCI_EXP_DEVCAP_RBER) && !aspm_force) { |
510 | dev_info(&child->dev, "disabling ASPM on pre-1.1 PCIe device. You can enable it with 'pcie_aspm=force'\n"); | 520 | dev_printk(KERN_INFO, &child->dev, "disabling ASPM" |
521 | " on pre-1.1 PCIe device. You can enable it" | ||
522 | " with 'pcie_aspm=force'\n"); | ||
511 | return -EINVAL; | 523 | return -EINVAL; |
512 | } | 524 | } |
513 | } | 525 | } |
@@ -525,7 +537,7 @@ static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) | |||
525 | INIT_LIST_HEAD(&link->children); | 537 | INIT_LIST_HEAD(&link->children); |
526 | INIT_LIST_HEAD(&link->link); | 538 | INIT_LIST_HEAD(&link->link); |
527 | link->pdev = pdev; | 539 | link->pdev = pdev; |
528 | if (pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) { | 540 | if (pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) { |
529 | struct pcie_link_state *parent; | 541 | struct pcie_link_state *parent; |
530 | parent = pdev->bus->parent->self->link_state; | 542 | parent = pdev->bus->parent->self->link_state; |
531 | if (!parent) { | 543 | if (!parent) { |
@@ -558,12 +570,15 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
558 | 570 | ||
559 | if (!pci_is_pcie(pdev) || pdev->link_state) | 571 | if (!pci_is_pcie(pdev) || pdev->link_state) |
560 | return; | 572 | return; |
561 | if (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && | 573 | if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && |
562 | pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) | 574 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) |
575 | return; | ||
576 | |||
577 | if (aspm_disabled && !aspm_clear_state) | ||
563 | return; | 578 | return; |
564 | 579 | ||
565 | /* VIA has a strange chipset, root port is under a bridge */ | 580 | /* VIA has a strange chipset, root port is under a bridge */ |
566 | if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT && | 581 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT && |
567 | pdev->bus->self) | 582 | pdev->bus->self) |
568 | return; | 583 | return; |
569 | 584 | ||
@@ -593,7 +608,7 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
593 | * the BIOS's expectation, we'll do so once pci_enable_device() is | 608 | * the BIOS's expectation, we'll do so once pci_enable_device() is |
594 | * called. | 609 | * called. |
595 | */ | 610 | */ |
596 | if (aspm_policy != POLICY_POWERSAVE) { | 611 | if (aspm_policy != POLICY_POWERSAVE || aspm_clear_state) { |
597 | pcie_config_aspm_path(link); | 612 | pcie_config_aspm_path(link); |
598 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); | 613 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); |
599 | } | 614 | } |
@@ -620,8 +635,8 @@ static void pcie_update_aspm_capable(struct pcie_link_state *root) | |||
620 | if (link->root != root) | 635 | if (link->root != root) |
621 | continue; | 636 | continue; |
622 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 637 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
623 | if ((pci_pcie_type(child) != PCI_EXP_TYPE_ENDPOINT) && | 638 | if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) && |
624 | (pci_pcie_type(child) != PCI_EXP_TYPE_LEG_END)) | 639 | (child->pcie_type != PCI_EXP_TYPE_LEG_END)) |
625 | continue; | 640 | continue; |
626 | pcie_aspm_check_latency(child); | 641 | pcie_aspm_check_latency(child); |
627 | } | 642 | } |
@@ -634,10 +649,11 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) | |||
634 | struct pci_dev *parent = pdev->bus->self; | 649 | struct pci_dev *parent = pdev->bus->self; |
635 | struct pcie_link_state *link, *root, *parent_link; | 650 | struct pcie_link_state *link, *root, *parent_link; |
636 | 651 | ||
637 | if (!pci_is_pcie(pdev) || !parent || !parent->link_state) | 652 | if ((aspm_disabled && !aspm_clear_state) || !pci_is_pcie(pdev) || |
653 | !parent || !parent->link_state) | ||
638 | return; | 654 | return; |
639 | if ((pci_pcie_type(parent) != PCI_EXP_TYPE_ROOT_PORT) && | 655 | if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
640 | (pci_pcie_type(parent) != PCI_EXP_TYPE_DOWNSTREAM)) | 656 | (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) |
641 | return; | 657 | return; |
642 | 658 | ||
643 | down_read(&pci_bus_sem); | 659 | down_read(&pci_bus_sem); |
@@ -677,8 +693,8 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) | |||
677 | 693 | ||
678 | if (aspm_disabled || !pci_is_pcie(pdev) || !link) | 694 | if (aspm_disabled || !pci_is_pcie(pdev) || !link) |
679 | return; | 695 | return; |
680 | if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && | 696 | if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
681 | (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) | 697 | (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) |
682 | return; | 698 | return; |
683 | /* | 699 | /* |
684 | * Devices changed PM state, we should recheck if latency | 700 | * Devices changed PM state, we should recheck if latency |
@@ -702,8 +718,8 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) | |||
702 | if (aspm_policy != POLICY_POWERSAVE) | 718 | if (aspm_policy != POLICY_POWERSAVE) |
703 | return; | 719 | return; |
704 | 720 | ||
705 | if ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) && | 721 | if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
706 | (pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM)) | 722 | (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) |
707 | return; | 723 | return; |
708 | 724 | ||
709 | down_read(&pci_bus_sem); | 725 | down_read(&pci_bus_sem); |
@@ -718,20 +734,15 @@ void pcie_aspm_powersave_config_link(struct pci_dev *pdev) | |||
718 | * pci_disable_link_state - disable pci device's link state, so the link will | 734 | * pci_disable_link_state - disable pci device's link state, so the link will |
719 | * never enter specific states | 735 | * never enter specific states |
720 | */ | 736 | */ |
721 | static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, | 737 | static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem) |
722 | bool force) | ||
723 | { | 738 | { |
724 | struct pci_dev *parent = pdev->bus->self; | 739 | struct pci_dev *parent = pdev->bus->self; |
725 | struct pcie_link_state *link; | 740 | struct pcie_link_state *link; |
726 | 741 | ||
727 | if (aspm_disabled && !force) | 742 | if (aspm_disabled || !pci_is_pcie(pdev)) |
728 | return; | ||
729 | |||
730 | if (!pci_is_pcie(pdev)) | ||
731 | return; | 743 | return; |
732 | 744 | if (pdev->pcie_type == PCI_EXP_TYPE_ROOT_PORT || | |
733 | if (pci_pcie_type(pdev) == PCI_EXP_TYPE_ROOT_PORT || | 745 | pdev->pcie_type == PCI_EXP_TYPE_DOWNSTREAM) |
734 | pci_pcie_type(pdev) == PCI_EXP_TYPE_DOWNSTREAM) | ||
735 | parent = pdev; | 746 | parent = pdev; |
736 | if (!parent || !parent->link_state) | 747 | if (!parent || !parent->link_state) |
737 | return; | 748 | return; |
@@ -757,31 +768,16 @@ static void __pci_disable_link_state(struct pci_dev *pdev, int state, bool sem, | |||
757 | 768 | ||
758 | void pci_disable_link_state_locked(struct pci_dev *pdev, int state) | 769 | void pci_disable_link_state_locked(struct pci_dev *pdev, int state) |
759 | { | 770 | { |
760 | __pci_disable_link_state(pdev, state, false, false); | 771 | __pci_disable_link_state(pdev, state, false); |
761 | } | 772 | } |
762 | EXPORT_SYMBOL(pci_disable_link_state_locked); | 773 | EXPORT_SYMBOL(pci_disable_link_state_locked); |
763 | 774 | ||
764 | void pci_disable_link_state(struct pci_dev *pdev, int state) | 775 | void pci_disable_link_state(struct pci_dev *pdev, int state) |
765 | { | 776 | { |
766 | __pci_disable_link_state(pdev, state, true, false); | 777 | __pci_disable_link_state(pdev, state, true); |
767 | } | 778 | } |
768 | EXPORT_SYMBOL(pci_disable_link_state); | 779 | EXPORT_SYMBOL(pci_disable_link_state); |
769 | 780 | ||
770 | void pcie_clear_aspm(struct pci_bus *bus) | ||
771 | { | ||
772 | struct pci_dev *child; | ||
773 | |||
774 | /* | ||
775 | * Clear any ASPM setup that the firmware has carried out on this bus | ||
776 | */ | ||
777 | list_for_each_entry(child, &bus->devices, bus_list) { | ||
778 | __pci_disable_link_state(child, PCIE_LINK_STATE_L0S | | ||
779 | PCIE_LINK_STATE_L1 | | ||
780 | PCIE_LINK_STATE_CLKPM, | ||
781 | false, true); | ||
782 | } | ||
783 | } | ||
784 | |||
785 | static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) | 781 | static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) |
786 | { | 782 | { |
787 | int i; | 783 | int i; |
@@ -906,8 +902,8 @@ void pcie_aspm_create_sysfs_dev_files(struct pci_dev *pdev) | |||
906 | struct pcie_link_state *link_state = pdev->link_state; | 902 | struct pcie_link_state *link_state = pdev->link_state; |
907 | 903 | ||
908 | if (!pci_is_pcie(pdev) || | 904 | if (!pci_is_pcie(pdev) || |
909 | (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && | 905 | (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && |
910 | pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) | 906 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) |
911 | return; | 907 | return; |
912 | 908 | ||
913 | if (link_state->aspm_support) | 909 | if (link_state->aspm_support) |
@@ -923,8 +919,8 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
923 | struct pcie_link_state *link_state = pdev->link_state; | 919 | struct pcie_link_state *link_state = pdev->link_state; |
924 | 920 | ||
925 | if (!pci_is_pcie(pdev) || | 921 | if (!pci_is_pcie(pdev) || |
926 | (pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT && | 922 | (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && |
927 | pci_pcie_type(pdev) != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) | 923 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) || !link_state) |
928 | return; | 924 | return; |
929 | 925 | ||
930 | if (link_state->aspm_support) | 926 | if (link_state->aspm_support) |
@@ -939,7 +935,6 @@ void pcie_aspm_remove_sysfs_dev_files(struct pci_dev *pdev) | |||
939 | static int __init pcie_aspm_disable(char *str) | 935 | static int __init pcie_aspm_disable(char *str) |
940 | { | 936 | { |
941 | if (!strcmp(str, "off")) { | 937 | if (!strcmp(str, "off")) { |
942 | aspm_policy = POLICY_DEFAULT; | ||
943 | aspm_disabled = 1; | 938 | aspm_disabled = 1; |
944 | aspm_support_enabled = false; | 939 | aspm_support_enabled = false; |
945 | printk(KERN_INFO "PCIe ASPM is disabled\n"); | 940 | printk(KERN_INFO "PCIe ASPM is disabled\n"); |
@@ -952,18 +947,16 @@ static int __init pcie_aspm_disable(char *str) | |||
952 | 947 | ||
953 | __setup("pcie_aspm=", pcie_aspm_disable); | 948 | __setup("pcie_aspm=", pcie_aspm_disable); |
954 | 949 | ||
950 | void pcie_clear_aspm(void) | ||
951 | { | ||
952 | if (!aspm_force) | ||
953 | aspm_clear_state = 1; | ||
954 | } | ||
955 | |||
955 | void pcie_no_aspm(void) | 956 | void pcie_no_aspm(void) |
956 | { | 957 | { |
957 | /* | 958 | if (!aspm_force) |
958 | * Disabling ASPM is intended to prevent the kernel from modifying | ||
959 | * existing hardware state, not to clear existing state. To that end: | ||
960 | * (a) set policy to POLICY_DEFAULT in order to avoid changing state | ||
961 | * (b) prevent userspace from changing policy | ||
962 | */ | ||
963 | if (!aspm_force) { | ||
964 | aspm_policy = POLICY_DEFAULT; | ||
965 | aspm_disabled = 1; | 959 | aspm_disabled = 1; |
966 | } | ||
967 | } | 960 | } |
968 | 961 | ||
969 | /** | 962 | /** |