summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2005-06-02 15:41:48 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2005-07-01 13:35:49 -0700
commit26f674ae0e37190bf61c988e52911e4372fdb5f5 (patch)
tree625b05e5edd627a5cce0289e78057ca5ccf2290c
parentef6689eff4b58273fed9e54293a3da983b321e9a (diff)
downloadlinux-26f674ae0e37190bf61c988e52911e4372fdb5f5.tar.gz
linux-26f674ae0e37190bf61c988e52911e4372fdb5f5.tar.bz2
linux-26f674ae0e37190bf61c988e52911e4372fdb5f5.zip
[PATCH] PCI: Fix up PCI routing in parent bridge
When the cardbus bridge is behind another bridge change the routing in the parent bridge for new cards. This fixes Cardbus on various AMD64 laptops. Signed-off-by: Andi Kleen <ak@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/pci/probe.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 6a0a82f0508b..9392ff3fb803 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -398,6 +398,16 @@ static void pci_enable_crs(struct pci_dev *dev)
pci_write_config_word(dev, rpcap + PCI_EXP_RTCTL, rpctl);
}
+static void __devinit pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
+{
+ struct pci_bus *parent = child->parent;
+ while (parent->parent && parent->subordinate < max) {
+ parent->subordinate = max;
+ pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
+ parent = parent->parent;
+ }
+}
+
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
/*
@@ -499,7 +509,13 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
if (!is_cardbus) {
child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA;
-
+ /*
+ * Adjust subordinate busnr in parent buses.
+ * We do this before scanning for children because
+ * some devices may not be detected if the bios
+ * was lazy.
+ */
+ pci_fixup_parent_subordinate_busnr(child, max);
/* Now we can scan all subordinate buses... */
max = pci_scan_child_bus(child);
} else {
@@ -513,6 +529,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
max+i+1))
break;
max += i;
+ pci_fixup_parent_subordinate_busnr(child, max);
}
/*
* Set the subordinate bus number to its real value.