Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37577505 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'please-pull-root_bus_hotplug' of...

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()
parents 04bbc8e1 c4cbf6b9
Loading
Loading
Loading
Loading
+4 −6
Original line number Original line Diff line number Diff line
@@ -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_read platform_pci_legacy_read
#define pci_legacy_write platform_pci_legacy_write
#define pci_legacy_write platform_pci_legacy_write


struct pci_window {
struct iospace_resource {
	struct resource resource;
	struct list_head list;
	u64 offset;
	struct resource res;
};
};


struct pci_controller {
struct pci_controller {
@@ -100,12 +100,10 @@ struct pci_controller {
	int segment;
	int segment;
	int node;		/* nearest node with memory or -1 for global allocation */
	int node;		/* nearest node with memory or -1 for global allocation */


	unsigned int windows;
	struct pci_window *window;

	void *platform_data;
	void *platform_data;
};
};



#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
#define PCI_CONTROLLER(busdev) ((struct pci_controller *) busdev->sysdata)
#define pci_domain_nr(busdev)    (PCI_CONTROLLER(busdev)->segment)
#define pci_domain_nr(busdev)    (PCI_CONTROLLER(busdev)->segment)


+165 −74
Original line number Original line Diff line number Diff line
@@ -134,6 +134,10 @@ struct pci_root_info {
	struct acpi_device *bridge;
	struct acpi_device *bridge;
	struct pci_controller *controller;
	struct pci_controller *controller;
	struct list_head resources;
	struct list_head resources;
	struct resource *res;
	resource_size_t *res_offset;
	unsigned int res_num;
	struct list_head io_resources;
	char *name;
	char *name;
};
};


@@ -153,7 +157,7 @@ new_space (u64 phys_base, int sparse)
			return i;
			return i;


	if (num_io_spaces == MAX_IO_SPACES) {
	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);
			"(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES);
		return ~0;
		return ~0;
	}
	}
@@ -168,25 +172,22 @@ new_space (u64 phys_base, int sparse)
static u64 add_io_space(struct pci_root_info *info,
static u64 add_io_space(struct pci_root_info *info,
			struct acpi_resource_address64 *addr)
			struct acpi_resource_address64 *addr)
{
{
	struct iospace_resource *iospace;
	struct resource *resource;
	struct resource *resource;
	char *name;
	char *name;
	unsigned long base, min, max, base_port;
	unsigned long base, min, max, base_port;
	unsigned int sparse = 0, space_nr, len;
	unsigned int sparse = 0, space_nr, len;


	resource = kzalloc(sizeof(*resource), GFP_KERNEL);
	len = strlen(info->name) + 32;
	if (!resource) {
	iospace = kzalloc(sizeof(*iospace) + len, GFP_KERNEL);
		printk(KERN_ERR "PCI: No memory for %s I/O port space\n",
	if (!iospace) {
		dev_err(&info->bridge->dev,
				"PCI: No memory for %s I/O port space\n",
				info->name);
				info->name);
		goto out;
		goto out;
	}
	}


	len = strlen(info->name) + 32;
	name = (char *)(iospace + 1);
	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;
	}


	min = addr->minimum;
	min = addr->minimum;
	max = min + addr->address_length - 1;
	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);
	space_nr = new_space(addr->translation_offset, sparse);
	if (space_nr == ~0)
	if (space_nr == ~0)
		goto free_name;
		goto free_resource;


	base = __pa(io_space[space_nr].mmio_base);
	base = __pa(io_space[space_nr].mmio_base);
	base_port = IO_SPACE_BASE(space_nr);
	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)
	if (space_nr == 0)
		sparse = 1;
		sparse = 1;


	resource = &iospace->res;
	resource->name  = name;
	resource->name  = name;
	resource->flags = IORESOURCE_MEM;
	resource->flags = IORESOURCE_MEM;
	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
	resource->end   = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
	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;
	return base_port;


free_name:
	kfree(name);
free_resource:
free_resource:
	kfree(resource);
	kfree(iospace);
out:
out:
	return ~0;
	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)
