PCI: dwc: Wait for link up only if link is started
authorAjay Agarwal <ajayagarwal@google.com>
Wed, 12 Apr 2023 09:34:25 +0000 (15:04 +0530)
committerLorenzo Pieralisi <lpieralisi@kernel.org>
Fri, 26 May 2023 08:45:12 +0000 (10:45 +0200)
In dw_pcie_host_init() regardless of whether the link has been
started or not, the code waits for the link to come up. Even in
cases where start_link() is not defined the code ends up spinning
in a loop for 1 second. Since in some systems dw_pcie_host_init()
gets called during probe, this one second loop for each pcie
interface instance ends up extending the boot time.

Wait for the link up in only if the start_link() is defined.

Link: https://lore.kernel.org/r/20230412093425.3659088-1-ajayagarwal@google.com
Tested-by: Will McVicker <willmcvicker@google.com>
Signed-off-by: Sajid Dalvi <sdalvi@google.com>
Signed-off-by: Ajay Agarwal <ajayagarwal@google.com>
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
drivers/pci/controller/dwc/pcie-designware-host.c
drivers/pci/controller/dwc/pcie-designware.c
drivers/pci/controller/dwc/pcie-designware.h

index 9952057c8819c86ac7bb97dfe709f6337ddfa7c6..cf61733bf78d24a99114bb8bdf3262a771d5b44b 100644 (file)
@@ -485,14 +485,19 @@ int dw_pcie_host_init(struct dw_pcie_rp *pp)
        if (ret)
                goto err_remove_edma;
 
-       if (!dw_pcie_link_up(pci)) {
+       if (dw_pcie_link_up(pci)) {
+               dw_pcie_print_link_status(pci);
+       } else {
                ret = dw_pcie_start_link(pci);
                if (ret)
                        goto err_remove_edma;
-       }
 
-       /* Ignore errors, the link may come up later */
-       dw_pcie_wait_for_link(pci);
+               if (pci->ops && pci->ops->start_link) {
+                       ret = dw_pcie_wait_for_link(pci);
+                       if (ret)
+                               goto err_stop_link;
+               }
+       }
 
        bridge->sysdata = pp;
 
index 8e33e6e59e686b5d5e8462fdc737ca84ea349397..df092229e97d26b3dc8acb7606f850a0122c2086 100644 (file)
@@ -644,9 +644,20 @@ void dw_pcie_disable_atu(struct dw_pcie *pci, u32 dir, int index)
        dw_pcie_writel_atu(pci, dir, index, PCIE_ATU_REGION_CTRL2, 0);
 }
 
-int dw_pcie_wait_for_link(struct dw_pcie *pci)
+void dw_pcie_print_link_status(struct dw_pcie *pci)
 {
        u32 offset, val;
+
+       offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
+       val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
+
+       dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
+                FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
+                FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
+}
+
+int dw_pcie_wait_for_link(struct dw_pcie *pci)
+{
        int retries;
 
        /* Check if the link is up or not */
@@ -662,12 +673,7 @@ int dw_pcie_wait_for_link(struct dw_pcie *pci)
                return -ETIMEDOUT;
        }
 
-       offset = dw_pcie_find_capability(pci, PCI_CAP_ID_EXP);
-       val = dw_pcie_readw_dbi(pci, offset + PCI_EXP_LNKSTA);
-
-       dev_info(pci->dev, "PCIe Gen.%u x%u link up\n",
-                FIELD_GET(PCI_EXP_LNKSTA_CLS, val),
-                FIELD_GET(PCI_EXP_LNKSTA_NLW, val));
+       dw_pcie_print_link_status(pci);
 
        return 0;
 }
index 79713ce075cc1b6b3c1eff6b8535813c87837076..615660640801968cf5b76d36b9ceab3c3984d3f1 100644 (file)
@@ -429,6 +429,7 @@ void dw_pcie_setup(struct dw_pcie *pci);
 void dw_pcie_iatu_detect(struct dw_pcie *pci);
 int dw_pcie_edma_detect(struct dw_pcie *pci);
 void dw_pcie_edma_remove(struct dw_pcie *pci);
+void dw_pcie_print_link_status(struct dw_pcie *pci);
 
 static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
 {