Commit 7deaf3b8 authored by Russell King's avatar Russell King Committed by Linus Torvalds

[PATCH] Fix up pci_scan_bridge and friends

  Now we tackle pci_add_new_bus and pci_scan_bridge.  The hotplug code
  currently uses this, but I'd like it to die off; pci_scan_bridge()
  should be used to scan behind bridges.  This may mean hotplug needs
  some changes to pci_scan_bridge - if so, we need to find out what
  changes are required and fix it.

  pci_alloc_child_bus() does what pci_add_new_bus() did, except it
  doesn't attach the new bus to the parents list of child buses.  The
  only way this bus can be reached from the parent bus is by scanning
  the parents devices list, and locating a device with a non-NULL
  subordinate bus.  The only code which should be doing this is the
  PCI code.

  Since the new bus will have an empty list head for bus->node, we can
  detect unattached buses prety easily.  (see pci-3.diff.)

  pci_scan_bridge() changes slightly - we use our new pci_scan_child_bus()
  function from pci-3.diff, which doesn't attach devices to the global
  tree.  This means callers of pci_scan_child_bus() and pci_scan_bridge()
  (ie, hotplug) will need to call pci_bus_add_devices().
parent 5819c31c
......@@ -228,41 +228,57 @@ static struct pci_bus * __devinit pci_alloc_bus(void)
return b;
}
struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
static struct pci_bus * __devinit
pci_alloc_child_bus(struct pci_bus *parent, struct pci_dev *bridge, int busnr)
{
struct pci_bus *child;
int i;
/*
* Allocate a new bus, and inherit stuff from the parent..
*/
child = pci_alloc_bus();
list_add_tail(&child->node, &parent->children);
child->self = dev;
dev->subordinate = child;
child->parent = parent;
child->ops = parent->ops;
child->sysdata = parent->sysdata;
child->dev = &dev->dev;
if (child) {
int i;
/*
* Set up the primary, secondary and subordinate
* bus numbers.
*/
child->number = child->secondary = busnr;
child->primary = parent->secondary;
child->subordinate = 0xff;
child->self = bridge;
child->parent = parent;
child->ops = parent->ops;
child->sysdata = parent->sysdata;
child->dev = &bridge->dev;
/* Set up default resource pointers and names.. */
for (i = 0; i < 4; i++) {
child->resource[i] = &dev->resource[PCI_BRIDGE_RESOURCES+i];
child->resource[i]->name = child->name;
/*
* Set up the primary, secondary and subordinate
* bus numbers.
*/
child->number = child->secondary = busnr;
child->primary = parent->secondary;
child->subordinate = 0xff;
/* Set up default resource pointers and names.. */
for (i = 0; i < 4; i++) {
child->resource[i] = &bridge->resource[PCI_BRIDGE_RESOURCES+i];
child->resource[i]->name = child->name;
}
bridge->subordinate = child;
}
return child;
}
struct pci_bus * __devinit pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr)
{
struct pci_bus *child;
child = pci_alloc_child_bus(parent, dev, busnr);
if (child)
list_add_tail(&child->node, &parent->children);
return child;
}
static unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus);
/*
* If it's a bridge, configure it and scan the bus behind it.
* For CardBus bridges, we don't scan behind as the devices will
......@@ -289,12 +305,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
*/
if (pass)
return max;
child = pci_add_new_bus(bus, dev, 0);
child = pci_alloc_child_bus(bus, dev, 0);
child->primary = buses & 0xFF;
child->secondary = (buses >> 8) & 0xFF;
child->subordinate = (buses >> 16) & 0xFF;
child->number = child->secondary;
cmax = pci_do_scan_bus(child);
cmax = pci_scan_child_bus(child);
if (cmax > max) max = cmax;
} else {
/*
......@@ -307,18 +323,27 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max
/* Clear errors */
pci_write_config_word(dev, PCI_STATUS, 0xffff);
child = pci_add_new_bus(bus, dev, ++max);
child = pci_alloc_child_bus(bus, dev, ++max);
buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->secondary) << 8)
| ((unsigned int)(child->subordinate) << 16);
/*
* yenta.c forces a secondary latency timer of 176.
* Copy that behaviour here.
*/
if (is_cardbus)
buses = (buses & 0x00ffffff) | (176 << 24);
/*
* We need to blast all three values with a single write.
*/
pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
if (!is_cardbus) {
/* Now we can scan all subordinate buses... */
max = pci_do_scan_bus(child);
max = pci_scan_child_bus(child);
} else {
/*
* For CardBus bridges, we leave 4 bus numbers
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment