From: Maciej W. Rozycki Date: Sun, 11 Jun 2023 17:19:41 +0000 (+0100) Subject: PCI: Export pcie_retrain_link() for use outside ASPM X-Git-Tag: v6.6.17~4503^2~15^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=37edd87eb621a96d33ee4eefe4b54cfc5a7e03df;p=platform%2Fkernel%2Flinux-rpi.git PCI: Export pcie_retrain_link() for use outside ASPM Export pcie_retrain_link() for link retrain needs outside ASPM. Struct pcie_link_state is local to ASPM and only used by pcie_retrain_link() to get at the associated PCI device, so change the operand and adjust the lone call site accordingly. Document the interface. No functional change at this point. Link: https://lore.kernel.org/r/alpine.DEB.2.21.2306110229010.64925@angie.orcam.me.uk Signed-off-by: Maciej W. Rozycki Signed-off-by: Bjorn Helgaas --- diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 71645d568986..47ceb8567b2b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4856,6 +4856,55 @@ static int pci_pm_reset(struct pci_dev *dev, bool probe) return pci_dev_wait(dev, "PM D3hot->D0", PCIE_RESET_READY_POLL_MS); } +/** + * pcie_wait_for_link_status - Wait for link training end + * @pdev: Device whose link to wait for. + * + * Return TRUE if successful, or FALSE if training has not completed + * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. + */ +static bool pcie_wait_for_link_status(struct pci_dev *pdev) +{ + unsigned long end_jiffies; + u16 lnksta; + + end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); + do { + pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta); + if (!(lnksta & PCI_EXP_LNKSTA_LT)) + break; + msleep(1); + } while (time_before(jiffies, end_jiffies)); + return !(lnksta & PCI_EXP_LNKSTA_LT); +} + +/** + * 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) +{ + u16 lnkctl; + + pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl); + lnkctl |= PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + 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. + */ + lnkctl &= ~PCI_EXP_LNKCTL_RL; + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); + } + + return pcie_wait_for_link_status(pdev); +} + /** * pcie_wait_for_link_delay - Wait until link is active or inactive * @pdev: Bridge device diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index d5fe253114f2..0d9671b20d17 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -565,6 +565,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev, 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); diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 721e5c787cf3..0c5d392dc793 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -191,48 +191,6 @@ static void pcie_clkpm_cap_init(struct pcie_link_state *link, int blacklist) link->clkpm_disable = blacklist ? 1 : 0; } -/** - * pcie_wait_for_link_status - Wait for link training end - * @pdev: Device whose link to wait for. - * - * Return TRUE if successful, or FALSE if training has not completed - * within PCIE_LINK_RETRAIN_TIMEOUT_MS milliseconds. - */ -static bool pcie_wait_for_link_status(struct pci_dev *pdev) -{ - unsigned long end_jiffies; - u16 lnksta; - - end_jiffies = jiffies + msecs_to_jiffies(PCIE_LINK_RETRAIN_TIMEOUT_MS); - do { - pcie_capability_read_word(pdev, PCI_EXP_LNKSTA, &lnksta); - if (!(lnksta & PCI_EXP_LNKSTA_LT)) - break; - msleep(1); - } while (time_before(jiffies, end_jiffies)); - return !(lnksta & PCI_EXP_LNKSTA_LT); -} - -static bool pcie_retrain_link(struct pci_dev *pdev) -{ - u16 lnkctl; - - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &lnkctl); - lnkctl |= PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); - 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. - */ - lnkctl &= ~PCI_EXP_LNKCTL_RL; - pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, lnkctl); - } - - return pcie_wait_for_link_status(pdev); -} - /* * 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