static acpi_status add_window(struct acpi_resource *res, void *data)
{
{
	struct pci_root_info *info = data;
	struct pci_root_info *info = data;
	struct pci_window *window;
	struct resource *resource;
	struct acpi_resource_address64 addr;
	struct acpi_resource_address64 addr;
	acpi_status status;
	acpi_status status;
	unsigned long flags, offset = 0;
	unsigned long flags, offset = 0;
@@ -289,55 +295,146 @@ static acpi_status add_window(struct acpi_resource *res, void *data)
	} else
	} else
		return AE_OK;
		return AE_OK;


	window = &info->controller->window[info->controller->windows++];
	resource = &info->res[info->res_num];
	window->resource.name = info->name;
	resource->name = info->name;
	window->resource.flags = flags;
	resource->flags = flags;
	window->resource.start = addr.minimum + offset;
	resource->start = addr.minimum + offset;
	window->resource.end = window->resource.start + addr.address_length - 1;
	resource->end = resource->start + addr.address_length - 1;
	window->offset = offset;
	info->res_offset[info->res_num] = offset;


	if (insert_resource(root, &window->resource)) {
	if (insert_resource(root, resource)) {
		dev_err(&info->bridge->dev,
		dev_err(&info->bridge->dev,
			"can't allocate host bridge window %pR\n",
			"can't allocate host bridge window %pR\n",
			&window->resource);
			resource);
	} else {
	} else {
		if (offset)
		if (offset)
			dev_info(&info->bridge->dev, "host bridge window %pR "
			dev_info(&info->bridge->dev, "host bridge window %pR "
				 "(PCI address [%#llx-%#llx])\n",
				 "(PCI address [%#llx-%#llx])\n",
				 &window->resource,
				 resource,
				 window->resource.start - offset,
				 resource->start - offset,
				 window->resource.end - offset);
				 resource->end - offset);
		else
		else
			dev_info(&info->bridge->dev,
			dev_info(&info->bridge->dev,
				 "host bridge window %pR\n",
				 "host bridge window %pR\n", resource);
				 &window->resource);
	}
	}

	/* HP's firmware has a hack to work around a Windows bug.
	/* HP's firmware has a hack to work around a Windows bug.
	 * Ignore these tiny memory ranges */
	 * Ignore these tiny memory ranges */
	if (!((window->resource.flags & IORESOURCE_MEM) &&
	if (!((resource->flags & IORESOURCE_MEM) &&
	      (window->resource.end - window->resource.start < 16)))
	      (resource->end - resource->start < 16)))
		pci_add_resource_offset(&info->resources, &window->resource,
		pci_add_resource_offset(&info->resources, resource,
					window->offset);
					info->res_offset[info->res_num]);


	info->res_num++;
	return AE_OK;
	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 pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
{
{
	struct acpi_device *device = root->device;
	struct acpi_device *device = root->device;
	int domain = root->segment;
	int domain = root->segment;
	int bus = root->secondary.start;
	int bus = root->secondary.start;
	struct pci_controller *controller;
	struct pci_controller *controller;
	unsigned int windows = 0;
	struct pci_root_info *info = NULL;
	struct pci_root_info info;
	int busnum = root->secondary.start;
	struct pci_bus *pbus;
	struct pci_bus *pbus;
	char *name;
	int pxm, ret;
	int pxm;


	controller = alloc_pci_controller(domain);
	controller = alloc_pci_controller(domain);
	if (!controller)
	if (!controller)
		goto out1;
		return NULL;


	controller->acpi_handle = device->handle;
	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);
		controller->node = pxm_to_node(pxm);
#endif
#endif


	INIT_LIST_HEAD(&info.resources);
	info = kzalloc(sizeof(*info), GFP_KERNEL);
	/* insert busn resource at first */
	if (!info) {
	pci_add_resource(&info.resources, &root->secondary);
		dev_err(&device->dev,
	acpi_walk_resources(device->handle, METHOD_NAME__CRS, count_window,
				"pci_bus %04x:%02x: ignored (out of memory)\n",
			&windows);
				domain, busnum);
	if (windows) {
		kfree(controller);
		controller->window =
		return NULL;
			kzalloc_node(sizeof(*controller->window) * windows,
	}
				     GFP_KERNEL, controller->node);
		if (!controller->window)
			goto out2;


		name = kmalloc(16, GFP_KERNEL);
	info->controller = controller;
		if (!name)
	INIT_LIST_HEAD(&info->io_resources);
			goto out3;
	INIT_LIST_HEAD(&info->resources);


		sprintf(name, "PCI Bus %04x:%02x", domain, bus);
	ret = probe_pci_root_info(info, device, busnum, domain);
		info.bridge = device;
	if (ret) {
		info.controller = controller;
		kfree(info->controller);
		info.name = name;
		kfree(info);
		acpi_walk_resources(device->handle, METHOD_NAME__CRS,
		return NULL;
			add_window, &info);
	}
	}
	/* insert busn resource at first */
	pci_add_resource(&info->resources, &root->secondary);
	/*
	/*
	 * See arch/x86/pci/acpi.c.
	 * See arch/x86/pci/acpi.c.
	 * The desired pci bus might already be scanned in a quirk. We
	 * 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.
	 * such quirk. So we just ignore the case now.
	 */
	 */
	pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
	pbus = pci_create_root_bus(NULL, bus, &pci_root_ops, controller,
				   &info.resources);
				   &info->resources);
	if (!pbus) {
	if (!pbus) {
		pci_free_resource_list(&info.resources);
		pci_free_resource_list(&info->resources);
		__release_pci_root_info(info);
		return NULL;
		return NULL;
	}
	}


	pci_set_host_bridge_release(to_pci_host_bridge(pbus->bridge),
			release_pci_root_info, info);
	pci_scan_child_bus(pbus);
	pci_scan_child_bus(pbus);
	return pbus;
	return pbus;

