Skip to content

Commit

Permalink
linux: pci: Fix PCI probing race condition
Browse files Browse the repository at this point in the history
The Keystone PCI controller had a race condition hidden that made its
probing fail. Add a patch provided by TI (currently mainlined) that
fixes this race condition and returns PCI back to a funcional state.
Tested with a Hailo-8 NPU card.

While at it add a second patch suggested by TI that fixes "a 45 second
delay when no Endpoint Device is connected to the PCIe connector".

Signed-off-by: Diogo Ivo <[email protected]>
  • Loading branch information
diogo-ivo authored and BaochengSu committed Jan 30, 2024
1 parent 33d74ea commit 91c99e8
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Siddharth Vadapalli <[email protected]>
Date: Wed, 27 Sep 2023 09:48:45 +0530
Subject: [PATCH] PCI: keystone: Fix race condition when initializing PHYs

The PCI driver invokes the PHY APIs using the ks_pcie_enable_phy()
function. The PHY in this case is the Serdes. It is possible that the
PCI instance is configured for two lane operation across two different
Serdes instances, using one lane of each Serdes.

In such a configuration, if the reference clock for one Serdes is
provided by the other Serdes, it results in a race condition. After the
Serdes providing the reference clock is initialized by the PCI driver by
invoking its PHY APIs, it is not guaranteed that this Serdes remains
powered on long enough for the PHY APIs based initialization of the
dependent Serdes. In such cases, the PLL of the dependent Serdes fails
to lock due to the absence of the reference clock from the former Serdes
which has been powered off by the PM Core.

Fix this by obtaining reference to the PHYs before invoking the PHY
initialization APIs and releasing reference after the initialization is
complete.

Link: https://lore.kernel.org/linux-pci/[email protected]
Fixes: 49229238ab47 ("PCI: keystone: Cleanup PHY handling")
Signed-off-by: Siddharth Vadapalli <[email protected]>
Signed-off-by: Krzysztof Wilczyński <[email protected]>
Acked-by: Ravi Gunasekaran <[email protected]>
[Commit c12ca110c613 upstream]
---
drivers/pci/controller/dwc/pci-keystone.c | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index fefb375a777a..a5dbe8c9b077 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -1367,7 +1367,16 @@ static int __init ks_pcie_probe(struct platform_device *pdev)
goto err_link;
}

+ /* Obtain references to the PHYs */
+ for (i = 0; i < num_lanes; i++)
+ phy_pm_runtime_get_sync(ks_pcie->phy[i]);
+
ret = ks_pcie_enable_phy(ks_pcie);
+
+ /* Release references to the PHYs */
+ for (i = 0; i < num_lanes; i++)
+ phy_pm_runtime_put_sync(ks_pcie->phy[i]);
+
if (ret) {
dev_err(dev, "failed to enable phy\n");
goto err_link;
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Siddharth Vadapalli <[email protected]>
Date: Mon, 22 Jan 2024 11:19:32 +0000
Subject: [PATCH] PCI: keystone: Fix pci_ops for AM654x SoC

In the process of converting .scan_bus() callbacks to .add_bus(), the
ks_pcie_v3_65_scan_bus() function was changed to ks_pcie_v3_65_add_bus().
The .scan_bus() method belonged to ks_pcie_host_ops which was specific
to controller version 3.65a, while the .add_bus() method had been added
to ks_pcie_ops which is shared between the controller versions 3.65a and
4.90a. Neither the older ks_pcie_v3_65_scan_bus() method, nor the newer
ks_pcie_v3_65_add_bus() method are applicable to the controller version
4.90a which is present in AM654x SoCs.

Thus, fix this by creating ks_pcie_am6_ops for the AM654x SoC which uses DW
PCIe IP-core version 4.90a controller and omitting the .add_bus() method
which is not applicable to the 4.90a controller. Update ks_pcie_host_init()
accordingly in order to set the pci_ops to ks_pcie_am6_ops if the platform
is AM654x SoC and to ks_pcie_ops otherwise, by making use of the "is_am6"
flag.

Fixes: 6ab15b5e7057 ("PCI: dwc: keystone: Convert .scan_bus() callback to use add_bus")
Signed-off-by: Siddharth Vadapalli <[email protected]>
Reviewed-by: Serge Semin <[email protected]>
[Taken from https://lore.kernel.org/all/[email protected]/, manually edited]
---
drivers/pci/controller/dwc/pci-keystone.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/controller/dwc/pci-keystone.c b/drivers/pci/controller/dwc/pci-keystone.c
index a5dbe8c9b077..356bfdec00eb 100644
--- a/drivers/pci/controller/dwc/pci-keystone.c
+++ b/drivers/pci/controller/dwc/pci-keystone.c
@@ -581,6 +581,12 @@ static struct pci_ops ks_pcie_ops = {
.add_bus = ks_pcie_v3_65_add_bus,
};

+static struct pci_ops ks_pcie_am6_ops = {
+ .map_bus = dw_pcie_own_conf_map_bus,
+ .read = pci_generic_config_read,
+ .write = pci_generic_config_write,
+};
+
/**
* ks_pcie_link_up() - Check if link up
* @pci: A pointer to the dw_pcie structure which holds the DesignWare PCIe host
@@ -948,15 +954,15 @@ static int __init ks_pcie_host_init(struct dw_pcie_rp *pp)
struct keystone_pcie *ks_pcie = to_keystone_pcie(pci);
int ret;

- pp->bridge->ops = &ks_pcie_ops;
-
- if (!ks_pcie->is_am6) {
- pp->bridge->child_ops = &ks_child_pcie_ops;
- ret = ks_pcie_config_legacy_irq(ks_pcie);
+ if (ks_pcie->is_am6) {
+ pp->bridge->ops = &ks_pcie_am6_ops;
+ ret = ks_pcie_am654_config_legacy_irq(ks_pcie);
if (ret)
return ret;
} else {
- ret = ks_pcie_am654_config_legacy_irq(ks_pcie);
+ pp->bridge->ops = &ks_pcie_ops;
+ pp->bridge->child_ops = &ks_child_pcie_ops;
+ ret = ks_pcie_config_legacy_irq(ks_pcie);
if (ret)
return ret;
}

0 comments on commit 91c99e8

Please sign in to comment.