summaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/io_init.c
diff options
context:
space:
mode:
authorJohn Keller <jpk@sgi.com>2007-01-30 01:17:37 -0500
committerLen Brown <len.brown@intel.com>2007-02-02 22:14:35 -0500
commit6f09a9250a5d76c0765cd51a33e0a042e9761cfc (patch)
tree764db1dcd196fc1c272a8c6930924a5bc60623bc /arch/ia64/sn/kernel/io_init.c
parent647fb47dfabeffd2f1706013ebf5cfc92b70d273 (diff)
downloadlinux-6f09a9250a5d76c0765cd51a33e0a042e9761cfc.tar.bz2
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. Signed-off-by: John Keller <jpk@sgi.com> Cc: Greg KH <greg@kroah.com> Cc: "Luck, Tony" <tony.luck@intel.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'arch/ia64/sn/kernel/io_init.c')
-rw-r--r--arch/ia64/sn/kernel/io_init.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/arch/ia64/sn/kernel/io_init.c b/arch/ia64/sn/kernel/io_init.c
index 9ad843e0383b..600be3ebae05 100644
--- a/arch/ia64/sn/kernel/io_init.c
+++ b/arch/ia64/sn/kernel/io_init.c
@@ -56,6 +56,25 @@ static inline u64 sal_get_pcibus_info(u64 segment, u64 busnum, u64 address)
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, unsigned int count,
}
/*
- * 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, struct pcidev_info *pcidev_info)
*/
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);
}
}