out3:
	kfree(controller->window);
out2:
	kfree(controller);
out1:
	return NULL;
}
}


int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
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);
	status = ia64_pal_cache_summary(&levels, &unique_caches);
	if (status != 0) {
	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);
			"(status=%ld)\n", __func__, status);
		return;
		return;
	}
	}
@@ -699,7 +790,7 @@ static void __init set_pci_dfl_cacheline_size(void)
	status = ia64_pal_cache_config_info(levels - 1,
	status = ia64_pal_cache_config_info(levels - 1,
				/* cache_type (data_or_unified)= */ 2, &cci);
				/* cache_type (data_or_unified)= */ 2, &cci);
	if (status != 0) {
	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);
			"(status=%ld)\n", __func__, status);
		return;
		return;
	}
	}
+26 −83
Original line number Original line Diff line number Diff line
@@ -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
 *				legacy IO and MEM space. This needs to
 *				be done here, as the PROM does not have
 *				be done here, as the PROM does not have
 *				ACPI support defining the root buses
 *				ACPI support defining the root buses
 *				and their resources (_CRS),
 *				and their resources (_CRS),
 */
 */
static void
static void
sn_legacy_pci_window_fixup(struct pci_controller *controller,
sn_legacy_pci_window_fixup(struct resource *res,
		u64 legacy_io, u64 legacy_mem)
		u64 legacy_io, u64 legacy_mem)
{
{
		controller->window = kcalloc(2, sizeof(struct pci_window),
		res[0].name = "legacy_io";
					     GFP_KERNEL);
		res[0].flags = IORESOURCE_IO;
		BUG_ON(controller->window == NULL);
		res[0].start = legacy_io;
		controller->window[0].offset = legacy_io;
		res[0].end = res[0].start + 0xffff;
		controller->window[0].resource.name = "legacy_io";
		res[0].parent = &ioport_resource;
		controller->window[0].resource.flags = IORESOURCE_IO;
		res[1].name = "legacy_mem";
		controller->window[0].resource.start = legacy_io;
		res[1].flags = IORESOURCE_MEM;
		controller->window[0].resource.end =
		res[1].start = legacy_mem;
	    			controller->window[0].resource.start + 0xffff;
		res[1].end = res[1].start + (1024 * 1024) - 1;
		controller->window[0].resource.parent = &ioport_resource;
		res[1].parent = &iomem_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;
}
}


