Series to fix IOH hotplug in ia64
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJRzg9sAAoJEKurIx+X31iB+iEP/19NlzdUZW7M1s1Hi83K/W+H YoMFUgufVoTyDStDl22Vk9Iy6rDDs+ZLFKIVi1azTUWShf5PF/7nm8KYUMUwWHtj D/tS9HaemRZCLBYw+n+ITz8NDEYmD4omu8ieC9SDwJxdqwqEwq1XfP+Lz8N12WyE UU9D50gdelui7E7eduHrR2UusxjSK0Mem+fj7pENKCUxqIoXBYGAiU8VFCZOgng8 +t9tgX4QMQj+T1On/GUadcH3AVzNrtrL8pGbgRtMJpMOYXWOsm1/u8fGqgL9Zxee N8Mnk+QI+xGzEoa4B+OY5Ytx6KZY6qPoD8MLJPm0vjauGbdEOPd6l7dzhpVTebVe RiuLc2sw1t2DR0b50cwFO3wv/HqlBXDXyiAqxo75A84UYun/sDrEftYbD94SxX6O pwfz5aLXQ9RZ5g0xdbI4NzJt5fqizzTZlIYJtdiPEk1dOrbEaq9UUztCLcysJaXT b0n3s52CgBckv7aRyIC/Rkl2umcb5DreOCnm1sHET1PxbIMs/t5LMlbFgwqf0/rz yfAxCQ4WxN7yEP1lIp4eEAaDSGBb4jJtUYnncsAHU2wy+Aj1q2JzjcszglBSFY8m 1afAZXrxii/m5EDy4emuVwW+XJWXws4Zifq6oRFvyR7aji3PI5AiayOtAMhFt+Xk 6KQow+OGSPhM7GtyxBJA =Svre -----END PGP SIGNATURE----- Merge tag 'please-pull-root_bus_hotplug' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux Pull ia64 IOH hotplug fixes from Tony Luck: "Series to fix IOH hotplug in ia64" * tag 'please-pull-root_bus_hotplug' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux: PCI: Replace printks with appropriate pr_*() PCI/IA64: introduce probe_pci_root_info() to manage _CRS resource PCI/IA64: Add host bridge resource release for _CRS path PCI/IA64: fix memleak for create pci root bus fail PCI/IA64: Allocate pci_root_info instead of using stack PCI/IA64: embed pci hostbridge resources into pci_root_info PCI/IA64: SN: use normal resource instead of pci_window PCI/IA64: SN: remove sn_pci_window_fixup()
This commit is contained in:
commit
37577505ec
|
@ -89,9 +89,9 @@ extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
|
|||
#define pci_legacy_read platform_pci_legacy_read
|
||||
#define pci_legacy_write platform_pci_legacy_write
|
||||
|
||||
struct pci_window {
|
||||
struct resource resource;
|
||||
u64 offset;
|
||||
struct iospace_resource {
|
||||
struct list_head list;
|
||||
struct resource res;
|
||||
};
|
||||
|
||||
struct pci_controller {
|
||||
|
@ -100,12 +100,10 @@ struct pci_controller {
|
|||
int segment;
|
||||
int node; /* nearest node with memory or -1 for global allocation */
|
||||
|
||||
unsigned int windows;
|
||||
struct pci_window *window;
|
||||
|
||||
void *platform_data;
|
||||
};
|
||||
|
||||
|
||||
#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
|
||||
#define pci_domain_nr(busdev) (PCI_CONTROLLER(busdev)->segment)
|
||||
|
||||
|
|
|
@ -134,6 +134,10 @@ struct pci_root_info {
|
|||
struct acpi_device *bridge;
|
||||
struct pci_controller *controller;
|
||||
struct list_head resources;
|
||||
struct resource *res;
|
||||
resource_size_t *res_offset;
|
||||
unsigned int res_num;
|
||||
struct list_head io_resources;
|
||||
char *name;
|
||||
};
|
||||
|
||||
|
@ -153,7 +157,7 @@ new_space (u64 phys_base, int sparse)
|
|||
return i;
|
||||
|
||||
if (num_io_spaces == MAX_IO_SPACES) {
|
||||
printk(KERN_ERR "PCI: Too many IO port spaces "
|
||||
pr_err("PCI: Too many IO port spaces "
|
||||
"(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES);
|
||||
return ~0;
|
||||
}
|
||||
|
@ -168,25 +172,22 @@ new_space (u64 phys_base, int sparse)
|
|||
static u64 add_io_space(struct pci_root_info *info,
|
||||
struct acpi_resource_address64 *addr)
|
||||
{
|
||||
struct iospace_resource *iospace;
|
||||
struct resource *resource;
|
||||
char *name;
|
||||
unsigned long base, min, max, base_port;
|
||||
unsigned int sparse = 0, space_nr, len;
|
||||
|
||||
resource = kzalloc(sizeof(*resource), GFP_KERNEL);
|
||||
if (!resource) {
|
||||
printk(KERN_ERR "PCI: No memory for %s I/O port space\n",
|
||||
info->name);
|
||||
len = strlen(info->name) + 32;
|
||||
iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL);
|
||||
if (!iospace) {
|
||||
dev_err(&info->bridge->dev,
|
||||
"PCI: No memory for %s I/O port space\n",
|
||||
info->name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
len = strlen(info->name) + 32;
|
||||
name = kzalloc(len, GFP_KERNEL);
|
||||
if (!name) {
|
||||
printk(KERN_ERR "PCI: No memory for %s I/O port space name\n",
|
||||
info->name);
|
||||
goto free_resource;
|
||||
}
|
||||
name = (char *)(iospace + 1);
|
||||
|
||||
min = addr->minimum;
|
||||
max = min + addr->address_length - 1;
|
||||
|
@ -195,7 +196,7 @@ static u64 add_io_space(struct pci_root_info *info,
|
|||
|
||||
space_nr = new_space(addr->translation_offset, sparse);
|
||||
if (space_nr == ~0)
|
||||
goto free_name;
|
||||
goto free_resource;
|
||||
|
||||
base = __pa(io_space[space_nr].mmio_base);
|
||||
base_port = IO_SPACE_BASE(space_nr);
|
||||
|
@ -210,18 +211,23 @@ static u64 add_io_space(struct pci_root_info *info,
|
|||
if (space_nr == 0)
|
||||
sparse = 1;
|
||||
|
||||
resource = &iospace->res;
|
||||
resource->name = name;
|
||||
resource->flags = IORESOURCE_MEM;
|
||||
resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
|
||||
resource->end = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
|
||||
insert_resource(&iomem_resource, resource);
|
||||
if (insert_resource(&iomem_resource, resource)) {
|
||||
dev_err(&info->bridge->dev,
|
||||
"can't allocate host bridge io space resource %pR\n",
|
||||
resource);
|
||||
goto free_resource;
|
||||
}
|
||||
|
||||
list_add_tail(&iospace->list, &info->io_resources);
|
||||
return base_port;
|
||||
|
||||
free_name:
|
||||
kfree(name);
|
||||
free_resource:
|
||||
kfree(resource);
|
||||
kfree(iospace);
|
||||
out:
|
||||
return ~0;
|
||||
}
|
||||
|
@ -265,7 +271,7 @@ static acpi_status count_window(struct acpi_resource *resource, void *data)
|
|||
static acpi_status add_window(struct acpi_resource *res, void *data)
|
||||
{
|
||||
struct pci_root_info *info = data;
|
||||
struct pci_window *window;
|
||||
struct resource *resource;
|
||||
struct acpi_resource_address64 addr;
|
||||
acpi_status status;
|
||||
unsigned long flags, offset = 0;
|
||||
|
@ -289,55 +295,146 @@ static acpi_status add_window(struct acpi_resource *res, void *data)
|
|||
} else
|
||||
return AE_OK;
|
||||
|
||||
window = &info->controller->window[info->controller->windows++];
|
||||
window->resource.name = info->name;
|
||||
window->resource.flags = flags;
|
||||
window->resource.start = addr.minimum + offset;
|
||||
window->resource.end = window->resource.start + addr.address_length - 1;
|
||||
window->offset = offset;
|
||||
resource = &info->res[info->res_num];
|
||||
resource->name = info->name;
|
||||
resource->flags = flags;
|
||||
resource->start = addr.minimum + offset;
|
||||
resource->end = resource->start + addr.address_length - 1;
|
||||
info->res_offset[info->res_num] = offset;
|
||||
|
||||
if (insert_resource(root, &window->resource)) {
|
||||
if (insert_resource(root, resource)) {
|
||||
dev_err(&info->bridge->dev,
|
||||
"can't allocate host bridge window %pR\n",
|
||||
&window->resource);
|
||||
resource);
|
||||
} else {
|
||||
if (offset)
|
||||
dev_info(&info->bridge->dev, "host bridge window %pR "
|
||||
"(PCI address [%#llx-%#llx])\n",
|
||||
&window->resource,
|
||||
window->resource.start - offset,
|
||||
window->resource.end - offset);
|
||||
resource,
|
||||
resource->start - offset,
|
||||
resource->end - offset);
|
||||
else
|
||||
dev_info(&info->bridge->dev,
|
||||
"host bridge window %pR\n",
|
||||
&window->resource);
|
||||
"host bridge window %pR\n", resource);
|
||||
}
|
||||
|
||||
/* HP's firmware has a hack to work around a Windows bug.
|
||||
* Ignore these tiny memory ranges */
|
||||
if (!((window->resource.flags & IORESOURCE_MEM) &&
|
||||
(window->resource.end - window->resource.start < 16)))
|
||||
pci_add_resource_offset(&info->resources, &window->resource,
|
||||
window->offset);
|
||||
if (!((resource->flags & IORESOURCE_MEM) &&
|
||||
(resource->end - resource->start < 16)))
|
||||
pci_add_resource_offset(&info->resources, resource,
|
||||
info->res_offset[info->res_num]);
|
||||
|
||||
info->res_num++;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
static void free_pci_root_info_res(struct pci_root_info *info)
|
||||
{
|
||||
struct iospace_resource *iospace, *tmp;
|
||||
|
||||
list_for_each_entry_safe(iospace, tmp, &info->io_resources, list)
|
||||
kfree(iospace);
|
||||
|
||||
kfree(info->name);
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
kfree(info->res_offset);
|
||||
info->res_offset = NULL;
|
||||
info->res_num = 0;
|
||||
kfree(info->controller);
|
||||
info->controller = NULL;
|
||||
}
|
||||
|
||||
static void __release_pci_root_info(struct pci_root_info *info)
|
||||
{
|
||||
int i;
|
||||
struct resource *res;
|
||||
struct iospace_resource *iospace;
|
||||
|
||||
list_for_each_entry(iospace, &info->io_resources, list)
|
||||
release_resource(&iospace->res);
|
||||
|
||||
for (i = 0; i < info->res_num; i++) {
|
||||
res = &info->res[i];
|
||||
|
||||
if (!res->parent)
|
||||
continue;
|
||||
|
||||
if (!(res->flags & (IORESOURCE_MEM | IORESOURCE_IO)))
|
||||
continue;
|
||||
|
||||
release_resource(res);
|
||||
}
|
||||
|
||||
free_pci_root_info_res(info);
|
||||
kfree(info);
|
||||
}
|
||||
|
||||
static void release_pci_root_info(struct pci_host_bridge *bridge)
|
||||
{
|
||||
struct pci_root_info *info = bridge->release_data;
|
||||
|
||||
__release_pci_root_info(info);
|
||||
}
|
||||
|
||||
static int
|
||||
probe_pci_root_info(struct pci_root_info *info, struct acpi_device *device,
|
||||
int busnum, int domain)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = kmalloc(16, GFP_KERNEL);
|
||||
if (!name)
|
||||
return -ENOMEM;
|
||||
|
||||
sprintf(name, "PCI Bus %04x:%02x", domain, busnum);
|
||||
info->bridge = device;
|
||||
info->name = name;
|
||||
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
|
||||
&info->res_num);
|
||||
if (info->res_num) {
|
||||
info->res =
|
||||
kzalloc_node(sizeof(*info->res) * info->res_num,
|
||||
GFP_KERNEL, info->controller->node);
|
||||
if (!info->res) {
|
||||
kfree(name);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->res_offset =
|
||||
kzalloc_node(sizeof(*info->res_offset) * info->res_num,
|
||||
GFP_KERNEL, info->controller->node);
|
||||
if (!info->res_offset) {
|
||||
kfree(name);
|
||||
kfree(info->res);
|
||||
info->res = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
info->res_num = 0;
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS,
|
||||
add_window, info);
|
||||
} else
|
||||
kfree(name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
||||
{
|
||||
struct acpi_device *device = root->device;
|
||||
int domain = root->segment;
|
||||
int bus = root->secondary.start;
|
||||
struct pci_controller *controller;
|
||||
unsigned int windows = 0;
|
||||
struct pci_root_info info;
|
||||
struct pci_root_info *info = NULL;
|
||||
int busnum = root->secondary.start;
|
||||
struct pci_bus *pbus;
|
||||
char *name;
|
||||
int pxm;
|
||||
int pxm, ret;
|
||||
|
||||
controller = alloc_pci_controller(domain);
|
||||
if (!controller)
|
||||
goto out1;
|
||||
return NULL;
|
||||
|
||||
controller->acpi_handle = device->handle;
|
||||
|
||||
|
@ -347,29 +444,27 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
|||
controller->node = pxm_to_node(pxm);
|
||||
#endif
|
||||
|
||||
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,
|
||||
&windows);
|
||||
if (windows) {
|
||||
controller->window =
|
||||
kzalloc_node(sizeof(*controller->window) * windows,
|
||||
GFP_KERNEL, controller->node);
|
||||
if (!controller->window)
|
||||
goto out2;
|
||||
|
||||
name = kmalloc(16, GFP_KERNEL);
|
||||
if (!name)
|
||||
goto out3;
|
||||
|
||||
sprintf(name, "PCI Bus %04x:%02x", domain, bus);
|
||||
info.bridge = device;
|
||||
info.controller = controller;
|
||||
info.name = name;
|
||||
acpi_walk_resources(device->handle, METHOD_NAME__CRS,
|
||||
add_window, &info);
|
||||
info = kzalloc(sizeof(*info), GFP_KERNEL);
|
||||
if (!info) {
|
||||
dev_err(&device->dev,
|
||||
"pci_bus %04x:%02x: ignored (out of memory)\n",
|
||||
domain, busnum);
|
||||
kfree(controller);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->controller = controller;
|
||||
INIT_LIST_HEAD(&info->io_resources);
|
||||
INIT_LIST_HEAD(&info->resources);
|
||||
|
||||
ret = probe_pci_root_info(info, device, busnum, domain);
|
||||
if (ret) {
|
||||
kfree(info->controller);
|
||||
kfree(info);
|
||||
return NULL;
|
||||
}
|
||||
/* insert busn resource at first */
|
||||
pci_add_resource(&info->resources, &root->secondary);
|
||||
/*
|
||||
* See arch/x86/pci/acpi.c.
|
||||
* The desired pci bus might already be scanned in a quirk. We
|
||||
|
@ -377,21 +472,17 @@ struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
|
|||
* such quirk. So we just ignore the case now.
|
||||
*/
|
||||
pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
|
||||
&info.resources);
|
||||
&info->resources);
|
||||
if (!pbus) {
|
||||
pci_free_resource_list(&info.resources);
|
||||
pci_free_resource_list(&info->resources);
|
||||
__release_pci_root_info(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge),
|
||||
release_pci_root_info, info);
|
||||
pci_scan_child_bus(pbus);
|
||||
return pbus;
|
||||
|
||||
out3:
|
||||
kfree(controller->window);
|
||||
out2:
|
||||
kfree(controller);
|
||||
out1:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
|
||||
|
@ -691,7 +782,7 @@ static void __init set_pci_dfl_cacheline_size(void)
|
|||
|
||||
status = ia64_pal_cache_summary(&levels, &unique_caches);
|
||||
if (status != 0) {
|
||||
printk(KERN_ERR "%s: ia64_pal_cache_summary() failed "
|
||||
pr_err("%s: ia64_pal_cache_summary() failed "
|
||||
"(status=%ld)\n", __func__, status);
|
||||
return;
|
||||
}
|
||||
|
@ -699,7 +790,7 @@ static void __init set_pci_dfl_cacheline_size(void)
|
|||
status = ia64_pal_cache_config_info(levels - 1,
|
||||
/* cache_type (data_or_unified)= */ 2, &cci);
|
||||
if (status != 0) {
|
||||
printk(KERN_ERR "%s: ia64_pal_cache_config_info() failed "
|
||||
pr_err("%s: ia64_pal_cache_config_info() failed "
|
||||
"(status=%ld)\n", __func__, status);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -118,76 +118,26 @@ static void __init sn_fixup_ionodes(void)
|
|||
}
|
||||
|
||||
/*
|
||||
* sn_pci_legacy_window_fixup - Create PCI controller windows for
|
||||
* sn_pci_legacy_window_fixup - Setup PCI resources for
|
||||
* legacy IO and MEM space. This needs to
|
||||
* be done here, as the PROM does not have
|
||||
* ACPI support defining the root buses
|
||||
* and their resources (_CRS),
|
||||
*/
|
||||
static void
|
||||
sn_legacy_pci_window_fixup(struct pci_controller *controller,
|
||||
u64 legacy_io, u64 legacy_mem)
|
||||
sn_legacy_pci_window_fixup(struct resource *res,
|
||||
u64 legacy_io, u64 legacy_mem)
|
||||
{
|
||||
controller->window = kcalloc(2, sizeof(struct pci_window),
|
||||
GFP_KERNEL);
|
||||
BUG_ON(controller->window == NULL);
|
||||
controller->window[0].offset = legacy_io;
|
||||
controller->window[0].resource.name = "legacy_io";
|
||||
controller->window[0].resource.flags = IORESOURCE_IO;
|
||||
controller->window[0].resource.start = legacy_io;
|
||||
controller->window[0].resource.end =
|
||||
controller->window[0].resource.start + 0xffff;
|
||||
controller->window[0].resource.parent = &ioport_resource;
|
||||
controller->window[1].offset = legacy_mem;
|
||||
controller->window[1].resource.name = "legacy_mem";
|
||||
controller->window[1].resource.flags = IORESOURCE_MEM;
|
||||
controller->window[1].resource.start = legacy_mem;
|
||||
controller->window[1].resource.end =
|
||||
controller->window[1].resource.start + (1024 * 1024) - 1;
|
||||
controller->window[1].resource.parent = &iomem_resource;
|
||||
controller->windows = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* sn_pci_window_fixup() - Create a pci_window for each device resource.
|
||||
* It will setup pci_windows for use by
|
||||
* pcibios_bus_to_resource(), pcibios_resource_to_bus(),
|
||||
* etc.
|
||||
*/
|
||||
static void
|
||||
sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
|
||||
s64 * pci_addrs)
|
||||
{
|
||||
struct pci_controller *controller = PCI_CONTROLLER(dev->bus);
|
||||
unsigned int i;
|
||||
unsigned int idx;
|
||||
unsigned int new_count;
|
||||
struct pci_window *new_window;
|
||||
|
||||
if (count == 0)
|
||||
return;
|
||||
idx = controller->windows;
|
||||
new_count = controller->windows + count;
|
||||
new_window = kcalloc(new_count, sizeof(struct pci_window), GFP_KERNEL);
|
||||
BUG_ON(new_window == NULL);
|
||||
if (controller->window) {
|
||||
memcpy(new_window, controller->window,
|
||||
sizeof(struct pci_window) * controller->windows);
|
||||
kfree(controller->window);
|
||||
}
|
||||
|
||||
/* Setup a pci_window for each device resource. */
|
||||
for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
|
||||
if (pci_addrs[i] == -1)
|
||||
continue;
|
||||
|
||||
new_window[idx].offset = dev->resource[i].start - pci_addrs[i];
|
||||
new_window[idx].resource = dev->resource[i];
|
||||
idx++;
|
||||
}
|
||||
|
||||
controller->windows = new_count;
|
||||
controller->window = new_window;
|
||||
res[0].name = "legacy_io";
|
||||
res[0].flags = IORESOURCE_IO;
|
||||
res[0].start = legacy_io;
|
||||
res[0].end = res[0].start + 0xffff;
|
||||
res[0].parent = &ioport_resource;
|
||||
res[1].name = "legacy_mem";
|
||||
res[1].flags = IORESOURCE_MEM;
|
||||
res[1].start = legacy_mem;
|
||||
res[1].end = res[1].start + (1024 * 1024) - 1;
|
||||
res[1].parent = &iomem_resource;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -199,9 +149,7 @@ sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
|
|||
void
|
||||
sn_io_slot_fixup(struct pci_dev *dev)
|
||||
{
|
||||
unsigned int count = 0;
|
||||
int idx;
|
||||
s64 pci_addrs[PCI_ROM_RESOURCE + 1];
|
||||
unsigned long addr, end, size, start;
|
||||
struct pcidev_info *pcidev_info;
|
||||
struct sn_irq_info *sn_irq_info;
|
||||
|
@ -229,7 +177,6 @@ sn_io_slot_fixup(struct pci_dev *dev)
|
|||
for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
|
||||
|
||||
if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
|
||||
pci_addrs[idx] = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -237,11 +184,8 @@ sn_io_slot_fixup(struct pci_dev *dev)
|
|||
end = dev->resource[idx].end;
|
||||
size = end - start;
|
||||
if (size == 0) {
|
||||
pci_addrs[idx] = -1;
|
||||
continue;
|
||||
}
|
||||
pci_addrs[idx] = start;
|
||||
count++;
|
||||
addr = pcidev_info->pdi_pio_mapped_addr[idx];
|
||||
addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET;
|
||||
dev->resource[idx].start = addr;
|
||||
|
@ -276,11 +220,6 @@ sn_io_slot_fixup(struct pci_dev *dev)
|
|||
IORESOURCE_ROM_BIOS_COPY;
|
||||
}
|
||||
}
|
||||
/* Create a pci_window in the pci_controller struct for
|
||||
* each device resource.
|
||||
*/
|
||||
if (count > 0)
|
||||
sn_pci_window_fixup(dev, count, pci_addrs);
|
||||
|
||||
sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
|
||||
}
|
||||
|
@ -297,8 +236,8 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
|
|||
s64 status = 0;
|
||||
struct pci_controller *controller;
|
||||
struct pcibus_bussoft *prom_bussoft_ptr;
|
||||
struct resource *res;
|
||||
LIST_HEAD(resources);
|
||||
int i;
|
||||
|
||||
status = sal_get_pcibus_info((u64) segment, (u64) busnum,
|
||||
(u64) ia64_tpa(&prom_bussoft_ptr));
|
||||
|
@ -310,19 +249,23 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
|
|||
BUG_ON(!controller);
|
||||
controller->segment = segment;
|
||||
|
||||
res = kcalloc(2, sizeof(struct resource), GFP_KERNEL);
|
||||
BUG_ON(!res);
|
||||
|
||||
/*
|
||||
* Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup().
|
||||
* (platform_data will be overwritten later in sn_common_bus_fixup())
|
||||
*/
|
||||
controller->platform_data = prom_bussoft_ptr;
|
||||
|
||||
sn_legacy_pci_window_fixup(controller,
|
||||
prom_bussoft_ptr->bs_legacy_io,
|
||||
prom_bussoft_ptr->bs_legacy_mem);
|
||||
for (i = 0; i < controller->windows; i++)
|
||||
pci_add_resource_offset(&resources,
|
||||
&controller->window[i].resource,
|
||||
controller->window[i].offset);
|
||||
sn_legacy_pci_window_fixup(res,
|
||||
prom_bussoft_ptr->bs_legacy_io,
|
||||
prom_bussoft_ptr->bs_legacy_mem);
|
||||
pci_add_resource_offset(&resources, &res[0],
|
||||
prom_bussoft_ptr->bs_legacy_io);
|
||||
pci_add_resource_offset(&resources, &res[1],
|
||||
prom_bussoft_ptr->bs_legacy_mem);
|
||||
|
||||
bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
|
||||
&resources);
|
||||
if (bus == NULL)
|
||||
|
@ -333,7 +276,7 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
|
|||
return;
|
||||
|
||||
error_return:
|
||||
|
||||
kfree(res);
|
||||
kfree(controller);
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue