diff options
author | John Keller <jpk@sgi.com> | 2007-01-30 01:17:37 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 22:14:35 -0500 |
commit | 6f09a9250a5d76c0765cd51a33e0a042e9761cfc (patch) | |
tree | 764db1dcd196fc1c272a8c6930924a5bc60623bc /arch/ia64/sn/kernel/io_common.c | |
parent | 647fb47dfabeffd2f1706013ebf5cfc92b70d273 (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.c | 91 |
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 | ||
30 | extern void sn_init_cpei_timer(void); | 31 | extern void sn_init_cpei_timer(void); |
31 | extern void register_sn_procfs(void); | 32 | extern void register_sn_procfs(void); |
32 | extern void sn_acpi_bus_fixup(struct pci_bus *); | ||
33 | extern void sn_bus_fixup(struct pci_bus *); | ||
34 | extern void sn_acpi_slot_fixup(struct pci_dev *, struct pcidev_info *); | ||
35 | extern void sn_more_slot_fixup(struct pci_dev *, struct pcidev_info *); | ||
36 | extern void sn_legacy_pci_window_fixup(struct pci_controller *, u64, u64); | ||
37 | extern void sn_io_acpi_init(void); | 33 | extern void sn_io_acpi_init(void); |
38 | extern void sn_io_init(void); | 34 | extern void sn_io_init(void); |
39 | 35 | ||
@@ -48,16 +44,10 @@ struct sysdata_el { | |||
48 | 44 | ||
49 | int sn_ioif_inited; /* SN I/O infrastructure initialized? */ | 45 | int sn_ioif_inited; /* SN I/O infrastructure initialized? */ |
50 | 46 | ||
51 | struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */ | 47 | int sn_acpi_rev; /* SN ACPI revision */ |
48 | EXPORT_SYMBOL_GPL(sn_acpi_rev); | ||
52 | 49 | ||
53 | int sn_acpi_base_support(void) | 50 | struct 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 | */ | ||
113 | static inline u64 | ||
114 | sal_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 | */ |
266 | void sn_pci_fixup_slot(struct pci_dev *dev) | 234 | void 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 | */ | ||
506 | void __devinit | 447 | void __devinit |
507 | sn_pci_fixup_bus(struct pci_bus *bus) | 448 | sn_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 | ||
619 | fs_initcall(sn_io_late_init); | 569 | fs_initcall(sn_io_late_init); |
620 | 570 | ||
621 | EXPORT_SYMBOL(sn_pci_fixup_slot); | ||
622 | EXPORT_SYMBOL(sn_pci_unfixup_slot); | 571 | EXPORT_SYMBOL(sn_pci_unfixup_slot); |
623 | EXPORT_SYMBOL(sn_bus_store_sysdata); | 572 | EXPORT_SYMBOL(sn_bus_store_sysdata); |
624 | EXPORT_SYMBOL(sn_bus_free_sysdata); | 573 | EXPORT_SYMBOL(sn_bus_free_sysdata); |