/*
/*
@@ -199,9 +149,7 @@ sn_pci_window_fixup(struct pci_dev *dev, unsigned int count,
void
void
sn_io_slot_fixup(struct pci_dev *dev)
sn_io_slot_fixup(struct pci_dev *dev)
{
{
	unsigned int count = 0;
	int idx;
	int idx;
	s64 pci_addrs[PCI_ROM_RESOURCE + 1];
	unsigned long addr, end, size, start;
	unsigned long addr, end, size, start;
	struct pcidev_info *pcidev_info;
	struct pcidev_info *pcidev_info;
	struct sn_irq_info *sn_irq_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++) {
	for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {


		if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
		if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
			pci_addrs[idx] = -1;
			continue;
			continue;
		}
		}


@@ -237,11 +184,8 @@ sn_io_slot_fixup(struct pci_dev *dev)
		end = dev->resource[idx].end;
		end = dev->resource[idx].end;
		size = end - start;
		size = end - start;
		if (size == 0) {
		if (size == 0) {
			pci_addrs[idx] = -1;
			continue;
			continue;
		}
		}
		pci_addrs[idx] = start;
		count++;
		addr = pcidev_info->pdi_pio_mapped_addr[idx];
		addr = pcidev_info->pdi_pio_mapped_addr[idx];
		addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET;
		addr = ((addr << 4) >> 4) | __IA64_UNCACHED_OFFSET;
		dev->resource[idx].start = addr;
		dev->resource[idx].start = addr;
@@ -276,11 +220,6 @@ sn_io_slot_fixup(struct pci_dev *dev)
						 IORESOURCE_ROM_BIOS_COPY;
						 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);
	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;
	s64 status = 0;
	struct pci_controller *controller;
	struct pci_controller *controller;
	struct pcibus_bussoft *prom_bussoft_ptr;
	struct pcibus_bussoft *prom_bussoft_ptr;
	struct resource *res;
	LIST_HEAD(resources);
	LIST_HEAD(resources);
	int i;


 	status = sal_get_pcibus_info((u64) segment, (u64) busnum,
 	status = sal_get_pcibus_info((u64) segment, (u64) busnum,
 				     (u64) ia64_tpa(&prom_bussoft_ptr));
 				     (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);
	BUG_ON(!controller);
	controller->segment = segment;
	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().
	 * Temporarily save the prom_bussoft_ptr for use by sn_bus_fixup().
	 * (platform_data will be overwritten later in sn_common_bus_fixup())
	 * (platform_data will be overwritten later in sn_common_bus_fixup())
	 */
	 */
	controller->platform_data = prom_bussoft_ptr;
	controller->platform_data = prom_bussoft_ptr;


	sn_legacy_pci_window_fixup(controller,
	sn_legacy_pci_window_fixup(res,
			prom_bussoft_ptr->bs_legacy_io,
			prom_bussoft_ptr->bs_legacy_io,
			prom_bussoft_ptr->bs_legacy_mem);
			prom_bussoft_ptr->bs_legacy_mem);
	for (i = 0; i < controller->windows; i++)
	pci_add_resource_offset(&resources,	&res[0],
		pci_add_resource_offset(&resources,
			prom_bussoft_ptr->bs_legacy_io);
					&controller->window[i].resource,
	pci_add_resource_offset(&resources,	&res[1],
					controller->window[i].offset);
			prom_bussoft_ptr->bs_legacy_mem);

	bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
	bus = pci_scan_root_bus(NULL, busnum, &pci_root_ops, controller,
				&resources);
				&resources);
 	if (bus == NULL)
 	if (bus == NULL)
@@ -333,7 +276,7 @@ sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
	return;
	return;


error_return:
error_return:

	kfree(res);
	kfree(controller);
	kfree(controller);
	return;
	return;
}
}