Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1444

kernel-2.6.18-238.el5.src.rpm

From: Greg Edwards <gedwards@redhat.com>
Subject: [RHEL5.1 PATCH 1/8 v2] Altix ACPI support: sgiioc4: fixup use of mmio 	ops
Date: Wed, 20 Jun 2007 13:12:47 -0400
Bugzilla: 223577
Message-Id: <20070620171247.GB18042@redhat.com>
Changelog: [ia64] Altix ACPI support



BZ# 223577

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=1678df37be8abbb381becdc40242ed915e775550

[PATCH] sgiioc4: fixup use of mmio ops

Fix some bugs in the patch that converted the IOC4 driver from port IO ops to
memio ops.

http://marc.theaimsgroup.com/?l=linux-ide&m=114895892231438&w=2

  Problems fixed are:
   - Call to default_hwif_mmiops() was not being done until _after_
     first IO operation, resulting in the first IO operation being
     done as a port IO op, instead of memio.
   - request_region() calls needed to be request_mem_region()
   - Incomplete error case handling.
   - Non-usage of ioremap() and __iomem.

---
 arch/ia64/pci/pci.c                     |    4 
 arch/ia64/sn/kernel/Makefile            |    5 
 arch/ia64/sn/kernel/io_acpi_init.c      |  198 ++++++++++
 arch/ia64/sn/kernel/io_common.c         |  612 +++++++++++++++++++++++++++++++
 arch/ia64/sn/kernel/io_init.c           |  626 +++++---------------------------
 arch/ia64/sn/kernel/iomv.c              |   11 
 arch/ia64/sn/kernel/setup.c             |   18 
 arch/ia64/sn/kernel/tiocx.c             |    2 
 arch/ia64/sn/pci/pcibr/pcibr_provider.c |   17 
 arch/ia64/sn/pci/tioce_provider.c       |   18 
 include/asm-ia64/io.h                   |    2 
 include/asm-ia64/machvec.h              |   16 
 include/asm-ia64/machvec_sn2.h          |    3 
 include/asm-ia64/sn/acpi.h              |   16 
 include/asm-ia64/sn/pcidev.h            |   22 -
 include/asm-ia64/sn/sn_feature_sets.h   |    6 
 include/asm-ia64/sn/sn_sal.h            |    1 
 17 files changed, 993 insertions(+), 584 deletions(-)
---

Index: 2.6.18-28.el5/arch/ia64/pci/pci.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/pci/pci.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/pci/pci.c	2007-06-19 11:26:06.000000000 -0500
@@ -469,10 +469,11 @@ pcibios_fixup_resources(struct pci_dev *
 	}
 }
 
-static void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
+void __devinit pcibios_fixup_device_resources(struct pci_dev *dev)
 {
 	pcibios_fixup_resources(dev, 0, PCI_BRIDGE_RESOURCES);
 }
+EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
 
 static void __devinit pcibios_fixup_bridge_resources(struct pci_dev *dev)
 {
@@ -493,6 +494,7 @@ pcibios_fixup_bus (struct pci_bus *b)
 	}
 	list_for_each_entry(dev, &b->devices, bus_list)
 		pcibios_fixup_device_resources(dev);
+	platform_pci_fixup_bus(b);
 
 	return;
 }
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/Makefile
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/Makefile	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/Makefile	2007-06-19 11:26:06.000000000 -0500
@@ -4,13 +4,14 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 1999,2001-2005 Silicon Graphics, Inc.  All Rights Reserved.
+# Copyright (C) 1999,2001-2006 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
 CPPFLAGS += -I$(srctree)/arch/ia64/sn/include
 
 obj-y				+= setup.o bte.o bte_error.o irq.o mca.o idle.o \
