diff mbox series

[v3,3/7] PCI: brcmstb: Gate config space access on link status

Message ID 20220725151258.42574-4-jim2101024@gmail.com (mailing list archive)
State Accepted
Headers show
Series PCI: brcmstb: Re-submit reverted patchset | expand

Commit Message

Jim Quinlan July 25, 2022, 3:12 p.m. UTC
Our PCIe RC HW has an atypical behavior: if it does not have PCIe link
established between itself and downstream, any subsequent config space
access for a downstream device causes a CPU abort.  This commit allows a
config space access for dowwnstream devices only if the PCIe link is up.

Note that config space accesses to the root port are diverted to the RC
registers and are honored regardless of link status.

Some other minor changes are also made: (1) limit the "where" offset to
4K and (2) reject RC accesses if devfn != 0.

Signed-off-by: Jim Quinlan <jim2101024@gmail.com>
---
 drivers/pci/controller/pcie-brcmstb.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)
diff mbox series

Patch

diff --git a/drivers/pci/controller/pcie-brcmstb.c b/drivers/pci/controller/pcie-brcmstb.c
index 15e47e8c94eb..3443206d2a95 100644
--- a/drivers/pci/controller/pcie-brcmstb.c
+++ b/drivers/pci/controller/pcie-brcmstb.c
@@ -683,14 +683,18 @@  static void __iomem *brcm_pcie_map_conf(struct pci_bus *bus, unsigned int devfn,
 	void __iomem *base = pcie->base;
 	int idx;
 
-	/* Accesses to the RC go right to the RC registers if slot==0 */
+	/* Accesses to the RC go right to the RC registers if !devfn */
 	if (pci_is_root_bus(bus))
-		return PCI_SLOT(devfn) ? NULL : base + where;
+		return devfn ? NULL : base + (where & 0xfff);
+
+	/* An access to our HW w/o link-up will cause a CPU Abort */
+	if (!brcm_pcie_link_up(pcie))
+		return NULL;
 
 	/* For devices, write to the config space index register */
 	idx = PCIE_ECAM_OFFSET(bus->number, devfn, 0);
 	writel(idx, pcie->base + PCIE_EXT_CFG_INDEX);
-	return base + PCIE_EXT_CFG_DATA + where;
+	return base + PCIE_EXT_CFG_DATA + (where & 0xfff);
 }
 
 static void __iomem *brcm_pcie_map_conf32(struct pci_bus *bus, unsigned int devfn,
@@ -700,12 +704,16 @@  static void __iomem *brcm_pcie_map_conf32(struct pci_bus *bus, unsigned int devf
 	void __iomem *base = pcie->base;
 	int idx;
 
-	/* Accesses to the RC go right to the RC registers if slot==0 */
+	/* Accesses to the RC go right to the RC registers if !devfn */
 	if (pci_is_root_bus(bus))
-		return PCI_SLOT(devfn) ? NULL : base + (where & ~0x3);
+		return devfn ? NULL : base + (where & 0xffc);
+
+	/* An access to our HW w/o link-up will cause a CPU Abort */
+	if (!brcm_pcie_link_up(pcie))
+		return NULL;
 
 	/* For devices, write to the config space index register */
-	idx = PCIE_ECAM_OFFSET(bus->number, devfn, (where & ~3));
+	idx = PCIE_ECAM_OFFSET(bus->number, devfn, (where & 0xffc));
 	writel(idx, base + IDX_ADDR(pcie));
 	return base + DATA_ADDR(pcie);
 }