aboutsummaryrefslogtreecommitdiff
path: root/pkgs/patches-linux-5.15/0031-PCI-mvebu-Use-child_ops-API.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/patches-linux-5.15/0031-PCI-mvebu-Use-child_ops-API.patch')
-rw-r--r--pkgs/patches-linux-5.15/0031-PCI-mvebu-Use-child_ops-API.patch165
1 files changed, 165 insertions, 0 deletions
diff --git a/pkgs/patches-linux-5.15/0031-PCI-mvebu-Use-child_ops-API.patch b/pkgs/patches-linux-5.15/0031-PCI-mvebu-Use-child_ops-API.patch
new file mode 100644
index 0000000..41d7430
--- /dev/null
+++ b/pkgs/patches-linux-5.15/0031-PCI-mvebu-Use-child_ops-API.patch
@@ -0,0 +1,165 @@
+From a32d68b41dac1a1aeab94a2c8b2239534ac59c15 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Pali=20Roh=C3=A1r?= <pali@kernel.org>
+Date: Tue, 16 Nov 2021 10:43:17 +0100
+Subject: [PATCH 31/90] PCI: mvebu: Use child_ops API
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Split struct pci_ops between ops and child_ops. Member ops is used for
+accessing PCIe Root Ports via pci-bridge-emul.c driver and child_ops for
+accessing real PCIe cards.
+
+There is no need to mix these two struct pci_ops into one as PCI core code
+already provides separate callbacks via bridge->ops and bridge->child_ops.
+
+Signed-off-by: Pali Rohár <pali@kernel.org>
+---
+ drivers/pci/controller/pci-mvebu.c | 82 ++++++++++++++++--------------
+ 1 file changed, 44 insertions(+), 38 deletions(-)
+
+diff --git a/drivers/pci/controller/pci-mvebu.c b/drivers/pci/controller/pci-mvebu.c
+index 9ea2f6a7c2b0..1e90ab888075 100644
+--- a/drivers/pci/controller/pci-mvebu.c
++++ b/drivers/pci/controller/pci-mvebu.c
+@@ -294,11 +294,29 @@ static void mvebu_pcie_setup_hw(struct mvebu_pcie_port *port)
+ mvebu_writel(port, mask, PCIE_MASK_OFF);
+ }
+
+-static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
+- struct pci_bus *bus,
+- u32 devfn, int where, int size, u32 *val)
++static struct mvebu_pcie_port *mvebu_pcie_find_port(struct mvebu_pcie *pcie,
++ struct pci_bus *bus,
++ int devfn);
++
++static int mvebu_pcie_child_rd_conf(struct pci_bus *bus, u32 devfn, int where,
++ int size, u32 *val)
+ {
+- void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
++ struct mvebu_pcie *pcie = bus->sysdata;
++ struct mvebu_pcie_port *port;
++ void __iomem *conf_data;
++
++ port = mvebu_pcie_find_port(pcie, bus, devfn);
++ if (!port) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ if (!mvebu_pcie_link_up(port)) {
++ *val = 0xffffffff;
++ return PCIBIOS_DEVICE_NOT_FOUND;
++ }
++
++ conf_data = port->base + PCIE_CONF_DATA_OFF;
+
+ mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
+ PCIE_CONF_ADDR_OFF);
+@@ -321,11 +339,21 @@ static int mvebu_pcie_hw_rd_conf(struct mvebu_pcie_port *port,
+ return PCIBIOS_SUCCESSFUL;
+ }
+
+-static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
+- struct pci_bus *bus,
+- u32 devfn, int where, int size, u32 val)
++static int mvebu_pcie_child_wr_conf(struct pci_bus *bus, u32 devfn,
++ int where, int size, u32 val)
+ {
+- void __iomem *conf_data = port->base + PCIE_CONF_DATA_OFF;
++ struct mvebu_pcie *pcie = bus->sysdata;
++ struct mvebu_pcie_port *port;
++ void __iomem *conf_data;
++
++ port = mvebu_pcie_find_port(pcie, bus, devfn);
++ if (!port)
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ if (!mvebu_pcie_link_up(port))
++ return PCIBIOS_DEVICE_NOT_FOUND;
++
++ conf_data = port->base + PCIE_CONF_DATA_OFF;
+
+ mvebu_writel(port, PCIE_CONF_ADDR(bus->number, devfn, where),
+ PCIE_CONF_ADDR_OFF);
+@@ -347,6 +375,11 @@ static int mvebu_pcie_hw_wr_conf(struct mvebu_pcie_port *port,
+ return PCIBIOS_SUCCESSFUL;
+ }
+
++static struct pci_ops mvebu_pcie_child_ops = {
++ .read = mvebu_pcie_child_rd_conf,
++ .write = mvebu_pcie_child_wr_conf,
++};
++
+ /*
+ * Remove windows, starting from the largest ones to the smallest
+ * ones.
+@@ -862,25 +895,12 @@ static int mvebu_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+ {
+ struct mvebu_pcie *pcie = bus->sysdata;
+ struct mvebu_pcie_port *port;
+- int ret;
+
+ port = mvebu_pcie_find_port(pcie, bus, devfn);
+ if (!port)
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+- /* Access the emulated PCI-to-PCI bridge */
+- if (bus->number == 0)
+- return pci_bridge_emul_conf_write(&port->bridge, where,
+- size, val);
+-
+- if (!mvebu_pcie_link_up(port))
+- return PCIBIOS_DEVICE_NOT_FOUND;
+-
+- /* Access the real PCIe interface */
+- ret = mvebu_pcie_hw_wr_conf(port, bus, devfn,
+- where, size, val);
+-
+- return ret;
++ return pci_bridge_emul_conf_write(&port->bridge, where, size, val);
+ }
+
+ /* PCI configuration space read function */
+@@ -889,7 +909,6 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+ {
+ struct mvebu_pcie *pcie = bus->sysdata;
+ struct mvebu_pcie_port *port;
+- int ret;
+
+ port = mvebu_pcie_find_port(pcie, bus, devfn);
+ if (!port) {
+@@ -897,21 +916,7 @@ static int mvebu_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+- /* Access the emulated PCI-to-PCI bridge */
+- if (bus->number == 0)
+- return pci_bridge_emul_conf_read(&port->bridge, where,
+- size, val);
+-
+- if (!mvebu_pcie_link_up(port)) {
+- *val = 0xffffffff;
+- return PCIBIOS_DEVICE_NOT_FOUND;
+- }
+-
+- /* Access the real PCIe interface */
+- ret = mvebu_pcie_hw_rd_conf(port, bus, devfn,
+- where, size, val);
+-
+- return ret;
++ return pci_bridge_emul_conf_read(&port->bridge, where, size, val);
+ }
+
+ static struct pci_ops mvebu_pcie_ops = {
+@@ -1421,6 +1426,7 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
+
+ bridge->sysdata = pcie;
+ bridge->ops = &mvebu_pcie_ops;
++ bridge->child_ops = &mvebu_pcie_child_ops;
+ bridge->align_resource = mvebu_pcie_align_resource;
+ bridge->map_irq = mvebu_pcie_map_irq;
+
+--
+2.34.1
+