-				   huberror.o io_init.o iomv.o klconflib.o pio_phys.o \
+				   huberror.o io_acpi_init.o io_common.o \
+				   io_init.o iomv.o klconflib.o pio_phys.o \
 				   sn2/
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
 obj-$(CONFIG_SGI_TIOCX)		+= tiocx.o
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-19 11:36:25.000000000 -0500
@@ -0,0 +1,198 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/sn_sal.h>
+#include "xtalk/hubdev.h"
+#include <linux/acpi.h>
+
+
+/*
+ * The code in this file will only be executed when running with
+ * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
+ */
+
+
+/*
+ * This value must match the UUID the PROM uses
+ * (io/acpi/defblk.c) when building a vendor descriptor.
+ */
+struct acpi_vendor_uuid sn_uuid = {
+	.subtype = 0,
+	.data	= { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
+		    0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
+};
+
+/*
+ * Perform the early IO init in PROM.
+ */
+static s64
+sal_ioif_init(u64 *result)
+{
+	struct ia64_sal_retval isrv = {0,0,0,0};
+
+	SAL_CALL_NOLOCK(isrv,
+			SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
+	*result = isrv.v0;
+	return isrv.status;
+}
+
+/*
+ * sn_hubdev_add - The 'add' function of the acpi_sn_hubdev_driver.
+ *		   Called for every "SGIHUB" or "SGITIO" device defined
+ *		   in the ACPI namespace.
+ */
+static int __init
+sn_hubdev_add(struct acpi_device *device)
+{
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	u64 addr;
+	struct hubdev_info *hubdev;
+	struct hubdev_info *hubdev_ptr;
+	int i;
+	u64 nasid;
+	struct acpi_resource *resource;
+	int ret = 0;
+	acpi_status status;
+	struct acpi_resource_vendor_typed *vendor;
+	extern void sn_common_hubdev_init(struct hubdev_info *);
+
+	status = acpi_get_vendor_resource(device->handle, METHOD_NAME__CRS,
+					  &sn_uuid, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR
+		       "sn_hubdev_add: acpi_get_vendor_resource() failed: %d\n",
+		        status);
+		return 1;
+	}
+
+	resource = buffer.pointer;
+	vendor = &resource->data.vendor_typed;
+	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
+	    sizeof(struct hubdev_info *)) {
+		printk(KERN_ERR
+		       "sn_hubdev_add: Invalid vendor data length: %d\n",
+		        vendor->byte_length);
+		ret = 1;
+		goto exit;
+	}
+
+	memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
+	hubdev_ptr = __va((struct hubdev_info *) addr);
+
+	nasid = hubdev_ptr->hdi_nasid;
+	i = nasid_to_cnodeid(nasid);
+	hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
+	*hubdev = *hubdev_ptr;
+	sn_common_hubdev_init(hubdev);
+
+exit:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+/*
+ * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
+ *			  the ACPI Vendor resource for this bus.
+ */
+static struct pcibus_bussoft *
+sn_get_bussoft_ptr(struct pci_bus *bus)
+{
+	u64 addr;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_handle handle;
+	struct pcibus_bussoft *prom_bussoft_ptr;
+	struct acpi_resource *resource;
+	acpi_status status;
+	struct acpi_resource_vendor_typed *vendor;
+
+
+	handle = PCI_CONTROLLER(bus)->acpi_handle;
+	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
+					  &sn_uuid, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "get_acpi_pcibus_ptr: "
+		       "get_acpi_bussoft_info() failed: %d\n",
+		       status);
+		return NULL;
+	}
+	resource = buffer.pointer;
+	vendor = &resource->data.vendor_typed;
+
+	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
+	     sizeof(struct pcibus_bussoft *)) {
+		printk(KERN_ERR
+		       "get_acpi_bussoft_ptr: Invalid vendor data "
+		       "length %d\n", vendor->byte_length);
+		kfree(buffer.pointer);
+		return NULL;
+	}
+	memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
+	prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
+	kfree(buffer.pointer);
+
+	return prom_bussoft_ptr;
+}
+
+/*
+ * sn_acpi_bus_fixup
+ */
+void
+sn_acpi_bus_fixup(struct pci_bus *bus)
+{
+	struct pci_dev *pci_dev = NULL;
+	struct pcibus_bussoft *prom_bussoft_ptr;
+	extern void sn_common_bus_fixup(struct pci_bus *,
+					struct pcibus_bussoft *);
+
+	if (!bus->parent) {	/* If root bus */
+		prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
+		if (prom_bussoft_ptr == NULL) {
+			printk(KERN_ERR
+			       "sn_pci_fixup_bus: 0x%04x:0x%02x Unable to "
+			       "obtain prom_bussoft_ptr\n",
+			       pci_domain_nr(bus), bus->number);
+			return;
+		}
+		sn_common_bus_fixup(bus, prom_bussoft_ptr);
+	}
+	list_for_each_entry(pci_dev, &bus->devices, bus_list) {
+		sn_pci_fixup_slot(pci_dev);
+	}
+}
+
+static struct acpi_driver acpi_sn_hubdev_driver = {
+	.name = "SGI HUBDEV Driver",
+	.ids = "SGIHUB,SGITIO",
+	.ops = {
+		.add = sn_hubdev_add,
+		},
+};
+
+
+/*
+ * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
+ *		     nodes and root buses in the DSDT. As a result, bus scanning
+ *		     will be initiated by the Linux ACPI code.
+ */
+
+void __init
+sn_io_acpi_init(void)
+{
+	u64 result;
+	s64 status;
+
+	acpi_bus_register_driver(&acpi_sn_hubdev_driver);
+	status = sal_ioif_init(&result);
+	if (status || result)
+		panic("sal_ioif_init failed: [%lx] %s\n",
+		      status, ia64_sal_strerror(status));
+}
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_common.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_common.c	2007-06-19 11:36:25.000000000 -0500
@@ -0,0 +1,612 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#include <linux/bootmem.h>
+#include <asm/sn/types.h>
+#include <asm/sn/addrs.h>
+#include <asm/sn/sn_feature_sets.h>
+#include <asm/sn/geo.h>
+#include <asm/sn/io.h>
+#include <asm/sn/l1.h>
+#include <asm/sn/module.h>
+#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/pcibus_provider_defs.h>
+#include <asm/sn/pcidev.h>
+#include <asm/sn/simulator.h>
+#include <asm/sn/sn_sal.h>
+#include <asm/sn/tioca_provider.h>
+#include <asm/sn/tioce_provider.h>
+#include "xtalk/hubdev.h"
+#include "xtalk/xwidgetdev.h"
+#include <linux/acpi.h>
+#include <asm/sn/sn2/sn_hwperf.h>
+#include <asm/sn/acpi.h>
+
+extern void sn_init_cpei_timer(void);
+extern void register_sn_procfs(void);
+extern void sn_acpi_bus_fixup(struct pci_bus *);
+extern void sn_bus_fixup(struct pci_bus *);
+extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *);
+extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *);
+extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64);
+extern void sn_io_acpi_init(void);
+extern void sn_io_init(void);
+
+
+static struct list_head sn_sysdata_list;
+
+/* sysdata list struct */
+struct sysdata_el {
+	struct list_head entry;
+	void *sysdata;
+};
+
+int sn_ioif_inited;		/* SN I/O infrastructure initialized? */
+
+struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES];	/* indexed by asic type */
+
+/*
+ * Hooks and struct for unsupported pci providers
+ */
+
+static dma_addr_t
+sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
+{
+	return 0;
+}
+
+static void
+sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
+{
+	return;
+}
+
+static void *
+sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
+{
+	return NULL;
+}
+
+static struct sn_pcibus_provider sn_pci_default_provider = {
+	.dma_map = sn_default_pci_map,
+	.dma_map_consistent = sn_default_pci_map,
+	.dma_unmap = sn_default_pci_unmap,
+	.bus_fixup = sn_default_pci_bus_fixup,
+};
+
+/*
+ * Retrieve the DMA Flush List given nasid, widget, and device.
+ * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
+ */
+static inline u64
+sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
+			     u64 address)
+{
+	struct ia64_sal_retval ret_stuff;
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+
+	SAL_CALL_NOLOCK(ret_stuff,
+			(u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
+			(u64) nasid, (u64) widget_num,
+			(u64) device_num, (u64) address, 0, 0, 0);
+	return ret_stuff.status;
+}
+
+/*
+ * Retrieve the pci device information given the bus and device|function number.
+ */
+static inline u64
+sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
+		    u64 sn_irq_info)
+{
+	struct ia64_sal_retval ret_stuff;
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+
+	SAL_CALL_NOLOCK(ret_stuff,
+			(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
+			(u64) segment, (u64) bus_number, (u64) devfn,
+			(u64) pci_dev,
+			sn_irq_info, 0, 0);
+	return ret_stuff.v0;
+}
+
+/*
+ * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
+ *			  device.
+ */
+inline struct pcidev_info *
+sn_pcidev_info_get(struct pci_dev *dev)
+{
+	struct pcidev_info *pcidev;
+
+	list_for_each_entry(pcidev,
+			    &(SN_PLATFORM_DATA(dev)->pcidev_info), pdi_list) {
+		if (pcidev->pdi_linux_pcidev == dev)
+			return pcidev;
+	}
+	return NULL;
+}
+
+/* Older PROM flush WAR
+ *
+ * 01/16/06 -- This war will be in place until a new official PROM is released.
+ * Additionally note that the struct sn_flush_device_war also has to be
+ * removed from arch/ia64/sn/include/xtalk/hubdev.h
+ */
+static u8 war_implemented = 0;
+
+static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
+			       struct sn_flush_device_common *common)
+{
+	struct sn_flush_device_war *war_list;
+	struct sn_flush_device_war *dev_entry;
+	struct ia64_sal_retval isrv = {0,0,0,0};
+
+	if (!war_implemented) {
+		printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
+		       "PROM flush WAR\n");
+		war_implemented = 1;
+	}
+
+	war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
+	if (!war_list)
+		BUG();
+
+	SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
+			nasid, widget, __pa(war_list), 0, 0, 0 ,0);
+	if (isrv.status)
+		panic("sn_device_fixup_war failed: %s\n",
+		      ia64_sal_strerror(isrv.status));
+
+	dev_entry = war_list + device;
+	memcpy(common,dev_entry, sizeof(*common));
+	kfree(war_list);
+
+	return isrv.status;
+}
+
+/*
+ * sn_common_hubdev_init() - This routine is called to initialize the HUB data
+ *			     structure for each node in the system.
+ */
+void __init
+sn_common_hubdev_init(struct hubdev_info *hubdev)
+{
+
+	struct sn_flush_device_kernel *sn_flush_device_kernel;
+	struct sn_flush_device_kernel *dev_entry;
+	s64 status;
+	int widget, device, size;
+
+	/* Attach the error interrupt handlers */
+	if (hubdev->hdi_nasid & 1)	/* If TIO */
+		ice_error_init(hubdev);
+	else
+		hub_error_init(hubdev);
+
+	for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
+		hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
+
+	if (!hubdev->hdi_flush_nasid_list.widget_p)
+		return;
+
+	size = (HUB_WIDGET_ID_MAX + 1) *
+		sizeof(struct sn_flush_device_kernel *);
+	hubdev->hdi_flush_nasid_list.widget_p =
+		kzalloc(size, GFP_KERNEL);
+	if (!hubdev->hdi_flush_nasid_list.widget_p)
+		BUG();
+
+	for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
+		size = DEV_PER_WIDGET *
+			sizeof(struct sn_flush_device_kernel);
+		sn_flush_device_kernel = kzalloc(size, GFP_KERNEL);
+		if (!sn_flush_device_kernel)
+			BUG();
+
+		dev_entry = sn_flush_device_kernel;
+		for (device = 0; device < DEV_PER_WIDGET;
+		     device++, dev_entry++) {
+			size = sizeof(struct sn_flush_device_common);
+			dev_entry->common = kzalloc(size, GFP_KERNEL);
+			if (!dev_entry->common)
+				BUG();
+			if (sn_prom_feature_available(PRF_DEVICE_FLUSH_LIST))
+				status = sal_get_device_dmaflush_list(
+					     hubdev->hdi_nasid, widget, device,
+					     (u64)(dev_entry->common));
+			else
+				status = sn_device_fixup_war(hubdev->hdi_nasid,
+							     widget, device,
+							     dev_entry->common);
+			if (status != SALRET_OK)
+				panic("SAL call failed: %s\n",
+				      ia64_sal_strerror(status));
+
+			spin_lock_init(&dev_entry->sfdl_flush_lock);
+		}
+
+		if (sn_flush_device_kernel)
+			hubdev->hdi_flush_nasid_list.widget_p[widget] =
+							 sn_flush_device_kernel;
+	}
+}
+
+void sn_pci_unfixup_slot(struct pci_dev *dev)
+{
+	struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
+
+	sn_irq_unfixup(dev);
+	pci_dev_put(host_pci_dev);
+	pci_dev_put(dev);
+}
+
+/*
+ * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent
+ *			 with the Linux PCI abstraction layer. Resources
+ *			 acquired from our PCI provider include PIO maps
+ *			 to BAR space and interrupt objects.
+ */
+void sn_pci_fixup_slot(struct pci_dev *dev)
+{
+	int segment = pci_domain_nr(dev->bus);
+	int status = 0;
+	struct pcibus_bussoft *bs;
+ 	struct pci_bus *host_pci_bus;
+ 	struct pci_dev *host_pci_dev;
+	struct pcidev_info *pcidev_info;
+ 	struct sn_irq_info *sn_irq_info;
+ 	unsigned int bus_no, devfn;
+
+	pci_dev_get(dev); /* for the sysdata pointer */
+	pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
+	if (!pcidev_info)
+		BUG();		/* Cannot afford to run out of memory */
+
+	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+	if (!sn_irq_info)
+		BUG();		/* Cannot afford to run out of memory */
+
+	/* Call to retrieve pci device information needed by kernel. */
+	status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number,
+				     dev->devfn,
+				     (u64) __pa(pcidev_info),
+				     (u64) __pa(sn_irq_info));
+	if (status)
+		BUG(); /* Cannot get platform pci device information */
+
+	/* Add pcidev_info to list in pci_controller.platform_data */
+	list_add_tail(&pcidev_info->pdi_list,
+		      &(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
+
+	if (!SN_ACPI_BASE_SUPPORT())
+		sn_more_slot_fixup(dev, pcidev_info);
+
+	/*
+	 * Using the PROMs values for the PCI host bus, get the Linux
+ 	 * PCI host_pci_dev struct and set up host bus linkages
+ 	 */
+
+	bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
+	devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
+ 	host_pci_bus = pci_find_bus(segment, bus_no);
+ 	host_pci_dev = pci_get_slot(host_pci_bus, devfn);
+
+	pcidev_info->host_pci_dev = host_pci_dev;
+	pcidev_info->pdi_linux_pcidev = dev;
+	pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev);
+	bs = SN_PCIBUS_BUSSOFT(dev->bus);
+	pcidev_info->pdi_pcibus_info = bs;
+
+	if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
+		SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
+	} else {
+		SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
+	}
+
+	/* Only set up IRQ stuff if this device has a host bus context */
+	if (bs && sn_irq_info->irq_irq) {
+		pcidev_info->pdi_sn_irq_info = sn_irq_info;
+		dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq;
+		sn_irq_fixup(dev, sn_irq_info);
+	} else {
+		pcidev_info->pdi_sn_irq_info = NULL;
+		kfree(sn_irq_info);
+	}
+}
+
+/*
+ * sn_common_bus_fixup - Perform platform specific bus fixup.
+ *			 Execute the ASIC specific fixup routine
+ *			 for this bus.
+ */
+void
+sn_common_bus_fixup(struct pci_bus *bus,
+		    struct pcibus_bussoft *prom_bussoft_ptr)
+{
+	int cnode;
+	struct pci_controller *controller;
+	struct hubdev_info *hubdev_info;
+	int nasid;
+	void *provider_soft;
+	struct sn_pcibus_provider *provider;
+	struct sn_platform_data *sn_platform_data;
+
+	controller = PCI_CONTROLLER(bus);
+	/*
+	 * Per-provider fixup.  Copies the bus soft structure from prom
+	 * to local area and links SN_PCIBUS_BUSSOFT().
+	 */
+
+	if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES) {
+		printk(KERN_WARNING "sn_common_bus_fixup: Unsupported asic type, %d",
+		       prom_bussoft_ptr->bs_asic_type);
+		return;
+	}
+
+	if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
+		return;	/* no further fixup necessary */
+
+	provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
+	if (provider == NULL)
+		panic("sn_common_bus_fixup: No provider registered for this asic type, %d",
+		      prom_bussoft_ptr->bs_asic_type);
+
+	if (provider->bus_fixup)
+		provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr,
+				 controller);
+	else
+		provider_soft = NULL;
+
+	/*
+	 * Generic bus fixup goes here.  Don't reference prom_bussoft_ptr
+	 * after this point.
+	 */
+	controller->platform_data = kzalloc(sizeof(struct sn_platform_data),
+					    GFP_KERNEL);
+	if (controller->platform_data == NULL)
+		BUG();
+	sn_platform_data =
+			(struct sn_platform_data *) controller->platform_data;
+	sn_platform_data->provider_soft = provider_soft;
+	INIT_LIST_HEAD(&((struct sn_platform_data *)
+			 controller->platform_data)->pcidev_info);
+	nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
+	cnode = nasid_to_cnodeid(nasid);
+	hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
+	SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
+	    &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
+
+	/*
+	 * If the node information we obtained during the fixup phase is
+	 * invalid then set controller->node to -1 (undetermined)
+	 */
+	if (controller->node >= num_online_nodes()) {
+		struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
+
+		printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
+		       "L_IO=%lx L_MEM=%lx BASE=%lx\n",
+		       b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
+		       b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
+		printk(KERN_WARNING "on node %d but only %d nodes online."
+		       "Association set to undetermined.\n",
+		       controller->node, num_online_nodes());
+		controller->node = -1;
+	}
+}
+
+void sn_bus_store_sysdata(struct pci_dev *dev)
+{
+	struct sysdata_el *element;
+
+	element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
+	if (!element) {
+		dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
+		return;
+	}
+	element->sysdata = SN_PCIDEV_INFO(dev);
+	list_add(&element->entry, &sn_sysdata_list);
+}
+
+void sn_bus_free_sysdata(void)
+{
+	struct sysdata_el *element;
+	struct list_head *list, *safe;
+
+	list_for_each_safe(list, safe, &sn_sysdata_list) {
+		element = list_entry(list, struct sysdata_el, entry);
+		list_del(&element->entry);
+		list_del(&(((struct pcidev_info *)
+			     (element->sysdata))->pdi_list));
+		kfree(element->sysdata);
+		kfree(element);
+	}
+	return;
+}
+
+/*
+ * hubdev_init_node() - Creates the HUB data structure and link them to it's
+ *			own NODE specific data area.
+ */
+void hubdev_init_node(nodepda_t * npda, cnodeid_t node)
+{
+	struct hubdev_info *hubdev_info;
+	int size;
+	pg_data_t *pg;
+
+	size = sizeof(struct hubdev_info);
+
+	if (node >= num_online_nodes())	/* Headless/memless IO nodes */
+		pg = NODE_DATA(0);
+	else
+		pg = NODE_DATA(node);
+
+	hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size);
+
+	npda->pdinfo = (void *)hubdev_info;
+}
+
+geoid_t
+cnodeid_get_geoid(cnodeid_t cnode)
+{
+	struct hubdev_info *hubdev;
+
+	hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
+	return hubdev->hdi_geoid;
+}
+
+void sn_generate_path(struct pci_bus *pci_bus, char *address)
+{
+	nasid_t nasid;
+	cnodeid_t cnode;
+	geoid_t geoid;
+	moduleid_t moduleid;
+	u16 bricktype;
+
+	nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
+	cnode = nasid_to_cnodeid(nasid);
+	geoid = cnodeid_get_geoid(cnode);
+	moduleid = geo_module(geoid);
+
+	sprintf(address, "module_%c%c%c%c%.2d",
+		'0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
+		'0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
+		'0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
+		MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
+
+	/* Tollhouse requires slot id to be displayed */
+	bricktype = MODULE_GET_BTYPE(moduleid);
+	if ((bricktype == L1_BRICKTYPE_191010) ||
+	    (bricktype == L1_BRICKTYPE_1932))
+			sprintf(address, "%s^%d", address, geo_slot(geoid));
+}
+
+/*
+ * sn_pci_fixup_bus() - Perform SN specific setup of software structs
+ *			(pcibus_bussoft, pcidev_info) and hardware
+ *			registers, for the specified bus and devices under it.
+ */
+void __devinit
+sn_pci_fixup_bus(struct pci_bus *bus)
+{
+
+	if (SN_ACPI_BASE_SUPPORT())
+		sn_acpi_bus_fixup(bus);
+	else
+		sn_bus_fixup(bus);
+}
+
+/*
+ * sn_io_early_init - Perform early IO (and some non-IO) initialization.
+ *		      In particular, setup the sn_pci_provider[] array.
+ *		      This needs to be done prior to any bus scanning
+ *		      (acpi_scan_init()) in the ACPI case, as the SN
+ *		      bus fixup code will reference the array.
+ */
+static int __init
+sn_io_early_init(void)
+{
+	int i;
+
+	if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
+		return 0;
+
+	/*
+	 * prime sn_pci_provider[].  Individial provider init routines will
+	 * override their respective default entries.
+	 */
+
+	for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
+		sn_pci_provider[i] = &sn_pci_default_provider;
+
+	pcibr_init_provider();
+	tioca_init_provider();
+	tioce_init_provider();
+
+	/*
+	 * This is needed to avoid bounce limit checks in the blk layer
+	 */
+	ia64_max_iommu_merge_mask = ~PAGE_MASK;
+
+	sn_irq_lh_init();
+	INIT_LIST_HEAD(&sn_sysdata_list);
+	sn_init_cpei_timer();
+
+#ifdef CONFIG_PROC_FS
+	register_sn_procfs();
+#endif
+
+	printk(KERN_INFO "ACPI  DSDT OEM Rev 0x%x\n",
+	       acpi_gbl_DSDT->oem_revision);
+	if (SN_ACPI_BASE_SUPPORT())
+		sn_io_acpi_init();
+	else
+		sn_io_init();
+	return 0;
+}
+
+arch_initcall(sn_io_early_init);
+
+/*
+ * sn_io_late_init() - Perform any final platform specific IO initialization.
+ */
+
+int __init
+sn_io_late_init(void)
+{
+	struct pci_bus *bus;
+	struct pcibus_bussoft *bussoft;
+	cnodeid_t cnode;
+	nasid_t nasid;
+	cnodeid_t near_cnode;
+
+	if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
+		return 0;
+
+	/*
+	 * Setup closest node in pci_controller->node for
+	 * PIC, TIOCP, TIOCE (TIOCA does it during bus fixup using
+	 * info from the PROM).
+	 */
+	bus = NULL;
+	while ((bus = pci_find_next_bus(bus)) != NULL) {
+		bussoft = SN_PCIBUS_BUSSOFT(bus);
+		nasid = NASID_GET(bussoft->bs_base);
+		cnode = nasid_to_cnodeid(nasid);
+		if ((bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) ||
+		    (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCE)) {
+			/* TIO PCI Bridge: find nearest node with CPUs */
+			int e = sn_hwperf_get_nearest_node(cnode, NULL,
+							   &near_cnode);
+			if (e < 0) {
+				near_cnode = (cnodeid_t)-1; /* use any node */
+				printk(KERN_WARNING "pcibr_bus_fixup: failed "
+				       "to find near node with CPUs to TIO "
+				       "node %d, err=%d\n", cnode, e);
+			}
+			PCI_CONTROLLER(bus)->node = near_cnode;
+		} else if (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_PIC) {
+			PCI_CONTROLLER(bus)->node = cnode;
+		}
+	}
+
+	sn_ioif_inited = 1;	/* SN I/O infrastructure now initialized */
+
+	return 0;
+}
+
+fs_initcall(sn_io_late_init);
+
+EXPORT_SYMBOL(sn_pci_fixup_slot);
+EXPORT_SYMBOL(sn_pci_unfixup_slot);
+EXPORT_SYMBOL(sn_bus_store_sysdata);
+EXPORT_SYMBOL(sn_bus_free_sysdata);
+EXPORT_SYMBOL(sn_generate_path);
+
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_init.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_init.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_init.c	2007-06-19 11:36:25.000000000 -0500
@@ -3,103 +3,28 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
  */
 
-#include <linux/bootmem.h>
-#include <linux/nodemask.h>
 #include <asm/sn/types.h>
 #include <asm/sn/addrs.h>
-#include <asm/sn/sn_feature_sets.h>
-#include <asm/sn/geo.h>
 #include <asm/sn/io.h>
-#include <asm/sn/l1.h>
 #include <asm/sn/module.h>
-#include <asm/sn/pcibr_provider.h>
+#include <asm/sn/intr.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/pcidev.h>
-#include <asm/sn/simulator.h>
 #include <asm/sn/sn_sal.h>
-#include <asm/sn/tioca_provider.h>
-#include <asm/sn/tioce_provider.h>
 #include "xtalk/hubdev.h"
-#include "xtalk/xwidgetdev.h"
-
-
-extern void sn_init_cpei_timer(void);
-extern void register_sn_procfs(void);
-
-static struct list_head sn_sysdata_list;
-
-/* sysdata list struct */
-struct sysdata_el {
-	struct list_head entry;
-	void *sysdata;
-};
-
-struct slab_info {
-	struct hubdev_info hubdev;
-};
-
-struct brick {
-	moduleid_t id;		/* Module ID of this module        */
-	struct slab_info slab_info[MAX_SLABS + 1];
-};
-
-int sn_ioif_inited;		/* SN I/O infrastructure initialized? */
-
-struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES];	/* indexed by asic type */
-
-static int max_segment_number;		 /* Default highest segment number */
-static int max_pcibus_number = 255;	/* Default highest pci bus number */
 
 /*
- * Hooks and struct for unsupported pci providers
+ * The code in this file will only be executed when running with
+ * a PROM that does _not_ have base ACPI IO support.
+ * (i.e., SN_ACPI_BASE_SUPPORT() == 0)
  */
 
