提交 4d17e851 编写于 作者: B Bjorn Helgaas

Merge branch 'topic/yinghai-busn-alloc' into next

* topic/yinghai-busn-alloc: (33 commits)
  PCI: hotplug: remove pci_do_scan_bus()
  PCI: sgihp: use generic pci_hp_add_bridge()
  PCI: ibmhp: use generic pci_hp_add_bridge()
  PCI: cpqhp: use generic pci_hp_add_bridge()
  PCI: shpchp: use generic pci_hp_add_bridge()
  PCI: cpci_hotplug: use generic pci_hp_add_bridge()
  PCI: pciehp: use generic pci_hp_add_bridge()
  PCI: add generic pci_hp_add_bridge()
  PCI: sgihp: register busn_res
  PCI: ibmhp: register busn_res
  PCI: cpqhp: register busn_res
  PCI: shpchp: register busn_res
  PCI: cpci_hotplug: register busn_res
  PCI: insert busn_res for child bus
  PCI: register busn_res for iov bus
  tile/PCI: use pci_scan_root_bus instead pci_scan_bus
  parisc/PCI: register busn_res for root buses
  powerpc/PCI: register busn_res for root buses
  sparc/PCI: register busn_res for root buses
  ia64/PCI: register busn_res for root buses
  ...
