diff options
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 495 |
1 files changed, 241 insertions, 254 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 3d27c97e0486..f289ca9bf18d 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -26,6 +26,13 @@ | |||
26 | #endif | 26 | #endif |
27 | #define MODULE_PARAM_PREFIX "pcie_aspm." | 27 | #define MODULE_PARAM_PREFIX "pcie_aspm." |
28 | 28 | ||
29 | /* Note: those are not register definitions */ | ||
30 | #define ASPM_STATE_L0S_UP (1) /* Upstream direction L0s state */ | ||
31 | #define ASPM_STATE_L0S_DW (2) /* Downstream direction L0s state */ | ||
32 | #define ASPM_STATE_L1 (4) /* L1 state */ | ||
33 | #define ASPM_STATE_L0S (ASPM_STATE_L0S_UP | ASPM_STATE_L0S_DW) | ||
34 | #define ASPM_STATE_ALL (ASPM_STATE_L0S | ASPM_STATE_L1) | ||
35 | |||
29 | struct aspm_latency { | 36 | struct aspm_latency { |
30 | u32 l0s; /* L0s latency (nsec) */ | 37 | u32 l0s; /* L0s latency (nsec) */ |
31 | u32 l1; /* L1 latency (nsec) */ | 38 | u32 l1; /* L1 latency (nsec) */ |
@@ -40,17 +47,20 @@ struct pcie_link_state { | |||
40 | struct list_head link; /* node in parent's children list */ | 47 | struct list_head link; /* node in parent's children list */ |
41 | 48 | ||
42 | /* ASPM state */ | 49 | /* ASPM state */ |
43 | u32 aspm_support:2; /* Supported ASPM state */ | 50 | u32 aspm_support:3; /* Supported ASPM state */ |
44 | u32 aspm_enabled:2; /* Enabled ASPM state */ | 51 | u32 aspm_enabled:3; /* Enabled ASPM state */ |
45 | u32 aspm_default:2; /* Default ASPM state by BIOS */ | 52 | u32 aspm_capable:3; /* Capable ASPM state with latency */ |
53 | u32 aspm_default:3; /* Default ASPM state by BIOS */ | ||
54 | u32 aspm_disable:3; /* Disabled ASPM state */ | ||
46 | 55 | ||
47 | /* Clock PM state */ | 56 | /* Clock PM state */ |
48 | u32 clkpm_capable:1; /* Clock PM capable? */ | 57 | u32 clkpm_capable:1; /* Clock PM capable? */ |
49 | u32 clkpm_enabled:1; /* Current Clock PM state */ | 58 | u32 clkpm_enabled:1; /* Current Clock PM state */ |
50 | u32 clkpm_default:1; /* Default Clock PM state by BIOS */ | 59 | u32 clkpm_default:1; /* Default Clock PM state by BIOS */ |
51 | 60 | ||
52 | /* Latencies */ | 61 | /* Exit latencies */ |
53 | struct aspm_latency latency; /* Exit latency */ | 62 | struct aspm_latency latency_up; /* Upstream direction exit latency */ |
63 | struct aspm_latency latency_dw; /* Downstream direction exit latency */ | ||
54 | /* | 64 | /* |
55 | * Endpoint acceptable latencies. A pcie downstream port only | 65 | * Endpoint acceptable latencies. A pcie downstream port only |
56 | * has one slot under it, so at most there are 8 functions. | 66 | * has one slot under it, so at most there are 8 functions. |
@@ -82,7 +92,7 @@ static int policy_to_aspm_state(struct pcie_link_state *link) | |||
82 | return 0; | 92 | return 0; |
83 | case POLICY_POWERSAVE: | 93 | case POLICY_POWERSAVE: |
84 | /* Enable ASPM L0s/L1 */ | 94 | /* Enable ASPM L0s/L1 */ |
85 | return PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1; | 95 | return ASPM_STATE_ALL; |
86 | case POLICY_DEFAULT: | 96 | case POLICY_DEFAULT: |
87 | return link->aspm_default; | 97 | return link->aspm_default; |
88 | } | 98 | } |
@@ -164,18 +174,6 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) | |||
164 | link->clkpm_capable = (blacklist) ? 0 : capable; | 174 | link->clkpm_capable = (blacklist) ? 0 : capable; |
165 | } | 175 | } |
166 | 176 | ||
167 | static bool pcie_aspm_downstream_has_switch(struct pcie_link_state *link) | ||
168 | { | ||
169 | struct pci_dev *child; | ||
170 | struct pci_bus *linkbus = link->pdev->subordinate; | ||
171 | |||
172 | list_for_each_entry(child, &linkbus->devices, bus_list) { | ||
173 | if (child->pcie_type == PCI_EXP_TYPE_UPSTREAM) | ||
174 | return true; | ||
175 | } | ||
176 | return false; | ||
177 | } | ||
178 | |||
179 | /* | 177 | /* |
180 | * pcie_aspm_configure_common_clock: check if the 2 ends of a link | 178 | * pcie_aspm_configure_common_clock: check if the 2 ends of a link |
181 | * could use common clock. If they are, configure them to use the | 179 | * could use common clock. If they are, configure them to use the |
@@ -288,71 +286,133 @@ static u32 calc_l1_acceptable(u32 encoding) | |||
288 | return (1000 << encoding); | 286 | return (1000 << encoding); |
289 | } | 287 | } |
290 | 288 | ||
291 | static void pcie_aspm_get_cap_device(struct pci_dev *pdev, u32 *state, | 289 | struct aspm_register_info { |
292 | u32 *l0s, u32 *l1, u32 *enabled) | 290 | u32 support:2; |
291 | u32 enabled:2; | ||
292 | u32 latency_encoding_l0s; | ||
293 | u32 latency_encoding_l1; | ||
294 | }; | ||
295 | |||
296 | static void pcie_get_aspm_reg(struct pci_dev *pdev, | ||
297 | struct aspm_register_info *info) | ||
293 | { | 298 | { |
294 | int pos; | 299 | int pos; |
295 | u16 reg16; | 300 | u16 reg16; |
296 | u32 reg32, encoding; | 301 | u32 reg32; |
297 | 302 | ||
298 | *l0s = *l1 = *enabled = 0; | ||
299 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 303 | pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
300 | pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); | 304 | pci_read_config_dword(pdev, pos + PCI_EXP_LNKCAP, ®32); |
301 | *state = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; | 305 | info->support = (reg32 & PCI_EXP_LNKCAP_ASPMS) >> 10; |
302 | if (*state != PCIE_LINK_STATE_L0S && | 306 | /* 00b and 10b are defined as "Reserved". */ |
303 | *state != (PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_L0S)) | 307 | if (info->support == PCIE_LINK_STATE_L1) |
304 | *state = 0; | 308 | info->support = 0; |
305 | if (*state == 0) | 309 | info->latency_encoding_l0s = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; |
310 | info->latency_encoding_l1 = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; | ||
311 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | ||
312 | info->enabled = reg16 & PCI_EXP_LNKCTL_ASPMC; | ||
313 | } | ||
314 | |||
315 | static void pcie_aspm_check_latency(struct pci_dev *endpoint) | ||
316 | { | ||
317 | u32 latency, l1_switch_latency = 0; | ||
318 | struct aspm_latency *acceptable; | ||
319 | struct pcie_link_state *link; | ||
320 | |||
321 | /* Device not in D0 doesn't need latency check */ | ||
322 | if ((endpoint->current_state != PCI_D0) && | ||
323 | (endpoint->current_state != PCI_UNKNOWN)) | ||
306 | return; | 324 | return; |
307 | 325 | ||
308 | encoding = (reg32 & PCI_EXP_LNKCAP_L0SEL) >> 12; | 326 | link = endpoint->bus->self->link_state; |
309 | *l0s = calc_l0s_latency(encoding); | 327 | acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)]; |
310 | if (*state & PCIE_LINK_STATE_L1) { | 328 | |
311 | encoding = (reg32 & PCI_EXP_LNKCAP_L1EL) >> 15; | 329 | while (link) { |
312 | *l1 = calc_l1_latency(encoding); | 330 | /* Check upstream direction L0s latency */ |
331 | if ((link->aspm_capable & ASPM_STATE_L0S_UP) && | ||
332 | (link->latency_up.l0s > acceptable->l0s)) | ||
333 | link->aspm_capable &= ~ASPM_STATE_L0S_UP; | ||
334 | |||
335 | /* Check downstream direction L0s latency */ | ||
336 | if ((link->aspm_capable & ASPM_STATE_L0S_DW) && | ||
337 | (link->latency_dw.l0s > acceptable->l0s)) | ||
338 | link->aspm_capable &= ~ASPM_STATE_L0S_DW; | ||
339 | /* | ||
340 | * Check L1 latency. | ||
341 | * Every switch on the path to root complex need 1 | ||
342 | * more microsecond for L1. Spec doesn't mention L0s. | ||
343 | */ | ||
344 | latency = max_t(u32, link->latency_up.l1, link->latency_dw.l1); | ||
345 | if ((link->aspm_capable & ASPM_STATE_L1) && | ||
346 | (latency + l1_switch_latency > acceptable->l1)) | ||
347 | link->aspm_capable &= ~ASPM_STATE_L1; | ||
348 | l1_switch_latency += 1000; | ||
349 | |||
350 | link = link->parent; | ||
313 | } | 351 | } |
314 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | ||
315 | *enabled = reg16 & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); | ||
316 | } | 352 | } |
317 | 353 | ||
318 | static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | 354 | static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) |
319 | { | 355 | { |
320 | u32 support, l0s, l1, enabled; | ||
321 | struct pci_dev *child, *parent = link->pdev; | 356 | struct pci_dev *child, *parent = link->pdev; |
322 | struct pci_bus *linkbus = parent->subordinate; | 357 | struct pci_bus *linkbus = parent->subordinate; |
358 | struct aspm_register_info upreg, dwreg; | ||
323 | 359 | ||
324 | if (blacklist) { | 360 | if (blacklist) { |
325 | /* Set support state to 0, so we will disable ASPM later */ | 361 | /* Set enabled/disable so that we will disable ASPM later */ |
326 | link->aspm_support = 0; | 362 | link->aspm_enabled = ASPM_STATE_ALL; |
327 | link->aspm_default = 0; | 363 | link->aspm_disable = ASPM_STATE_ALL; |
328 | link->aspm_enabled = PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1; | ||
329 | return; | 364 | return; |
330 | } | 365 | } |
331 | 366 | ||
332 | /* Configure common clock before checking latencies */ | 367 | /* Configure common clock before checking latencies */ |
333 | pcie_aspm_configure_common_clock(link); | 368 | pcie_aspm_configure_common_clock(link); |
334 | 369 | ||
335 | /* upstream component states */ | 370 | /* Get upstream/downstream components' register state */ |
336 | pcie_aspm_get_cap_device(parent, &support, &l0s, &l1, &enabled); | 371 | pcie_get_aspm_reg(parent, &upreg); |
337 | link->aspm_support = support; | ||
338 | link->latency.l0s = l0s; | ||
339 | link->latency.l1 = l1; | ||
340 | link->aspm_enabled = enabled; | ||
341 | |||
342 | /* downstream component states, all functions have the same setting */ | ||
343 | child = list_entry(linkbus->devices.next, struct pci_dev, bus_list); | 372 | child = list_entry(linkbus->devices.next, struct pci_dev, bus_list); |
344 | pcie_aspm_get_cap_device(child, &support, &l0s, &l1, &enabled); | 373 | pcie_get_aspm_reg(child, &dwreg); |
345 | link->aspm_support &= support; | ||
346 | link->latency.l0s = max_t(u32, link->latency.l0s, l0s); | ||
347 | link->latency.l1 = max_t(u32, link->latency.l1, l1); | ||
348 | 374 | ||
349 | if (!link->aspm_support) | 375 | /* |
350 | return; | 376 | * Setup L0s state |
351 | 377 | * | |
352 | link->aspm_enabled &= link->aspm_support; | 378 | * Note that we must not enable L0s in either direction on a |
379 | * given link unless components on both sides of the link each | ||
380 | * support L0s. | ||
381 | */ | ||
382 | if (dwreg.support & upreg.support & PCIE_LINK_STATE_L0S) | ||
383 | link->aspm_support |= ASPM_STATE_L0S; | ||
384 | if (dwreg.enabled & PCIE_LINK_STATE_L0S) | ||
385 | link->aspm_enabled |= ASPM_STATE_L0S_UP; | ||
386 | if (upreg.enabled & PCIE_LINK_STATE_L0S) | ||
387 | link->aspm_enabled |= ASPM_STATE_L0S_DW; | ||
388 | link->latency_up.l0s = calc_l0s_latency(upreg.latency_encoding_l0s); | ||
389 | link->latency_dw.l0s = calc_l0s_latency(dwreg.latency_encoding_l0s); | ||
390 | |||
391 | /* Setup L1 state */ | ||
392 | if (upreg.support & dwreg.support & PCIE_LINK_STATE_L1) | ||
393 | link->aspm_support |= ASPM_STATE_L1; | ||
394 | if (upreg.enabled & dwreg.enabled & PCIE_LINK_STATE_L1) | ||
395 | link->aspm_enabled |= ASPM_STATE_L1; | ||
396 | link->latency_up.l1 = calc_l1_latency(upreg.latency_encoding_l1); | ||
397 | link->latency_dw.l1 = calc_l1_latency(dwreg.latency_encoding_l1); | ||
398 | |||
399 | /* Save default state */ | ||
353 | link->aspm_default = link->aspm_enabled; | 400 | link->aspm_default = link->aspm_enabled; |
354 | 401 | ||
355 | /* ENDPOINT states*/ | 402 | /* Setup initial capable state. Will be updated later */ |
403 | link->aspm_capable = link->aspm_support; | ||
404 | /* | ||
405 | * If the downstream component has pci bridge function, don't | ||
406 | * do ASPM for now. | ||
407 | */ | ||
408 | list_for_each_entry(child, &linkbus->devices, bus_list) { | ||
409 | if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) { | ||
410 | link->aspm_disable = ASPM_STATE_ALL; | ||
411 | break; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | /* Get and check endpoint acceptable latencies */ | ||
356 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 416 | list_for_each_entry(child, &linkbus->devices, bus_list) { |
357 | int pos; | 417 | int pos; |
358 | u32 reg32, encoding; | 418 | u32 reg32, encoding; |
@@ -365,109 +425,46 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
365 | 425 | ||
366 | pos = pci_find_capability(child, PCI_CAP_ID_EXP); | 426 | pos = pci_find_capability(child, PCI_CAP_ID_EXP); |
367 | pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); | 427 | pci_read_config_dword(child, pos + PCI_EXP_DEVCAP, ®32); |
428 | /* Calculate endpoint L0s acceptable latency */ | ||
368 | encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; | 429 | encoding = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; |
369 | acceptable->l0s = calc_l0s_acceptable(encoding); | 430 | acceptable->l0s = calc_l0s_acceptable(encoding); |
370 | if (link->aspm_support & PCIE_LINK_STATE_L1) { | 431 | /* Calculate endpoint L1 acceptable latency */ |
371 | encoding = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; | 432 | encoding = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; |
372 | acceptable->l1 = calc_l1_acceptable(encoding); | 433 | acceptable->l1 = calc_l1_acceptable(encoding); |
373 | } | ||
374 | } | ||
375 | } | ||
376 | |||
377 | /** | ||
378 | * __pcie_aspm_check_state_one - check latency for endpoint device. | ||
379 | * @endpoint: pointer to the struct pci_dev of endpoint device | ||
380 | * | ||
381 | * TBD: The latency from the endpoint to root complex vary per switch's | ||
382 | * upstream link state above the device. Here we just do a simple check | ||
383 | * which assumes all links above the device can be in L1 state, that | ||
384 | * is we just consider the worst case. If switch's upstream link can't | ||
385 | * be put into L0S/L1, then our check is too strictly. | ||
386 | */ | ||
387 | static u32 __pcie_aspm_check_state_one(struct pci_dev *endpoint, u32 state) | ||
388 | { | ||
389 | u32 l1_switch_latency = 0; | ||
390 | struct aspm_latency *acceptable; | ||
391 | struct pcie_link_state *link; | ||
392 | |||
393 | link = endpoint->bus->self->link_state; | ||
394 | state &= link->aspm_support; | ||
395 | acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)]; | ||
396 | 434 | ||
397 | while (link && state) { | 435 | pcie_aspm_check_latency(child); |
398 | if ((state & PCIE_LINK_STATE_L0S) && | ||
399 | (link->latency.l0s > acceptable->l0s)) | ||
400 | state &= ~PCIE_LINK_STATE_L0S; | ||
401 | if ((state & PCIE_LINK_STATE_L1) && | ||
402 | (link->latency.l1 + l1_switch_latency > acceptable->l1)) | ||
403 | state &= ~PCIE_LINK_STATE_L1; | ||
404 | link = link->parent; | ||
405 | /* | ||
406 | * Every switch on the path to root complex need 1 | ||
407 | * more microsecond for L1. Spec doesn't mention L0s. | ||
408 | */ | ||
409 | l1_switch_latency += 1000; | ||
410 | } | ||
411 | return state; | ||
412 | } | ||
413 | |||
414 | static u32 pcie_aspm_check_state(struct pcie_link_state *link, u32 state) | ||
415 | { | ||
416 | pci_power_t power_state; | ||
417 | struct pci_dev *child; | ||
418 | struct pci_bus *linkbus = link->pdev->subordinate; | ||
419 | |||
420 | /* If no child, ignore the link */ | ||
421 | if (list_empty(&linkbus->devices)) | ||
422 | return state; | ||
423 | |||
424 | list_for_each_entry(child, &linkbus->devices, bus_list) { | ||
425 | /* | ||
426 | * If downstream component of a link is pci bridge, we | ||
427 | * disable ASPM for now for the link | ||
428 | */ | ||
429 | if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) | ||
430 | return 0; | ||
431 | |||
432 | if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT && | ||
433 | child->pcie_type != PCI_EXP_TYPE_LEG_END)) | ||
434 | continue; | ||
435 | /* Device not in D0 doesn't need check latency */ | ||
436 | power_state = child->current_state; | ||
437 | if (power_state == PCI_D1 || power_state == PCI_D2 || | ||
438 | power_state == PCI_D3hot || power_state == PCI_D3cold) | ||
439 | continue; | ||
440 | state = __pcie_aspm_check_state_one(child, state); | ||
441 | } | 436 | } |
442 | return state; | ||
443 | } | 437 | } |
444 | 438 | ||
445 | static void __pcie_aspm_config_one_dev(struct pci_dev *pdev, unsigned int state) | 439 | static void pcie_config_aspm_dev(struct pci_dev *pdev, u32 val) |
446 | { | 440 | { |
447 | u16 reg16; | 441 | u16 reg16; |
448 | int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); | 442 | int pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); |
449 | 443 | ||
450 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); | 444 | pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, ®16); |
451 | reg16 &= ~0x3; | 445 | reg16 &= ~0x3; |
452 | reg16 |= state; | 446 | reg16 |= val; |
453 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); | 447 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); |
454 | } | 448 | } |
455 | 449 | ||
456 | static void __pcie_aspm_config_link(struct pcie_link_state *link, u32 state) | 450 | static void pcie_config_aspm_link(struct pcie_link_state *link, u32 state) |
457 | { | 451 | { |
452 | u32 upstream = 0, dwstream = 0; | ||
458 | struct pci_dev *child, *parent = link->pdev; | 453 | struct pci_dev *child, *parent = link->pdev; |
459 | struct pci_bus *linkbus = parent->subordinate; | 454 | struct pci_bus *linkbus = parent->subordinate; |
460 | 455 | ||
461 | /* If no child, disable the link */ | 456 | /* Nothing to do if the link is already in the requested state */ |
462 | if (list_empty(&linkbus->devices)) | 457 | state &= (link->aspm_capable & ~link->aspm_disable); |
463 | state = 0; | 458 | if (link->aspm_enabled == state) |
464 | /* | 459 | return; |
465 | * If the downstream component has pci bridge function, don't | 460 | /* Convert ASPM state to upstream/downstream ASPM register state */ |
466 | * do ASPM now. | 461 | if (state & ASPM_STATE_L0S_UP) |
467 | */ | 462 | dwstream |= PCIE_LINK_STATE_L0S; |
468 | list_for_each_entry(child, &linkbus->devices, bus_list) { | 463 | if (state & ASPM_STATE_L0S_DW) |
469 | if (child->pcie_type == PCI_EXP_TYPE_PCI_BRIDGE) | 464 | upstream |= PCIE_LINK_STATE_L0S; |
470 | return; | 465 | if (state & ASPM_STATE_L1) { |
466 | upstream |= PCIE_LINK_STATE_L1; | ||
467 | dwstream |= PCIE_LINK_STATE_L1; | ||
471 | } | 468 | } |
472 | /* | 469 | /* |
473 | * Spec 2.0 suggests all functions should be configured the | 470 | * Spec 2.0 suggests all functions should be configured the |
@@ -475,67 +472,24 @@ static void __pcie_aspm_config_link(struct pcie_link_state *link, u32 state) | |||
475 | * upstream component first and then downstream, and vice | 472 | * upstream component first and then downstream, and vice |
476 | * versa for disabling ASPM L1. Spec doesn't mention L0S. | 473 | * versa for disabling ASPM L1. Spec doesn't mention L0S. |
477 | */ | 474 | */ |
478 | if (state & PCIE_LINK_STATE_L1) | 475 | if (state & ASPM_STATE_L1) |
479 | __pcie_aspm_config_one_dev(parent, state); | 476 | pcie_config_aspm_dev(parent, upstream); |
480 | |||
481 | list_for_each_entry(child, &linkbus->devices, bus_list) | 477 | list_for_each_entry(child, &linkbus->devices, bus_list) |
482 | __pcie_aspm_config_one_dev(child, state); | 478 | pcie_config_aspm_dev(child, dwstream); |
483 | 479 | if (!(state & ASPM_STATE_L1)) | |
484 | if (!(state & PCIE_LINK_STATE_L1)) | 480 | pcie_config_aspm_dev(parent, upstream); |
485 | __pcie_aspm_config_one_dev(parent, state); | ||
486 | 481 | ||
487 | link->aspm_enabled = state; | 482 | link->aspm_enabled = state; |
488 | } | 483 | } |
489 | 484 | ||
490 | /* Check the whole hierarchy, and configure each link in the hierarchy */ | 485 | static void pcie_config_aspm_path(struct pcie_link_state *link) |
491 | static void __pcie_aspm_configure_link_state(struct pcie_link_state *link, | ||
492 | u32 state) | ||
493 | { | 486 | { |
494 | struct pcie_link_state *leaf, *root = link->root; | 487 | while (link) { |
495 | 488 | pcie_config_aspm_link(link, policy_to_aspm_state(link)); | |
496 | state &= (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1); | 489 | link = link->parent; |
497 | |||
498 | /* Check all links who have specific root port link */ | ||
499 | list_for_each_entry(leaf, &link_list, sibling) { | ||
500 | if (!list_empty(&leaf->children) || (leaf->root != root)) | ||
501 | continue; | ||
502 | state = pcie_aspm_check_state(leaf, state); | ||
503 | } | ||
504 | /* Check root port link too in case it hasn't children */ | ||
505 | state = pcie_aspm_check_state(root, state); | ||
506 | if (link->aspm_enabled == state) | ||
507 | return; | ||
508 | /* | ||
509 | * We must change the hierarchy. See comments in | ||
510 | * __pcie_aspm_config_link for the order | ||
511 | **/ | ||
512 | if (state & PCIE_LINK_STATE_L1) { | ||
513 | list_for_each_entry(leaf, &link_list, sibling) { | ||
514 | if (leaf->root == root) | ||
515 | __pcie_aspm_config_link(leaf, state); | ||
516 | } | ||
517 | } else { | ||
518 | list_for_each_entry_reverse(leaf, &link_list, sibling) { | ||
519 | if (leaf->root == root) | ||
520 | __pcie_aspm_config_link(leaf, state); | ||
521 | } | ||
522 | } | 490 | } |
523 | } | 491 | } |
524 | 492 | ||
525 | /* | ||
526 | * pcie_aspm_configure_link_state: enable/disable PCI express link state | ||
527 | * @pdev: the root port or switch downstream port | ||
528 | */ | ||
529 | static void pcie_aspm_configure_link_state(struct pcie_link_state *link, | ||
530 | u32 state) | ||
531 | { | ||
532 | down_read(&pci_bus_sem); | ||
533 | mutex_lock(&aspm_lock); | ||
534 | __pcie_aspm_configure_link_state(link, state); | ||
535 | mutex_unlock(&aspm_lock); | ||
536 | up_read(&pci_bus_sem); | ||
537 | } | ||
538 | |||
539 | static void free_link_state(struct pcie_link_state *link) | 493 | static void free_link_state(struct pcie_link_state *link) |
540 | { | 494 | { |
541 | link->pdev->link_state = NULL; | 495 | link->pdev->link_state = NULL; |
@@ -570,10 +524,9 @@ static int pcie_aspm_sanity_check(struct pci_dev *pdev) | |||
570 | return 0; | 524 | return 0; |
571 | } | 525 | } |
572 | 526 | ||
573 | static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev) | 527 | static struct pcie_link_state *alloc_pcie_link_state(struct pci_dev *pdev) |
574 | { | 528 | { |
575 | struct pcie_link_state *link; | 529 | struct pcie_link_state *link; |
576 | int blacklist = !!pcie_aspm_sanity_check(pdev); | ||
577 | 530 | ||
578 | link = kzalloc(sizeof(*link), GFP_KERNEL); | 531 | link = kzalloc(sizeof(*link), GFP_KERNEL); |
579 | if (!link) | 532 | if (!link) |
@@ -599,15 +552,7 @@ static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev) | |||
599 | link->root = link->parent->root; | 552 | link->root = link->parent->root; |
600 | 553 | ||
601 | list_add(&link->sibling, &link_list); | 554 | list_add(&link->sibling, &link_list); |
602 | |||
603 | pdev->link_state = link; | 555 | pdev->link_state = link; |
604 | |||
605 | /* Check ASPM capability */ | ||
606 | pcie_aspm_cap_init(link, blacklist); | ||
607 | |||
608 | /* Check Clock PM capability */ | ||
609 | pcie_clkpm_cap_init(link, blacklist); | ||
610 | |||
611 | return link; | 556 | return link; |
612 | } | 557 | } |
613 | 558 | ||
@@ -618,8 +563,8 @@ static struct pcie_link_state *pcie_aspm_setup_link_state(struct pci_dev *pdev) | |||
618 | */ | 563 | */ |
619 | void pcie_aspm_init_link_state(struct pci_dev *pdev) | 564 | void pcie_aspm_init_link_state(struct pci_dev *pdev) |
620 | { | 565 | { |
621 | u32 state; | ||
622 | struct pcie_link_state *link; | 566 | struct pcie_link_state *link; |
567 | int blacklist = !!pcie_aspm_sanity_check(pdev); | ||
623 | 568 | ||
624 | if (aspm_disabled || !pdev->is_pcie || pdev->link_state) | 569 | if (aspm_disabled || !pdev->is_pcie || pdev->link_state) |
625 | return; | 570 | return; |
@@ -637,47 +582,64 @@ void pcie_aspm_init_link_state(struct pci_dev *pdev) | |||
637 | goto out; | 582 | goto out; |
638 | 583 | ||
639 | mutex_lock(&aspm_lock); | 584 | mutex_lock(&aspm_lock); |
640 | link = pcie_aspm_setup_link_state(pdev); | 585 | link = alloc_pcie_link_state(pdev); |
641 | if (!link) | 586 | if (!link) |
642 | goto unlock; | 587 | goto unlock; |
643 | /* | 588 | /* |
644 | * Setup initial ASPM state | 589 | * Setup initial ASPM state. Note that we need to configure |
645 | * | 590 | * upstream links also because capable state of them can be |
646 | * If link has switch, delay the link config. The leaf link | 591 | * update through pcie_aspm_cap_init(). |
647 | * initialization will config the whole hierarchy. But we must | ||
648 | * make sure BIOS doesn't set unsupported link state. | ||
649 | */ | 592 | */ |
650 | if (pcie_aspm_downstream_has_switch(link)) { | 593 | pcie_aspm_cap_init(link, blacklist); |
651 | state = pcie_aspm_check_state(link, link->aspm_default); | 594 | pcie_config_aspm_path(link); |
652 | __pcie_aspm_config_link(link, state); | ||
653 | } else { | ||
654 | state = policy_to_aspm_state(link); | ||
655 | __pcie_aspm_configure_link_state(link, state); | ||
656 | } | ||
657 | 595 | ||
658 | /* Setup initial Clock PM state */ | 596 | /* Setup initial Clock PM state */ |
659 | state = (link->clkpm_capable) ? policy_to_clkpm_state(link) : 0; | 597 | pcie_clkpm_cap_init(link, blacklist); |
660 | pcie_set_clkpm(link, state); | 598 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); |
661 | unlock: | 599 | unlock: |
662 | mutex_unlock(&aspm_lock); | 600 | mutex_unlock(&aspm_lock); |
663 | out: | 601 | out: |
664 | up_read(&pci_bus_sem); | 602 | up_read(&pci_bus_sem); |
665 | } | 603 | } |
666 | 604 | ||
605 | /* Recheck latencies and update aspm_capable for links under the root */ | ||
606 | static void pcie_update_aspm_capable(struct pcie_link_state *root) | ||
607 | { | ||
608 | struct pcie_link_state *link; | ||
609 | BUG_ON(root->parent); | ||
610 | list_for_each_entry(link, &link_list, sibling) { | ||
611 | if (link->root != root) | ||
612 | continue; | ||
613 | link->aspm_capable = link->aspm_support; | ||
614 | } | ||
615 | list_for_each_entry(link, &link_list, sibling) { | ||
616 | struct pci_dev *child; | ||
617 | struct pci_bus *linkbus = link->pdev->subordinate; | ||
618 | if (link->root != root) | ||
619 | continue; | ||
620 | list_for_each_entry(child, &linkbus->devices, bus_list) { | ||
621 | if ((child->pcie_type != PCI_EXP_TYPE_ENDPOINT) && | ||
622 | (child->pcie_type != PCI_EXP_TYPE_LEG_END)) | ||
623 | continue; | ||
624 | pcie_aspm_check_latency(child); | ||
625 | } | ||
626 | } | ||
627 | } | ||
628 | |||
667 | /* @pdev: the endpoint device */ | 629 | /* @pdev: the endpoint device */ |
668 | void pcie_aspm_exit_link_state(struct pci_dev *pdev) | 630 | void pcie_aspm_exit_link_state(struct pci_dev *pdev) |
669 | { | 631 | { |
670 | struct pci_dev *parent = pdev->bus->self; | 632 | struct pci_dev *parent = pdev->bus->self; |
671 | struct pcie_link_state *link_state = parent->link_state; | 633 | struct pcie_link_state *link, *root, *parent_link; |
672 | 634 | ||
673 | if (aspm_disabled || !pdev->is_pcie || !parent || !link_state) | 635 | if (aspm_disabled || !pdev->is_pcie || !parent || !parent->link_state) |
674 | return; | 636 | return; |
675 | if (parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT && | 637 | if ((parent->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
676 | parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) | 638 | (parent->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) |
677 | return; | 639 | return; |
640 | |||
678 | down_read(&pci_bus_sem); | 641 | down_read(&pci_bus_sem); |
679 | mutex_lock(&aspm_lock); | 642 | mutex_lock(&aspm_lock); |
680 | |||
681 | /* | 643 | /* |
682 | * All PCIe functions are in one slot, remove one function will remove | 644 | * All PCIe functions are in one slot, remove one function will remove |
683 | * the whole slot, so just wait until we are the last function left. | 645 | * the whole slot, so just wait until we are the last function left. |
@@ -685,13 +647,20 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev) | |||
685 | if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices)) | 647 | if (!list_is_last(&pdev->bus_list, &parent->subordinate->devices)) |
686 | goto out; | 648 | goto out; |
687 | 649 | ||
650 | link = parent->link_state; | ||
651 | root = link->root; | ||
652 | parent_link = link->parent; | ||
653 | |||
688 | /* All functions are removed, so just disable ASPM for the link */ | 654 | /* All functions are removed, so just disable ASPM for the link */ |
689 | __pcie_aspm_config_one_dev(parent, 0); | 655 | pcie_config_aspm_link(link, 0); |
690 | list_del(&link_state->sibling); | 656 | list_del(&link->sibling); |
691 | list_del(&link_state->link); | 657 | list_del(&link->link); |
692 | /* Clock PM is for endpoint device */ | 658 | /* Clock PM is for endpoint device */ |
659 | free_link_state(link); | ||
693 | 660 | ||
694 | free_link_state(link_state); | 661 | /* Recheck latencies and configure upstream links */ |
662 | pcie_update_aspm_capable(root); | ||
663 | pcie_config_aspm_path(parent_link); | ||
695 | out: | 664 | out: |
696 | mutex_unlock(&aspm_lock); | 665 | mutex_unlock(&aspm_lock); |
697 | up_read(&pci_bus_sem); | 666 | up_read(&pci_bus_sem); |
@@ -700,18 +669,23 @@ out: | |||
700 | /* @pdev: the root port or switch downstream port */ | 669 | /* @pdev: the root port or switch downstream port */ |
701 | void pcie_aspm_pm_state_change(struct pci_dev *pdev) | 670 | void pcie_aspm_pm_state_change(struct pci_dev *pdev) |
702 | { | 671 | { |
703 | struct pcie_link_state *link_state = pdev->link_state; | 672 | struct pcie_link_state *link = pdev->link_state; |
704 | 673 | ||
705 | if (aspm_disabled || !pdev->is_pcie || !pdev->link_state) | 674 | if (aspm_disabled || !pdev->is_pcie || !link) |
706 | return; | 675 | return; |
707 | if (pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT && | 676 | if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) && |
708 | pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM) | 677 | (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM)) |
709 | return; | 678 | return; |
710 | /* | 679 | /* |
711 | * devices changed PM state, we should recheck if latency meets all | 680 | * Devices changed PM state, we should recheck if latency |
712 | * functions' requirement | 681 | * meets all functions' requirement |
713 | */ | 682 | */ |
714 | pcie_aspm_configure_link_state(link_state, link_state->aspm_enabled); | 683 | down_read(&pci_bus_sem); |
684 | mutex_lock(&aspm_lock); | ||
685 | pcie_update_aspm_capable(link->root); | ||
686 | pcie_config_aspm_path(link); | ||
687 | mutex_unlock(&aspm_lock); | ||
688 | up_read(&pci_bus_sem); | ||
715 | } | 689 | } |
716 | 690 | ||
717 | /* | 691 | /* |
@@ -721,7 +695,7 @@ void pcie_aspm_pm_state_change(struct pci_dev *pdev) | |||
721 | void pci_disable_link_state(struct pci_dev *pdev, int state) | 695 | void pci_disable_link_state(struct pci_dev *pdev, int state) |
722 | { | 696 | { |
723 | struct pci_dev *parent = pdev->bus->self; | 697 | struct pci_dev *parent = pdev->bus->self; |
724 | struct pcie_link_state *link_state; | 698 | struct pcie_link_state *link; |
725 | 699 | ||
726 | if (aspm_disabled || !pdev->is_pcie) | 700 | if (aspm_disabled || !pdev->is_pcie) |
727 | return; | 701 | return; |
@@ -733,12 +707,16 @@ void pci_disable_link_state(struct pci_dev *pdev, int state) | |||
733 | 707 | ||
734 | down_read(&pci_bus_sem); | 708 | down_read(&pci_bus_sem); |
735 | mutex_lock(&aspm_lock); | 709 | mutex_lock(&aspm_lock); |
736 | link_state = parent->link_state; | 710 | link = parent->link_state; |
737 | link_state->aspm_support &= ~state; | 711 | if (state & PCIE_LINK_STATE_L0S) |
738 | __pcie_aspm_configure_link_state(link_state, link_state->aspm_enabled); | 712 | link->aspm_disable |= ASPM_STATE_L0S; |
713 | if (state & PCIE_LINK_STATE_L1) | ||
714 | link->aspm_disable |= ASPM_STATE_L1; | ||
715 | pcie_config_aspm_link(link, policy_to_aspm_state(link)); | ||
716 | |||
739 | if (state & PCIE_LINK_STATE_CLKPM) { | 717 | if (state & PCIE_LINK_STATE_CLKPM) { |
740 | link_state->clkpm_capable = 0; | 718 | link->clkpm_capable = 0; |
741 | pcie_set_clkpm(link_state, 0); | 719 | pcie_set_clkpm(link, 0); |
742 | } | 720 | } |
743 | mutex_unlock(&aspm_lock); | 721 | mutex_unlock(&aspm_lock); |
744 | up_read(&pci_bus_sem); | 722 | up_read(&pci_bus_sem); |
@@ -748,7 +726,7 @@ EXPORT_SYMBOL(pci_disable_link_state); | |||
748 | static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) | 726 | static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) |
749 | { | 727 | { |
750 | int i; | 728 | int i; |
751 | struct pcie_link_state *link_state; | 729 | struct pcie_link_state *link; |
752 | 730 | ||
753 | for (i = 0; i < ARRAY_SIZE(policy_str); i++) | 731 | for (i = 0; i < ARRAY_SIZE(policy_str); i++) |
754 | if (!strncmp(val, policy_str[i], strlen(policy_str[i]))) | 732 | if (!strncmp(val, policy_str[i], strlen(policy_str[i]))) |
@@ -761,10 +739,9 @@ static int pcie_aspm_set_policy(const char *val, struct kernel_param *kp) | |||
761 | down_read(&pci_bus_sem); | 739 | down_read(&pci_bus_sem); |
762 | mutex_lock(&aspm_lock); | 740 | mutex_lock(&aspm_lock); |
763 | aspm_policy = i; | 741 | aspm_policy = i; |
764 | list_for_each_entry(link_state, &link_list, sibling) { | 742 | list_for_each_entry(link, &link_list, sibling) { |
765 | __pcie_aspm_configure_link_state(link_state, | 743 | pcie_config_aspm_link(link, policy_to_aspm_state(link)); |
766 | policy_to_aspm_state(link_state)); | 744 | pcie_set_clkpm(link, policy_to_clkpm_state(link)); |
767 | pcie_set_clkpm(link_state, policy_to_clkpm_state(link_state)); | ||
768 | } | 745 | } |
769 | mutex_unlock(&aspm_lock); | 746 | mutex_unlock(&aspm_lock); |
770 | up_read(&pci_bus_sem); | 747 | up_read(&pci_bus_sem); |
@@ -802,18 +779,28 @@ static ssize_t link_state_store(struct device *dev, | |||
802 | size_t n) | 779 | size_t n) |
803 | { | 780 | { |
804 | struct pci_dev *pdev = to_pci_dev(dev); | 781 | struct pci_dev *pdev = to_pci_dev(dev); |
805 | int state; | 782 | struct pcie_link_state *link, *root = pdev->link_state->root; |
783 | u32 val = buf[0] - '0', state = 0; | ||
806 | 784 | ||
807 | if (n < 1) | 785 | if (n < 1 || val > 3) |
808 | return -EINVAL; | 786 | return -EINVAL; |
809 | state = buf[0]-'0'; | ||
810 | if (state >= 0 && state <= 3) { | ||
811 | /* setup link aspm state */ | ||
812 | pcie_aspm_configure_link_state(pdev->link_state, state); | ||
813 | return n; | ||
814 | } | ||
815 | 787 | ||
816 | return -EINVAL; | 788 | /* Convert requested state to ASPM state */ |
789 | if (val & PCIE_LINK_STATE_L0S) | ||
790 | state |= ASPM_STATE_L0S; | ||
791 | if (val & PCIE_LINK_STATE_L1) | ||
792 | state |= ASPM_STATE_L1; | ||
793 | |||
794 | down_read(&pci_bus_sem); | ||
795 | mutex_lock(&aspm_lock); | ||
796 | list_for_each_entry(link, &link_list, sibling) { | ||
797 | if (link->root != root) | ||
798 | continue; | ||
799 | pcie_config_aspm_link(link, state); | ||
800 | } | ||
801 | mutex_unlock(&aspm_lock); | ||
802 | up_read(&pci_bus_sem); | ||
803 | return n; | ||
817 | } | 804 | } |
818 | 805 | ||
819 | static ssize_t clk_ctl_show(struct device *dev, | 806 | static ssize_t clk_ctl_show(struct device *dev, |