diff options
author | Yinghai Lu <yinghai@kernel.org> | 2013-07-22 14:37:17 -0700 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-07-25 12:35:03 -0600 |
commit | 928bea964827d7824b548c1f8e06eccbbc4d0d7d (patch) | |
tree | 13110a5f05a65aa487cee8be5bd58017986f4929 /drivers/pci/pci.c | |
parent | 55ed83a615730c2578da155bc99b68f4417ffe20 (diff) | |
download | kernel-common-928bea964827d7824b548c1f8e06eccbbc4d0d7d.tar.gz kernel-common-928bea964827d7824b548c1f8e06eccbbc4d0d7d.tar.bz2 kernel-common-928bea964827d7824b548c1f8e06eccbbc4d0d7d.zip |
PCI: Delay enabling bridges until they're needed
We currently enable PCI bridges after scanning a bus and assigning
resources. This is often done in arch code.
This patch changes this so we don't enable a bridge until necessary, i.e.,
until we enable a PCI device behind the bridge. We do this in the generic
pci_enable_device() path, so this also removes the arch-specific code to
enable bridges.
[bhelgaas: changelog]
Signed-off-by: Yinghai Lu <yinghai@kernel.org>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Diffstat (limited to 'drivers/pci/pci.c')
-rw-r--r-- | drivers/pci/pci.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index e37fea6e178d..44a1a8a0ad7b 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1145,6 +1145,24 @@ int pci_reenable_device(struct pci_dev *dev) return 0; } +static void pci_enable_bridge(struct pci_dev *dev) +{ + int retval; + + if (!dev) + return; + + pci_enable_bridge(dev->bus->self); + + if (pci_is_enabled(dev)) + return; + retval = pci_enable_device(dev); + if (retval) + dev_err(&dev->dev, "Error enabling bridge (%d), continuing\n", + retval); + pci_set_master(dev); +} + static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) { int err; @@ -1165,6 +1183,8 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) if (atomic_inc_return(&dev->enable_cnt) > 1) return 0; /* already enabled */ + pci_enable_bridge(dev->bus->self); + /* only skip sriov related */ for (i = 0; i <= PCI_ROM_RESOURCE; i++) if (dev->resource[i].flags & flags) |