...@@ -359,7 +359,7 @@ common_init_pci(void) ...@@ -359,7 +359,7 @@ common_init_pci(void)
hose, &resources); hose, &resources);
hose->bus = bus; hose->bus = bus;
hose->need_domain_info = need_domain_info; hose->need_domain_info = need_domain_info;
next_busno = bus->subordinate + 1; next_busno = bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose - /* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */ reserve some space for bridges. */
if (next_busno > 224) { if (next_busno > 224) {
......
...@@ -461,7 +461,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head) ...@@ -461,7 +461,7 @@ static void __init pcibios_init_hw(struct hw_pci *hw, struct list_head *head)
if (!sys->bus) if (!sys->bus)
panic("PCI: unable to scan bus!"); panic("PCI: unable to scan bus!");
busnr = sys->bus->subordinate + 1; busnr = sys->bus->busn_res.end + 1;
list_add(&sys->node, head); list_add(&sys->node, head);
} else { } else {
......
...@@ -351,6 +351,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root) ...@@ -351,6 +351,8 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
#endif #endif
INIT_LIST_HEAD(&info.resources); INIT_LIST_HEAD(&info.resources);
/* insert busn resource at first */
pci_add_resource(&info.resources, &root->secondary);
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window, acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
&windows); &windows);
if (windows) { if (windows) {
...@@ -384,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root) ...@@ -384,7 +386,7 @@ pci_acpi_scan_root(struct acpi_pci_root *root)
return NULL; return NULL;
} }
pbus->subordinate = pci_scan_child_bus(pbus); pci_scan_child_bus(pbus);
return pbus; return pbus;
out3: out3:
......
...@@ -1506,10 +1506,10 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose) ...@@ -1506,10 +1506,10 @@ static void __devinit pcibios_scan_phb(struct pci_controller *hose)
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
return; return;
} }
bus->secondary = hose->first_busno; bus->busn_res.start = hose->first_busno;
hose->bus = bus; hose->bus = bus;
hose->last_busno = bus->subordinate; hose->last_busno = bus->busn_res.end;
} }
static int __init pcibios_init(void) static int __init pcibios_init(void)
......
...@@ -102,7 +102,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose) ...@@ -102,7 +102,7 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose)
need_domain_info = need_domain_info || hose->index; need_domain_info = need_domain_info || hose->index;
hose->need_domain_info = need_domain_info; hose->need_domain_info = need_domain_info;
if (bus) { if (bus) {
next_busno = bus->subordinate + 1; next_busno = bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose - /* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */ reserve some space for bridges. */
if (next_busno > 224) { if (next_busno > 224) {
......
...@@ -30,6 +30,7 @@ struct pci_controller { ...@@ -30,6 +30,7 @@ struct pci_controller {
int first_busno; int first_busno;
int last_busno; int last_busno;
int self_busno; int self_busno;
struct resource busn;
void __iomem *io_base_virt; void __iomem *io_base_virt;
#ifdef CONFIG_PPC64 #ifdef CONFIG_PPC64
......
...@@ -1637,6 +1637,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) ...@@ -1637,6 +1637,11 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
/* Wire up PHB bus resources */ /* Wire up PHB bus resources */
pcibios_setup_phb_resources(hose, &resources); pcibios_setup_phb_resources(hose, &resources);
hose->busn.start = hose->first_busno;
hose->busn.end = hose->last_busno;
hose->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &hose->busn);
/* Create an empty bus for the toplevel */ /* Create an empty bus for the toplevel */
bus = pci_create_root_bus(hose->parent, hose->first_busno, bus = pci_create_root_bus(hose->parent, hose->first_busno,
hose->ops, hose, &resources); hose->ops, hose, &resources);
...@@ -1646,7 +1651,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) ...@@ -1646,7 +1651,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
return; return;
} }
bus->secondary = hose->first_busno;
hose->bus = bus; hose->bus = bus;
/* Get probe mode and perform scan */ /* Get probe mode and perform scan */
...@@ -1654,13 +1658,14 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose) ...@@ -1654,13 +1658,14 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
if (node && ppc_md.pci_probe_mode) if (node && ppc_md.pci_probe_mode)
mode = ppc_md.pci_probe_mode(bus); mode = ppc_md.pci_probe_mode(bus);
pr_debug(" probe mode: %d\n", mode); pr_debug(" probe mode: %d\n", mode);
if (mode == PCI_PROBE_DEVTREE) { if (mode == PCI_PROBE_DEVTREE)
bus->subordinate = hose->last_busno;
of_scan_bus(node, bus); of_scan_bus(node, bus);
}
if (mode == PCI_PROBE_NORMAL) if (mode == PCI_PROBE_NORMAL) {
hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); pci_bus_update_busn_res_end(bus, 255);
hose->last_busno = pci_scan_child_bus(bus);
pci_bus_update_busn_res_end(bus, hose->last_busno);
}
/* Platform gets a chance to do some global fixups before /* Platform gets a chance to do some global fixups before
* we proceed to resource allocation * we proceed to resource allocation
......
...@@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, ...@@ -236,7 +236,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus,
for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) {
bus = pci_bus_b(ln); bus = pci_bus_b(ln);
if (in_bus >= bus->number && in_bus <= bus->subordinate) if (in_bus >= bus->number && in_bus <= bus->busn_res.end)
break; break;
bus = NULL; bus = NULL;
} }
......
...@@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev) ...@@ -240,7 +240,7 @@ void __devinit of_scan_pci_bridge(struct pci_dev *dev)
} }
bus->primary = dev->bus->number; bus->primary = dev->bus->number;
bus->subordinate = busrange[1]; pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
bus->bridge_ctl = 0; bus->bridge_ctl = 0;
/* parse ranges property */ /* parse ranges property */
......
...@@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb, ...@@ -589,7 +589,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER; dcomp = OPAL_IGNORE_RID_DEVICE_NUMBER;
fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER; fcomp = OPAL_IGNORE_RID_FUNCTION_NUMBER;
parent = pe->pbus->self; parent = pe->pbus->self;
count = pe->pbus->subordinate - pe->pbus->secondary + 1; count = pe->pbus->busn_res.end - pe->pbus->busn_res.start + 1;
switch(count) { switch(count) {
case 1: bcomp = OpalPciBusAll; break; case 1: bcomp = OpalPciBusAll; break;
case 2: bcomp = OpalPciBus7Bits; break; case 2: bcomp = OpalPciBus7Bits; break;
...@@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev, ...@@ -816,11 +816,11 @@ static void __devinit pnv_ioda_setup_bus_PE(struct pci_dev *dev,
pe->pdev = NULL; pe->pdev = NULL;
pe->tce32_seg = -1; pe->tce32_seg = -1;
pe->mve_number = -1; pe->mve_number = -1;
pe->rid = bus->secondary << 8; pe->rid = bus->busn_res.start << 8;
pe->dma_weight = 0; pe->dma_weight = 0;
pe_info(pe, "Secondary busses %d..%d associated with PE\n", pe_info(pe, "Secondary busses %pR associated with PE\n",
bus->secondary, bus->subordinate); &bus->busn_res);
if (pnv_ioda_configure_pe(phb, pe)) { if (pnv_ioda_configure_pe(phb, pe)) {
/* XXX What do we do here ? */ /* XXX What do we do here ? */
......
...@@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus) ...@@ -121,7 +121,7 @@ void pcibios_add_pci_devices(struct pci_bus * bus)
if (!num) if (!num)
return; return;
pcibios_setup_bus_devices(bus); pcibios_setup_bus_devices(bus);
max = bus->secondary; max = bus->busn_res.start;
for (pass=0; pass < 2; pass++) for (pass=0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list) { list_for_each_entry(dev, &bus->devices, bus_list) {
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
......
...@@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose) ...@@ -59,7 +59,7 @@ static void __devinit pcibios_scanbus(struct pci_channel *hose)
need_domain_info = need_domain_info || hose->index; need_domain_info = need_domain_info || hose->index;
hose->need_domain_info = need_domain_info; hose->need_domain_info = need_domain_info;
if (bus) { if (bus) {
next_busno = bus->subordinate + 1; next_busno = bus->busn_res.end + 1;
/* Don't allow 8-bit bus number overflow inside the hose - /* Don't allow 8-bit bus number overflow inside the hose -
reserve some space for bridges. */ reserve some space for bridges. */
if (next_busno > 224) { if (next_busno > 224) {
......
...@@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm, ...@@ -535,7 +535,7 @@ static void __devinit of_scan_pci_bridge(struct pci_pbm_info *pbm,
} }
bus->primary = dev->bus->number; bus->primary = dev->bus->number;
bus->subordinate = busrange[1]; pci_bus_insert_busn_res(bus, busrange[0], busrange[1]);
bus->bridge_ctl = 0; bus->bridge_ctl = 0;
/* parse ranges property, or cook one up by hand for Simba */ /* parse ranges property, or cook one up by hand for Simba */
...@@ -685,6 +685,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, ...@@ -685,6 +685,10 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
pbm->io_space.start); pbm->io_space.start);
pci_add_resource_offset(&resources, &pbm->mem_space, pci_add_resource_offset(&resources, &pbm->mem_space,
pbm->mem_space.start); pbm->mem_space.start);
pbm->busn.start = pbm->pci_first_busno;
pbm->busn.end = pbm->pci_last_busno;
pbm->busn.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &pbm->busn);
bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops, bus = pci_create_root_bus(parent, pbm->pci_first_busno, pbm->pci_ops,
pbm, &resources); pbm, &resources);
if (!bus) { if (!bus) {
...@@ -693,8 +697,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, ...@@ -693,8 +697,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm,
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
return NULL; return NULL;
} }
bus->secondary = pbm->pci_first_busno;
bus->subordinate = pbm->pci_last_busno;
pci_of_scan_bus(pbm, node, bus); pci_of_scan_bus(pbm, node, bus);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
......
...@@ -97,6 +97,7 @@ struct pci_pbm_info { ...@@ -97,6 +97,7 @@ struct pci_pbm_info {
/* PBM I/O and Memory space resources. */ /* PBM I/O and Memory space resources. */
struct resource io_space; struct resource io_space;
struct resource mem_space; struct resource mem_space;
struct resource busn;
/* Base of PCI Config space, can be per-PBM or shared. */ /* Base of PCI Config space, can be per-PBM or shared. */
unsigned long config_space; unsigned long config_space;
......
...@@ -310,6 +310,7 @@ int __init pcibios_init(void) ...@@ -310,6 +310,7 @@ int __init pcibios_init(void)
if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) { if (pci_scan_flags[i] == 0 && controllers[i].ops != NULL) {
struct pci_controller *controller = &controllers[i]; struct pci_controller *controller = &controllers[i];
struct pci_bus *bus; struct pci_bus *bus;
LIST_HEAD(resources);
if (tile_init_irqs(i, controller)) { if (tile_init_irqs(i, controller)) {
pr_err("PCI: Could not initialize IRQs\n"); pr_err("PCI: Could not initialize IRQs\n");
...@@ -327,9 +328,11 @@ int __init pcibios_init(void) ...@@ -327,9 +328,11 @@ int __init pcibios_init(void)
* This is inlined in linux/pci.h and calls into * This is inlined in linux/pci.h and calls into
* pci_scan_bus_parented() in probe.c. * pci_scan_bus_parented() in probe.c.
*/ */
bus = pci_scan_bus(0, controller->ops, controller); pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource);
bus = pci_scan_root_bus(NULL, 0, controller->ops, controller, &resources);
controller->root_bus = bus; controller->root_bus = bus;
controller->last_busno = bus->subordinate; controller->last_busno = bus->busn_res.end;
} }
} }
...@@ -366,7 +369,7 @@ int __init pcibios_init(void) ...@@ -366,7 +369,7 @@ int __init pcibios_init(void)
*/ */
if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI && if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
(PCI_SLOT(dev->devfn) == 0)) { (PCI_SLOT(dev->devfn) == 0)) {
next_bus = dev->subordinate; next_bus = dev->busn_res.end;
controllers[i].mem_resources[0] = controllers[i].mem_resources[0] =
*next_bus->resource[0]; *next_bus->resource[0];
controllers[i].mem_resources[1] = controllers[i].mem_resources[1] =
......
...@@ -12,7 +12,6 @@ struct pci_root_info { ...@@ -12,7 +12,6 @@ struct pci_root_info {
char name[16]; char name[16];
unsigned int res_num; unsigned int res_num;
struct resource *res; struct resource *res;
int busnum;
struct pci_sysdata sd; struct pci_sysdata sd;
}; };
...@@ -347,7 +346,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, ...@@ -347,7 +346,9 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
{ {
size_t size; size_t size;
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
info->bridge = device; info->bridge = device;
info->res_num = 0; info->res_num = 0;
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource, acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_resource,
info); info);
...@@ -360,8 +361,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device, ...@@ -360,8 +361,6 @@ probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
if (!info->res) if (!info->res)
return; return;
sprintf(info->name, "PCI Bus %04x:%02x", domain, busnum);
acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource, acpi_walk_resources(device->handle, METHOD_NAME__CRS, setup_resource,
info); info);
} }
...@@ -426,6 +425,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) ...@@ -426,6 +425,8 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
} else { } else {
probe_pci_root_info(info, device, busnum, domain); probe_pci_root_info(info, device, busnum, domain);
/* insert busn res at first */
pci_add_resource(&resources, &root->secondary);
/* /*
* _CRS with no apertures is normal, so only fall back to * _CRS with no apertures is normal, so only fall back to
* defaults or native bridge info if we're ignoring _CRS. * defaults or native bridge info if we're ignoring _CRS.
...@@ -440,7 +441,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root) ...@@ -440,7 +441,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_pci_root *root)
bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd, bus = pci_create_root_bus(NULL, busnum, &pci_root_ops, sd,
&resources); &resources);
if (bus) { if (bus) {
bus->subordinate = pci_scan_child_bus(bus); pci_scan_child_bus(bus);
pci_set_host_bridge_release( pci_set_host_bridge_release(
to_pci_host_bridge(bus->bridge), to_pci_host_bridge(bus->bridge),
release_pci_root_info, info); release_pci_root_info, info);
......
...@@ -121,7 +121,6 @@ static int __init early_fill_mp_bus_info(void) ...@@ -121,7 +121,6 @@ static int __init early_fill_mp_bus_info(void)
link = (reg >> 8) & 0x03; link = (reg >> 8) & 0x03;
info = alloc_pci_root_info(min_bus, max_bus, node, link); info = alloc_pci_root_info(min_bus, max_bus, node, link);
sprintf(info->name, "PCI Bus #%02x", min_bus);
} }
/* get the default node and link for left over res */ /* get the default node and link for left over res */
...@@ -300,9 +299,9 @@ static int __init early_fill_mp_bus_info(void) ...@@ -300,9 +299,9 @@ static int __init early_fill_mp_bus_info(void)
int busnum; int busnum;
struct pci_root_res *root_res; struct pci_root_res *root_res;
busnum = info->bus_min; busnum = info->busn.start;
printk(KERN_DEBUG "bus: [%02x, %02x] on node %x link %x\n", printk(KERN_DEBUG "bus: %pR on node %x link %x\n",
info->bus_min, info->bus_max, info->node, info->link); &info->busn, info->node, info->link);
list_for_each_entry(root_res, &info->resources, list) list_for_each_entry(root_res, &info->resources, list)
printk(KERN_DEBUG "bus: %02x %pR\n", printk(KERN_DEBUG "bus: %02x %pR\n",
busnum, &root_res->res); busnum, &root_res->res);
......
...@@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus) ...@@ -14,7 +14,7 @@ static struct pci_root_info *x86_find_pci_root_info(int bus)
return NULL; return NULL;
list_for_each_entry(info, &pci_root_infos, list) list_for_each_entry(info, &pci_root_infos, list)
if (info->bus_min == bus) if (info->busn.start == bus)
return info; return info;
return NULL; return NULL;
...@@ -24,6 +24,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources) ...@@ -24,6 +24,8 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
{ {
struct pci_root_info *info = x86_find_pci_root_info(bus); struct pci_root_info *info = x86_find_pci_root_info(bus);
struct pci_root_res *root_res; struct pci_root_res *root_res;
struct pci_host_bridge_window *window;
bool found = false;
if (!info) if (!info)
goto default_resources; goto default_resources;
...@@ -31,6 +33,16 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources) ...@@ -31,6 +33,16 @@ void x86_pci_root_bus_resources(int bus, struct list_head *resources)
printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n", printk(KERN_DEBUG "PCI: root bus %02x: hardware-probed resources\n",
bus); bus);
/* already added by acpi ? */
list_for_each_entry(window, resources, list)
if (window->res->flags & IORESOURCE_BUS) {
found = true;
break;
}
if (!found)
pci_add_resource(resources, &info->busn);
list_for_each_entry(root_res, &info->resources, list) { list_for_each_entry(root_res, &info->resources, list) {
struct resource *res; struct resource *res;
struct resource *root; struct resource *root;
...@@ -66,9 +78,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max, ...@@ -66,9 +78,13 @@ struct pci_root_info __init *alloc_pci_root_info(int bus_min, int bus_max,
if (!info) if (!info)
return info; return info;
sprintf(info->name, "PCI Bus #%02x", bus_min);
INIT_LIST_HEAD(&info->resources); INIT_LIST_HEAD(&info->resources);
info->bus_min = bus_min; info->busn.name = info->name;
info->bus_max = bus_max; info->busn.start = bus_min;
info->busn.end = bus_max;
info->busn.flags = IORESOURCE_BUS;
info->node = node; info->node = node;
info->link = link; info->link = link;
......
...@@ -13,8 +13,7 @@ struct pci_root_info { ...@@ -13,8 +13,7 @@ struct pci_root_info {
struct list_head list; struct list_head list;
char name[12]; char name[12];
struct list_head resources; struct list_head resources;
int bus_min; struct resource busn;
int bus_max;
int node; int node;
int link; int link;
}; };
......
...@@ -187,7 +187,7 @@ static int __init pcibios_init(void) ...@@ -187,7 +187,7 @@ static int __init pcibios_init(void)
bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno, bus = pci_scan_root_bus(NULL, pci_ctrl->first_busno,
pci_ctrl->ops, pci_ctrl, &resources); pci_ctrl->ops, pci_ctrl, &resources);
pci_ctrl->bus = bus; pci_ctrl->bus = bus;
pci_ctrl->last_busno = bus->subordinate; pci_ctrl->last_busno = bus->busn_res.end;
if (next_busno <= pci_ctrl->last_busno) if (next_busno <= pci_ctrl->last_busno)
next_busno = pci_ctrl->last_busno+1; next_busno = pci_ctrl->last_busno+1;
} }
......
...@@ -661,7 +661,7 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) ...@@ -661,7 +661,7 @@ static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn)
if (drhd->devices[i] && if (drhd->devices[i] &&
drhd->devices[i]->subordinate && drhd->devices[i]->subordinate &&
drhd->devices[i]->subordinate->number <= bus && drhd->devices[i]->subordinate->number <= bus &&
drhd->devices[i]->subordinate->subordinate >= bus) drhd->devices[i]->subordinate->busn_res.end >= bus)
return drhd->iommu; return drhd->iommu;
} }
......
...@@ -14168,7 +14168,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -14168,7 +14168,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (bridge->subordinate && if (bridge->subordinate &&
(bridge->subordinate->number <= (bridge->subordinate->number <=
tp->pdev->bus->number) && tp->pdev->bus->number) &&
(bridge->subordinate->subordinate >= (bridge->subordinate->busn_res.end >=
tp->pdev->bus->number)) { tp->pdev->bus->number)) {
tg3_flag_set(tp, 5701_DMA_BUG); tg3_flag_set(tp, 5701_DMA_BUG);
pci_dev_put(bridge); pci_dev_put(bridge);
...@@ -14196,7 +14196,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) ...@@ -14196,7 +14196,7 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
if (bridge && bridge->subordinate && if (bridge && bridge->subordinate &&
(bridge->subordinate->number <= (bridge->subordinate->number <=
tp->pdev->bus->number) && tp->pdev->bus->number) &&
(bridge->subordinate->subordinate >= (bridge->subordinate->busn_res.end >=
tp->pdev->bus->number)) { tp->pdev->bus->number)) {
tg3_flag_set(tp, 40BIT_DMA_BUG); tg3_flag_set(tp, 40BIT_DMA_BUG);
pci_dev_put(bridge); pci_dev_put(bridge);
......
...@@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -174,7 +174,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val) int size, u32 *val)
{ {
struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
void __iomem *base_addr = d->hba.base_addr; void __iomem *base_addr = d->hba.base_addr;
unsigned long flags; unsigned long flags;
...@@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, ...@@ -209,7 +209,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 val) int size, u32 val)
{ {
struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge)); struct dino_device *d = DINO_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3); u32 v = DINO_CFG_TOK(local_bus, devfn, where & ~3);
void __iomem *base_addr = d->hba.base_addr; void __iomem *base_addr = d->hba.base_addr;
unsigned long flags; unsigned long flags;
...@@ -554,7 +554,7 @@ dino_fixup_bus(struct pci_bus *bus) ...@@ -554,7 +554,7 @@ dino_fixup_bus(struct pci_bus *bus)
struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge)); struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n", DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n",
__func__, bus, bus->secondary, __func__, bus, bus->busn_res.start,
bus->bridge->platform_data); bus->bridge->platform_data);
/* Firmware doesn't set up card-mode dino, so we have to */ /* Firmware doesn't set up card-mode dino, so we have to */
...@@ -898,6 +898,7 @@ static int __init dino_probe(struct parisc_device *dev) ...@@ -898,6 +898,7 @@ static int __init dino_probe(struct parisc_device *dev)
LIST_HEAD(resources); LIST_HEAD(resources);
struct pci_bus *bus; struct pci_bus *bus;
unsigned long hpa = dev->hpa.start; unsigned long hpa = dev->hpa.start;
int max;
name = "Dino"; name = "Dino";
if (is_card_dino(&dev->id)) { if (is_card_dino(&dev->id)) {
...@@ -983,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev) ...@@ -983,6 +984,10 @@ static int __init dino_probe(struct parisc_device *dev)
if (dino_dev->hba.gmmio_space.flags) if (dino_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &dino_dev->hba.gmmio_space); pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
dino_dev->hba.bus_num.start = dino_current_bus;
dino_dev->hba.bus_num.end = 255;
dino_dev->hba.bus_num.flags = IORESOURCE_BUS;
pci_add_resource(&resources, &dino_dev->hba.bus_num);
/* /*
** It's not used to avoid chicken/egg problems ** It's not used to avoid chicken/egg problems
** with configuration accessor functions. ** with configuration accessor functions.
...@@ -998,12 +1003,13 @@ static int __init dino_probe(struct parisc_device *dev) ...@@ -998,12 +1003,13 @@ static int __init dino_probe(struct parisc_device *dev)
return 0; return 0;
} }
bus->subordinate = pci_scan_child_bus(bus); max = pci_scan_child_bus(bus);
pci_bus_update_busn_res_end(bus, max);
/* This code *depends* on scanning being single threaded /* This code *depends* on scanning being single threaded
* if it isn't, this global bus number count will fail * if it isn't, this global bus number count will fail
*/ */
dino_current_bus = bus->subordinate + 1; dino_current_bus = max + 1;
pci_bus_assign_resources(bus); pci_bus_assign_resources(bus);
pci_bus_add_devices(bus); pci_bus_add_devices(bus);
return 0; return 0;
......
...@@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) ...@@ -532,7 +532,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
intr_slot = PCI_SLOT(pcidev->devfn); intr_slot = PCI_SLOT(pcidev->devfn);
} }
DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n", DBG_IRT("iosapic_xlate_pin: bus %d slot %d pin %d\n",
pcidev->bus->secondary, intr_slot, intr_pin); pcidev->bus->busn_res.start, intr_slot, intr_pin);
return irt_find_irqline(isi, intr_slot, intr_pin); return irt_find_irqline(isi, intr_slot, intr_pin);
} }
......
...@@ -189,8 +189,8 @@ lba_dump_res(struct resource *r, int d) ...@@ -189,8 +189,8 @@ lba_dump_res(struct resource *r, int d)
static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d) static int lba_device_present(u8 bus, u8 dfn, struct lba_device *d)
{ {
u8 first_bus = d->hba.hba_bus->secondary; u8 first_bus = d->hba.hba_bus->busn_res.start;
u8 last_sub_bus = d->hba.hba_bus->subordinate; u8 last_sub_bus = d->hba.hba_bus->busn_res.end;
if ((bus < first_bus) || if ((bus < first_bus) ||
(bus > last_sub_bus) || (bus > last_sub_bus) ||
...@@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size) ...@@ -364,7 +364,7 @@ lba_rd_cfg(struct lba_device *d, u32 tok, u8 reg, u32 size)
static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
{ {
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
u32 tok = LBA_CFG_TOK(local_bus, devfn); u32 tok = LBA_CFG_TOK(local_bus, devfn);
void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
...@@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int ...@@ -380,7 +380,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int
return 0; return 0;
} }
if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) { if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->busn_res.start, devfn, d)) {
DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos); DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos);
/* either don't want to look or know device isn't present. */ /* either don't want to look or know device isn't present. */
*data = ~0U; *data = ~0U;
...@@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size) ...@@ -431,7 +431,7 @@ lba_wr_cfg(struct lba_device *d, u32 tok, u8 reg, u32 data, u32 size)
static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data) static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 data)
{ {
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
u32 tok = LBA_CFG_TOK(local_bus,devfn); u32 tok = LBA_CFG_TOK(local_bus,devfn);
if ((pos > 255) || (devfn > 255)) if ((pos > 255) || (devfn > 255))
...@@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int ...@@ -444,7 +444,7 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int
return 0; return 0;
} }
if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) { if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->busn_res.start, devfn, d))) {
DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data); DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data);
return 1; /* New Workaround */ return 1; /* New Workaround */
} }
...@@ -481,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = { ...@@ -481,7 +481,7 @@ static struct pci_ops elroy_cfg_ops = {
static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data) static int mercury_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int size, u32 *data)
{ {
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
u32 tok = LBA_CFG_TOK(local_bus, devfn); u32 tok = LBA_CFG_TOK(local_bus, devfn);
void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
...@@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i ...@@ -514,7 +514,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i
{ {
struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge)); struct lba_device *d = LBA_DEV(parisc_walk_tree(bus->bridge));
void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA; void __iomem *data_reg = d->hba.base_addr + LBA_PCI_CFG_DATA;
u32 local_bus = (bus->parent == NULL) ? 0 : bus->secondary; u32 local_bus = (bus->parent == NULL) ? 0 : bus->busn_res.start;
u32 tok = LBA_CFG_TOK(local_bus,devfn); u32 tok = LBA_CFG_TOK(local_bus,devfn);
if ((pos > 255) || (devfn > 255)) if ((pos > 255) || (devfn > 255))
...@@ -636,7 +636,7 @@ lba_fixup_bus(struct pci_bus *bus) ...@@ -636,7 +636,7 @@ lba_fixup_bus(struct pci_bus *bus)
struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge)); struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n", DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
bus, bus->secondary, bus->bridge->platform_data); bus, (int)bus->busn_res.start, bus->bridge->platform_data);
/* /*
** Properly Setup MMIO resources for this bus. ** Properly Setup MMIO resources for this bus.
...@@ -989,6 +989,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev) ...@@ -989,6 +989,7 @@ lba_pat_resources(struct parisc_device *pa_dev, struct lba_device *lba_dev)
case PAT_PBNUM: case PAT_PBNUM:
lba_dev->hba.bus_num.start = p->start; lba_dev->hba.bus_num.start = p->start;
lba_dev->hba.bus_num.end = p->end; lba_dev->hba.bus_num.end = p->end;
lba_dev->hba.bus_num.flags = IORESOURCE_BUS;
break; break;
case PAT_LMMIO: case PAT_LMMIO:
...@@ -1366,6 +1367,7 @@ lba_driver_probe(struct parisc_device *dev) ...@@ -1366,6 +1367,7 @@ lba_driver_probe(struct parisc_device *dev)
void *tmp_obj; void *tmp_obj;
char *version; char *version;
void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096); void __iomem *addr = ioremap_nocache(dev->hpa.start, 4096);
int max;
/* Read HW Rev First */ /* Read HW Rev First */
func_class = READ_REG32(addr + LBA_FCLASS); func_class = READ_REG32(addr + LBA_FCLASS);
...@@ -1502,6 +1504,8 @@ lba_driver_probe(struct parisc_device *dev) ...@@ -1502,6 +1504,8 @@ lba_driver_probe(struct parisc_device *dev)
if (lba_dev->hba.gmmio_space.flags) if (lba_dev->hba.gmmio_space.flags)
pci_add_resource(&resources, &lba_dev->hba.gmmio_space); pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
pci_add_resource(&resources, &lba_dev->hba.bus_num);
dev->dev.platform_data = lba_dev; dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus = lba_bus = lba_dev->hba.hba_bus =
pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start, pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
...@@ -1511,7 +1515,7 @@ lba_driver_probe(struct parisc_device *dev) ...@@ -1511,7 +1515,7 @@ lba_driver_probe(struct parisc_device *dev)
return 0; return 0;
} }
lba_bus->subordinate = pci_scan_child_bus(lba_bus); max = pci_scan_child_bus(lba_bus);
/* This is in lieu of calling pci_assign_unassigned_resources() */ /* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) { if (is_pdc_pat()) {
...@@ -1541,7 +1545,7 @@ lba_driver_probe(struct parisc_device *dev) ...@@ -1541,7 +1545,7 @@ lba_driver_probe(struct parisc_device *dev)
lba_dev->flags |= LBA_FLAG_SKIP_PROBE; lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
} }
lba_next_bus = lba_bus->subordinate + 1; lba_next_bus = max + 1;
pci_bus_add_devices(lba_bus); pci_bus_add_devices(lba_bus);
/* Whew! Finally done! Tell services we got this one covered. */ /* Whew! Finally done! Tell services we got this one covered. */
......
...@@ -4,18 +4,26 @@ ...@@ -4,18 +4,26 @@
#include <linux/export.h> #include <linux/export.h>
#include "pci.h" #include "pci.h"
int __ref pci_hp_add_bridge(struct pci_dev *dev)
unsigned int __devinit pci_do_scan_bus(struct pci_bus *bus)
{ {
unsigned int max; struct pci_bus *parent = dev->bus;
int pass, busnr, start = parent->busn_res.start;
max = pci_scan_child_bus(bus); int end = parent->busn_res.end;
/* for (busnr = start; busnr <= end; busnr++) {
* Make the discovered devices available. if (!pci_find_bus(pci_domain_nr(parent), busnr))
*/ break;
pci_bus_add_devices(bus); }
if (busnr-- > end) {
printk(KERN_ERR "No bus number available for hot-added bridge %s\n",
pci_name(dev));
return -1;
}
for (pass = 0; pass < 2; pass++)
busnr = pci_scan_bridge(parent, dev, busnr, pass);
if (!dev->subordinate)
return -1;
return max; return 0;
} }
EXPORT_SYMBOL(pci_do_scan_bus); EXPORT_SYMBOL_GPL(pci_hp_add_bridge);
...@@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val, ...@@ -100,11 +100,11 @@ static int post_dock_fixups(struct notifier_block *nb, unsigned long val,
PCI_PRIMARY_BUS, PCI_PRIMARY_BUS,
&buses); &buses);
if (((buses >> 8) & 0xff) != bus->secondary) { if (((buses >> 8) & 0xff) != bus->busn_res.start) {
buses = (buses & 0xff000000) buses = (buses & 0xff000000)
| ((unsigned int)(bus->primary) << 0) | ((unsigned int)(bus->primary) << 0)
| ((unsigned int)(bus->secondary) << 8) | ((unsigned int)(bus->busn_res.start) << 8)
| ((unsigned int)(bus->subordinate) << 16); | ((unsigned int)(bus->busn_res.end) << 16);
pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses); pci_write_config_dword(bus->self, PCI_PRIMARY_BUS, buses);
} }
return NOTIFY_OK; return NOTIFY_OK;
...@@ -692,7 +692,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus) ...@@ -692,7 +692,7 @@ static unsigned char acpiphp_max_busnr(struct pci_bus *bus)
* bus->subordinate value because it could have * bus->subordinate value because it could have
* padding in it. * padding in it.
*/ */
max = bus->secondary; max = bus->busn_res.start;
list_for_each(tmp, &bus->children) { list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp)); n = pci_bus_max_busnr(pci_bus_b(tmp));
......
...@@ -285,42 +285,19 @@ int __ref cpci_configure_slot(struct slot *slot) ...@@ -285,42 +285,19 @@ int __ref cpci_configure_slot(struct slot *slot)
for (fn = 0; fn < 8; fn++) { for (fn = 0; fn < 8; fn++) {
struct pci_dev *dev; struct pci_dev *dev;
dev = pci_get_slot(parent, PCI_DEVFN(PCI_SLOT(slot->devfn), fn)); dev = pci_get_slot(parent,
PCI_DEVFN(PCI_SLOT(slot->devfn), fn));
if (!dev) if (!dev)
continue; continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
/* Find an unused bus number for the new bridge */ pci_hp_add_bridge(dev);
struct pci_bus *child;
unsigned char busnr, start = parent->secondary;
unsigned char end = parent->subordinate;
for (busnr = start; busnr <= end; busnr++) {
if (!pci_find_bus(pci_domain_nr(parent),
busnr))
break;
}
if (busnr >= end) {
err("No free bus for hot-added bridge\n");
pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
err("Cannot add new bus for %s\n",
pci_name(dev));
pci_dev_put(dev);
continue;
}
child->subordinate = pci_do_scan_bus(child);
pci_bus_size_bridges(child);
}
pci_dev_put(dev); pci_dev_put(dev);
} }
pci_bus_assign_resources(parent); pci_assign_unassigned_bridge_resources(parent->self);
pci_bus_add_devices(parent); pci_bus_add_devices(parent);
pci_enable_bridges(parent);
dbg("%s - exit", __func__); dbg("%s - exit", __func__);
return 0; return 0;
......
...@@ -83,7 +83,6 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom ...@@ -83,7 +83,6 @@ static void __iomem *detect_HRT_floating_pointer(void __iomem *begin, void __iom
int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
{ {
unsigned char bus;
struct pci_bus *child; struct pci_bus *child;
int num; int num;
...@@ -106,9 +105,10 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func) ...@@ -106,9 +105,10 @@ int cpqhp_configure_device (struct controller* ctrl, struct pci_func* func)
} }
if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { if (func->pci_dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
pci_read_config_byte(func->pci_dev, PCI_SECONDARY_BUS, &bus); pci_hp_add_bridge(func->pci_dev);
child = (struct pci_bus*) pci_add_new_bus(func->pci_dev->bus, (func->pci_dev), bus); child = func->pci_dev->subordinate;
pci_do_scan_bus(child); if (child)
pci_bus_add_devices(child);
} }
pci_dev_put(func->pci_dev); pci_dev_put(func->pci_dev);
......
...@@ -775,7 +775,6 @@ static u8 bus_structure_fixup(u8 busno) ...@@ -775,7 +775,6 @@ static u8 bus_structure_fixup(u8 busno)
static int ibm_configure_device(struct pci_func *func) static int ibm_configure_device(struct pci_func *func)
{ {
unsigned char bus;
struct pci_bus *child; struct pci_bus *child;
int num; int num;
int flag = 0; /* this is to make sure we don't double scan the bus, int flag = 0; /* this is to make sure we don't double scan the bus,
...@@ -805,9 +804,10 @@ static int ibm_configure_device(struct pci_func *func) ...@@ -805,9 +804,10 @@ static int ibm_configure_device(struct pci_func *func)
} }
} }
if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) { if (!(flag) && (func->dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
pci_read_config_byte(func->dev, PCI_SECONDARY_BUS, &bus); pci_hp_add_bridge(func->dev);
child = pci_add_new_bus(func->dev->bus, func->dev, bus); child = func->dev->subordinate;
pci_do_scan_bus(child); if (child)
pci_bus_add_devices(child);
} }
return 0; return 0;
......
...@@ -34,29 +34,6 @@ ...@@ -34,29 +34,6 @@
#include "../pci.h" #include "../pci.h"
#include "pciehp.h" #include "pciehp.h"
static int __ref pciehp_add_bridge(struct pci_dev *dev)
{
struct pci_bus *parent = dev->bus;
int pass, busnr, start = parent->secondary;
int end = parent->subordinate;
for (busnr = start; busnr <= end; busnr++) {
if (!pci_find_bus(pci_domain_nr(parent), busnr))
break;
}
if (busnr-- > end) {
err("No bus number available for hot-added bridge %s\n",
pci_name(dev));
return -1;
}
for (pass = 0; pass < 2; pass++)
busnr = pci_scan_bridge(parent, dev, busnr, pass);
if (!dev->subordinate)
return -1;
return 0;
}
int pciehp_configure_device(struct slot *p_slot) int pciehp_configure_device(struct slot *p_slot)
{ {
struct pci_dev *dev; struct pci_dev *dev;
...@@ -85,9 +62,8 @@ int pciehp_configure_device(struct slot *p_slot) ...@@ -85,9 +62,8 @@ int pciehp_configure_device(struct slot *p_slot)
if (!dev) if (!dev)
continue; continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
pciehp_add_bridge(dev); pci_hp_add_bridge(dev);
}
pci_dev_put(dev); pci_dev_put(dev);
} }
......
...@@ -397,13 +397,11 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot) ...@@ -397,13 +397,11 @@ static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
else else
sn_io_slot_fixup(dev); sn_io_slot_fixup(dev);
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) { if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
unsigned char sec_bus; pci_hp_add_bridge(dev);
pci_read_config_byte(dev, PCI_SECONDARY_BUS, if (dev->subordinate) {
&sec_bus); new_bus = dev->subordinate;
new_bus = pci_add_new_bus(dev->bus, dev, new_ppb = 1;
sec_bus); }
pci_scan_child_bus(new_bus);
new_ppb = 1;
} }
pci_dev_put(dev); pci_dev_put(dev);
} }
......
...@@ -37,9 +37,10 @@ ...@@ -37,9 +37,10 @@
int __ref shpchp_configure_device(struct slot *p_slot) int __ref shpchp_configure_device(struct slot *p_slot)
{ {
struct pci_dev *dev; struct pci_dev *dev;
struct pci_bus *parent = p_slot->ctrl->pci_dev->subordinate;
int num, fn;
struct controller *ctrl = p_slot->ctrl; struct controller *ctrl = p_slot->ctrl;
struct pci_dev *bridge = ctrl->pci_dev;
struct pci_bus *parent = bridge->subordinate;
int num, fn;
dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0)); dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, 0));
if (dev) { if (dev) {
...@@ -61,39 +62,23 @@ int __ref shpchp_configure_device(struct slot *p_slot) ...@@ -61,39 +62,23 @@ int __ref shpchp_configure_device(struct slot *p_slot)
if (!dev) if (!dev)
continue; continue;
if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) || if ((dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) ||
(dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)) { (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS))
/* Find an unused bus number for the new bridge */ pci_hp_add_bridge(dev);
struct pci_bus *child; pci_dev_put(dev);
unsigned char busnr, start = parent->secondary; }
unsigned char end = parent->subordinate;
for (busnr = start; busnr <= end; busnr++) { pci_assign_unassigned_bridge_resources(bridge);
if (!pci_find_bus(pci_domain_nr(parent),
busnr)) for (fn = 0; fn < 8; fn++) {
break; dev = pci_get_slot(parent, PCI_DEVFN(p_slot->device, fn));
} if (!dev)
if (busnr > end) { continue;
ctrl_err(ctrl,
"No free bus for hot-added bridge\n");
pci_dev_put(dev);
continue;
}
child = pci_add_new_bus(parent, dev, busnr);
if (!child) {
ctrl_err(ctrl, "Cannot add new bus for %s\n",
pci_name(dev));
pci_dev_put(dev);
continue;
}
child->subordinate = pci_do_scan_bus(child);
pci_bus_size_bridges(child);
}
pci_configure_slot(dev); pci_configure_slot(dev);
pci_dev_put(dev); pci_dev_put(dev);
} }
pci_bus_assign_resources(parent);
pci_bus_add_devices(parent); pci_bus_add_devices(parent);
pci_enable_bridges(parent);
return 0; return 0;
} }
......
...@@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha ...@@ -73,13 +73,13 @@ static ssize_t show_ctrl (struct device *dev, struct device_attribute *attr, cha
} }
} }
out += sprintf(out, "Free resources: bus numbers\n"); out += sprintf(out, "Free resources: bus numbers\n");
for (busnr = bus->secondary; busnr <= bus->subordinate; busnr++) { for (busnr = bus->busn_res.start; busnr <= bus->busn_res.end; busnr++) {
if (!pci_find_bus(pci_domain_nr(bus), busnr)) if (!pci_find_bus(pci_domain_nr(bus), busnr))
break; break;
} }
if (busnr < bus->subordinate) if (busnr < bus->busn_res.end)
out += sprintf(out, "start = %8.8x, length = %8.8x\n", out += sprintf(out, "start = %8.8x, length = %8.8x\n",
busnr, (bus->subordinate - busnr)); busnr, (int)(bus->busn_res.end - busnr));
return out - buf; return out - buf;
} }
......
...@@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr) ...@@ -47,7 +47,7 @@ static struct pci_bus *virtfn_add_bus(struct pci_bus *bus, int busnr)
if (!child) if (!child)
return NULL; return NULL;
child->subordinate = busnr; pci_bus_insert_busn_res(child, busnr, busnr);
child->dev.parent = bus->bridge; child->dev.parent = bus->bridge;
rc = pci_bus_add_child(child); rc = pci_bus_add_child(child);
if (rc) { if (rc) {
...@@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) ...@@ -327,7 +327,7 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
iov->offset = offset; iov->offset = offset;
iov->stride = stride; iov->stride = stride;
if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->subordinate) { if (virtfn_bus(dev, nr_virtfn - 1) > dev->bus->busn_res.end) {
dev_err(&dev->dev, "SR-IOV: bus number out of range\n"); dev_err(&dev->dev, "SR-IOV: bus number out of range\n");
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus) ...@@ -110,7 +110,7 @@ unsigned char pci_bus_max_busnr(struct pci_bus* bus)
struct list_head *tmp; struct list_head *tmp;
unsigned char max, n; unsigned char max, n;
max = bus->subordinate; max = bus->busn_res.end;
list_for_each(tmp, &bus->children) { list_for_each(tmp, &bus->children) {
n = pci_bus_max_busnr(pci_bus_b(tmp)); n = pci_bus_max_busnr(pci_bus_b(tmp));
if(n > max) if(n > max)
......
...@@ -124,7 +124,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; } ...@@ -124,7 +124,7 @@ static inline int pci_proc_detach_bus(struct pci_bus *bus) { return 0; }
#endif #endif
/* Functions for PCI Hotplug drivers to use */ /* Functions for PCI Hotplug drivers to use */
extern unsigned int pci_do_scan_bus(struct pci_bus *bus); int pci_hp_add_bridge(struct pci_dev *dev);
#ifdef HAVE_PCI_LEGACY #ifdef HAVE_PCI_LEGACY
extern void pci_create_legacy_files(struct pci_bus *bus); extern void pci_create_legacy_files(struct pci_bus *bus);
......
...@@ -16,10 +16,47 @@ ...@@ -16,10 +16,47 @@
#define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */ #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
#define CARDBUS_RESERVE_BUSNR 3 #define CARDBUS_RESERVE_BUSNR 3
struct resource busn_resource = {
.name = "PCI busn",
.start = 0,
.end = 255,
.flags = IORESOURCE_BUS,
};
/* Ugh. Need to stop exporting this to modules. */ /* Ugh. Need to stop exporting this to modules. */
LIST_HEAD(pci_root_buses); LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses); EXPORT_SYMBOL(pci_root_buses);
static LIST_HEAD(pci_domain_busn_res_list);
struct pci_domain_busn_res {
struct list_head list;
struct resource res;
int domain_nr;
};
static struct resource *get_pci_domain_busn_res(int domain_nr)
{
struct pci_domain_busn_res *r;
list_for_each_entry(r, &pci_domain_busn_res_list, list)
if (r->domain_nr == domain_nr)
return &r->res;
r = kzalloc(sizeof(*r), GFP_KERNEL);
if (!r)
return NULL;
r->domain_nr = domain_nr;
r->res.start = 0;
r->res.end = 0xff;
r->res.flags = IORESOURCE_BUS | IORESOURCE_PCI_FIXED;
list_add_tail(&r->list, &pci_domain_busn_res_list);
return &r->res;
}
static int find_anything(struct device *dev, void *data) static int find_anything(struct device *dev, void *data)
{ {
return 1; return 1;
...@@ -381,8 +418,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) ...@@ -381,8 +418,8 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child)
if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */ if (pci_is_root_bus(child)) /* It's a host bus, nothing to read */
return; return;
dev_info(&dev->dev, "PCI bridge to [bus %02x-%02x]%s\n", dev_info(&dev->dev, "PCI bridge to %pR%s\n",
child->secondary, child->subordinate, &child->busn_res,
dev->transparent ? " (subtractive decode)" : ""); dev->transparent ? " (subtractive decode)" : "");
pci_bus_remove_resources(child); pci_bus_remove_resources(child);
...@@ -599,9 +636,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent, ...@@ -599,9 +636,9 @@ static struct pci_bus *pci_alloc_child_bus(struct pci_bus *parent,
* Set up the primary, secondary and subordinate * Set up the primary, secondary and subordinate
* bus numbers. * bus numbers.
*/ */
child->number = child->secondary = busnr; child->number = child->busn_res.start = busnr;
child->primary = parent->secondary; child->primary = parent->busn_res.start;
child->subordinate = 0xff; child->busn_res.end = 0xff;
if (!bridge) if (!bridge)
return child; return child;
...@@ -643,8 +680,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max) ...@@ -643,8 +680,8 @@ static void pci_fixup_parent_subordinate_busnr(struct pci_bus *child, int max)
if (!pcibios_assign_all_busses()) if (!pcibios_assign_all_busses())
return; return;
while (parent->parent && parent->subordinate < max) { while (parent->parent && parent->busn_res.end < max) {
parent->subordinate = max; parent->busn_res.end = max;
pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max); pci_write_config_byte(parent->self, PCI_SUBORDINATE_BUS, max);
parent = parent->parent; parent = parent->parent;
} }
...@@ -718,15 +755,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, ...@@ -718,15 +755,15 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
if (!child) if (!child)
goto out; goto out;
child->primary = primary; child->primary = primary;
child->subordinate = subordinate; pci_bus_insert_busn_res(child, secondary, subordinate);
child->bridge_ctl = bctl; child->bridge_ctl = bctl;
} }
cmax = pci_scan_child_bus(child); cmax = pci_scan_child_bus(child);
if (cmax > max) if (cmax > max)
max = cmax; max = cmax;
if (child->subordinate > max) if (child->busn_res.end > max)
max = child->subordinate; max = child->busn_res.end;
} else { } else {
/* /*
* We need to assign a number to this bus which we always * We need to assign a number to this bus which we always
...@@ -756,11 +793,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, ...@@ -756,11 +793,12 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
child = pci_add_new_bus(bus, dev, ++max); child = pci_add_new_bus(bus, dev, ++max);
if (!child) if (!child)
goto out; goto out;
pci_bus_insert_busn_res(child, max, 0xff);
} }
buses = (buses & 0xff000000) buses = (buses & 0xff000000)
| ((unsigned int)(child->primary) << 0) | ((unsigned int)(child->primary) << 0)
| ((unsigned int)(child->secondary) << 8) | ((unsigned int)(child->busn_res.start) << 8)
| ((unsigned int)(child->subordinate) << 16); | ((unsigned int)(child->busn_res.end) << 16);
/* /*
* yenta.c forces a secondary latency timer of 176. * yenta.c forces a secondary latency timer of 176.
...@@ -805,8 +843,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, ...@@ -805,8 +843,8 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
break; break;
while (parent->parent) { while (parent->parent) {
if ((!pcibios_assign_all_busses()) && if ((!pcibios_assign_all_busses()) &&
(parent->subordinate > max) && (parent->busn_res.end > max) &&
(parent->subordinate <= max+i)) { (parent->busn_res.end <= max+i)) {
j = 1; j = 1;
} }
parent = parent->parent; parent = parent->parent;
...@@ -827,7 +865,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, ...@@ -827,7 +865,7 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
/* /*
* Set the subordinate bus number to its real value. * Set the subordinate bus number to its real value.
*/ */
child->subordinate = max; pci_bus_update_busn_res_end(child, max);
pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max); pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
} }
...@@ -837,19 +875,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, ...@@ -837,19 +875,19 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max,
/* Has only triggered on CardBus, fixup is in yenta_socket */ /* Has only triggered on CardBus, fixup is in yenta_socket */
while (bus->parent) { while (bus->parent) {
if ((child->subordinate > bus->subordinate) || if ((child->busn_res.end > bus->busn_res.end) ||
(child->number > bus->subordinate) || (child->number > bus->busn_res.end) ||
(child->number < bus->number) || (child->number < bus->number) ||
(child->subordinate < bus->number)) { (child->busn_res.end < bus->number)) {
dev_info(&child->dev, "[bus %02x-%02x] %s " dev_info(&child->dev, "%pR %s "
"hidden behind%s bridge %s [bus %02x-%02x]\n", "hidden behind%s bridge %s %pR\n",
child->number, child->subordinate, &child->busn_res,
(bus->number > child->subordinate && (bus->number > child->busn_res.end &&
bus->subordinate < child->number) ? bus->busn_res.end < child->number) ?
"wholly" : "partially", "wholly" : "partially",
bus->self->transparent ? " transparent" : "", bus->self->transparent ? " transparent" : "",
dev_name(&bus->dev), dev_name(&bus->dev),
bus->number, bus->subordinate); &bus->busn_res);
} }
bus = bus->parent; bus = bus->parent;
} }
...@@ -1548,7 +1586,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings); ...@@ -1548,7 +1586,7 @@ EXPORT_SYMBOL_GPL(pcie_bus_configure_settings);
unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus) unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
{ {
unsigned int devfn, pass, max = bus->secondary; unsigned int devfn, pass, max = bus->busn_res.start;
struct pci_dev *dev; struct pci_dev *dev;
dev_dbg(&bus->dev, "scanning bus\n"); dev_dbg(&bus->dev, "scanning bus\n");
...@@ -1642,7 +1680,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -1642,7 +1680,7 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
/* Create legacy_io and legacy_mem files for this bus */ /* Create legacy_io and legacy_mem files for this bus */
pci_create_legacy_files(b); pci_create_legacy_files(b);
b->number = b->secondary = bus; b->number = b->busn_res.start = bus;
if (parent) if (parent)
dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev)); dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
...@@ -1654,7 +1692,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -1654,7 +1692,10 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
list_move_tail(&window->list, &bridge->windows); list_move_tail(&window->list, &bridge->windows);
res = window->res; res = window->res;
offset = window->offset; offset = window->offset;
pci_bus_add_resource(b, res, 0); if (res->flags & IORESOURCE_BUS)
pci_bus_insert_busn_res(b, bus, res->end);
else
pci_bus_add_resource(b, res, 0);
if (offset) { if (offset) {
if (resource_type(res) == IORESOURCE_IO) if (resource_type(res) == IORESOURCE_IO)
fmt = " (bus address [%#06llx-%#06llx])"; fmt = " (bus address [%#06llx-%#06llx])";
...@@ -1684,16 +1725,104 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus, ...@@ -1684,16 +1725,104 @@ struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
return NULL; return NULL;
} }
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int bus_max)
{
struct resource *res = &b->busn_res;
struct resource *parent_res, *conflict;
res->start = bus;
res->end = bus_max;
res->flags = IORESOURCE_BUS;
if (!pci_is_root_bus(b))
parent_res = &b->parent->busn_res;
else {
parent_res = get_pci_domain_busn_res(pci_domain_nr(b));
res->flags |= IORESOURCE_PCI_FIXED;
}
conflict = insert_resource_conflict(parent_res, res);
if (conflict)
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: can not insert %pR under %s%pR (conflicts with %s %pR)\n",
res, pci_is_root_bus(b) ? "domain " : "",
parent_res, conflict->name, conflict);
else
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: %pR is inserted under %s%pR\n",
res, pci_is_root_bus(b) ? "domain " : "",
parent_res);
return conflict == NULL;
}
int pci_bus_update_busn_res_end(struct pci_bus *b, int bus_max)
{
struct resource *res = &b->busn_res;
struct resource old_res = *res;
resource_size_t size;
int ret;
if (res->start > bus_max)
return -EINVAL;
size = bus_max - res->start + 1;
ret = adjust_resource(res, res->start, size);
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: %pR end %s updated to %02x\n",
&old_res, ret ? "can not be" : "is", bus_max);
if (!ret && !res->parent)
pci_bus_insert_busn_res(b, res->start, res->end);
return ret;
}
void pci_bus_release_busn_res(struct pci_bus *b)
{
struct resource *res = &b->busn_res;
int ret;
if (!res->flags || !res->parent)
return;
ret = release_resource(res);
dev_printk(KERN_DEBUG, &b->dev,
"busn_res: %pR %s released\n",
res, ret ? "can not be" : "is");
}
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct list_head *resources) struct pci_ops *ops, void *sysdata, struct list_head *resources)
{ {
struct pci_host_bridge_window *window;
bool found = false;
struct pci_bus *b; struct pci_bus *b;
int max;
list_for_each_entry(window, resources, list)
if (window->res->flags & IORESOURCE_BUS) {
found = true;
break;
}
b = pci_create_root_bus(parent, bus, ops, sysdata, resources); b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
if (!b) if (!b)
return NULL; return NULL;
b->subordinate = pci_scan_child_bus(b); if (!found) {
dev_info(&b->dev,
"No busn resource found for root bus, will use [bus %02x-ff]\n",
bus);
pci_bus_insert_busn_res(b, bus, 255);
}
max = pci_scan_child_bus(b);
if (!found)
pci_bus_update_busn_res_end(b, max);
pci_bus_add_devices(b); pci_bus_add_devices(b);
return b; return b;
} }
...@@ -1708,9 +1837,10 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent, ...@@ -1708,9 +1837,10 @@ struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
pci_add_resource(&resources, &ioport_resource); pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource); pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(parent, bus, ops, sysdata, &resources); b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
if (b) if (b)
b->subordinate = pci_scan_child_bus(b); pci_scan_child_bus(b);
else else
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
return b; return b;
...@@ -1725,9 +1855,10 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops, ...@@ -1725,9 +1855,10 @@ struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
pci_add_resource(&resources, &ioport_resource); pci_add_resource(&resources, &ioport_resource);
pci_add_resource(&resources, &iomem_resource); pci_add_resource(&resources, &iomem_resource);
pci_add_resource(&resources, &busn_resource);
b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources); b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
if (b) { if (b) {
b->subordinate = pci_scan_child_bus(b); pci_scan_child_bus(b);
pci_bus_add_devices(b); pci_bus_add_devices(b);
} else { } else {
pci_free_resource_list(&resources); pci_free_resource_list(&resources);
......
...@@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus) ...@@ -68,6 +68,7 @@ void pci_remove_bus(struct pci_bus *pci_bus)
down_write(&pci_bus_sem); down_write(&pci_bus_sem);
list_del(&pci_bus->node); list_del(&pci_bus->node);
pci_bus_release_busn_res(pci_bus);
up_write(&pci_bus_sem); up_write(&pci_bus_sem);
if (!pci_bus->is_added) if (!pci_bus->is_added)
return; return;
......
...@@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus) ...@@ -404,8 +404,8 @@ void pci_setup_cardbus(struct pci_bus *bus)
struct resource *res; struct resource *res;
struct pci_bus_region region; struct pci_bus_region region;
dev_info(&bridge->dev, "CardBus bridge to [bus %02x-%02x]\n", dev_info(&bridge->dev, "CardBus bridge to %pR\n",
bus->secondary, bus->subordinate); &bus->busn_res);
res = bus->resource[0]; res = bus->resource[0];
pcibios_resource_to_bus(bridge, &region, res); pcibios_resource_to_bus(bridge, &region, res);
...@@ -553,8 +553,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type) ...@@ -553,8 +553,8 @@ static void __pci_setup_bridge(struct pci_bus *bus, unsigned long type)
{ {
struct pci_dev *bridge = bus->self; struct pci_dev *bridge = bus->self;
dev_info(&bridge->dev, "PCI bridge to [bus %02x-%02x]\n", dev_info(&bridge->dev, "PCI bridge to %pR\n",
bus->secondary, bus->subordinate); &bus->busn_res);
if (type & IORESOURCE_IO) if (type & IORESOURCE_IO)
pci_setup_bridge_io(bus); pci_setup_bridge_io(bus);
...@@ -745,8 +745,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -745,8 +745,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
if (!size0 && !size1) { if (!size0 && !size1) {
if (b_res->start || b_res->end) if (b_res->start || b_res->end)
dev_info(&bus->self->dev, "disabling bridge window " dev_info(&bus->self->dev, "disabling bridge window "
"%pR to [bus %02x-%02x] (unused)\n", b_res, "%pR to %pR (unused)\n", b_res,
bus->secondary, bus->subordinate); &bus->busn_res);
b_res->flags = 0; b_res->flags = 0;
return; return;
} }
...@@ -757,8 +757,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size, ...@@ -757,8 +757,8 @@ static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
if (size1 > size0 && realloc_head) { if (size1 > size0 && realloc_head) {
add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096); add_to_list(realloc_head, bus->self, b_res, size1-size0, 4096);
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
"%pR to [bus %02x-%02x] add_size %lx\n", b_res, "%pR to %pR add_size %lx\n", b_res,
bus->secondary, bus->subordinate, size1-size0); &bus->busn_res, size1-size0);
} }
} }
...@@ -863,8 +863,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -863,8 +863,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (!size0 && !size1) { if (!size0 && !size1) {
if (b_res->start || b_res->end) if (b_res->start || b_res->end)
dev_info(&bus->self->dev, "disabling bridge window " dev_info(&bus->self->dev, "disabling bridge window "
"%pR to [bus %02x-%02x] (unused)\n", b_res, "%pR to %pR (unused)\n", b_res,
bus->secondary, bus->subordinate); &bus->busn_res);
b_res->flags = 0; b_res->flags = 0;
return 1; return 1;
} }
...@@ -874,8 +874,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask, ...@@ -874,8 +874,8 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
if (size1 > size0 && realloc_head) { if (size1 > size0 && realloc_head) {
add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align); add_to_list(realloc_head, bus->self, b_res, size1-size0, min_align);
dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window " dev_printk(KERN_DEBUG, &bus->self->dev, "bridge window "
"%pR to [bus %02x-%02x] add_size %llx\n", b_res, "%pR to %pR add_size %llx\n", b_res,
bus->secondary, bus->subordinate, (unsigned long long)size1-size0); &bus->busn_res, (unsigned long long)size1-size0);
} }
return 1; return 1;
} }
......
...@@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket *s) ...@@ -73,7 +73,7 @@ int __ref cb_alloc(struct pcmcia_socket *s)
s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0)); s->functions = pci_scan_slot(bus, PCI_DEVFN(0, 0));
pci_fixup_cardbus(bus); pci_fixup_cardbus(bus);
max = bus->secondary; max = bus->busn_res.start;
for (pass = 0; pass < 2; pass++) for (pass = 0; pass < 2; pass++)
list_for_each_entry(dev, &bus->devices, bus_list) list_for_each_entry(dev, &bus->devices, bus_list)
if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
......
...@@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket) ...@@ -1048,8 +1048,8 @@ static void yenta_config_init(struct yenta_socket *socket)
config_writeb(socket, PCI_LATENCY_TIMER, 168); config_writeb(socket, PCI_LATENCY_TIMER, 168);
config_writel(socket, PCI_PRIMARY_BUS, config_writel(socket, PCI_PRIMARY_BUS,
(176 << 24) | /* sec. latency timer */ (176 << 24) | /* sec. latency timer */
(dev->subordinate->subordinate << 16) | /* subordinate bus */ ((unsigned int)dev->subordinate->busn_res.end << 16) | /* subordinate bus */
(dev->subordinate->secondary << 8) | /* secondary bus */ ((unsigned int)dev->subordinate->busn_res.start << 8) | /* secondary bus */
dev->subordinate->primary); /* primary bus */ dev->subordinate->primary); /* primary bus */
/* /*
...@@ -1086,14 +1086,14 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) ...@@ -1086,14 +1086,14 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
struct pci_bus *bridge_to_fix = cardbus_bridge->parent; struct pci_bus *bridge_to_fix = cardbus_bridge->parent;
/* Check bus numbers are already set up correctly: */ /* Check bus numbers are already set up correctly: */
if (bridge_to_fix->subordinate >= cardbus_bridge->subordinate) if (bridge_to_fix->busn_res.end >= cardbus_bridge->busn_res.end)
return; /* The subordinate number is ok, nothing to do */ return; /* The subordinate number is ok, nothing to do */
if (!bridge_to_fix->parent) if (!bridge_to_fix->parent)
return; /* Root bridges are ok */ return; /* Root bridges are ok */
/* stay within the limits of the bus range of the parent: */ /* stay within the limits of the bus range of the parent: */
upper_limit = bridge_to_fix->parent->subordinate; upper_limit = bridge_to_fix->parent->busn_res.end;
/* check the bus ranges of all silbling bridges to prevent overlap */ /* check the bus ranges of all silbling bridges to prevent overlap */
list_for_each(tmp, &bridge_to_fix->parent->children) { list_for_each(tmp, &bridge_to_fix->parent->children) {
...@@ -1104,36 +1104,36 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge) ...@@ -1104,36 +1104,36 @@ static void yenta_fixup_parent_bridge(struct pci_bus *cardbus_bridge)
* current upper limit, set the new upper limit to * current upper limit, set the new upper limit to
* the bus number below the silbling's range: * the bus number below the silbling's range:
*/ */
if (silbling->secondary > bridge_to_fix->subordinate if (silbling->busn_res.start > bridge_to_fix->busn_res.end
&& silbling->secondary <= upper_limit) && silbling->busn_res.start <= upper_limit)
upper_limit = silbling->secondary - 1; upper_limit = silbling->busn_res.start - 1;
} }
/* Show that the wanted subordinate number is not possible: */ /* Show that the wanted subordinate number is not possible: */
if (cardbus_bridge->subordinate > upper_limit) if (cardbus_bridge->busn_res.end > upper_limit)
dev_printk(KERN_WARNING, &cardbus_bridge->dev, dev_printk(KERN_WARNING, &cardbus_bridge->dev,
"Upper limit for fixing this " "Upper limit for fixing this "
"bridge's parent bridge: #%02x\n", upper_limit); "bridge's parent bridge: #%02x\n", upper_limit);
/* If we have room to increase the bridge's subordinate number, */ /* If we have room to increase the bridge's subordinate number, */
if (bridge_to_fix->subordinate < upper_limit) { if (bridge_to_fix->busn_res.end < upper_limit) {
/* use the highest number of the hidden bus, within limits */ /* use the highest number of the hidden bus, within limits */
unsigned char subordinate_to_assign = unsigned char subordinate_to_assign =
min(cardbus_bridge->subordinate, upper_limit); min_t(int, cardbus_bridge->busn_res.end, upper_limit);
dev_printk(KERN_INFO, &bridge_to_fix->dev, dev_printk(KERN_INFO, &bridge_to_fix->dev,
"Raising subordinate bus# of parent " "Raising subordinate bus# of parent "
"bus (#%02x) from #%02x to #%02x\n", "bus (#%02x) from #%02x to #%02x\n",
bridge_to_fix->number, bridge_to_fix->number,
bridge_to_fix->subordinate, subordinate_to_assign); (int)bridge_to_fix->busn_res.end, subordinate_to_assign);
/* Save the new subordinate in the bus struct of the bridge */ /* Save the new subordinate in the bus struct of the bridge */
bridge_to_fix->subordinate = subordinate_to_assign; bridge_to_fix->busn_res.end = subordinate_to_assign;
/* and update the PCI config space with the new subordinate */ /* and update the PCI config space with the new subordinate */
pci_write_config_byte(bridge_to_fix->self, pci_write_config_byte(bridge_to_fix->self,
PCI_SUBORDINATE_BUS, bridge_to_fix->subordinate); PCI_SUBORDINATE_BUS, bridge_to_fix->busn_res.end);
} }
} }
......
...@@ -368,6 +368,8 @@ static inline int pci_channel_offline(struct pci_dev *pdev) ...@@ -368,6 +368,8 @@ static inline int pci_channel_offline(struct pci_dev *pdev)
return (pdev->error_state != pci_channel_io_normal); return (pdev->error_state != pci_channel_io_normal);
} }
extern struct resource busn_resource;
struct pci_host_bridge_window { struct pci_host_bridge_window {
struct list_head list; struct list_head list;
struct resource *res; /* host bridge aperture (CPU address) */ struct resource *res; /* host bridge aperture (CPU address) */
...@@ -419,6 +421,7 @@ struct pci_bus { ...@@ -419,6 +421,7 @@ struct pci_bus {
struct list_head slots; /* list of slots on this bus */ struct list_head slots; /* list of slots on this bus */
struct resource *resource[PCI_BRIDGE_RESOURCE_NUM]; struct resource *resource[PCI_BRIDGE_RESOURCE_NUM];
struct list_head resources; /* address space routed to this bus */ struct list_head resources; /* address space routed to this bus */
struct resource busn_res; /* bus numbers routed to this bus */
struct pci_ops *ops; /* configuration access functions */ struct pci_ops *ops; /* configuration access functions */
void *sysdata; /* hook for sys-specific extension */ void *sysdata; /* hook for sys-specific extension */
...@@ -426,8 +429,6 @@ struct pci_bus { ...@@ -426,8 +429,6 @@ struct pci_bus {
unsigned char number; /* bus number */ unsigned char number; /* bus number */
unsigned char primary; /* number of primary bridge */ unsigned char primary; /* number of primary bridge */
unsigned char secondary; /* number of secondary bridge */
unsigned char subordinate; /* max number of subordinate buses */
unsigned char max_bus_speed; /* enum pci_bus_speed */ unsigned char max_bus_speed; /* enum pci_bus_speed */
unsigned char cur_bus_speed; /* enum pci_bus_speed */ unsigned char cur_bus_speed; /* enum pci_bus_speed */
...@@ -668,6 +669,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata); ...@@ -668,6 +669,9 @@ struct pci_bus *pci_scan_bus(int bus, struct pci_ops *ops, void *sysdata);
struct pci_bus *pci_create_root_bus(struct device *parent, int bus, struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct pci_ops *ops, void *sysdata,
struct list_head *resources); struct list_head *resources);
int pci_bus_insert_busn_res(struct pci_bus *b, int bus, int busmax);
int pci_bus_update_busn_res_end(struct pci_bus *b, int busmax);
void pci_bus_release_busn_res(struct pci_bus *b);
struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus, struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
struct pci_ops *ops, void *sysdata, struct pci_ops *ops, void *sysdata,
struct list_head *resources); struct list_head *resources);
......
...@@ -722,14 +722,12 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t ...@@ -722,14 +722,12 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
write_lock(&resource_lock); write_lock(&resource_lock);
if (!parent)
goto skip;
if ((start < parent->start) || (end > parent->end)) if ((start < parent->start) || (end > parent->end))
goto out; goto out;
for (tmp = res->child; tmp; tmp = tmp->sibling) {
if ((tmp->start < start) || (tmp->end > end))
goto out;
}
if (res->sibling && (res->sibling->start <= end)) if (res->sibling && (res->sibling->start <= end))
goto out; goto out;
...@@ -741,6 +739,11 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t ...@@ -741,6 +739,11 @@ int adjust_resource(struct resource *res, resource_size_t start, resource_size_t
goto out; goto out;
} }
skip:
for (tmp = res->child; tmp; tmp = tmp->sibling)
if ((tmp->start < start) || (tmp->end > end))
goto out;
res->start = start; res->start = start;
res->end = end; res->end = end;
result = 0; result = 0;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册