Skip to content

Commit 680e9c4

Browse files
maciej-w-rozyckibjorn-helgaas
authored andcommitted
PCI: Add support for polling DLLLA to pcie_retrain_link()
Let the caller of pcie_retrain_link() specify whether they want to use the LT bit or the DLLLA bit of the Link Status Register to determine if link training has completed. It is up to the caller to verify whether the use of the DLLLA bit, the implementation of which is optional, is valid for the device requested. Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Maciej W. Rozycki <[email protected]> Signed-off-by: Bjorn Helgaas <[email protected]>
1 parent 37edd87 commit 680e9c4

File tree

3 files changed

+22
-10
lines changed

3 files changed

+22
-10
lines changed

drivers/pci/pci.c

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4857,35 +4857,47 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe)
48574857
}
48584858

48594859
/**
4860-
* pcie_wait_for_link_status - Wait for link training end
4860+
* pcie_wait_for_link_status - Wait for link status change
48614861
* @pdev: Device whose link to wait for.
4862+
* @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE.
4863+
* @active: Waiting for active or inactive?
48624864
*
4863-
* Return TRUE if successful, or FALSE if training has not completed
4864-
* within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds.
4865+
* Return TRUE if successful, or FALSE if status has not changed within
4866+
* PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds.
48654867
*/
4866-
static bool pcie_wait_for_link_status(struct pci_dev *pdev)
4868+
static bool pcie_wait_for_link_status(struct pci_dev *pdev,
4869+
bool use_lt, bool active)
48674870
{
4871+
u16 lnksta_mask, lnksta_match;
48684872
unsigned long end_jiffies;
48694873
u16 lnksta;
48704874

4875+
lnksta_mask = use_lt ? PCI_EXP_LNKSTA_LT : PCI_EXP_LNKSTA_DLLLA;
4876+
lnksta_match = active ? lnksta_mask : 0;
4877+
48714878
end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS);
48724879
do {
48734880
pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta);
4874-
if (!(lnksta & PCI_EXP_LNKSTA_LT))
4881+
if ((lnksta & lnksta_mask) == lnksta_match)
48754882
break;
48764883
msleep(1);
48774884
} while (time_before(jiffies, end_jiffies));
4878-
return !(lnksta & PCI_EXP_LNKSTA_LT);
4885+
return (lnksta & lnksta_mask) == lnksta_match;
48794886
}
48804887

48814888
/**
48824889
* pcie_retrain_link - Request a link retrain and wait for it to complete
48834890
* @pdev: Device whose link to retrain.
4891+
* @use_lt: Use the LT bit if TRUE, or the DLLLA bit if FALSE, for status.
4892+
*
4893+
* Retrain completion status is retrieved from the Link Status Register
4894+
* according to @use_lt. It is not verified whether the use of the DLLLA
4895+
* bit is valid.
48844896
*
48854897
* Return TRUE if successful, or FALSE if training has not completed
48864898
* within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds.
48874899
*/
4888-
bool pcie_retrain_link(struct pci_dev *pdev)
4900+
bool pcie_retrain_link(struct pci_dev *pdev, bool use_lt)
48894901
{
48904902
u16 lnkctl;
48914903

@@ -4902,7 +4914,7 @@ bool pcie_retrain_link(struct pci_dev *pdev)
49024914
pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl);
49034915
}
49044916

4905-
return pcie_wait_for_link_status(pdev);
4917+
return pcie_wait_for_link_status(pdev, use_lt, !use_lt);
49064918
}
49074919

49084920
/**

drivers/pci/pci.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
565565
pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
566566

567567
bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
568-
bool pcie_retrain_link(struct pci_dev *pdev);
568+
bool pcie_retrain_link(struct pci_dev *pdev, bool use_lt);
569569
#ifdef CONFIG_PCIEASPM
570570
void pcie_aspm_init_link_state(struct pci_dev *pdev);
571571
void pcie_aspm_exit_link_state(struct pci_dev *pdev);

drivers/pci/pcie/aspm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ static void pcie_aspm_configure_common_clock(struct pcie_link_state *link)
257257
reg16 &= ~PCI_EXP_LNKCTL_CCC;
258258
pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16);
259259

260-
if (pcie_retrain_link(link->pdev))
260+
if (pcie_retrain_link(link->pdev, true))
261261
return;
262262

263263
/* Training failed. Restore common clock configurations */

0 commit comments

Comments
 (0)