PCI: Allow root and child buses to have different pci_ops
authorRob Herring <robh@kernel.org>
Fri, 21 Aug 2020 03:53:41 +0000 (21:53 -0600)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Mon, 7 Sep 2020 09:30:38 +0000 (10:30 +0100)
PCI host bridges often have different ways to access the root and child
bus config spaces. The host bridge drivers have invented their own
abstractions to handle this. Let's support having different root and
child bus pci_ops so these per driver abstractions can be removed.

Link: https://lore.kernel.org/r/20200821035420.380495-2-robh@kernel.org
Signed-off-by: Rob Herring <robh@kernel.org>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/probe.c
include/linux/pci.h

index 03d37128a24f205602b7f6e9299dde8bb5fea81e..0c9ebc72532e79125c9a999fe09ea49b97eee061 100644 (file)
@@ -1036,6 +1036,7 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
                                           struct pci_dev *bridge, int busnr)
 {
        struct pci_bus *child;
+       struct pci_host_bridge *host;
        int i;
        int ret;
 
@@ -1045,11 +1046,16 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
                return NULL;
 
        child->parent = parent;
-       child->ops = parent->ops;
        child->msi = parent->msi;
        child->sysdata = parent->sysdata;
        child->bus_flags = parent->bus_flags;
 
+       host = pci_find_host_bridge(parent);
+       if (host->child_ops)
+               child->ops = host->child_ops;
+       else
+               child->ops = parent->ops;
+
        /*
         * Initialize some portions of the bus device, but don't register
         * it now as the parent is not properly set up yet.
index 835530605c0d7b4a4626f65c5b869bc49f48fd5c..1fbe95a7d3867852b02b3fdc3dd60404bf1a2bde 100644 (file)
@@ -523,6 +523,7 @@ struct pci_host_bridge {
        struct device   dev;
        struct pci_bus  *bus;           /* Root bus */
        struct pci_ops  *ops;
+       struct pci_ops  *child_ops;
        void            *sysdata;
        int             busnr;
        struct list_head windows;       /* resource_entry */