-static dma_addr_t
-sn_default_pci_map(struct pci_dev *pdev, unsigned long paddr, size_t size, int type)
-{
-	return 0;
-}
-
-static void
-sn_default_pci_unmap(struct pci_dev *pdev, dma_addr_t addr, int direction)
-{
-	return;
-}
-
-static void *
-sn_default_pci_bus_fixup(struct pcibus_bussoft *soft, struct pci_controller *controller)
-{
-	return NULL;
-}
-
-static struct sn_pcibus_provider sn_pci_default_provider = {
-	.dma_map = sn_default_pci_map,
-	.dma_map_consistent = sn_default_pci_map,
-	.dma_unmap = sn_default_pci_unmap,
-	.bus_fixup = sn_default_pci_bus_fixup,
-};
-
-/*
- * Retrieve the DMA Flush List given nasid, widget, and device.
- * This list is needed to implement the WAR - Flush DMA data on PIO Reads.
- */
-static inline u64
-sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
-			     u64 address)
-{
-	struct ia64_sal_retval ret_stuff;
-	ret_stuff.status = 0;
-	ret_stuff.v0 = 0;
+static int max_segment_number;		 /* Default highest segment number */
+static int max_pcibus_number = 255;	/* Default highest pci bus number */
 
-	SAL_CALL_NOLOCK(ret_stuff,
-			(u64) SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST,
-			(u64) nasid, (u64) widget_num,
-			(u64) device_num, (u64) address, 0, 0, 0);
-	return ret_stuff.status;
-}
 
 /*
  * Retrieve the hub device info structure for the given nasid.
@@ -131,93 +56,20 @@ static inline u64 sal_get_pcibus_info(u6
 	return ret_stuff.v0;
 }
 
-/*
- * Retrieve the pci device information given the bus and device|function number.
- */
-static inline u64
-sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
-		    u64 sn_irq_info)
-{
-	struct ia64_sal_retval ret_stuff;
-	ret_stuff.status = 0;
-	ret_stuff.v0 = 0;
-
-	SAL_CALL_NOLOCK(ret_stuff,
-			(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
-			(u64) segment, (u64) bus_number, (u64) devfn,
-			(u64) pci_dev,
-			sn_irq_info, 0, 0);
-	return ret_stuff.v0;
-}
-
-/*
- * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
- *			  device.
- */
-inline struct pcidev_info *
-sn_pcidev_info_get(struct pci_dev *dev)
-{
-	struct pcidev_info *pcidev;
-
-	list_for_each_entry(pcidev,
-			    &(SN_PCI_CONTROLLER(dev)->pcidev_info), pdi_list) {
-		if (pcidev->pdi_linux_pcidev == dev) {
-			return pcidev;
-		}
-	}
-	return NULL;
-}
-
-/* Older PROM flush WAR
- *
- * 01/16/06 -- This war will be in place until a new official PROM is released.
- * Additionally note that the struct sn_flush_device_war also has to be
- * removed from arch/ia64/sn/include/xtalk/hubdev.h
- */
-static u8 war_implemented = 0;
-
-static s64 sn_device_fixup_war(u64 nasid, u64 widget, int device,
-			       struct sn_flush_device_common *common)
-{
-	struct sn_flush_device_war *war_list;
-	struct sn_flush_device_war *dev_entry;
-	struct ia64_sal_retval isrv = {0,0,0,0};
-
-	if (!war_implemented) {
-		printk(KERN_WARNING "PROM version < 4.50 -- implementing old "
-		       "PROM flush WAR\n");
-		war_implemented = 1;
-	}
-
-	war_list = kzalloc(DEV_PER_WIDGET * sizeof(*war_list), GFP_KERNEL);
-	if (!war_list)
-		BUG();
-
-	SAL_CALL_NOLOCK(isrv, SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST,
-			nasid, widget, __pa(war_list), 0, 0, 0 ,0);
-	if (isrv.status)
-		panic("sn_device_fixup_war failed: %s\n",
-		      ia64_sal_strerror(isrv.status));
-
-	dev_entry = war_list + device;
-	memcpy(common,dev_entry, sizeof(*common));
-	kfree(war_list);
-
-	return isrv.status;
-}
 
 /*
- * sn_fixup_ionodes() - This routine initializes the HUB data strcuture for
- *	each node in the system.
+ * sn_fixup_ionodes() - This routine initializes the HUB data structure for
+ *			each node in the system. This function is only
+ *			executed when running with a non-ACPI capable PROM.
  */
 static void __init sn_fixup_ionodes(void)
 {
-	struct sn_flush_device_kernel *sn_flush_device_kernel;
-	struct sn_flush_device_kernel *dev_entry;
+
 	struct hubdev_info *hubdev;
 	u64 status;
 	u64 nasid;
-	int i, widget, device, size;
+	int i;
+	extern void sn_common_hubdev_init(struct hubdev_info *);
 
 	/*
 	 * Get SGI Specific HUB chipset information.
@@ -240,70 +92,47 @@ static void __init sn_fixup_ionodes(void
 			max_segment_number = hubdev->max_segment_number;
 			max_pcibus_number = hubdev->max_pcibus_number;
 		}
+		sn_common_hubdev_init(hubdev);
+	}
+}
 
-		/* Attach the error interrupt handlers */
-		if (nasid & 1)
-			ice_error_init(hubdev);
-		else
-			hub_error_init(hubdev);
-
-		for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++)
-			hubdev->hdi_xwidget_info[widget].xwi_hubinfo = hubdev;
-
-		if (!hubdev->hdi_flush_nasid_list.widget_p)
-			continue;
-
-		size = (HUB_WIDGET_ID_MAX + 1) *
-			sizeof(struct sn_flush_device_kernel *);
-		hubdev->hdi_flush_nasid_list.widget_p =
-			kzalloc(size, GFP_KERNEL);
-		if (!hubdev->hdi_flush_nasid_list.widget_p)
+/*
+ * sn_pci_legacy_window_fixup - Create PCI controller windows 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)
+{
+		controller->window = kcalloc(2, sizeof(struct pci_window),
+					     GFP_KERNEL);
+		if (controller->window == NULL)
 			BUG();
-
-		for (widget = 0; widget <= HUB_WIDGET_ID_MAX; widget++) {
-			size = DEV_PER_WIDGET *
-				sizeof(struct sn_flush_device_kernel);
-			sn_flush_device_kernel = kzalloc(size, GFP_KERNEL);
-			if (!sn_flush_device_kernel)
-				BUG();
-
-			dev_entry = sn_flush_device_kernel;
-			for (device = 0; device < DEV_PER_WIDGET;
-			     device++,dev_entry++) {
-				size = sizeof(struct sn_flush_device_common);
-				dev_entry->common = kzalloc(size, GFP_KERNEL);
-				if (!dev_entry->common)
-					BUG();
-
-				if (sn_prom_feature_available(
-						       PRF_DEVICE_FLUSH_LIST))
-					status = sal_get_device_dmaflush_list(
-						     nasid, widget, device,
-						     (u64)(dev_entry->common));
-				else
-					status = sn_device_fixup_war(nasid,
-						     widget, device,
-						     dev_entry->common);
-				if (status != SALRET_OK)
-					panic("SAL call failed: %s\n",
-					      ia64_sal_strerror(status));
-
-				spin_lock_init(&dev_entry->sfdl_flush_lock);
-			}
-
-			if (sn_flush_device_kernel)
-				hubdev->hdi_flush_nasid_list.widget_p[widget] =
-						       sn_flush_device_kernel;
-	        }
-	}
+		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.
- *			   Until ACPI support is added, we need this code
- *			   to setup pci_windows for use by
- *			   pcibios_bus_to_resource(),
- *			   pcibios_resource_to_bus(), etc.
+ *			   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,
@@ -342,60 +171,22 @@ sn_pci_window_fixup(struct pci_dev *dev,
 	controller->window = new_window;
 }
 
-void sn_pci_unfixup_slot(struct pci_dev *dev)
-{
-	struct pci_dev *host_pci_dev = SN_PCIDEV_INFO(dev)->host_pci_dev;
-
-	sn_irq_unfixup(dev);
-	pci_dev_put(host_pci_dev);
-	pci_dev_put(dev);
-}
-
 /*
- * sn_pci_fixup_slot() - This routine sets up a slot's resources
- * consistent with the Linux PCI abstraction layer.  Resources acquired
- * from our PCI provider include PIO maps to BAR space and interrupt
- * objects.
+ * sn_more_slot_fixup() - We are not running with an ACPI capable PROM,
+ *			  and need to convert the pci_dev->resource
+ *			  'start' and 'end' addresses to mapped addresses,
+ *			  and setup the pci_controller->window array entries.
  */
-void sn_pci_fixup_slot(struct pci_dev *dev)
+void
+sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
 {
 	unsigned int count = 0;
 	int idx;
-	int segment = pci_domain_nr(dev->bus);
-	int status = 0;
-	struct pcibus_bussoft *bs;
- 	struct pci_bus *host_pci_bus;
- 	struct pci_dev *host_pci_dev;
-	struct pcidev_info *pcidev_info;
 	s64 pci_addrs[PCI_ROM_RESOURCE + 1];
- 	struct sn_irq_info *sn_irq_info;
- 	unsigned long size;
- 	unsigned int bus_no, devfn;
-
-	pci_dev_get(dev); /* for the sysdata pointer */
-	pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
-	if (!pcidev_info)
-		BUG();		/* Cannot afford to run out of memory */
-
-	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
-	if (!sn_irq_info)
-		BUG();		/* Cannot afford to run out of memory */
-
-	/* Call to retrieve pci device information needed by kernel. */
-	status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number, 
-				     dev->devfn,
-				     (u64) __pa(pcidev_info),
-				     (u64) __pa(sn_irq_info));
-	if (status)
-		BUG(); /* Cannot get platform pci device information */
-
-	/* Add pcidev_info to list in sn_pci_controller struct */
-	list_add_tail(&pcidev_info->pdi_list,
-		      &(SN_PCI_CONTROLLER(dev->bus)->pcidev_info));
+	unsigned long addr, end, size, start;
 
 	/* Copy over PIO Mapped Addresses */
 	for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
-		unsigned long start, end, addr;
 
 		if (!pcidev_info->pdi_pio_mapped_addr[idx]) {
 			pci_addrs[idx] = -1;
@@ -425,54 +216,19 @@ void sn_pci_fixup_slot(struct pci_dev *d
 	 */
 	if (count > 0)
 		sn_pci_window_fixup(dev, count, pci_addrs);
-
-	/*
-	 * Using the PROMs values for the PCI host bus, get the Linux
- 	 * PCI host_pci_dev struct and set up host bus linkages
- 	 */
-
-	bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
-	devfn = pcidev_info->pdi_slot_host_handle & 0xffffffff;
- 	host_pci_bus = pci_find_bus(segment, bus_no);
- 	host_pci_dev = pci_get_slot(host_pci_bus, devfn);
-
-	pcidev_info->host_pci_dev = host_pci_dev;
-	pcidev_info->pdi_linux_pcidev = dev;
-	pcidev_info->pdi_host_pcidev_info = SN_PCIDEV_INFO(host_pci_dev);
-	bs = SN_PCIBUS_BUSSOFT(dev->bus);
-	pcidev_info->pdi_pcibus_info = bs;
-
-	if (bs && bs->bs_asic_type < PCIIO_ASIC_MAX_TYPES) {
-		SN_PCIDEV_BUSPROVIDER(dev) = sn_pci_provider[bs->bs_asic_type];
-	} else {
-		SN_PCIDEV_BUSPROVIDER(dev) = &sn_pci_default_provider;
-	}
-
-	/* Only set up IRQ stuff if this device has a host bus context */
-	if (bs && sn_irq_info->irq_irq) {
-		pcidev_info->pdi_sn_irq_info = sn_irq_info;
-		dev->irq = pcidev_info->pdi_sn_irq_info->irq_irq;
-		sn_irq_fixup(dev, sn_irq_info);
-	} else {
-		pcidev_info->pdi_sn_irq_info = NULL;
-		kfree(sn_irq_info);
-	}
 }
 
 /*
  * sn_pci_controller_fixup() - This routine sets up a bus's resources
- * consistent with the Linux PCI abstraction layer.
+ *			       consistent with the Linux PCI abstraction layer.
  */
-void sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
+static void
+sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
 {
-	int status;
-	int nasid, cnode;
+	s64 status = 0;
 	struct pci_controller *controller;
-	struct sn_pci_controller *sn_controller;
 	struct pcibus_bussoft *prom_bussoft_ptr;
-	struct hubdev_info *hubdev_info;
-	void *provider_soft;
-	struct sn_pcibus_provider *provider;
+
 
  	status = sal_get_pcibus_info((u64) segment, (u64) busnum,
  				     (u64) ia64_tpa(&prom_bussoft_ptr));
@@ -480,261 +236,77 @@ void sn_pci_controller_fixup(int segment
 		return;		/*bus # does not exist */
 	prom_bussoft_ptr = __va(prom_bussoft_ptr);
 
-	/* Allocate a sn_pci_controller, which has a pci_controller struct
-	 * as the first member.
-	 */
-	sn_controller = kzalloc(sizeof(struct sn_pci_controller), GFP_KERNEL);
-	if (!sn_controller)
+	controller = kzalloc(sizeof(*controller), GFP_KERNEL);
+	if (!controller)
 		BUG();
-	INIT_LIST_HEAD(&sn_controller->pcidev_info);
-	controller = &sn_controller->pci_controller;
 	controller->segment = segment;
 
-	if (bus == NULL) {
- 		bus = pci_scan_bus(busnum, &pci_root_ops, controller);
- 		if (bus == NULL)
- 			goto error_return; /* error, or bus already scanned */
- 		bus->sysdata = NULL;
-	}
-
-	if (bus->sysdata)
-		goto error_return; /* sysdata already alloc'd */
-
 	/*
-	 * Per-provider fixup.  Copies the contents from prom to local
-	 * area and links SN_PCIBUS_BUSSOFT().
+	 * 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;
 
-	if (prom_bussoft_ptr->bs_asic_type >= PCIIO_ASIC_MAX_TYPES)
-		goto error_return; /* unsupported asic type */
-
-	if (prom_bussoft_ptr->bs_asic_type == PCIIO_ASIC_TYPE_PPB)
-		goto error_return; /* no further fixup necessary */
-
-	provider = sn_pci_provider[prom_bussoft_ptr->bs_asic_type];
-	if (provider == NULL)
-		goto error_return; /* no provider registerd for this asic */
+	bus = pci_scan_bus(busnum, &pci_root_ops, controller);
+ 	if (bus == NULL)
+ 		goto error_return; /* error, or bus already scanned */
 
 	bus->sysdata = controller;
-	if (provider->bus_fixup)
-		provider_soft = (*provider->bus_fixup) (prom_bussoft_ptr, controller);
-	else
-		provider_soft = NULL;
-
-	if (provider_soft == NULL) {
-		/* fixup failed or not applicable */
-		bus->sysdata = NULL;
-		goto error_return;
-	}
-
-	/*
-	 * Setup pci_windows for legacy IO and MEM space.
-	 * (Temporary until ACPI support is in place.)
-	 */
-	controller->window = kcalloc(2, sizeof(struct pci_window), GFP_KERNEL);
-	if (controller->window == NULL)
-		BUG();
-	controller->window[0].offset = prom_bussoft_ptr->bs_legacy_io;
-	controller->window[0].resource.name = "legacy_io";
-	controller->window[0].resource.flags = IORESOURCE_IO;
-	controller->window[0].resource.start = prom_bussoft_ptr->bs_legacy_io;
-	controller->window[0].resource.end =
-	    controller->window[0].resource.start + 0xffff;
-	controller->window[0].resource.parent = &ioport_resource;
-	controller->window[1].offset = prom_bussoft_ptr->bs_legacy_mem;
-	controller->window[1].resource.name = "legacy_mem";
-	controller->window[1].resource.flags = IORESOURCE_MEM;
-	controller->window[1].resource.start = prom_bussoft_ptr->bs_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;
-
-	/*
-	 * Generic bus fixup goes here.  Don't reference prom_bussoft_ptr
-	 * after this point.
-	 */
-
-	PCI_CONTROLLER(bus)->platform_data = provider_soft;
-	nasid = NASID_GET(SN_PCIBUS_BUSSOFT(bus)->bs_base);
-	cnode = nasid_to_cnodeid(nasid);
-	hubdev_info = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
-	SN_PCIBUS_BUSSOFT(bus)->bs_xwidget_info =
-	    &(hubdev_info->hdi_xwidget_info[SN_PCIBUS_BUSSOFT(bus)->bs_xid]);
-
-	/*
-	 * If the node information we obtained during the fixup phase is invalid
-	 * then set controller->node to -1 (undetermined)
-	 */
-	if (controller->node >= num_online_nodes()) {
-		struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus);
 
-		printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u"
-				    "L_IO=%lx L_MEM=%lx BASE=%lx\n",
-			b->bs_asic_type, b->bs_xid, b->bs_persist_busnum,
-			b->bs_legacy_io, b->bs_legacy_mem, b->bs_base);
-		printk(KERN_WARNING "on node %d but only %d nodes online."
-			"Association set to undetermined.\n",
-			controller->node, num_online_nodes());
-		controller->node = -1;
-	}
 	return;
 
 error_return:
 
-	kfree(sn_controller);
+	kfree(controller);
 	return;
 }
 
-void sn_bus_store_sysdata(struct pci_dev *dev)
+/*
+ * sn_bus_fixup
+ */
+void
+sn_bus_fixup(struct pci_bus *bus)
 {
-	struct sysdata_el *element;
+	struct pci_dev *pci_dev = NULL;
+	struct pcibus_bussoft *prom_bussoft_ptr;
+	extern void sn_common_bus_fixup(struct pci_bus *,
+					struct pcibus_bussoft *);
 
-	element = kzalloc(sizeof(struct sysdata_el), GFP_KERNEL);
-	if (!element) {
-		dev_dbg(dev, "%s: out of memory!\n", __FUNCTION__);
-		return;
-	}
-	element->sysdata = SN_PCIDEV_INFO(dev);
-	list_add(&element->entry, &sn_sysdata_list);
-}
 
-void sn_bus_free_sysdata(void)
-{
-	struct sysdata_el *element;
-	struct list_head *list, *safe;
+	if (!bus->parent) {  /* If root bus */
+		prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
+		if (prom_bussoft_ptr == NULL) {
+			printk(KERN_ERR
+			       "sn_bus_fixup: 0x%04x:0x%02x Unable to "
+			       "obtain prom_bussoft_ptr\n",
+			       pci_domain_nr(bus), bus->number);
+			return;
+		}
+		sn_common_bus_fixup(bus, prom_bussoft_ptr);
+		sn_legacy_pci_window_fixup(PCI_CONTROLLER(bus),
+					   prom_bussoft_ptr->bs_legacy_io,
+					   prom_bussoft_ptr->bs_legacy_mem);
+        }
+        list_for_each_entry(pci_dev, &bus->devices, bus_list) {
+                sn_pci_fixup_slot(pci_dev);
+        }
 
-	list_for_each_safe(list, safe, &sn_sysdata_list) {
-		element = list_entry(list, struct sysdata_el, entry);
-		list_del(&element->entry);
-		list_del(&(((struct pcidev_info *)
-			     (element->sysdata))->pdi_list));
-		kfree(element->sysdata);
-		kfree(element);
-	}
-	return;
 }
 
 /*
- * Ugly hack to get PCI setup until we have a proper ACPI namespace.
+ * sn_io_init - PROM does not have ACPI support to define nodes or root buses,
+ *		so we need to do things the hard way, including initiating the
+ *		bus scanning ourselves.
  */
 
-#define PCI_BUSES_TO_SCAN 256
-
-static int __init sn_pci_init(void)
+void __init sn_io_init(void)
 {
 	int i, j;
-	struct pci_dev *pci_dev = NULL;
-
-	if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
-		return 0;
-
-	/*
-	 * prime sn_pci_provider[].  Individial provider init routines will
-	 * override their respective default entries.
-	 */
-
-	for (i = 0; i < PCIIO_ASIC_MAX_TYPES; i++)
-		sn_pci_provider[i] = &sn_pci_default_provider;
 
-	pcibr_init_provider();
-	tioca_init_provider();
-	tioce_init_provider();
-
-	/*
-	 * This is needed to avoid bounce limit checks in the blk layer
-	 */
-	ia64_max_iommu_merge_mask = ~PAGE_MASK;
 	sn_fixup_ionodes();
-	sn_irq_lh_init();
-	INIT_LIST_HEAD(&sn_sysdata_list);
-	sn_init_cpei_timer();
-
-#ifdef CONFIG_PROC_FS
-	register_sn_procfs();
-#endif
 
 	/* busses are not known yet ... */
 	for (i = 0; i <= max_segment_number; i++)
 		for (j = 0; j <= max_pcibus_number; j++)
 			sn_pci_controller_fixup(i, j, NULL);
-
-	/*
-	 * Generic Linux PCI Layer has created the pci_bus and pci_dev 
-	 * structures - time for us to add our SN PLatform specific 
-	 * information.
-	 */
-
-	while ((pci_dev =
-		pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) != NULL)
-		sn_pci_fixup_slot(pci_dev);
-
-	sn_ioif_inited = 1;	/* sn I/O infrastructure now initialized */
-
-	return 0;
 }
-
-/*
- * hubdev_init_node() - Creates the HUB data structure and link them to it's 
- *	own NODE specific data area.
- */
-void hubdev_init_node(nodepda_t * npda, cnodeid_t node)
-{
-	struct hubdev_info *hubdev_info;
-	int size;
-	pg_data_t *pg;
-
-	size = sizeof(struct hubdev_info);
-
-	if (node >= num_online_nodes())	/* Headless/memless IO nodes */
-		pg = NODE_DATA(0);
-	else
-		pg = NODE_DATA(node);
-
-	hubdev_info = (struct hubdev_info *)alloc_bootmem_node(pg, size);
-
-	npda->pdinfo = (void *)hubdev_info;
-}
-
-geoid_t
-cnodeid_get_geoid(cnodeid_t cnode)
-{
-	struct hubdev_info *hubdev;
-
-	hubdev = (struct hubdev_info *)(NODEPDA(cnode)->pdinfo);
-	return hubdev->hdi_geoid;
-}
-
-void sn_generate_path(struct pci_bus *pci_bus, char *address)
-{
-	nasid_t nasid;
-	cnodeid_t cnode;
-	geoid_t geoid;
-	moduleid_t moduleid;
-	u16 bricktype;
-
-	nasid = NASID_GET(SN_PCIBUS_BUSSOFT(pci_bus)->bs_base);
-	cnode = nasid_to_cnodeid(nasid);
-	geoid = cnodeid_get_geoid(cnode);
-	moduleid = geo_module(geoid);
-
-	sprintf(address, "module_%c%c%c%c%.2d",
-		'0'+RACK_GET_CLASS(MODULE_GET_RACK(moduleid)),
-		'0'+RACK_GET_GROUP(MODULE_GET_RACK(moduleid)),
-		'0'+RACK_GET_NUM(MODULE_GET_RACK(moduleid)),
-		MODULE_GET_BTCHAR(moduleid), MODULE_GET_BPOS(moduleid));
-
-	/* Tollhouse requires slot id to be displayed */
-	bricktype = MODULE_GET_BTYPE(moduleid);
-	if ((bricktype == L1_BRICKTYPE_191010) ||
-	    (bricktype == L1_BRICKTYPE_1932))
-			sprintf(address, "%s^%d", address, geo_slot(geoid));
-}
-
-subsys_initcall(sn_pci_init);
-EXPORT_SYMBOL(sn_pci_fixup_slot);
-EXPORT_SYMBOL(sn_pci_unfixup_slot);
-EXPORT_SYMBOL(sn_pci_controller_fixup);
-EXPORT_SYMBOL(sn_bus_store_sysdata);
-EXPORT_SYMBOL(sn_bus_free_sysdata);
-EXPORT_SYMBOL(sn_generate_path);
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/iomv.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/iomv.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/iomv.c	2007-06-19 11:26:06.000000000 -0500
@@ -3,10 +3,11 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2000-2003, 2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/module.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 #include <asm/delay.h>
 #include <asm/vga.h>
@@ -15,6 +16,7 @@
 #include <asm/sn/pda.h>
 #include <asm/sn/sn_cpuid.h>
 #include <asm/sn/shub_mmr.h>
+#include <asm/sn/acpi.h>
 
 #define IS_LEGACY_VGA_IOPORT(p) \
 	(((p) >= 0x3b0 && (p) <= 0x3bb) || ((p) >= 0x3c0 && (p) <= 0x3df))
@@ -31,11 +33,14 @@ void *sn_io_addr(unsigned long port)
 {
 	if (!IS_RUNNING_ON_SIMULATOR()) {
 		if (IS_LEGACY_VGA_IOPORT(port))
-			port += vga_console_iobase;
+			return (__ia64_mk_io_addr(port));
 		/* On sn2, legacy I/O ports don't point at anything */
 		if (port < (64 * 1024))
 			return NULL;
-		return ((void *)(port | __IA64_UNCACHED_OFFSET));
+		if (SN_ACPI_BASE_SUPPORT())
+			return (__ia64_mk_io_addr(port));
+		else
+			return ((void *)(port | __IA64_UNCACHED_OFFSET));
 	} else {
 		/* but the simulator uses them... */
 		unsigned long addr;
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/setup.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/setup.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/setup.c	2007-06-19 11:26:06.000000000 -0500
@@ -389,6 +389,14 @@ void __init sn_setup(char **cmdline_p)
 	ia64_sn_plat_set_error_handling_features();	// obsolete
 	ia64_sn_set_os_feature(OSF_MCA_SLV_TO_OS_INIT_SLV);
 	ia64_sn_set_os_feature(OSF_FEAT_LOG_SBES);
+	/*
+	 * Note: The calls to notify the PROM of ACPI and PCI Segment
+	 *	 support must be done prior to acpi_load_tables(), as
+	 *	 an ACPI capable PROM will rebuild the DSDT as result
+	 *	 of the call.
+	 */
+	ia64_sn_set_os_feature(OSF_PCISEGMENT_ENABLE);
+	ia64_sn_set_os_feature(OSF_ACPI_ENABLE);
 
 
 #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
@@ -414,6 +422,16 @@ void __init sn_setup(char **cmdline_p)
 	if (! vga_console_membase)
 		sn_scan_pcdp();
 
+	/*
+	 *	Setup legacy IO space.
+	 *	vga_console_iobase maps to PCI IO Space address 0 on the
+	 * 	bus containing the VGA console.
+	 */
+	if (vga_console_iobase) {
+		io_space[0].mmio_base = vga_console_iobase;
+		io_space[0].sparse = 0;
+	}
+
 	if (vga_console_membase) {
 		/* usable vga ... make tty0 the preferred default console */
 		if (!strstr(*cmdline_p, "console="))
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/tiocx.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/tiocx.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/tiocx.c	2007-06-19 11:26:06.000000000 -0500
@@ -552,7 +552,7 @@ static void __exit tiocx_exit(void)
 	bus_unregister(&tiocx_bus_type);
 }
 
-subsys_initcall(tiocx_init);
+fs_initcall(tiocx_init);
 module_exit(tiocx_exit);
 
 /************************************************************************
Index: 2.6.18-28.el5/arch/ia64/sn/pci/pcibr/pcibr_provider.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2007-06-19 11:36:25.000000000 -0500
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2001-2004, 2006 Silicon Graphics, Inc. All rights reserved.
  */
 
 #include <linux/interrupt.h>
@@ -109,7 +109,6 @@ void *
 pcibr_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
 {
 	int nasid, cnode, j;
-	cnodeid_t near_cnode;
 	struct hubdev_info *hubdev_info;
 	struct pcibus_info *soft;
 	struct sn_flush_device_kernel *sn_flush_device_kernel;
@@ -186,20 +185,6 @@ pcibr_bus_fixup(struct pcibus_bussoft *p
 		return NULL;
 	}
 
-	if (prom_bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) {
-		/* TIO PCI Bridge: find nearest node with CPUs */
-		int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode);
-
-		if (e < 0) {
-			near_cnode = (cnodeid_t)-1; /* use any node */
-			printk(KERN_WARNING "pcibr_bus_fixup: failed to find "
-				"near node with CPUs to TIO node %d, err=%d\n",
-				cnode, e);
-		}
-		controller->node = near_cnode;
-	}
-	else
-		controller->node = cnode;
 	return soft;
 }
 
Index: 2.6.18-28.el5/arch/ia64/sn/pci/tioce_provider.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/pci/tioce_provider.c	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/pci/tioce_provider.c	2007-06-19 11:26:06.000000000 -0500
@@ -15,7 +15,6 @@
 #include <asm/sn/pcidev.h>
 #include <asm/sn/pcibus_provider_defs.h>
 #include <asm/sn/tioce_provider.h>
-#include <asm/sn/sn2/sn_hwperf.h>
 
 /*
  * 1/26/2006
@@ -991,8 +990,6 @@ tioce_target_interrupt(struct sn_irq_inf
 static void *
 tioce_bus_fixup(struct pcibus_bussoft *prom_bussoft, struct pci_controller *controller)
 {
-	int my_nasid;
-	cnodeid_t my_cnode, mem_cnode;
 	struct tioce_common *tioce_common;
 	struct tioce_kernel *tioce_kern;
 	struct tioce *tioce_mmr;
@@ -1036,21 +1033,6 @@ tioce_bus_fixup(struct pcibus_bussoft *p
 		       tioce_common->ce_pcibus.bs_persist_segment,
 		       tioce_common->ce_pcibus.bs_persist_busnum);
 
-	/*
-	 * identify closest nasid for memory allocations
-	 */
-
-	my_nasid = NASID_GET(tioce_common->ce_pcibus.bs_base);
-	my_cnode = nasid_to_cnodeid(my_nasid);
-
-	if (sn_hwperf_get_nearest_node(my_cnode, &mem_cnode, NULL) < 0) {
-		printk(KERN_WARNING "tioce_bus_fixup: failed to find "
-		       "closest node with MEM to TIO node %d\n", my_cnode);
-		mem_cnode = (cnodeid_t)-1; /* use any node */
-	}
-
-	controller->node = mem_cnode;
-
 	return tioce_common;
 }
 
Index: 2.6.18-28.el5/include/asm-ia64/io.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/io.h	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/io.h	2007-06-19 11:26:06.000000000 -0500
@@ -32,7 +32,7 @@
  */
 #define IO_SPACE_LIMIT		0xffffffffffffffffUL
 
-#define MAX_IO_SPACES_BITS		4
+#define MAX_IO_SPACES_BITS		8
 #define MAX_IO_SPACES			(1UL << MAX_IO_SPACES_BITS)
 #define IO_SPACE_BITS			24
 #define IO_SPACE_SIZE			(1UL << IO_SPACE_BITS)
Index: 2.6.18-28.el5/include/asm-ia64/machvec.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/machvec.h	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/machvec.h	2007-06-19 11:28:55.000000000 -0500
@@ -35,9 +35,10 @@ typedef int ia64_mv_pci_legacy_read_t (s
 typedef int ia64_mv_pci_legacy_write_t (struct pci_bus *, u16 port, u32 val,
 					u8 size);
 typedef void ia64_mv_migrate_t(struct task_struct * task);
+typedef void ia64_mv_pci_fixup_bus_t (struct pci_bus *);
 typedef void ia64_mv_kernel_launch_event_t(void);
 
-/* DMA-mapping interface: */
+/*ADMA-mapping interface: */
 typedef void ia64_mv_dma_init (void);
 typedef void *ia64_mv_dma_alloc_coherent (struct device *, size_t, dma_addr_t *, gfp_t);
 typedef void ia64_mv_dma_free_coherent (struct device *, size_t, void *, dma_addr_t);
@@ -93,6 +94,11 @@ machvec_noop_task (struct task_struct *t
 {
 }
 
+static inline void
+machvec_noop_bus (struct pci_bus *bus)
+{
+}
+
 extern void machvec_setup (char **);
 extern void machvec_timer_interrupt (int, void *, struct pt_regs *);
 extern void machvec_dma_sync_single (struct device *, dma_addr_t, size_t, int);
@@ -157,6 +163,7 @@ extern void machvec_tlb_migrate_finish (
 #  define platform_migrate		ia64_mv.migrate
 #  define platform_msi_init		ia64_mv.msi_init
 #  define platform_kernel_launch_event	ia64_mv.kernel_launch_event
+#  define platform_pci_fixup_bus	ia64_mv.pci_fixup_bus
 # endif
 
 /* __attribute__((__aligned__(16))) is required to make size of the
@@ -208,6 +215,9 @@ struct ia64_machine_vector {
 	ia64_mv_migrate_t *migrate;
 	ia64_mv_msi_init_t *msi_init;
 	ia64_mv_kernel_launch_event_t *kernel_launch_event;
+#ifndef __GENKSYMS__
+	ia64_mv_pci_fixup_bus_t *pci_fixup_bus;
+#endif
 } __attribute__((__aligned__(16))); /* align attrib? see above comment */
 
 #define MACHVEC_INIT(name)			\
@@ -255,6 +265,7 @@ struct ia64_machine_vector {
 	platform_migrate,			\
 	platform_msi_init,			\
 	platform_kernel_launch_event,		\
+ 	platform_pci_fixup_bus,			\
 }
 
 extern struct ia64_machine_vector ia64_mv;
@@ -414,5 +425,8 @@ extern int ia64_pci_legacy_write(struct 
 #ifndef platform_msi_init
 # define platform_msi_init	((ia64_mv_msi_init_t*)NULL)
 #endif
+#ifndef platform_pci_fixup_bus
+# define platform_pci_fixup_bus	machvec_noop_bus
+#endif
 
 #endif /* _ASM_IA64_MACHVEC_H */
Index: 2.6.18-28.el5/include/asm-ia64/machvec_sn2.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/machvec_sn2.h	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/machvec_sn2.h	2007-06-19 11:26:06.000000000 -0500
@@ -69,7 +69,7 @@ extern ia64_mv_dma_supported		sn_dma_sup
 extern ia64_mv_migrate_t		sn_migrate;
 extern ia64_mv_kernel_launch_event_t	sn_kernel_launch_event;
 extern ia64_mv_msi_init_t		sn_msi_init;
-
+extern ia64_mv_pci_fixup_bus_t		sn_pci_fixup_bus;
 
 /*
  * This stuff has dual use!
@@ -126,6 +126,7 @@ extern ia64_mv_msi_init_t		sn_msi_init;
 #else
 #define platform_msi_init		((ia64_mv_msi_init_t*)NULL)
 #endif
+#define platform_pci_fixup_bus		sn_pci_fixup_bus
 
 #include <asm/sn/io.h>
 
Index: 2.6.18-28.el5/include/asm-ia64/sn/acpi.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ 2.6.18-28.el5/include/asm-ia64/sn/acpi.h	2007-06-19 11:36:25.000000000 -0500
@@ -0,0 +1,16 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
+ */
+
+#ifndef _ASM_IA64_SN_ACPI_H
+#define _ASM_IA64_SN_ACPI_H
+
+#include "acpi/acglobal.h"
+
+#define SN_ACPI_BASE_SUPPORT()   (acpi_gbl_DSDT->oem_revision >= 0x20101)
+
+#endif /* _ASM_IA64_SN_ACPI_H */
Index: 2.6.18-28.el5/include/asm-ia64/sn/pcidev.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/sn/pcidev.h	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/sn/pcidev.h	2007-06-19 11:36:25.000000000 -0500
@@ -3,7 +3,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1992 - 1997, 2000-2005 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 1992 - 1997, 2000-2006 Silicon Graphics, Inc. All rights reserved.
  */
 #ifndef _ASM_IA64_SN_PCI_PCIDEV_H
 #define _ASM_IA64_SN_PCI_PCIDEV_H
@@ -12,31 +12,29 @@
 
 /*
  * In ia64, pci_dev->sysdata must be a *pci_controller. To provide access to
- * the pcidev_info structs for all devices under a controller, we extend the
- * definition of pci_controller, via sn_pci_controller, to include a list
- * of pcidev_info.
+ * the pcidev_info structs for all devices under a controller, we keep a
+ * list of pcidev_info under pci_controller->platform_data.
  */
-struct sn_pci_controller {
-	struct pci_controller pci_controller;
+struct sn_platform_data {
+	void *provider_soft;
 	struct list_head pcidev_info;
 };
 
-#define SN_PCI_CONTROLLER(dev) ((struct sn_pci_controller *) dev->sysdata)
+#define SN_PLATFORM_DATA(busdev) \
+	((struct sn_platform_data *)(PCI_CONTROLLER(busdev)->platform_data))
 
 #define SN_PCIDEV_INFO(dev)	sn_pcidev_info_get(dev)
 
-#define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
-	(struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
 /*
  * Given a pci_bus, return the sn pcibus_bussoft struct.  Note that
  * this only works for root busses, not for busses represented by PPB's.
  */
 
 #define SN_PCIBUS_BUSSOFT(pci_bus) \
-        ((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
+	((struct pcibus_bussoft *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
 
 #define SN_PCIBUS_BUSSOFT_INFO(pci_bus) \
-	(struct pcibus_info *)((struct pcibus_bussoft *)(PCI_CONTROLLER((pci_bus))->platform_data))
+	((struct pcibus_info *)(SN_PLATFORM_DATA(pci_bus)->provider_soft))
 /*
  * Given a struct pci_dev, return the sn pcibus_bussoft struct.  Note
  * that this is not equivalent to SN_PCIBUS_BUSSOFT(pci_dev->bus) due
@@ -72,8 +70,6 @@ extern void sn_irq_fixup(struct pci_dev 
 			 struct sn_irq_info *sn_irq_info);
 extern void sn_irq_unfixup(struct pci_dev *pci_dev);
 extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *);
-extern void sn_pci_controller_fixup(int segment, int busnum,
- 				    struct pci_bus *bus);
 extern void sn_bus_store_sysdata(struct pci_dev *dev);
 extern void sn_bus_free_sysdata(void);
 extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
Index: 2.6.18-28.el5/include/asm-ia64/sn/sn_feature_sets.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/sn/sn_feature_sets.h	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/sn/sn_feature_sets.h	2007-06-19 11:26:06.000000000 -0500
@@ -44,8 +44,14 @@ extern int sn_prom_feature_available(int
  * Once enabled, a feature cannot be disabled.
  *
  * By default, features are disabled unless explicitly enabled.
+ *
+ * These defines must be kept in sync with the corresponding
+ * PROM definitions in feature_sets.h.
  */
 #define  OSF_MCA_SLV_TO_OS_INIT_SLV	0
 #define  OSF_FEAT_LOG_SBES		1
+#define  OSF_ACPI_ENABLE		2
+#define  OSF_PCISEGMENT_ENABLE		3
+
 
 #endif /* _ASM_IA64_SN_FEATURE_SETS_H */
Index: 2.6.18-28.el5/include/asm-ia64/sn/sn_sal.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/sn/sn_sal.h	2007-06-19 11:25:48.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/sn/sn_sal.h	2007-06-19 11:26:06.000000000 -0500
@@ -77,6 +77,7 @@
 #define  SN_SAL_IOIF_GET_WIDGET_DMAFLUSH_LIST	   0x02000058	// deprecated
 #define  SN_SAL_IOIF_GET_DEVICE_DMAFLUSH_LIST	   0x0200005a
 
+#define SN_SAL_IOIF_INIT			   0x0200005f
 #define SN_SAL_HUB_ERROR_INTERRUPT		   0x02000060
 #define SN_SAL_BTE_RECOVER			   0x02000061
 #define SN_SAL_RESERVED_DO_NOT_USE		   0x02000062

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=9f581f162e2b304be25dee49bf3945d4ed65dfb6

Altix: SN ACPI hotplug support.

A few minor changes to the way slot/device fixup is done.

No need to be calling sn_pci_controller_fixup(), as
a root bus cannot be hotplugged.

---
 drivers/pci/hotplug/sgi_hotplug.c |   35 +++++++++++++----------------------
 1 file changed, 13 insertions(+), 22 deletions(-)
---


Index: 2.6.18-28.el5/drivers/pci/hotplug/sgi_hotplug.c
===================================================================
--- 2.6.18-28.el5.orig/drivers/pci/hotplug/sgi_hotplug.c	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/drivers/pci/hotplug/sgi_hotplug.c	2007-06-18 16:19:55.000000000 -0500
@@ -205,21 +205,6 @@ static struct hotplug_slot * sn_hp_destr
 	return bss_hotplug_slot;
 }
 
-static void sn_bus_alloc_data(struct pci_dev *dev)
-{
-	struct pci_bus *subordinate_bus;
-	struct pci_dev *child;
-
-	sn_pci_fixup_slot(dev);
-
-	/* Recursively sets up the sn_irq_info structs */
-	if (dev->subordinate) {
-		subordinate_bus = dev->subordinate;
-		list_for_each_entry(child, &subordinate_bus->devices, bus_list)
-			sn_bus_alloc_data(child);
-	}
-}
-
 static void sn_bus_free_data(struct pci_dev *dev)
 {
 	struct pci_bus *subordinate_bus;
@@ -337,6 +322,11 @@ static int sn_slot_disable(struct hotplu
 	return rc;
 }
 
+/*
+ * Power up and configure the slot via a SAL call to PROM.
+ * Scan slot (and any children), do any platform specific fixup,
+ * and find device driver.
+ */
 static int enable_slot(struct hotplug_slot *bss_hotplug_slot)
 {
 	struct slot *slot = bss_hotplug_slot->private;
@@ -345,6 +335,7 @@ static int enable_slot(struct hotplug_sl
 	int func, num_funcs;
 	int new_ppb = 0;
 	int rc;
+	void pcibios_fixup_device_resources(struct pci_dev *);
 
 	/* Serialize the Linux PCI infrastructure */
 	mutex_lock(&sn_hotplug_mutex);
@@ -367,9 +358,6 @@ static int enable_slot(struct hotplug_sl
 		return -ENODEV;
 	}
 
-	sn_pci_controller_fixup(pci_domain_nr(slot->pci_bus),
-				slot->pci_bus->number,
-				slot->pci_bus);
 	/*
 	 * Map SN resources for all functions on the card
 	 * to the Linux PCI interface and tell the drivers
@@ -380,6 +368,13 @@ static int enable_slot(struct hotplug_sl
 				   PCI_DEVFN(slot->device_num + 1,
 					     PCI_FUNC(func)));
 		if (dev) {
+			/* Need to do slot fixup on PPB before fixup of children
+			 * (PPB's pcidev_info needs to be in pcidev_info list
+			 * before child's SN_PCIDEV_INFO() call to setup
+			 * pdi_host_pcidev_info).
+			 */
+			pcibios_fixup_device_resources(dev);
+			sn_pci_fixup_slot(dev);
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 				unsigned char sec_bus;
 				pci_read_config_byte(dev, PCI_SECONDARY_BUS,
@@ -387,12 +382,8 @@ static int enable_slot(struct hotplug_sl
 				new_bus = pci_add_new_bus(dev->bus, dev,
 							  sec_bus);
 				pci_scan_child_bus(new_bus);
-				sn_pci_controller_fixup(pci_domain_nr(new_bus),
-							new_bus->number,
-							new_bus);
 				new_ppb = 1;
 			}
-			sn_bus_alloc_data(dev);
 			pci_dev_put(dev);
 		}
 	}


http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=a2302c68d923537436b1114aa207787c1a31bd50

Altix: Initial ACPI support - ROM shadowing.

Support a shadowed ROM when running with an ACPI capable PROM.

Define a new dev.resource flag IORESOURCE_ROM_BIOS_COPY to
describe the case of a BIOS shadowed ROM, which can then
be used to avoid pci_map_rom() making an unneeded call to
pci_enable_rom().

---
 arch/ia64/sn/kernel/io_acpi_init.c |   33 +++++++++++++++++++++++++++++++++
 arch/ia64/sn/kernel/io_common.c    |    5 +++--
 arch/ia64/sn/kernel/io_init.c      |    3 +++
 drivers/pci/rom.c                  |    9 ++++++---
 include/linux/ioport.h             |    1 +
 5 files changed, 46 insertions(+), 5 deletions(-)
---

Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-18 16:19:52.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-18 16:19:58.000000000 -0500
@@ -169,6 +169,39 @@ sn_acpi_bus_fixup(struct pci_bus *bus)
 	}
 }
 
+/*
+ * sn_acpi_slot_fixup - Perform any SN specific slot fixup.
+ *			At present there does not appear to be
+ *			any generic way to handle a ROM image
+ *			that has been shadowed by the PROM, so
+ *			we pass a pointer to it	within the
+ *			pcidev_info structure.
+ */
+
+void
+sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
+{
+	void __iomem *addr;
+	size_t size;
+
+	if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
+		/*
+		 * A valid ROM image exists and has been shadowed by the
+		 * PROM. Setup the pci_dev ROM resource to point to
+		 * the shadowed copy.
+		 */
+		size = dev->resource[PCI_ROM_RESOURCE].end -
+				dev->resource[PCI_ROM_RESOURCE].start;
+		addr =
+		     ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
+			     size);
+		dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
+		dev->resource[PCI_ROM_RESOURCE].end =
+						(unsigned long) addr + size;
+		dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
+	}
+}
+
 static struct acpi_driver acpi_sn_hubdev_driver = {
 	.name = "SGI HUBDEV Driver",
 	.ids = "SGIHUB,SGITIO",
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_common.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_common.c	2007-06-18 16:19:52.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_common.c	2007-06-18 16:19:58.000000000 -0500
@@ -286,9 +286,10 @@ void sn_pci_fixup_slot(struct pci_dev *d
 	list_add_tail(&pcidev_info->pdi_list,
 		      &(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
 
-	if (!SN_ACPI_BASE_SUPPORT())
+	if (SN_ACPI_BASE_SUPPORT())
+		sn_acpi_slot_fixup(dev, pcidev_info);
+	else
 		sn_more_slot_fixup(dev, pcidev_info);
-
 	/*
 	 * Using the PROMs values for the PCI host bus, get the Linux
  	 * PCI host_pci_dev struct and set up host bus linkages
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_init.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_init.c	2007-06-18 16:19:52.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_init.c	2007-06-18 16:19:58.000000000 -0500
@@ -210,6 +210,9 @@ sn_more_slot_fixup(struct pci_dev *dev, 
 			dev->resource[idx].parent = &ioport_resource;
 		else
 			dev->resource[idx].parent = &iomem_resource;
+		/* If ROM, mark as shadowed in PROM */
+		if (idx == PCI_ROM_RESOURCE)
+			dev->resource[idx].flags |= IORESOURCE_ROM_BIOS_COPY;
 	}
 	/* Create a pci_window in the pci_controller struct for
 	 * each device resource.
Index: 2.6.18-28.el5/drivers/pci/rom.c
===================================================================
--- 2.6.18-28.el5.orig/drivers/pci/rom.c	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/drivers/pci/rom.c	2007-06-18 16:19:58.000000000 -0500
@@ -77,7 +77,8 @@ void __iomem *pci_map_rom(struct pci_dev
 		start = (loff_t)0xC0000;
 		*size = 0x20000; /* cover C000:0 through E000:0 */
 	} else {
-		if (res->flags & IORESOURCE_ROM_COPY) {
+		if (res->flags &
+			(IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY)) {
 			*size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
 			return (void __iomem *)(unsigned long)
 				pci_resource_start(pdev, PCI_ROM_RESOURCE);
@@ -161,7 +162,8 @@ void __iomem *pci_map_rom_copy(struct pc
 	if (!rom)
 		return NULL;
 
-	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW))
+	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_SHADOW |
+			  IORESOURCE_ROM_BIOS_COPY))
 		return rom;
 
 	res->start = (unsigned long)kmalloc(*size, GFP_KERNEL);
@@ -187,7 +189,7 @@ void pci_unmap_rom(struct pci_dev *pdev,
 {
 	struct resource *res = &pdev->resource[PCI_ROM_RESOURCE];
 
-	if (res->flags & IORESOURCE_ROM_COPY)
+	if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
 		return;
 
 	iounmap(rom);
@@ -211,6 +213,7 @@ void pci_remove_rom(struct pci_dev *pdev
 		sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr);
 	if (!(res->flags & (IORESOURCE_ROM_ENABLE |
 			    IORESOURCE_ROM_SHADOW |
+			    IORESOURCE_ROM_BIOS_COPY |
 			    IORESOURCE_ROM_COPY)))
 		pci_disable_rom(pdev);
 }
Index: 2.6.18-28.el5/include/linux/ioport.h
===================================================================
--- 2.6.18-28.el5.orig/include/linux/ioport.h	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/include/linux/ioport.h	2007-06-18 16:19:58.000000000 -0500
@@ -89,6 +89,7 @@ struct resource_list {
 #define IORESOURCE_ROM_ENABLE		(1<<0)	/* ROM is enabled, same as PCI_ROM_ADDRESS_ENABLE */
 #define IORESOURCE_ROM_SHADOW		(1<<1)	/* ROM is copy at C000:0 */
 #define IORESOURCE_ROM_COPY		(1<<2)	/* ROM is alloc'd copy, resource field overlaid */
+#define IORESOURCE_ROM_BIOS_COPY	(1<<3)	/* ROM is BIOS copy, resource field overlaid */
 
 /* PC/ISA/whatever - the normal PC address spaces: IO and memory */
 extern struct resource ioport_resource;


http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=6f09a9250a5d76c0765cd51a33e0a042e9761cfc

Altix: ACPI SSDT PCI device support

Add SN platform support for running with an ACPI
capable PROM that defines PCI devices in SSDT
tables. There is a SSDT table for every occupied
slot on a root bus, containing info for every
PPB and/or device on the bus. The SSDTs will be
dynamically loaded/unloaded at hotplug enable/disable.

Platform specific information that is currently
passed via a SAL call, will now be passed via the
Vendor resource in the ACPI Device object(s) defined
in each SSDT.

---
 arch/ia64/sn/kernel/io_acpi_init.c      |  314 +++++++++++++++++++++++++++++---
 arch/ia64/sn/kernel/io_common.c         |   68 +-----
 arch/ia64/sn/kernel/io_init.c           |   54 ++++-
 arch/ia64/sn/pci/pcibr/pcibr_provider.c |   21 ++
 include/asm-ia64/sn/acpi.h              |    5 
 include/asm-ia64/sn/pcibr_provider.h    |    2 
 include/asm-ia64/sn/pcidev.h            |    8 
 7 files changed, 380 insertions(+), 92 deletions(-)
---

Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-19 12:42:16.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-19 15:23:35.000000000 -0500
@@ -13,6 +13,7 @@
 #include <asm/sn/sn_sal.h>
 #include "xtalk/hubdev.h"
 #include <linux/acpi.h>
+#include <acpi/acnamesp.h>
 
 
 /*
@@ -31,6 +32,12 @@ struct acpi_vendor_uuid sn_uuid = {
 		    0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
 };
 
+struct sn_pcidev_match {
+	u8 bus;
+	unsigned int devfn;
+	acpi_handle handle;
+};
+
 /*
  * Perform the early IO init in PROM.
  */
@@ -119,9 +126,11 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
 	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
 					  &sn_uuid, &buffer);
 	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR "get_acpi_pcibus_ptr: "
-		       "get_acpi_bussoft_info() failed: %d\n",
-		       status);
+		printk(KERN_ERR "%s: "
+		       "acpi_get_vendor_resource() failed (0x%x) for: ",
+		       __FUNCTION__, status);
+		acpi_ns_print_node_pathname(handle, NULL);
+		printk("\n");
 		return NULL;
 	}
 	resource = buffer.pointer;
@@ -130,8 +139,8 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
 	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
 	     sizeof(struct pcibus_bussoft *)) {
 		printk(KERN_ERR
-		       "get_acpi_bussoft_ptr: Invalid vendor data "
-		       "length %d\n", vendor->byte_length);
+		       "%s: Invalid vendor data length %d\n",
+			__FUNCTION__, vendor->byte_length);
 		kfree(buffer.pointer);
 		return NULL;
 	}
@@ -143,34 +152,254 @@ sn_get_bussoft_ptr(struct pci_bus *bus)
 }
 
 /*
- * sn_acpi_bus_fixup
+ * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
+ *			    pointers from the vendor resource using the
+ *			    provided acpi handle, and copy the structures
+ *			    into the argument buffers.
  */
-void
-sn_acpi_bus_fixup(struct pci_bus *bus)
+static int
+sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
+		    struct sn_irq_info **sn_irq_info)
 {
-	struct pci_dev *pci_dev = NULL;
-	struct pcibus_bussoft *prom_bussoft_ptr;
-	extern void sn_common_bus_fixup(struct pci_bus *,
-					struct pcibus_bussoft *);
+	u64 addr;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+	struct sn_irq_info *irq_info, *irq_info_prom;
+	struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
+	struct acpi_resource *resource;
+	int ret = 0;
+	acpi_status status;
+	struct acpi_resource_vendor_typed *vendor;
 
-	if (!bus->parent) {	/* If root bus */
-		prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
-		if (prom_bussoft_ptr == NULL) {
+	/*
+	 * The pointer to this device's pcidev_info structure in
+	 * the PROM, is in the vendor resource.
+	 */
+	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
+					  &sn_uuid, &buffer);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR
+		       "%s: acpi_get_vendor_resource() failed (0x%x) for: ",
+		        __FUNCTION__, status);
+		acpi_ns_print_node_pathname(handle, NULL);
+		printk("\n");
+		return 1;
+	}
+
+	resource = buffer.pointer;
+	vendor = &resource->data.vendor_typed;
+	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
+	    sizeof(struct pci_devdev_info *)) {
+		printk(KERN_ERR
+		       "%s: Invalid vendor data length: %d for: ",
+		        __FUNCTION__, vendor->byte_length);
+		acpi_ns_print_node_pathname(handle, NULL);
+		printk("\n");
+		ret = 1;
+		goto exit;
+	}
+
+	pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
+	if (!pcidev_ptr)
+		panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);
+
+	memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
+	pcidev_prom_ptr = __va(addr);
+	memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));
+
+	/* Get the IRQ info */
+	irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+	if (!irq_info)
+		 panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);
+
+	if (pcidev_ptr->pdi_sn_irq_info) {
+		irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
+		memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
+	}
+
+	*pcidev_info = pcidev_ptr;
+	*sn_irq_info = irq_info;
+
+exit:
+	kfree(buffer.pointer);
+	return ret;
+}
+
+static unsigned int
+get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
+{
+	unsigned long adr;
+	acpi_handle child;
+	unsigned int devfn;
+	int function;
+	acpi_handle parent;
+	int slot;
+	acpi_status status;
+
+	/*
+	 * Do an upward search to find the root bus device, and
+	 * obtain the host devfn from the previous child device.
+	 */
+	child = device_handle;
+	while (child) {
+		status = acpi_get_parent(child, &parent);
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_ERR "%s: acpi_get_parent() failed "
+			       "(0x%x) for: ", __FUNCTION__, status);
+			acpi_ns_print_node_pathname(child, NULL);
+			printk("\n");
+			panic("%s: Unable to find host devfn\n", __FUNCTION__);
+		}
+		if (parent == rootbus_handle)
+			break;
+		child = parent;
+	}
+	if (!child) {
+		printk(KERN_ERR "%s: Unable to find root bus for: ",
+		       __FUNCTION__);
+		acpi_ns_print_node_pathname(device_handle, NULL);
+		printk("\n");
+		BUG();
+	}
+
+	status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
+	if (ACPI_FAILURE(status)) {
+		printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ",
+		       __FUNCTION__, status);
+		acpi_ns_print_node_pathname(child, NULL);
+		printk("\n");
+		panic("%s: Unable to find host devfn\n", __FUNCTION__);
+	}
+
+	slot = (adr >> 16) & 0xffff;
+       	function = adr & 0xffff;
+	devfn = PCI_DEVFN(slot, function);
+	return devfn;
+}
+
+/*
+ * find_matching_device - Callback routine to find the ACPI device
+ *			  that matches up with our pci_dev device.
+ *			  Matching is done on bus number and devfn.
+ *			  To find the bus number for a particular
+ *			  ACPI device, we must look at the _BBN method
+ *			  of its parent.
+ */
+static acpi_status
+find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
+{
+	unsigned long bbn = -1;
+	unsigned long adr;
+	acpi_handle parent = NULL;
+	acpi_status status;
+	unsigned int devfn;
+	int function;
+	int slot;
+	struct sn_pcidev_match *info = context;
+
+        status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
+                                       &adr);
+        if (ACPI_SUCCESS(status)) {
+		status = acpi_get_parent(handle, &parent);
+		if (ACPI_FAILURE(status)) {
 			printk(KERN_ERR
-			       "sn_pci_fixup_bus: 0x%04x:0x%02x Unable to "
-			       "obtain prom_bussoft_ptr\n",
-			       pci_domain_nr(bus), bus->number);
-			return;
+			       "%s: acpi_get_parent() failed (0x%x) for: ",
+		       		__FUNCTION__, status);
+			acpi_ns_print_node_pathname(handle, NULL);
+			printk("\n");
+			return AE_OK;
+		}
+		status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
+					       NULL, &bbn);
+		if (ACPI_FAILURE(status)) {
+			printk(KERN_ERR
+			  "%s: Failed to find _BBN in parent of: ",
+		       		__FUNCTION__);
+			acpi_ns_print_node_pathname(handle, NULL);
+			printk("\n");
+			return AE_OK;
+		}
+
+                slot = (adr >> 16) & 0xffff;
+                function = adr & 0xffff;
+                devfn = PCI_DEVFN(slot, function);
+                if ((info->devfn == devfn) && (info->bus == bbn)) {
+			/* We have a match! */
+			info->handle = handle;
+			return 1;
 		}
