diff options
Diffstat (limited to 'drivers/pci/pcie/aspm.c')
-rw-r--r-- | drivers/pci/pcie/aspm.c | 67 |
1 files changed, 25 insertions, 42 deletions
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 68a4d4b15f9f..694ba5657758 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -370,56 +370,39 @@ static void pcie_aspm_cap_init(struct pcie_link_state *link, int blacklist) | |||
370 | } | 370 | } |
371 | } | 371 | } |
372 | 372 | ||
373 | static unsigned int __pcie_aspm_check_state_one(struct pci_dev *pdev, | 373 | /** |
374 | unsigned int state) | 374 | * __pcie_aspm_check_state_one - check latency for endpoint device. |
375 | * @endpoint: pointer to the struct pci_dev of endpoint device | ||
376 | * | ||
377 | * TBD: The latency from the endpoint to root complex vary per switch's | ||
378 | * upstream link state above the device. Here we just do a simple check | ||
379 | * which assumes all links above the device can be in L1 state, that | ||
380 | * is we just consider the worst case. If switch's upstream link can't | ||
381 | * be put into L0S/L1, then our check is too strictly. | ||
382 | */ | ||
383 | static u32 __pcie_aspm_check_state_one(struct pci_dev *endpoint, u32 state) | ||
375 | { | 384 | { |
376 | struct pci_dev *parent_dev, *tmp_dev; | 385 | u32 l1_switch_latency = 0; |
377 | unsigned int l1_latency = 0; | ||
378 | struct pcie_link_state *link_state; | ||
379 | struct aspm_latency *acceptable; | 386 | struct aspm_latency *acceptable; |
387 | struct pcie_link_state *link; | ||
380 | 388 | ||
381 | parent_dev = pdev->bus->self; | 389 | link = endpoint->bus->self->link_state; |
382 | link_state = parent_dev->link_state; | 390 | state &= link->aspm_support; |
383 | state &= link_state->aspm_support; | 391 | acceptable = &link->acceptable[PCI_FUNC(endpoint->devfn)]; |
384 | if (state == 0) | ||
385 | return 0; | ||
386 | acceptable = &link_state->acceptable[PCI_FUNC(pdev->devfn)]; | ||
387 | 392 | ||
388 | /* | 393 | while (link && state) { |
389 | * Check latency for endpoint device. | ||
390 | * TBD: The latency from the endpoint to root complex vary per | ||
391 | * switch's upstream link state above the device. Here we just do a | ||
392 | * simple check which assumes all links above the device can be in L1 | ||
393 | * state, that is we just consider the worst case. If switch's upstream | ||
394 | * link can't be put into L0S/L1, then our check is too strictly. | ||
395 | */ | ||
396 | tmp_dev = pdev; | ||
397 | while (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { | ||
398 | parent_dev = tmp_dev->bus->self; | ||
399 | link_state = parent_dev->link_state; | ||
400 | if ((state & PCIE_LINK_STATE_L0S) && | 394 | if ((state & PCIE_LINK_STATE_L0S) && |
401 | (link_state->latency.l0s > acceptable->l0s)) | 395 | (link->latency.l0s > acceptable->l0s)) |
402 | state &= ~PCIE_LINK_STATE_L0S; | 396 | state &= ~PCIE_LINK_STATE_L0S; |
403 | |||
404 | if ((state & PCIE_LINK_STATE_L1) && | 397 | if ((state & PCIE_LINK_STATE_L1) && |
405 | (link_state->latency.l1 + l1_latency > acceptable->l1)) | 398 | (link->latency.l1 + l1_switch_latency > acceptable->l1)) |
406 | state &= ~PCIE_LINK_STATE_L1; | 399 | state &= ~PCIE_LINK_STATE_L1; |
407 | 400 | link = link->parent; | |
408 | if (!parent_dev->bus->self) /* parent_dev is a root port */ | 401 | /* |
409 | break; | 402 | * Every switch on the path to root complex need 1 |
410 | else { | 403 | * more microsecond for L1. Spec doesn't mention L0s. |
411 | /* | 404 | */ |
412 | * parent_dev is the downstream port of a switch, make | 405 | l1_switch_latency += 1000; |
413 | * tmp_dev the upstream port of the switch | ||
414 | */ | ||
415 | tmp_dev = parent_dev->bus->self; | ||
416 | /* | ||
417 | * every switch on the path to root complex need 1 more | ||
418 | * microsecond for L1. Spec doesn't mention L0S. | ||
419 | */ | ||
420 | if (state & PCIE_LINK_STATE_L1) | ||
421 | l1_latency += 1000; | ||
422 | } | ||
423 | } | 406 | } |
424 | return state; | 407 | return state; |
425 | } | 408 | } |