diff options
-rw-r--r-- | drivers/pci/pcie/aspm.c | 66 |
1 files changed, 28 insertions, 38 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index fdb3b7da7383..88351c242a48 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -26,9 +26,9 @@ | |||
26 | #endif | 26 | #endif |
27 | #define MODULE_PARAM_PREFIX "pcie_aspm." | 27 | #define MODULE_PARAM_PREFIX "pcie_aspm." |
28 | 28 | ||
29 | struct endpoint_state { | 29 | struct aspm_latency { |
30 | unsigned int l0s_acceptable_latency; | 30 | u32 l0s; /* L0s latency (nsec) */ |
31 | unsigned int l1_acceptable_latency; | 31 | u32 l1; /* L1 latency (nsec) */ |
32 | }; | 32 | }; |
33 | 33 | ||
34 | struct pcie_link_state { | 34 | struct pcie_link_state { |
@@ -45,22 +45,19 @@ struct pcie_link_state { | |||
45 | u32 aspm_enabled:2; /* Enabled ASPM state */ | 45 | u32 aspm_enabled:2; /* Enabled ASPM state */ |
46 | u32 aspm_default:2; /* Default ASPM state by BIOS */ | 46 | u32 aspm_default:2; /* Default ASPM state by BIOS */ |
47 | 47 | ||
48 | /* upstream component */ | 48 | /* Latencies */ |
49 | unsigned int l0s_upper_latency; | 49 | struct aspm_latency latency; /* Exit latency */ |
50 | unsigned int l1_upper_latency; | 50 | |
51 | /* downstream component */ | ||
52 | unsigned int l0s_down_latency; | ||
53 | unsigned int l1_down_latency; | ||
54 | /* Clock PM state*/ | 51 | /* Clock PM state*/ |
55 | unsigned int clk_pm_capable; | 52 | unsigned int clk_pm_capable; |
56 | unsigned int clk_pm_enabled; | 53 | unsigned int clk_pm_enabled; |
57 | unsigned int bios_clk_state; | 54 | unsigned int bios_clk_state; |
58 | 55 | ||
59 | /* | 56 | /* |
60 | * A pcie downstream port only has one slot under it, so at most there | 57 | * Endpoint acceptable latencies. A pcie downstream port only |
61 | * are 8 functions | 58 | * has one slot under it, so at most there are 8 functions. |
62 | */ | 59 | */ |
63 | struct endpoint_state endpoints[8]; | 60 | struct aspm_latency acceptable[8]; |
64 | }; | 61 | }; |
65 | 62 | ||
66 | static int aspm_disabled, aspm_force; | 63 | static int aspm_disabled, aspm_force; |
@@ -341,8 +338,8 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) | |||
341 | /* upstream component states */ | 338 | /* upstream component states */ |
342 | pcie_aspm_get_cap_device(pdev, &support, &l0s, &l1, &enabled); | 339 | pcie_aspm_get_cap_device(pdev, &support, &l0s, &l1, &enabled); |
343 | link_state->aspm_support = support; | 340 | link_state->aspm_support = support; |
344 | link_state->l0s_upper_latency = l0s; | 341 | link_state->latency.l0s = l0s; |
345 | link_state->l1_upper_latency = l1; | 342 | link_state->latency.l1 = l1; |
346 | link_state->aspm_enabled = enabled; | 343 | link_state->aspm_enabled = enabled; |
347 | 344 | ||
348 | /* downstream component states, all functions have the same setting */ | 345 | /* downstream component states, all functions have the same setting */ |
@@ -350,8 +347,8 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) | |||
350 | bus_list); | 347 | bus_list); |
351 | pcie_aspm_get_cap_device(child_dev, &support, &l0s, &l1, &enabled); | 348 | pcie_aspm_get_cap_device(child_dev, &support, &l0s, &l1, &enabled); |
352 | link_state->aspm_support &= support; | 349 | link_state->aspm_support &= support; |
353 | link_state->l0s_down_latency = l0s; | 350 | link_state->latency.l0s = max_t(u32, link_state->latency.l0s, l0s); |
354 | link_state->l1_down_latency = l1; | 351 | link_state->latency.l1 = max_t(u32, link_state->latency.l1, l1); |
355 | 352 | ||
356 | if (!link_state->aspm_support) | 353 | if (!link_state->aspm_support) |
357 | return; | 354 | return; |
@@ -364,8 +361,8 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) | |||
364 | int pos; | 361 | int pos; |
365 | u32 reg32; | 362 | u32 reg32; |
366 | unsigned int latency; | 363 | unsigned int latency; |
367 | struct endpoint_state *ep_state = | 364 | struct aspm_latency *acceptable = |
368 | &link_state->endpoints[PCI_FUNC(child_dev->devfn)]; | 365 | &link_state->acceptable[PCI_FUNC(child_dev->devfn)]; |
369 | 366 | ||
370 | if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT && | 367 | if (child_dev->pcie_type != PCI_EXP_TYPE_ENDPOINT && |
371 | child_dev->pcie_type != PCI_EXP_TYPE_LEG_END) | 368 | child_dev->pcie_type != PCI_EXP_TYPE_LEG_END) |
@@ -375,11 +372,11 @@ static void pcie_aspm_cap_init(struct pci_dev *pdev) | |||
375 | pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, ®32); | 372 | pci_read_config_dword(child_dev, pos + PCI_EXP_DEVCAP, ®32); |
376 | latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; | 373 | latency = (reg32 & PCI_EXP_DEVCAP_L0S) >> 6; |
377 | latency = calc_L0S_latency(latency, 1); | 374 | latency = calc_L0S_latency(latency, 1); |
378 | ep_state->l0s_acceptable_latency = latency; | 375 | acceptable->l0s = latency; |
379 | if (link_state->aspm_support & PCIE_LINK_STATE_L1) { | 376 | if (link_state->aspm_support & PCIE_LINK_STATE_L1) { |
380 | latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; | 377 | latency = (reg32 & PCI_EXP_DEVCAP_L1) >> 9; |
381 | latency = calc_L1_latency(latency, 1); | 378 | latency = calc_L1_latency(latency, 1); |
382 | ep_state->l1_acceptable_latency = latency; | 379 | acceptable->l1 = latency; |
383 | } | 380 | } |
384 | } | 381 | } |
385 | } | 382 | } |
@@ -388,16 +385,16 @@ static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev, | |||
388 | unsigned int state) | 385 | unsigned int state) |
389 | { | 386 | { |
390 | struct pci_dev *parent_dev, *tmp_dev; | 387 | struct pci_dev *parent_dev, *tmp_dev; |
391 | unsigned int latency, l1_latency = 0; | 388 | unsigned int l1_latency = 0; |
392 | struct pcie_link_state *link_state; | 389 | struct pcie_link_state *link_state; |
393 | struct endpoint_state *ep_state; | 390 | struct aspm_latency *acceptable; |
394 | 391 | ||
395 | parent_dev = pdev->bus->self; | 392 | parent_dev = pdev->bus->self; |
396 | link_state = parent_dev->link_state; | 393 | link_state = parent_dev->link_state; |
397 | state &= link_state->aspm_support; | 394 | state &= link_state->aspm_support; |
398 | if (state == 0) | 395 | if (state == 0) |
399 | return 0; | 396 | return 0; |
400 | ep_state = &link_state->endpoints[PCI_FUNC(pdev->devfn)]; | 397 | acceptable = &link_state->acceptable[PCI_FUNC(pdev->devfn)]; |
401 | 398 | ||
402 | /* | 399 | /* |
403 | * Check latency for endpoint device. | 400 | * Check latency for endpoint device. |
@@ -411,21 +408,14 @@ static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev, | |||
411 | while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { | 408 | while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { |
412 | parent_dev = tmp_dev->bus->self; | 409 | parent_dev = tmp_dev->bus->self; |
413 | link_state = parent_dev->link_state; | 410 | link_state = parent_dev->link_state; |
414 | if (state & PCIE_LINK_STATE_L0S) { | 411 | if ((state & PCIE_LINK_STATE_L0S) && |
415 | latency = max_t(unsigned int, | 412 | (link_state->latency.l0s > acceptable->l0s)) |
416 | link_state->l0s_upper_latency, | 413 | state &= ~PCIE_LINK_STATE_L0S; |
417 | link_state->l0s_down_latency); | 414 | |
418 | if (latency > ep_state->l0s_acceptable_latency) | 415 | if ((state & PCIE_LINK_STATE_L1) && |
419 | state &= ~PCIE_LINK_STATE_L0S; | 416 | (link_state->latency.l1 + l1_latency > acceptable->l1)) |
420 | } | 417 | state &= ~PCIE_LINK_STATE_L1; |
421 | if (state & PCIE_LINK_STATE_L1) { | 418 | |
422 | latency = max_t(unsigned int, | ||
423 | link_state->l1_upper_latency, | ||
424 | link_state->l1_down_latency); | ||
425 | if (latency + l1_latency > | ||
426 | ep_state->l1_acceptable_latency) | ||
427 | state &= ~PCIE_LINK_STATE_L1; | ||
428 | } | ||
429 | if (!parent_dev->bus->self) /* parent_dev is a root port */ | 419 | if (!parent_dev->bus->self) /* parent_dev is a root port */ |
430 | break; | 420 | break; |
431 | else { | 421 | else { |