-		sn_common_bus_fixup(bus, prom_bussoft_ptr);
 	}
-	list_for_each_entry(pci_dev, &bus->devices, bus_list) {
-		sn_pci_fixup_slot(pci_dev);
+	return AE_OK;
+}
+
+/*
+ * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
+ *			     device matching the specified pci_dev,
+ *			     and return the pcidev info and irq info.
+ */
+int
+sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
+			struct sn_irq_info **sn_irq_info)
+{
+	unsigned int host_devfn;
+	struct sn_pcidev_match pcidev_match;
+	acpi_handle rootbus_handle;
+	unsigned long segment;
+	acpi_status status;
+
+	rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
+        status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
+                                       &segment);
+        if (ACPI_SUCCESS(status)) {
+		if (segment != pci_domain_nr(dev)) {
+			printk(KERN_ERR
+			       "%s: Segment number mismatch, 0x%lx vs 0x%x for: ",
+			       __FUNCTION__, segment, pci_domain_nr(dev));
+			acpi_ns_print_node_pathname(rootbus_handle, NULL);
+			printk("\n");
+			return 1;
+		}
+	} else {
+		printk(KERN_ERR "%s: Unable to get __SEG from: ",
+		       __FUNCTION__);
+		acpi_ns_print_node_pathname(rootbus_handle, NULL);
+		printk("\n");
+		return 1;
 	}
+
+	/*
+	 * We want to search all devices in this segment/domain
+	 * of the ACPI namespace for the matching ACPI device,
+	 * which holds the pcidev_info pointer in its vendor resource.
+	 */
+	pcidev_match.bus = dev->bus->number;
+	pcidev_match.devfn = dev->devfn;
+	pcidev_match.handle = NULL;
+
+	acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
+			    find_matching_device, &pcidev_match, NULL);
+
+	if (!pcidev_match.handle) {
+		printk(KERN_ERR
+		       "%s: Could not find matching ACPI device for %s.\n",
+		       __FUNCTION__, pci_name(dev));
+		return 1;
+	}
+
+	if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
+		return 1;
+
+	/* Build up the pcidev_info.pdi_slot_host_handle */
+	host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
+	(*pcidev_info)->pdi_slot_host_handle =
+			((unsigned long) pci_domain_nr(dev) << 40) |
+					/* bus == 0 */
+					host_devfn;
+	return 0;
 }
 
 /*
- * sn_acpi_slot_fixup - Perform any SN specific slot fixup.
+ * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
+ *			Perform any SN specific slot fixup.
  *			At present there does not appear to be
  *			any generic way to handle a ROM image
  *			that has been shadowed by the PROM, so
@@ -179,11 +408,18 @@ sn_acpi_bus_fixup(struct pci_bus *bus)
  */
 
 void
-sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
+sn_acpi_slot_fixup(struct pci_dev *dev)
 {
 	void __iomem *addr;
+	struct pcidev_info *pcidev_info = NULL;
+	struct sn_irq_info *sn_irq_info = NULL;
 	size_t size;
 
+	if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
+		panic("%s:  Failure obtaining pcidev_info for %s\n",
+		      __FUNCTION__, pci_name(dev));
+	}
+
 	if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
 		/*
 		 * A valid ROM image exists and has been shadowed by the
@@ -200,8 +436,11 @@ sn_acpi_slot_fixup(struct pci_dev *dev, 
 						(unsigned long) addr + size;
 		dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
 	}
+	sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
 }
 
+EXPORT_SYMBOL(sn_acpi_slot_fixup);
+
 static struct acpi_driver acpi_sn_hubdev_driver = {
 	.name = "SGI HUBDEV Driver",
 	.ids = "SGIHUB,SGITIO",
@@ -212,6 +451,33 @@ static struct acpi_driver acpi_sn_hubdev
 
 
 /*
+ * sn_acpi_bus_fixup -  Perform SN specific setup of software structs
+ *			(pcibus_bussoft, pcidev_info) and hardware
+ *			registers, for the specified bus and devices under it.
+ */
+void
+sn_acpi_bus_fixup(struct pci_bus *bus)
+{
+	struct pci_dev *pci_dev = NULL;
+	struct pcibus_bussoft *prom_bussoft_ptr;
+
+	if (!bus->parent) {	/* If root bus */
+		prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
+		if (prom_bussoft_ptr == NULL) {
+			printk(KERN_ERR
+			       "%s: 0x%04x:0x%02x Unable to "
+			       "obtain prom_bussoft_ptr\n",
+			       __FUNCTION__, pci_domain_nr(bus), bus->number);
+			return;
+		}
+		sn_common_bus_fixup(bus, prom_bussoft_ptr);
+	}
+	list_for_each_entry(pci_dev, &bus->devices, bus_list) {
+		sn_acpi_slot_fixup(pci_dev);
+	}
+}
+
+/*
  * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
  *		     nodes and root buses in the DSDT. As a result, bus scanning
  *		     will be initiated by the Linux ACPI code.
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_common.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_common.c	2007-06-19 12:42:16.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_common.c	2007-06-19 12:42:16.000000000 -0500
@@ -26,14 +26,10 @@
 #include <linux/acpi.h>
 #include <asm/sn/sn2/sn_hwperf.h>
 #include <asm/sn/acpi.h>
+#include "acpi/acglobal.h"
 
 extern void sn_init_cpei_timer(void);
 extern void register_sn_procfs(void);
-extern void sn_acpi_bus_fixup(struct pci_bus *);
-extern void sn_bus_fixup(struct pci_bus *);
-extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *);
-extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *);
-extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64);
 extern void sn_io_acpi_init(void);
 extern void sn_io_init(void);
 
@@ -48,6 +44,9 @@ struct sysdata_el {
 
 int sn_ioif_inited;		/* SN I/O infrastructure initialized? */
 
+int sn_acpi_rev;		/* SN ACPI revision */
+EXPORT_SYMBOL_GPL(sn_acpi_rev);
+
 struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES];	/* indexed by asic type */
 
 /*
@@ -99,25 +98,6 @@ sal_get_device_dmaflush_list(u64 nasid, 
 }
 
 /*
- * Retrieve the pci device information given the bus and device|function number.
- */
-static inline u64
-sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
-		    u64 sn_irq_info)
-{
-	struct ia64_sal_retval ret_stuff;
-	ret_stuff.status = 0;
-	ret_stuff.v0 = 0;
-
-	SAL_CALL_NOLOCK(ret_stuff,
-			(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
-			(u64) segment, (u64) bus_number, (u64) devfn,
-			(u64) pci_dev,
-			sn_irq_info, 0, 0);
-	return ret_stuff.v0;
-}
-
-/*
  * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
  *			  device.
  */
@@ -249,47 +229,22 @@ void sn_pci_unfixup_slot(struct pci_dev 
 }
 
 /*
- * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent
- *			 with the Linux PCI abstraction layer. Resources
- *			 acquired from our PCI provider include PIO maps
- *			 to BAR space and interrupt objects.
+ * sn_pci_fixup_slot()
  */
-void sn_pci_fixup_slot(struct pci_dev *dev)
+void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
+		       struct sn_irq_info *sn_irq_info)
 {
 	int segment = pci_domain_nr(dev->bus);
-	int status = 0;
 	struct pcibus_bussoft *bs;
  	struct pci_bus *host_pci_bus;
  	struct pci_dev *host_pci_dev;
-	struct pcidev_info *pcidev_info;
- 	struct sn_irq_info *sn_irq_info;
  	unsigned int bus_no, devfn;
 
 	pci_dev_get(dev); /* for the sysdata pointer */
-	pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
-	if (!pcidev_info)
-		BUG();		/* Cannot afford to run out of memory */
-
-	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
-	if (!sn_irq_info)
-		BUG();		/* Cannot afford to run out of memory */
-
-	/* Call to retrieve pci device information needed by kernel. */
-	status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number,
-				     dev->devfn,
-				     (u64) __pa(pcidev_info),
-				     (u64) __pa(sn_irq_info));
-	if (status)
-		BUG(); /* Cannot get platform pci device information */
 
 	/* Add pcidev_info to list in pci_controller.platform_data */
 	list_add_tail(&pcidev_info->pdi_list,
 		      &(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
-
-	if (SN_ACPI_BASE_SUPPORT())
-		sn_acpi_slot_fixup(dev, pcidev_info);
-	else
-		sn_more_slot_fixup(dev, pcidev_info);
 	/*
 	 * Using the PROMs values for the PCI host bus, get the Linux
  	 * PCI host_pci_dev struct and set up host bus linkages
@@ -489,11 +444,6 @@ void sn_generate_path(struct pci_bus *pc
 			sprintf(address, "%s^%d", address, geo_slot(geoid));
 }
 
-/*
- * sn_pci_fixup_bus() - Perform SN specific setup of software structs
- *			(pcibus_bussoft, pcidev_info) and hardware
- *			registers, for the specified bus and devices under it.
- */
 void __devinit
 sn_pci_fixup_bus(struct pci_bus *bus)
 {
@@ -519,6 +469,9 @@ sn_io_early_init(void)
 	if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
 		return 0;
 
+	/* we set the acpi revision to that of the DSDT table OEM rev. */
+	sn_acpi_rev = acpi_gbl_DSDT->oem_revision;
+
 	/*
 	 * prime sn_pci_provider[].  Individial provider init routines will
 	 * override their respective default entries.
@@ -605,7 +558,6 @@ sn_io_late_init(void)
 
 fs_initcall(sn_io_late_init);
 
-EXPORT_SYMBOL(sn_pci_fixup_slot);
 EXPORT_SYMBOL(sn_pci_unfixup_slot);
 EXPORT_SYMBOL(sn_bus_store_sysdata);
 EXPORT_SYMBOL(sn_bus_free_sysdata);
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_init.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_init.c	2007-06-19 12:42:16.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_init.c	2007-06-19 12:42:16.000000000 -0500
@@ -56,6 +56,25 @@ static inline u64 sal_get_pcibus_info(u6
 	return ret_stuff.v0;
 }
 
+/*
+ * Retrieve the pci device information given the bus and device|function number.
+ */
+static inline u64
+sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
+		    u64 sn_irq_info)
+{
+	struct ia64_sal_retval ret_stuff;
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+
+	SAL_CALL_NOLOCK(ret_stuff,
+			(u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
+			(u64) segment, (u64) bus_number, (u64) devfn,
+			(u64) pci_dev,
+			sn_irq_info, 0, 0);
+	return ret_stuff.v0;
+}
+
 
 /*
  * sn_fixup_ionodes() - This routine initializes the HUB data structure for
@@ -172,18 +191,40 @@ sn_pci_window_fixup(struct pci_dev *dev,
 }
 
 /*
- * sn_more_slot_fixup() - We are not running with an ACPI capable PROM,
+ * sn_io_slot_fixup() -   We are not running with an ACPI capable PROM,
  *			  and need to convert the pci_dev->resource
  *			  'start' and 'end' addresses to mapped addresses,
  *			  and setup the pci_controller->window array entries.
  */
 void
-sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
+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;
+	int status;
+
+	pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
+	if (!pcidev_info)
+		panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);
+
+	sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
+	if (!sn_irq_info)
+		panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);
+
+	/* Call to retrieve pci device information needed by kernel. */
+	status = sal_get_pcidev_info((u64) pci_domain_nr(dev),
+		(u64) dev->bus->number,
+		dev->devfn,
+		(u64) __pa(pcidev_info),
+		(u64) __pa(sn_irq_info));
+
+	if (status)
+		BUG(); /* Cannot get platform pci device information */
+
 
 	/* Copy over PIO Mapped Addresses */
 	for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
@@ -219,8 +260,12 @@ sn_more_slot_fixup(struct pci_dev *dev, 
 	 */
 	if (count > 0)
 		sn_pci_window_fixup(dev, count, pci_addrs);
+
+	sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
 }
 
+EXPORT_SYMBOL(sn_io_slot_fixup);
+
 /*
  * sn_pci_controller_fixup() - This routine sets up a bus's resources
  *			       consistent with the Linux PCI abstraction layer.
@@ -272,9 +317,6 @@ sn_bus_fixup(struct pci_bus *bus)
 {
 	struct pci_dev *pci_dev = NULL;
 	struct pcibus_bussoft *prom_bussoft_ptr;
-	extern void sn_common_bus_fixup(struct pci_bus *,
-					struct pcibus_bussoft *);
-
 
 	if (!bus->parent) {  /* If root bus */
 		prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
@@ -291,7 +333,7 @@ sn_bus_fixup(struct pci_bus *bus)
 					   prom_bussoft_ptr->bs_legacy_mem);
         }
         list_for_each_entry(pci_dev, &bus->devices, bus_list) {
-                sn_pci_fixup_slot(pci_dev);
+                sn_io_slot_fixup(pci_dev);
         }
 
 }
