diff options
author | Eric W. Biederman <ebiederm@aristanetworks.com> | 2009-09-09 14:09:24 -0700 |
---|---|---|
committer | Jesse Barnes <jbarnes@virtuousgeek.org> | 2009-09-09 14:10:24 -0700 |
commit | 28760489a3f1e136c5ae8581c0fa8f63511f2f4c (patch) | |
tree | a3c890e9c8d9e98385691d56f5c007d280514fe5 /drivers/pci/probe.c | |
parent | 0ba379ec0fb182a87b8891c5754abbcd9c035b4f (diff) | |
download | linux-28760489a3f1e136c5ae8581c0fa8f63511f2f4c.tar.bz2 |
PCI: pcie: Ensure hotplug ports have a minimum number of resources
In general a BIOS may goof or we may hotplug in a hotplug controller.
In either case the kernel needs to reserve resources for plugging
in more devices in the future instead of creating a minimal resource
assignment.
We already do this for cardbus bridges I am just adding a variant
for pcie bridges.
v2: Make testing for pcie hotplug bridges based on a flag.
So far we only set the flag for pcie but a header_quirk
could easily be added for the non-standard pci hotplug
bridges.
Signed-off-by: Eric W. Biederman <ebiederm@aristanetworks.com>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Diffstat (limited to 'drivers/pci/probe.c')
-rw-r--r-- | drivers/pci/probe.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index ab52840f4753..882383b61d30 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -697,6 +697,23 @@ static void set_pcie_port_type(struct pci_dev *pdev) pdev->pcie_type = (reg16 & PCI_EXP_FLAGS_TYPE) >> 4; } +static void set_pcie_hotplug_bridge(struct pci_dev *pdev) +{ + int pos; + u16 reg16; + u32 reg32; + + pos = pci_find_capability(pdev, PCI_CAP_ID_EXP); + if (!pos) + return; + pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, ®16); + if (!(reg16 & PCI_EXP_FLAGS_SLOT)) + return; + pci_read_config_dword(pdev, pos + PCI_EXP_SLTCAP, ®32); + if (reg32 & PCI_EXP_SLTCAP_HPC) + pdev->is_hotplug_bridge = 1; +} + #define LEGACY_IO_RESOURCE (IORESOURCE_IO | IORESOURCE_PCI_FIXED) /** @@ -804,6 +821,7 @@ int pci_setup_device(struct pci_dev *dev) pci_read_irq(dev); dev->transparent = ((dev->class & 0xff) == 1); pci_read_bases(dev, 2, PCI_ROM_ADDRESS1); + set_pcie_hotplug_bridge(dev); break; case PCI_HEADER_TYPE_CARDBUS: /* CardBus bridge header */ |