From 67727b7e408b5dad2f286f3512a9f0f0f5a9e980 Mon Sep 17 00:00:00 2001 From: Bernhard Kaindl Date: Tue, 30 May 2006 18:00:34 +0200 Subject: [PATCH] --- yaml --- r: 31479 b: refs/heads/master c: b435261b1e09bb2bb6acc4abbc7f6e3d885f9e62 h: refs/heads/master i: 31477: ac2ce385883ca258721223ccb7f855beb6a5d705 31475: f9ca23892c39c95b577ab16bc8c7c7c0e7638441 31471: cea8540c12bd4e81121c31c2d22231cd11a63022 v: v3 --- [refs] | 2 +- trunk/drivers/pcmcia/yenta_socket.c | 73 +++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/[refs] b/[refs] index cd10a5486fab..0d9b490839cb 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: d250a4810402ec68f64802b66340a0e70c61cbd3 +refs/heads/master: b435261b1e09bb2bb6acc4abbc7f6e3d885f9e62 diff --git a/trunk/drivers/pcmcia/yenta_socket.c b/trunk/drivers/pcmcia/yenta_socket.c index 006749dc8d75..d9d005ec920c 100644 --- a/trunk/drivers/pcmcia/yenta_socket.c +++ b/trunk/drivers/pcmcia/yenta_socket.c @@ -1005,6 +1005,77 @@ static void yenta_config_init(struct yenta_socket *socket) config_writew(socket, CB_BRIDGE_CONTROL, bridge); } +/** + * yenta_fixup_parent_subordinate - Fix subordinate bus# of the parent bridge + * @cardbus_bridge: The PCI bus which the CardBus bridge bridges to + * + * Checks if devices on the bus which the CardBus bridge bridges to would be + * invisible during PCI scans because of a misconfigured subordinate number + * of the parent brige - some BIOSes seem to be too lazy to set it right. + * Does the fixup carefully by checking how far it can go without conflicts. + * See http://bugzilla.kernel.org/show_bug.cgi?id=2944 for more information. + */ +static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) +{ + struct list_head *tmp; + unsigned char upper_limit; + /* + * We only check and fix the parent bridge: All systems which need + * this fixup that have been reviewed are laptops and the only bridge + * which needed fixing was the parent bridge of the CardBus bridge: + */ + struct pci_bus *bridge_to_fix = cardbus_bridge->parent; + + /* Check bus numbers are already set up correctly: */ + if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate) + return; /* The subordinate number is ok, nothing to do */ + + if (!bridge_to_fix->parent) + return; /* Root bridges are ok */ + + /* stay within the limits of the bus range of the parent: */ + upper_limit = bridge_to_fix->parent->subordinate; + + /* check the bus ranges of all silbling bridges to prevent overlap */ + list_for_each(tmp, &bridge_to_fix->parent->children) { + struct pci_bus * silbling = pci_bus_b(tmp); + /* + * If the silbling has a higher secondary bus number + * and it's secondary is equal or smaller than our + * current upper limit, set the new upper limit to + * the bus number below the silbling's range: + */ + if (silbling->secondary > bridge_to_fix->subordinate + && silbling->secondary <= upper_limit) + upper_limit = silbling->secondary - 1; + } + + /* Show that the wanted subordinate number is not possible: */ + if (cardbus_bridge->subordinate > upper_limit) + printk(KERN_WARNING "Yenta: Upper limit for fixing this " + "bridge's parent bridge: #%02x\n", upper_limit); + + /* If we have room to increase the bridge's subordinate number, */ + if (bridge_to_fix->subordinate < upper_limit) { + + /* use the highest number of the hidden bus, within limits */ + unsigned char subordinate_to_assign = + min(cardbus_bridge->subordinate, upper_limit); + + printk(KERN_INFO "Yenta: Raising subordinate bus# of parent " + "bus (#%02x) from #%02x to #%02x\n", + bridge_to_fix->number, + bridge_to_fix->subordinate, subordinate_to_assign); + + /* Save the new subordinate in the bus struct of the bridge */ + bridge_to_fix->subordinate = subordinate_to_assign; + + /* and update the PCI config space with the new subordinate */ + pci_write_config_byte(bridge_to_fix->self, + PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate); + } +} + /* * Initialize a cardbus controller. Make sure we have a usable * interrupt, and that we can map the cardbus area. Fill in the @@ -1120,6 +1191,8 @@ static int __devinit yenta_probe (struct pci_dev *dev, const struct pci_device_i yenta_get_socket_capabilities(socket, isa_interrupts); printk(KERN_INFO "Socket status: %08x\n", cb_readl(socket, CB_SOCKET_STATE)); + yenta_fixup_parent_bridge(dev->subordinate); + /* Register it with the pcmcia layer.. */ ret = pcmcia_register_socket(&socket->socket); if (ret == 0) {