Index: 2.6.18-28.el5/arch/ia64/sn/pci/pcibr/pcibr_provider.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2007-06-19 11:40:40.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/pci/pcibr/pcibr_provider.c	2007-06-19 15:20:38.000000000 -0500
@@ -38,6 +38,26 @@ sal_pcibr_slot_enable(struct pcibus_info
 }
 
 int
+sal_pcibr_slot_enable2(struct pcibus_info *soft, int device, void *resp,
+                      char **ssdt)
+{
+	struct ia64_sal_retval ret_stuff;
+	u64 busnum;
+	u64 segment;
+
+	ret_stuff.status = 0;
+	ret_stuff.v0 = 0;
+
+	segment = soft->pbi_buscommon.bs_persist_segment;
+	busnum = soft->pbi_buscommon.bs_persist_busnum;
+	SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
+			busnum, (u64) device, (u64) resp, (u64)ia64_tpa(ssdt),
+			0, 0);
+
+	return (int)ret_stuff.v0;
+}
+
+int
 sal_pcibr_slot_disable(struct pcibus_info *soft, int device, int action,
 		       void *resp)
 {
@@ -255,5 +275,6 @@ pcibr_init_provider(void)
 }
 
 EXPORT_SYMBOL_GPL(sal_pcibr_slot_enable);
+EXPORT_SYMBOL_GPL(sal_pcibr_slot_enable2);
 EXPORT_SYMBOL_GPL(sal_pcibr_slot_disable);
 EXPORT_SYMBOL_GPL(sn_ioboard_to_pci_bus);
Index: 2.6.18-28.el5/include/asm-ia64/sn/acpi.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/sn/acpi.h	2007-06-19 11:40:40.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/sn/acpi.h	2007-06-19 12:42:16.000000000 -0500
@@ -9,8 +9,7 @@
 #ifndef _ASM_IA64_SN_ACPI_H
 #define _ASM_IA64_SN_ACPI_H
 
-#include "acpi/acglobal.h"
-
-#define SN_ACPI_BASE_SUPPORT()   (acpi_gbl_DSDT->oem_revision >= 0x20101)
+extern int sn_acpi_rev;
+#define SN_ACPI_BASE_SUPPORT()   (sn_acpi_rev >= 0x20101)
 
 #endif /* _ASM_IA64_SN_ACPI_H */
Index: 2.6.18-28.el5/include/asm-ia64/sn/pcibr_provider.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/sn/pcibr_provider.h	2007-06-19 11:40:40.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/sn/pcibr_provider.h	2007-06-19 15:24:18.000000000 -0500
@@ -143,6 +143,8 @@ extern void 		pcibr_ate_free(struct pcib
 extern void 		ate_write(struct pcibus_info *, int, int, u64);
 extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device,
 				 void *resp);
+extern int sal_pcibr_slot_enable2(struct pcibus_info *soft, int device,
+				 void *resp, char **ssdt);
 extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device,
 				  int action, void *resp);
 extern u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus);
Index: 2.6.18-28.el5/include/asm-ia64/sn/pcidev.h
===================================================================
--- 2.6.18-28.el5.orig/include/asm-ia64/sn/pcidev.h	2007-06-19 11:40:40.000000000 -0500
+++ 2.6.18-28.el5/include/asm-ia64/sn/pcidev.h	2007-06-19 12:42:16.000000000 -0500
@@ -70,10 +70,16 @@ extern void sn_irq_fixup(struct pci_dev 
 			 struct sn_irq_info *sn_irq_info);
 extern void sn_irq_unfixup(struct pci_dev *pci_dev);
 extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *);
+extern void sn_bus_fixup(struct pci_bus *);
+extern void sn_acpi_bus_fixup(struct pci_bus *);
+extern void sn_common_bus_fixup(struct pci_bus *, struct pcibus_bussoft *);
 extern void sn_bus_store_sysdata(struct pci_dev *dev);
 extern void sn_bus_free_sysdata(void);
 extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
-extern void sn_pci_fixup_slot(struct pci_dev *dev);
+extern void sn_io_slot_fixup(struct pci_dev *);
+extern void sn_acpi_slot_fixup(struct pci_dev *);
+extern void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *,
+			      struct sn_irq_info *);
 extern void sn_pci_unfixup_slot(struct pci_dev *dev);
 extern void sn_irq_lh_init(void);
 #endif				/* _ASM_IA64_SN_PCI_PCIDEV_H */


http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3e643e77a929202455a0cc868c2030a5ba8d1371

Altix: Add ACPI SSDT PCI device support (hotplug)

Support for dynamic loading and unloading of ACPI SSDT tables upon slot
hotplugs and unplugs.

On SN platforms, we now represent every populated root bus slot with a single
ACPI SSDT table containing info for every device and PPB attached to the slot.
 These SSDTs are generated by the prom at initial boot and hotplug time.  The
info in these SSDT tables is used by the SN kernel IO "fixup" code (which is
called at boot and hotplug time).

On hotplugs (i.e.  enable_slot()), if running with an ACPI capable prom,
attempt to obtain a new ACPI SSDT table for the slot being hotplugged.  If
successful, add the table to the ACPI namespace (acpi_load_table()) and then
walk the new devices and add them to the ACPI infrastructure (acpi_bus_add()).

On hot unplugs (i.e.  disable_slot()), if running with an ACPI capable prom,
attempt to remove the SSDT table associated with the slot from the ACPI
namespace (acpi_unload_table_id()) and infastructure (acpi_bus_trim()).


 A bug was fixed where the sgi hotplug driver was removing
 the slot's SSDT table from the ACPI namespace a bit too early in
 disable_slot(). Also, we now call acpi_bus_start() subsequent
 to acpi_bus_add().

---
 drivers/pci/hotplug/sgi_hotplug.c |  155 ++++++++++++++++++++++++++++++++++++--
 1 file changed, 148 insertions(+), 7 deletions(-)
---

Index: 2.6.18-28.el5/drivers/pci/hotplug/sgi_hotplug.c
===================================================================
--- 2.6.18-28.el5.orig/drivers/pci/hotplug/sgi_hotplug.c	2007-06-19 15:18:31.000000000 -0500
+++ 2.6.18-28.el5/drivers/pci/hotplug/sgi_hotplug.c	2007-06-19 15:21:36.000000000 -0500
@@ -27,6 +27,8 @@
 #include <asm/sn/sn_feature_sets.h>
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/types.h>
+#include <linux/acpi.h>
+#include <asm/sn/acpi.h>
 
 #include "../pci.h"
 #include "pci_hotplug.h"
@@ -35,14 +37,17 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("SGI (prarit@sgi.com, dickie@sgi.com, habeck@sgi.com)");
 MODULE_DESCRIPTION("SGI Altix Hot Plug PCI Controller Driver");
 
-#define PCIIO_ASIC_TYPE_TIOCA		4
+
+/* SAL call error codes. Keep in sync with prom header io/include/pcibr.h */
 #define PCI_SLOT_ALREADY_UP		2	/* slot already up */
 #define PCI_SLOT_ALREADY_DOWN		3	/* slot already down */
 #define PCI_L1_ERR			7	/* L1 console command error */
 #define PCI_EMPTY_33MHZ			15	/* empty 33 MHz bus */
+
+
+#define PCIIO_ASIC_TYPE_TIOCA		4
 #define PCI_L1_QSIZE			128	/* our L1 message buffer size */
 #define SN_MAX_HP_SLOTS			32	/* max hotplug slots */
-#define SGI_HOTPLUG_PROM_REV		0x0430	/* Min. required PROM version */
 #define SN_SLOT_NAME_SIZE		33	/* size of name string */
 
 /* internal list head */
