Export `pcie_retrain_link' for link retrain needs outside ASPM. There is no functional change at this point, but `struct pcie_link_state' is local to ASPM and not used within `pcie_retrain_link' other than to get at the associated PCI device, so change the operand and adjust the lone call site accordingly. Document the interface. Signed-off-by: Maciej W. Rozycki <macro@xxxxxxxxxxx> --- There's a missing full stop added in a comment in the course of the move, not worth mentioning in the change description IMHO and not worth its own change either. This comment will go away in a subsequent change anyway. New change in v9. --- drivers/pci/pci.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/pci/pci.h | 1 + drivers/pci/pcie/aspm.c | 32 +------------------------------- 3 files changed, 38 insertions(+), 31 deletions(-) linux-pcie-retrain-link-export.diff Index: linux-macro/drivers/pci/pci.c =================================================================== --- linux-macro.orig/drivers/pci/pci.c +++ linux-macro/drivers/pci/pci.c @@ -4912,6 +4912,42 @@ bool pcie_wait_for_link(struct pci_dev * return pcie_wait_for_link_delay(pdev, active, 100); } +/** + * pcie_retrain_link - Request a link retrain and wait for it to complete + * @pdev: Device whose link to retrain. + * + * Return TRUE if successful, or FALSE if training has not completed + * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. + */ +bool pcie_retrain_link(struct pci_dev *pdev) +{ + unsigned long end_jiffies; + u16 reg16; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, ®16); + reg16 |= PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, reg16); + if (pdev->clear_retrain_link) { + /* + * Due to an erratum in some devices the Retrain Link bit + * needs to be cleared again manually to allow the link + * training to succeed. + */ + reg16 &= ~PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, reg16); + } + + /* Wait for link training end. Break out after waiting for timeout. */ + end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); + do { + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, ®16); + if (!(reg16 & PCI_EXP_LNKSTA_LT)) + break; + msleep(1); + } while (time_before(jiffies, end_jiffies)); + return !(reg16 & PCI_EXP_LNKSTA_LT); +} + /* * Find maximum D3cold delay required by all the devices on the bus. The * spec says 100 ms, but firmware can lower it and we allow drivers to Index: linux-macro/drivers/pci/pci.h =================================================================== --- linux-macro.orig/drivers/pci/pci.h +++ linux-macro/drivers/pci/pci.h @@ -561,6 +561,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev)); bool pcie_wait_for_link(struct pci_dev *pdev, bool active); +bool pcie_retrain_link(struct pci_dev *pdev); #ifdef CONFIG_PCIEASPM void pcie_aspm_init_link_state(struct pci_dev *pdev); void pcie_aspm_exit_link_state(struct pci_dev *pdev); Index: linux-macro/drivers/pci/pcie/aspm.c =================================================================== --- linux-macro.orig/drivers/pci/pcie/aspm.c +++ linux-macro/drivers/pci/pcie/aspm.c @@ -191,36 +191,6 @@ static void pcie_clkpm_cap_init(struct p link->clkpm_disable = blacklist ? 1 : 0; } -static bool pcie_retrain_link(struct pcie_link_state *link) -{ - struct pci_dev *parent = link->pdev; - unsigned long end_jiffies; - u16 reg16; - - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, ®16); - reg16 |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (parent->clear_retrain_link) { - /* - * Due to an erratum in some devices the Retrain Link bit - * needs to be cleared again manually to allow the link - * training to succeed. - */ - reg16 &= ~PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - } - - /* Wait for link training end. Break out after waiting for timeout */ - end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); - do { - pcie_capability_read_word(parent, PCI_EXP_LNKSTA, ®16); - if (!(reg16 & PCI_EXP_LNKSTA_LT)) - break; - msleep(1); - } while (time_before(jiffies, end_jiffies)); - return !(reg16 & PCI_EXP_LNKSTA_LT); -} - /* * pcie_aspm_configure_common_clock: check if the 2 ends of a link * could use common clock. If they are, configure them to use the @@ -287,7 +257,7 @@ static void pcie_aspm_configure_common_c reg16 &= ~PCI_EXP_LNKCTL_CCC; pcie_capability_write_word(parent, PCI_EXP_LNKCTL, reg16); - if (pcie_retrain_link(link)) + if (pcie_retrain_link(link->pdev)) return; /* Training failed. Restore common clock configurations */