aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/sn/kernel/io_common.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_common.c
parent647fb47dfabeffd2f1706013ebf5cfc92b70d273 (diff)
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_common.c')
-rw-r--r--arch/ia64/sn/kernel/io_common.c91
1 files changed, 20 insertions, 71 deletions
diff --git a/arch/ia64/sn/kernel/io_common.c b/arch/ia64/sn/kernel/io_common.c
index 75f0379958f9..d48bcd83253c 100644
--- a/arch/ia64/sn/kernel/io_common.c
+++ b/arch/ia64/sn/kernel/io_common.c
@@ -26,14 +26,10 @@
26#include <linux/acpi.h> 26#include <linux/acpi.h>
27#include <asm/sn/sn2/sn_hwperf.h> 27#include <asm/sn/sn2/sn_hwperf.h>
28#include <asm/sn/acpi.h> 28#include <asm/sn/acpi.h>
29#include "acpi/acglobal.h"
29 30
30extern void sn_init_cpei_timer(void); 31extern void sn_init_cpei_timer(void);
31extern void register_sn_procfs(void); 32extern void register_sn_procfs(void);
32extern void sn_acpi_bus_fixup(struct pci_bus *);
33extern void sn_bus_fixup(struct pci_bus *);
34extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *);
35extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *);
36extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64);
37extern void sn_io_acpi_init(void); 33extern void sn_io_acpi_init(void);
38extern void sn_io_init(void); 34extern void sn_io_init(void);
39 35
@@ -48,16 +44,10 @@ struct sysdata_el {
48 44
49int sn_ioif_inited; /* SN I/O infrastructure initialized? */ 45int sn_ioif_inited; /* SN I/O infrastructure initialized? */
50 46
51struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ 47int sn_acpi_rev; /* SN ACPI revision */
48EXPORT_SYMBOL_GPL(sn_acpi_rev);
52 49
53int sn_acpi_base_support(void) 50struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
54{
55 struct acpi_table_header *header;
56 (void)acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header);
57 if (header && header->oem_revision >= 0x20101)
58 return 1;
59 return 0;
60}
61 51
62/* 52/*
63 * Hooks and struct for unsupported pci providers 53 * Hooks and struct for unsupported pci providers
@@ -108,25 +98,6 @@ sal_get_device_dmaflush_list(u64 nasid, u64 widget_num, u64 device_num,
108} 98}
109 99
110/* 100/*
111 * Retrieve the pci device information given the bus and device|function number.
112 */
113static inline u64
114sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
115 u64 sn_irq_info)
116{
117 struct ia64_sal_retval ret_stuff;
118 ret_stuff.status = 0;
119 ret_stuff.v0 = 0;
120
121 SAL_CALL_NOLOCK(ret_stuff,
122 (u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
123 (u64) segment, (u64) bus_number, (u64) devfn,
124 (u64) pci_dev,
125 sn_irq_info, 0, 0);
126 return ret_stuff.v0;
127}
128
129/*
130 * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified 101 * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
131 * device. 102 * device.
132 */ 103 */
@@ -258,50 +229,25 @@ void sn_pci_unfixup_slot(struct pci_dev *dev)
258} 229}
259 230
260/* 231/*
261 * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent 232 * sn_pci_fixup_slot()
262 * with the Linux PCI abstraction layer. Resources
263 * acquired from our PCI provider include PIO maps
264 * to BAR space and interrupt objects.
265 */ 233 */
266void sn_pci_fixup_slot(struct pci_dev *dev) 234void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *pcidev_info,
235 struct sn_irq_info *sn_irq_info)
267{ 236{
268 int segment = pci_domain_nr(dev->bus); 237 int segment = pci_domain_nr(dev->bus);
269 int status = 0;
270 struct pcibus_bussoft *bs; 238 struct pcibus_bussoft *bs;
271 struct pci_bus *host_pci_bus; 239 struct pci_bus *host_pci_bus;
272 struct pci_dev *host_pci_dev; 240 struct pci_dev *host_pci_dev;
273 struct pcidev_info *pcidev_info; 241 unsigned int bus_no, devfn;
274 struct sn_irq_info *sn_irq_info;
275 unsigned int bus_no, devfn;
276 242
277 pci_dev_get(dev); /* for the sysdata pointer */ 243 pci_dev_get(dev); /* for the sysdata pointer */
278 pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
279 if (!pcidev_info)
280 BUG(); /* Cannot afford to run out of memory */
281
282 sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
283 if (!sn_irq_info)
284 BUG(); /* Cannot afford to run out of memory */
285
286 /* Call to retrieve pci device information needed by kernel. */
287 status = sal_get_pcidev_info((u64) segment, (u64) dev->bus->number,
288 dev->devfn,
289 (u64) __pa(pcidev_info),
290 (u64) __pa(sn_irq_info));
291 if (status)
292 BUG(); /* Cannot get platform pci device information */
293 244
294 /* Add pcidev_info to list in pci_controller.platform_data */ 245 /* Add pcidev_info to list in pci_controller.platform_data */
295 list_add_tail(&pcidev_info->pdi_list, 246 list_add_tail(&pcidev_info->pdi_list,
296 &(SN_PLATFORM_DATA(dev->bus)->pcidev_info)); 247 &(SN_PLATFORM_DATA(dev->bus)->pcidev_info));
297
298 if (SN_ACPI_BASE_SUPPORT())
299 sn_acpi_slot_fixup(dev, pcidev_info);
300 else
301 sn_more_slot_fixup(dev, pcidev_info);
302 /* 248 /*
303 * Using the PROMs values for the PCI host bus, get the Linux 249 * Using the PROMs values for the PCI host bus, get the Linux
304 * PCI host_pci_dev struct and set up host bus linkages 250 * PCI host_pci_dev struct and set up host bus linkages
305 */ 251 */
306 252
307 bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff; 253 bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
@@ -498,11 +444,6 @@ void sn_generate_path(struct pci_bus *pci_bus, char *address)
498 sprintf(address, "%s^%d", address, geo_slot(geoid)); 444 sprintf(address, "%s^%d", address, geo_slot(geoid));
499} 445}
500 446
501/*
502 * sn_pci_fixup_bus() - Perform SN specific setup of software structs
503 * (pcibus_bussoft, pcidev_info) and hardware
504 * registers, for the specified bus and devices under it.
505 */
506void __devinit 447void __devinit
507sn_pci_fixup_bus(struct pci_bus *bus) 448sn_pci_fixup_bus(struct pci_bus *bus)
508{ 449{
@@ -528,6 +469,15 @@ sn_io_early_init(void)
528 if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM()) 469 if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
529 return 0; 470 return 0;
530 471
472 /* we set the acpi revision to that of the DSDT table OEM rev. */
473 {
474 struct acpi_table_header *header = NULL;
475
476 acpi_get_table_by_index(ACPI_TABLE_INDEX_DSDT, &header);
477 BUG_ON(header == NULL);
478 sn_acpi_rev = header->oem_revision;
479 }
480
531 /* 481 /*
532 * prime sn_pci_provider[]. Individial provider init routines will 482 * prime sn_pci_provider[]. Individial provider init routines will
533 * override their respective default entries. 483 * override their respective default entries.
@@ -618,7 +568,6 @@ sn_io_late_init(void)
618 568
619fs_initcall(sn_io_late_init); 569fs_initcall(sn_io_late_init);
620 570
621EXPORT_SYMBOL(sn_pci_fixup_slot);
622EXPORT_SYMBOL(sn_pci_unfixup_slot); 571EXPORT_SYMBOL(sn_pci_unfixup_slot);
623EXPORT_SYMBOL(sn_bus_store_sysdata); 572EXPORT_SYMBOL(sn_bus_store_sysdata);
624EXPORT_SYMBOL(sn_bus_free_sysdata); 573EXPORT_SYMBOL(sn_bus_free_sysdata);