@@ -227,7 +232,7 @@ static void sn_bus_free_data(struct pci_
 }
 
 static int sn_slot_enable(struct hotplug_slot *bss_hotplug_slot,
-			  int device_num)
+			  int device_num, char **ssdt)
 {
 	struct slot *slot = bss_hotplug_slot->private;
 	struct pcibus_info *pcibus_info;
@@ -240,7 +245,8 @@ static int sn_slot_enable(struct hotplug
 	 * Power-on and initialize the slot in the SN
 	 * PCI infrastructure.
 	 */
-	rc = sal_pcibr_slot_enable(pcibus_info, device_num, &resp);
+	rc = sal_pcibr_slot_enable2(pcibus_info, device_num, &resp, ssdt);
+
 
 	if (rc == PCI_SLOT_ALREADY_UP) {
 		dev_dbg(slot->pci_bus->self, "is already active\n");
@@ -335,6 +341,7 @@ static int enable_slot(struct hotplug_sl
 	int func, num_funcs;
 	int new_ppb = 0;
 	int rc;
+	char *ssdt = NULL;
 	void pcibios_fixup_device_resources(struct pci_dev *);
 
 	/* Serialize the Linux PCI infrastructure */
@@ -342,14 +349,29 @@ static int enable_slot(struct hotplug_sl
 
 	/*
 	 * Power-on and initialize the slot in the SN
-	 * PCI infrastructure.
+	 * PCI infrastructure. Also, retrieve the ACPI SSDT
+	 * table for the slot (if ACPI capable PROM).
 	 */
-	rc = sn_slot_enable(bss_hotplug_slot, slot->device_num);
+	rc = sn_slot_enable(bss_hotplug_slot, slot->device_num, &ssdt);
 	if (rc) {
 		mutex_unlock(&sn_hotplug_mutex);
 		return rc;
 	}
 
+	if (ssdt)
+		ssdt = __va(ssdt);
+	/* Add the new SSDT for the slot to the ACPI namespace */
+	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
+		acpi_status ret;
+
+		ret = acpi_load_table((struct acpi_table_header *)ssdt);
+		if (ACPI_FAILURE(ret)) {
+			printk(KERN_ERR "%s: acpi_load_table failed (0x%x)\n",
+			       __FUNCTION__, ret);
+			/* try to continue on */
+		}
+	}
+
 	num_funcs = pci_scan_slot(slot->pci_bus,
 				  PCI_DEVFN(slot->device_num + 1, 0));
 	if (!num_funcs) {
@@ -374,7 +396,10 @@ static int enable_slot(struct hotplug_sl
 			 * pdi_host_pcidev_info).
 			 */
 			pcibios_fixup_device_resources(dev);
-			sn_pci_fixup_slot(dev);
+			if (SN_ACPI_BASE_SUPPORT())
+				sn_acpi_slot_fixup(dev);
+			else
+				sn_io_slot_fixup(dev);
 			if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
 				unsigned char sec_bus;
 				pci_read_config_byte(dev, PCI_SECONDARY_BUS,
@@ -388,6 +413,63 @@ static int enable_slot(struct hotplug_sl
 		}
 	}
 
+	/*
+	 * Add the slot's devices to the ACPI infrastructure */
+	if (SN_ACPI_BASE_SUPPORT() && ssdt) {
+		unsigned long adr;
+		struct acpi_device *pdevice;
+		struct acpi_device *device;
+		acpi_handle phandle;
+		acpi_handle chandle = NULL;
+		acpi_handle rethandle;
+		acpi_status ret;
+
+		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
+
+		if (acpi_bus_get_device(phandle, &pdevice)) {
+			dev_dbg(slot->pci_bus->self,
+				"no parent device, assuming NULL\n");
+			pdevice = NULL;
+		}
+
+		/*
+		 * Walk the rootbus node's immediate children looking for
+		 * the slot's device node(s). There can be more than
+		 * one for multifunction devices.
+		 */
+		for (;;) {
+			rethandle = NULL;
+			ret = acpi_get_next_object(ACPI_TYPE_DEVICE,
+						   phandle, chandle,
+						   &rethandle);
+
+			if (ret == AE_NOT_FOUND || rethandle == NULL)
+				break;
+
+			chandle = rethandle;
+
+			ret = acpi_evaluate_integer(chandle, METHOD_NAME__ADR,
+						    NULL, &adr);
+
+			if (ACPI_SUCCESS(ret) &&
+			    (adr>>16) == (slot->device_num + 1)) {
+
+				ret = acpi_bus_add(&device, pdevice, chandle,
+						   ACPI_BUS_TYPE_DEVICE);
+				if (ACPI_FAILURE(ret)) {
+					printk(KERN_ERR "%s: acpi_bus_add "
+					       "failed (0x%x) for slot %d "
+					       "func %d\n", __FUNCTION__,
+					       ret, (int)(adr>>16),
+					       (int)(adr&0xffff));
+					/* try to continue on */
+				} else {
+					acpi_bus_start(device);
+				}
+			}
+		}
+	}
+
 	/* Call the driver for the new device */
 	pci_bus_add_devices(slot->pci_bus);
 	/* Call the drivers for the new devices subordinate to PPB */
@@ -412,6 +494,7 @@ static int disable_slot(struct hotplug_s
 	struct pci_dev *dev;
 	int func;
 	int rc;
+	acpi_owner_id ssdt_id = 0;
 
 	/* Acquire update access to the bus */
 	mutex_lock(&sn_hotplug_mutex);
@@ -422,6 +505,52 @@ static int disable_slot(struct hotplug_s
 	if (rc)
 		goto leaving;
 
+	/* free the ACPI resources for the slot */
+	if (SN_ACPI_BASE_SUPPORT() &&
+            PCI_CONTROLLER(slot->pci_bus)->acpi_handle) {
+		unsigned long adr;
+		struct acpi_device *device;
+		acpi_handle phandle;
+		acpi_handle chandle = NULL;
+		acpi_handle rethandle;
+		acpi_status ret;
+
+		/* Get the rootbus node pointer */
+		phandle = PCI_CONTROLLER(slot->pci_bus)->acpi_handle;
+
+		/*
+		 * Walk the rootbus node's immediate children looking for
+		 * the slot's device node(s). There can be more than
+		 * one for multifunction devices.
+		 */
+		for (;;) {
+			rethandle = NULL;
+			ret = acpi_get_next_object(ACPI_TYPE_DEVICE,
+						   phandle, chandle,
+						   &rethandle);
+
+			if (ret == AE_NOT_FOUND || rethandle == NULL)
+				break;
+
+			chandle = rethandle;
+
+			ret = acpi_evaluate_integer(chandle,
+						    METHOD_NAME__ADR,
+						    NULL, &adr);
+			if (ACPI_SUCCESS(ret) &&
+			    (adr>>16) == (slot->device_num + 1)) {
+				/* retain the owner id */
+				acpi_get_id(chandle, &ssdt_id);
+
+				ret = acpi_bus_get_device(chandle,
+							  &device);
+				if (ACPI_SUCCESS(ret))
+					acpi_bus_trim(device, 1);
+			}
+		}
+
+	}
+
 	/* Free the SN resources assigned to the Linux device.*/
 	for (func = 0; func < 8;  func++) {
 		dev = pci_get_slot(slot->pci_bus,
@@ -434,6 +563,18 @@ static int disable_slot(struct hotplug_s
 		}
 	}
 
+	/* Remove the SSDT for the slot from the ACPI namespace */
+	if (SN_ACPI_BASE_SUPPORT() && ssdt_id) {
+		acpi_status ret;
+		ret = acpi_unload_table_id(ACPI_TABLE_ID_SSDT, ssdt_id);
+		if (ACPI_FAILURE(ret)) {
+			printk(KERN_ERR "%s: acpi_unload_table_id "
+			       "failed (0x%x) for id %d\n",
+			       __FUNCTION__, ret, ssdt_id);
+			/* try to continue on */
+		}
+	}
+
 	/* free the collected sysdata pointers */
 	sn_bus_free_sysdata();
 


http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=0f0fe1a08aa421266060ac67e50453a06d9ceb63

ACPI: Add support for acpi_load_table/acpi_unload_table_id

Make acpi_load_table() available for use by removing it from the #ifdef
ACPI_FUTURE_USAGE.

Also add a new routine used to unload an ACPI table of a given type and "id" -
acpi_unload_table_id().  The implementation of this new routine was almost a
direct copy of existing routine acpi_unload_table() - only difference being
that it only removes a specific table id instead of ALL tables of a given
type.  The SN hotplug driver (sgi_hotplug.c) now uses both of these interfaces
to dynamically load and unload SSDT ACPI tables.

Also, a few other ACPI routines now used by the SN hotplug driver are exported
(since the driver can be a loadable module):

 acpi_ns_map_handle_to_node
 acpi_ns_convert_entry_to_handle
 acpi_ns_get_next_node

---
 drivers/acpi/namespace/nsxfobj.c |   44 +++++++++++++++++++++++++++++++
 drivers/acpi/tables/tbxface.c    |   54 ++++++++++++++++++++++++++++++++++++++-
 include/acpi/acpixf.h            |    7 +++--
 3 files changed, 102 insertions(+), 3 deletions(-)
---

Index: 2.6.18-28.el5/drivers/acpi/namespace/nsxfobj.c
===================================================================
--- 2.6.18-28.el5.orig/drivers/acpi/namespace/nsxfobj.c	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/drivers/acpi/namespace/nsxfobj.c	2007-06-18 16:20:07.000000000 -0500
@@ -50,6 +50,50 @@ ACPI_MODULE_NAME("nsxfobj")
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_get_id
+ *
+ * PARAMETERS:  Handle          - Handle of object whose id is desired
+ *              ret_id          - Where the id will be placed
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This routine returns the owner id associated with a handle
+ *
+ ******************************************************************************/
+acpi_status acpi_get_id(acpi_handle handle, acpi_owner_id * ret_id)
+{
+	struct acpi_namespace_node *node;
+	acpi_status status;
+
+	/* Parameter Validation */
+
+	if (!ret_id) {
+		return (AE_BAD_PARAMETER);
+	}
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
+	if (ACPI_FAILURE(status)) {
+		return (status);
+	}
+
+	/* Convert and validate the handle */
+
+	node = acpi_ns_map_handle_to_node(handle);
+	if (!node) {
+		(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+		return (AE_BAD_PARAMETER);
+	}
+
+	*ret_id = node->owner_id;
+
+	status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
+	return (status);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_get_id)
+
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_get_type
  *
  * PARAMETERS:  Handle          - Handle of object whose type is desired
Index: 2.6.18-28.el5/drivers/acpi/tables/tbxface.c
===================================================================
--- 2.6.18-28.el5.orig/drivers/acpi/tables/tbxface.c	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/drivers/acpi/tables/tbxface.c	2007-06-18 16:20:07.000000000 -0500
@@ -123,7 +123,6 @@ acpi_status acpi_load_tables(void)
 
 ACPI_EXPORT_SYMBOL(acpi_load_tables)
 
-#ifdef ACPI_FUTURE_USAGE
 /*******************************************************************************
  *
  * FUNCTION:    acpi_load_table
@@ -221,6 +220,59 @@ ACPI_EXPORT_SYMBOL(acpi_load_table)
 
 /*******************************************************************************
  *
+ * FUNCTION:    acpi_unload_table_id
+ *
+ * PARAMETERS:  table_type    - Type of table to be unloaded
+ *              id            - Owner ID of the table to be removed.
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: This routine is used to force the unload of a table (by id)
+ *
+ ******************************************************************************/
+acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id)
+{
+	struct acpi_table_desc *table_desc;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE(acpi_unload_table);
+
+	/* Parameter validation */
+	if (table_type > ACPI_TABLE_ID_MAX)
+		return_ACPI_STATUS(AE_BAD_PARAMETER);
+
+	/* Find table from the requested type list */
+	table_desc = acpi_gbl_table_lists[table_type].next;
+	while (table_desc && table_desc->owner_id != id)
+		table_desc = table_desc->next;
+
+	if (!table_desc)
+		return_ACPI_STATUS(AE_NOT_EXIST);
+
+	/*
+	 * Delete all namespace objects owned by this table. Note that these
+	 * objects can appear anywhere in the namespace by virtue of the AML
+	 * "Scope" operator. Thus, we need to track ownership by an ID, not
+	 * simply a position within the hierarchy
+	 */
+	acpi_ns_delete_namespace_by_owner(table_desc->owner_id);
+
+	status = acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
+	if (ACPI_FAILURE(status))
+		return_ACPI_STATUS(status);
+
+	(void)acpi_tb_uninstall_table(table_desc);
+
+	(void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
+
+	return_ACPI_STATUS(AE_OK);
+}
+
+ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
+
+#ifdef ACPI_FUTURE_USAGE
+/*******************************************************************************
+ *
  * FUNCTION:    acpi_unload_table
  *
  * PARAMETERS:  table_type    - Type of table to be unloaded
Index: 2.6.18-28.el5/include/acpi/acpixf.h
===================================================================
--- 2.6.18-28.el5.orig/include/acpi/acpixf.h	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/include/acpi/acpixf.h	2007-06-18 16:20:07.000000000 -0500
@@ -97,11 +97,12 @@ acpi_find_root_pointer(u32 flags, struct
 
 acpi_status acpi_load_tables(void);
 
-#ifdef ACPI_FUTURE_USAGE
 acpi_status acpi_load_table(struct acpi_table_header *table_ptr);
 
-acpi_status acpi_unload_table(acpi_table_type table_type);
+acpi_status acpi_unload_table_id(acpi_table_type table_type, acpi_owner_id id);
 
+#ifdef ACPI_FUTURE_USAGE
+acpi_status acpi_unload_table(acpi_table_type table_type);
 acpi_status
 acpi_get_table_header(acpi_table_type table_type,
 		      u32 instance, struct acpi_table_header *out_table_header);
@@ -180,6 +181,8 @@ acpi_get_next_object(acpi_object_type ty
 
 acpi_status acpi_get_type(acpi_handle object, acpi_object_type * out_type);
 
+acpi_status acpi_get_id(acpi_handle object, acpi_owner_id * out_type);
+
 acpi_status acpi_get_parent(acpi_handle object, acpi_handle * out_handle);
 
 /*


http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=3948ec9406f9a60a43d63f23f6f5284db6529b9c

ACPI: Altix: ACPI _PRT support

Provide ACPI _PRT support for SN Altix systems.

The SN Altix platform does not conform to the
IOSAPIC IRQ routing model, so a new acpi_irq_model
(ACPI_IRQ_MODEL_PLATFORM) has been defined. The SN
platform specific code sets acpi_irq_model to
this new value, and keys off of it in acpi_register_gsi()
to avoid the iosapic code path.

---
 arch/ia64/kernel/acpi.c            |    3 +++
 arch/ia64/sn/kernel/io_acpi_init.c |    3 +++
 drivers/acpi/bus.c                 |    3 +++
 include/linux/acpi.h               |    1 +
 4 files changed, 10 insertions(+)
---

Index: 2.6.18-28.el5/arch/ia64/kernel/acpi.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/kernel/acpi.c	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/kernel/acpi.c	2007-06-18 16:20:10.000000000 -0500
@@ -593,6 +593,9 @@ void __init acpi_numa_arch_fixup(void)
  */
 int acpi_register_gsi(u32 gsi, int triggering, int polarity)
 {
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+		return gsi;
+
 	if (has_8259 && gsi < 16)
 		return isa_irq_to_vector(gsi);
 
Index: 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-18 16:20:01.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/sn/kernel/io_acpi_init.c	2007-06-18 16:20:10.000000000 -0500
@@ -489,6 +489,9 @@ sn_io_acpi_init(void)
 	u64 result;
 	s64 status;
 
+	/* SN Altix does not follow the IOSAPIC IRQ routing model */
+	acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
+
 	acpi_bus_register_driver(&acpi_sn_hubdev_driver);
 	status = sal_ioif_init(&result);
 	if (status || result)
Index: 2.6.18-28.el5/drivers/acpi/bus.c
===================================================================
--- 2.6.18-28.el5.orig/drivers/acpi/bus.c	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/drivers/acpi/bus.c	2007-06-18 16:20:10.000000000 -0500
@@ -561,6 +561,9 @@ static int __init acpi_bus_init_irq(void
 	case ACPI_IRQ_MODEL_IOSAPIC:
 		message = "IOSAPIC";
 		break;
+	case ACPI_IRQ_MODEL_PLATFORM:
+		message = "platform specific model";
+		break;
 	default:
 		printk(KERN_WARNING PREFIX "Unknown interrupt routing model\n");
 		return -ENODEV;
Index: 2.6.18-28.el5/include/linux/acpi.h
===================================================================
--- 2.6.18-28.el5.orig/include/linux/acpi.h	2007-06-18 15:53:32.000000000 -0500
+++ 2.6.18-28.el5/include/linux/acpi.h	2007-06-18 16:20:10.000000000 -0500
@@ -47,6 +47,7 @@ enum acpi_irq_model_id {
 	ACPI_IRQ_MODEL_PIC = 0,
 	ACPI_IRQ_MODEL_IOAPIC,
 	ACPI_IRQ_MODEL_IOSAPIC,
+	ACPI_IRQ_MODEL_PLATFORM,
 	ACPI_IRQ_MODEL_COUNT
 };
 


http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=72253943f7281fc5c6249d9cafd63e7de3266fe9

Altix: more ACPI PRT support

The SN Altix platform does not conform to the IOSAPIC IRQ routing model.
Add code in acpi_unregister_gsi() to check if (acpi_irq_model ==
ACPI_IRQ_MODEL_PLATFORM) and return.

Due to an oversight, this code was not added previously when
similar code was added to acpi_register_gsi().

http://marc.theaimsgroup.com/?l=linux-acpi&m=116680983430121&w=2

---
 arch/ia64/kernel/acpi.c |    3 +++
 1 file changed, 3 insertions(+)
---

Index: 2.6.18-28.el5/arch/ia64/kernel/acpi.c
===================================================================
--- 2.6.18-28.el5.orig/arch/ia64/kernel/acpi.c	2007-06-19 15:24:31.000000000 -0500
+++ 2.6.18-28.el5/arch/ia64/kernel/acpi.c	2007-06-20 09:49:52.000000000 -0500
@@ -612,6 +612,9 @@ EXPORT_SYMBOL(acpi_register_gsi);
 
 void acpi_unregister_gsi(u32 gsi)
 {
+	if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM)
+		return;
+
 	iosapic_unregister_intr(gsi);
 }
 

From: Prarit Bhargava <prarit@redhat.com>
Subject: Re: header file break in linux-2.6-ia64-altix-acpi-support.patch?
Date: Wed, 18 Jul 2007 12:49:49 -0400
Message-Id: <469E44AD.7060209@redhat.com>

This is an additional patch to BZ 223577.  This patch fixes kabi breakage
introduced by the original patchset.

This patch has been successfully tested (rpmbuild -bb).

diff -urNp -X linux-2.6.18.ia64/Documentation/dontdiff linux-2.6.18.ia64.orig/arch/ia64/sn/kernel/io_acpi_init.c linux-2.6.18.ia64/arch/ia64/sn/kernel/io_acpi_init.c
--- linux-2.6.18.ia64.orig/arch/ia64/sn/kernel/io_acpi_init.c	2007-07-18 10:29:33.000000000 -0400
+++ linux-2.6.18.ia64/arch/ia64/sn/kernel/io_acpi_init.c	2007-07-18 10:43:45.000000000 -0400
@@ -436,7 +436,7 @@ sn_acpi_slot_fixup(struct pci_dev *dev)
 						(unsigned long) addr + size;
 		dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
 	}
-	sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
+	sn_pci_fixup_slot_new(dev, pcidev_info, sn_irq_info);
 }
 
 EXPORT_SYMBOL(sn_acpi_slot_fixup);
diff -urNp -X linux-2.6.18.ia64/Documentation/dontdiff linux-2.6.18.ia64.orig/arch/ia64/sn/kernel/io_common.c linux-2.6.18.ia64/arch/ia64/sn/kernel/io_common.c
--- linux-2.6.18.ia64.orig/arch/ia64/sn/kernel/io_common.c	2007-07-18 10:29:33.000000000 -0400
+++ linux-2.6.18.ia64/arch/ia64/sn/kernel/io_common.c	2007-07-18 10:44:41.000000000 -0400
@@ -229,10 +229,13 @@ void sn_pci_unfixup_slot(struct pci_dev 
 }
 
 /*
- * sn_pci_fixup_slot()
+ * sn_pci_fixup_slot_new()
+ *
+ * Note that upstream code has this function as sn_pci_fixup_slot.
+ * It has been renamed to sn_pci_fixup_slot_new to avoid kabi issues.
  */
-void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
-		       struct sn_irq_info *sn_irq_info)
+void sn_pci_fixup_slot_new(struct pci_dev *dev, struct pcidev_info *pcidev_info,
+		           struct sn_irq_info *sn_irq_info)
 {
 	int segment = pci_domain_nr(dev->bus);
 	struct pcibus_bussoft *bs;
diff -urNp -X linux-2.6.18.ia64/Documentation/dontdiff linux-2.6.18.ia64.orig/arch/ia64/sn/kernel/io_init.c linux-2.6.18.ia64/arch/ia64/sn/kernel/io_init.c
--- linux-2.6.18.ia64.orig/arch/ia64/sn/kernel/io_init.c	2007-07-18 10:29:33.000000000 -0400
+++ linux-2.6.18.ia64/arch/ia64/sn/kernel/io_init.c	2007-07-18 10:48:52.000000000 -0400
@@ -261,7 +261,7 @@ sn_io_slot_fixup(struct pci_dev *dev)
 	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_new(dev, pcidev_info, sn_irq_info);
 }
 
 EXPORT_SYMBOL(sn_io_slot_fixup);
@@ -270,7 +270,7 @@ EXPORT_SYMBOL(sn_io_slot_fixup);
  * sn_pci_controller_fixup() - This routine sets up a bus's resources
  *			       consistent with the Linux PCI abstraction layer.
  */
-static void
+void
 sn_pci_controller_fixup(int segment, int busnum, struct pci_bus *bus)
 {
 	s64 status = 0;
@@ -309,6 +309,22 @@ error_return:
 	return;
 }
 
+EXPORT_SYMBOL(sn_pci_controller_fixup);
+
+/*
+ * sn_pci_fixup_slot
+ *
+ * This is the "old" sn_pci_fixup_slot, and is simply a panic to prevent
+ * anyone from using it.  This has been done to prevent kabi issues.
+ *
+ */
+void sn_pci_fixup_slot(struct pci_dev *dev)
+{
+	panic("Use sn_pci_fixup_slot_new\n");
+}
+
+EXPORT_SYMBOL(sn_pci_fixup_slot);
+
 /*
  * sn_bus_fixup
  */
diff -urNp -X linux-2.6.18.ia64/Documentation/dontdiff linux-2.6.18.ia64.orig/include/asm-ia64/sn/pcidev.h linux-2.6.18.ia64/include/asm-ia64/sn/pcidev.h
--- linux-2.6.18.ia64.orig/include/asm-ia64/sn/pcidev.h	2007-07-18 10:29:33.000000000 -0400
+++ linux-2.6.18.ia64/include/asm-ia64/sn/pcidev.h	2007-07-18 10:43:35.000000000 -0400
@@ -78,8 +78,9 @@ extern void sn_bus_free_sysdata(void);
 extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
 extern void sn_io_slot_fixup(struct pci_dev *);
 extern void sn_acpi_slot_fixup(struct pci_dev *);
-extern void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *,
-			      struct sn_irq_info *);
+extern void sn_pci_fixup_slot(struct pci_dev *dev);
+extern void sn_pci_fixup_slot_new(struct pci_dev *dev, struct pcidev_info *,
+			          struct sn_irq_info *);
 extern void sn_pci_unfixup_slot(struct pci_dev *dev);
 extern void sn_irq_lh_init(void);
 #endif				/* _ASM_IA64_SN_PCI_PCIDEV_H */