summaryrefslogtreecommitdiff
path: root/drivers/pci/pci.c
diff options
context:
space:
mode:
authorYinghai Lu <yinghai@kernel.org>2013-07-22 14:37:17 -0700
committerBjorn Helgaas <bhelgaas@google.com>2013-07-25 12:35:03 -0600
commit928bea964827d7824b548c1f8e06eccbbc4d0d7d (patch)
tree13110a5f05a65aa487cee8be5bd58017986f4929 /drivers/pci/pci.c
parent55ed83a615730c2578da155bc99b68f4417ffe20 (diff)
downloadkernel-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.c20
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)