Commit 6f09a9250a5d76c0765cd51a33e0a042e9761cfc

Authored by John Keller
Committed by Len Brown
1 parent 647fb47dfa

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>

Showing 7 changed files with 372 additions and 108 deletions Side-by-side Diff

arch/ia64/sn/kernel/io_acpi_init.c
... ... @@ -13,6 +13,7 @@
13 13 #include <asm/sn/sn_sal.h>
14 14 #include "xtalk/hubdev.h"
15 15 #include <linux/acpi.h>
  16 +#include <acpi/acnamesp.h>
16 17  
17 18  
18 19 /*
... ... @@ -31,6 +32,12 @@
31 32 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
32 33 };
33 34  
  35 +struct sn_pcidev_match {
  36 + u8 bus;
  37 + unsigned int devfn;
  38 + acpi_handle handle;
  39 +};
  40 +
34 41 /*
35 42 * Perform the early IO init in PROM.
36 43 */
... ... @@ -119,9 +126,11 @@
119 126 status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
120 127 &sn_uuid, &buffer);
121 128 if (ACPI_FAILURE(status)) {
122   - printk(KERN_ERR "get_acpi_pcibus_ptr: "
123   - "get_acpi_bussoft_info() failed: %d\n",
124   - status);
  129 + printk(KERN_ERR "%s: "
  130 + "acpi_get_vendor_resource() failed (0x%x) for: ",
  131 + __FUNCTION__, status);
  132 + acpi_ns_print_node_pathname(handle, NULL);
  133 + printk("\n");
125 134 return NULL;
126 135 }
127 136 resource = buffer.pointer;
... ... @@ -130,8 +139,8 @@
130 139 if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
131 140 sizeof(struct pcibus_bussoft *)) {
132 141 printk(KERN_ERR
133   - "get_acpi_bussoft_ptr: Invalid vendor data "
134   - "length %d\n", vendor->byte_length);
  142 + "%s: Invalid vendor data length %d\n",
  143 + __FUNCTION__, vendor->byte_length);
135 144 kfree(buffer.pointer);
136 145 return NULL;
137 146 }
138 147  
139 148  
140 149  
141 150  
142 151  
143 152  
144 153  
145 154  
... ... @@ -143,34 +152,254 @@
143 152 }
144 153  
145 154 /*
146   - * sn_acpi_bus_fixup
  155 + * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
  156 + * pointers from the vendor resource using the
  157 + * provided acpi handle, and copy the structures
  158 + * into the argument buffers.
147 159 */
148   -void
149   -sn_acpi_bus_fixup(struct pci_bus *bus)
  160 +static int
  161 +sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
  162 + struct sn_irq_info **sn_irq_info)
150 163 {
151   - struct pci_dev *pci_dev = NULL;
152   - struct pcibus_bussoft *prom_bussoft_ptr;
153   - extern void sn_common_bus_fixup(struct pci_bus *,
154   - struct pcibus_bussoft *);
  164 + u64 addr;
  165 + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  166 + struct sn_irq_info *irq_info, *irq_info_prom;
  167 + struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
  168 + struct acpi_resource *resource;
  169 + int ret = 0;
  170 + acpi_status status;
  171 + struct acpi_resource_vendor_typed *vendor;
155 172  
156   - if (!bus->parent) { /* If root bus */
157   - prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
158   - if (prom_bussoft_ptr == NULL) {
  173 + /*
  174 + * The pointer to this device's pcidev_info structure in
  175 + * the PROM, is in the vendor resource.
  176 + */
  177 + status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
  178 + &sn_uuid, &buffer);
  179 + if (ACPI_FAILURE(status)) {
  180 + printk(KERN_ERR
  181 + "%s: acpi_get_vendor_resource() failed (0x%x) for: ",
  182 + __FUNCTION__, status);
  183 + acpi_ns_print_node_pathname(handle, NULL);
  184 + printk("\n");
  185 + return 1;
  186 + }
  187 +
  188 + resource = buffer.pointer;
  189 + vendor = &resource->data.vendor_typed;
  190 + if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
  191 + sizeof(struct pci_devdev_info *)) {
  192 + printk(KERN_ERR
  193 + "%s: Invalid vendor data length: %d for: ",
  194 + __FUNCTION__, vendor->byte_length);
  195 + acpi_ns_print_node_pathname(handle, NULL);
  196 + printk("\n");
  197 + ret = 1;
  198 + goto exit;
  199 + }
  200 +
  201 + pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
  202 + if (!pcidev_ptr)
  203 + panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);
  204 +
  205 + memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
  206 + pcidev_prom_ptr = __va(addr);
  207 + memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));
  208 +
  209 + /* Get the IRQ info */
  210 + irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
  211 + if (!irq_info)
  212 + panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);
  213 +
  214 + if (pcidev_ptr->pdi_sn_irq_info) {
  215 + irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
  216 + memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
  217 + }
  218 +
  219 + *pcidev_info = pcidev_ptr;
  220 + *sn_irq_info = irq_info;
  221 +
  222 +exit:
  223 + kfree(buffer.pointer);
  224 + return ret;
  225 +}
  226 +
  227 +static unsigned int
  228 +get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
  229 +{
  230 + unsigned long adr;
  231 + acpi_handle child;
  232 + unsigned int devfn;
  233 + int function;
  234 + acpi_handle parent;
  235 + int slot;
  236 + acpi_status status;
  237 +
  238 + /*
  239 + * Do an upward search to find the root bus device, and
  240 + * obtain the host devfn from the previous child device.
  241 + */
  242 + child = device_handle;
  243 + while (child) {
  244 + status = acpi_get_parent(child, &parent);
  245 + if (ACPI_FAILURE(status)) {
  246 + printk(KERN_ERR "%s: acpi_get_parent() failed "
  247 + "(0x%x) for: ", __FUNCTION__, status);
  248 + acpi_ns_print_node_pathname(child, NULL);
  249 + printk("\n");
  250 + panic("%s: Unable to find host devfn\n", __FUNCTION__);
  251 + }
  252 + if (parent == rootbus_handle)
  253 + break;
  254 + child = parent;
  255 + }
  256 + if (!child) {
  257 + printk(KERN_ERR "%s: Unable to find root bus for: ",
  258 + __FUNCTION__);
  259 + acpi_ns_print_node_pathname(device_handle, NULL);
  260 + printk("\n");
  261 + BUG();
  262 + }
  263 +
  264 + status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
  265 + if (ACPI_FAILURE(status)) {
  266 + printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: ",
  267 + __FUNCTION__, status);
  268 + acpi_ns_print_node_pathname(child, NULL);
  269 + printk("\n");
  270 + panic("%s: Unable to find host devfn\n", __FUNCTION__);
  271 + }
  272 +
  273 + slot = (adr >> 16) & 0xffff;
  274 + function = adr & 0xffff;
  275 + devfn = PCI_DEVFN(slot, function);
  276 + return devfn;
  277 +}
  278 +
  279 +/*
  280 + * find_matching_device - Callback routine to find the ACPI device
  281 + * that matches up with our pci_dev device.
  282 + * Matching is done on bus number and devfn.
  283 + * To find the bus number for a particular
  284 + * ACPI device, we must look at the _BBN method
  285 + * of its parent.
  286 + */
  287 +static acpi_status
  288 +find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
  289 +{
  290 + unsigned long bbn = -1;
  291 + unsigned long adr;
  292 + acpi_handle parent = NULL;
  293 + acpi_status status;
  294 + unsigned int devfn;
  295 + int function;
  296 + int slot;
  297 + struct sn_pcidev_match *info = context;
  298 +
  299 + status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
  300 + &adr);
  301 + if (ACPI_SUCCESS(status)) {
  302 + status = acpi_get_parent(handle, &parent);
  303 + if (ACPI_FAILURE(status)) {
159 304 printk(KERN_ERR
160   - "sn_pci_fixup_bus: 0x%04x:0x%02x Unable to "
161   - "obtain prom_bussoft_ptr\n",
162   - pci_domain_nr(bus), bus->number);
163   - return;
  305 + "%s: acpi_get_parent() failed (0x%x) for: ",
  306 + __FUNCTION__, status);
  307 + acpi_ns_print_node_pathname(handle, NULL);
  308 + printk("\n");
  309 + return AE_OK;
164 310 }
165   - sn_common_bus_fixup(bus, prom_bussoft_ptr);
  311 + status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
  312 + NULL, &bbn);
  313 + if (ACPI_FAILURE(status)) {
  314 + printk(KERN_ERR
  315 + "%s: Failed to find _BBN in parent of: ",
  316 + __FUNCTION__);
  317 + acpi_ns_print_node_pathname(handle, NULL);
  318 + printk("\n");
  319 + return AE_OK;
  320 + }
  321 +
  322 + slot = (adr >> 16) & 0xffff;
  323 + function = adr & 0xffff;
  324 + devfn = PCI_DEVFN(slot, function);
  325 + if ((info->devfn == devfn) && (info->bus == bbn)) {
  326 + /* We have a match! */
  327 + info->handle = handle;
  328 + return 1;
  329 + }
166 330 }
167   - list_for_each_entry(pci_dev, &bus->devices, bus_list) {
168   - sn_pci_fixup_slot(pci_dev);
  331 + return AE_OK;
  332 +}
  333 +
  334 +/*
  335 + * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
  336 + * device matching the specified pci_dev,
  337 + * and return the pcidev info and irq info.
  338 + */
  339 +int
  340 +sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
  341 + struct sn_irq_info **sn_irq_info)
  342 +{
  343 + unsigned int host_devfn;
  344 + struct sn_pcidev_match pcidev_match;
  345 + acpi_handle rootbus_handle;
  346 + unsigned long segment;
  347 + acpi_status status;
  348 +
  349 + rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
  350 + status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
  351 + &segment);
  352 + if (ACPI_SUCCESS(status)) {
  353 + if (segment != pci_domain_nr(dev)) {
  354 + printk(KERN_ERR
  355 + "%s: Segment number mismatch, 0x%lx vs 0x%x for: ",
  356 + __FUNCTION__, segment, pci_domain_nr(dev));
  357 + acpi_ns_print_node_pathname(rootbus_handle, NULL);
  358 + printk("\n");
  359 + return 1;
  360 + }
  361 + } else {
  362 + printk(KERN_ERR "%s: Unable to get __SEG from: ",
  363 + __FUNCTION__);
  364 + acpi_ns_print_node_pathname(rootbus_handle, NULL);
  365 + printk("\n");
  366 + return 1;
169 367 }
  368 +
  369 + /*
  370 + * We want to search all devices in this segment/domain
  371 + * of the ACPI namespace for the matching ACPI device,
  372 + * which holds the pcidev_info pointer in its vendor resource.
  373 + */
  374 + pcidev_match.bus = dev->bus->number;
  375 + pcidev_match.devfn = dev->devfn;
  376 + pcidev_match.handle = NULL;
  377 +
  378 + acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
  379 + find_matching_device, &pcidev_match, NULL);
  380 +
  381 + if (!pcidev_match.handle) {
  382 + printk(KERN_ERR
  383 + "%s: Could not find matching ACPI device for %s.\n",
  384 + __FUNCTION__, pci_name(dev));
  385 + return 1;
  386 + }
  387 +
  388 + if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
  389 + return 1;
  390 +
  391 + /* Build up the pcidev_info.pdi_slot_host_handle */
  392 + host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
  393 + (*pcidev_info)->pdi_slot_host_handle =
  394 + ((unsigned long) pci_domain_nr(dev) << 40) |
  395 + /* bus == 0 */
  396 + host_devfn;
  397 + return 0;
170 398 }
171 399  
172 400 /*
173   - * sn_acpi_slot_fixup - Perform any SN specific slot fixup.
  401 + * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
  402 + * Perform any SN specific slot fixup.
174 403 * At present there does not appear to be
175 404 * any generic way to handle a ROM image
176 405 * that has been shadowed by the PROM, so
177 406  
178 407  
... ... @@ -179,11 +408,18 @@
179 408 */
180 409  
181 410 void
182   -sn_acpi_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
  411 +sn_acpi_slot_fixup(struct pci_dev *dev)
183 412 {
184 413 void __iomem *addr;
  414 + struct pcidev_info *pcidev_info = NULL;
  415 + struct sn_irq_info *sn_irq_info = NULL;
185 416 size_t size;
186 417  
  418 + if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
  419 + panic("%s: Failure obtaining pcidev_info for %s\n",
  420 + __FUNCTION__, pci_name(dev));
  421 + }
  422 +
187 423 if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
188 424 /*
189 425 * A valid ROM image exists and has been shadowed by the
190 426  
... ... @@ -200,8 +436,11 @@
200 436 (unsigned long) addr + size;
201 437 dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
202 438 }
  439 + sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
203 440 }
204 441  
  442 +EXPORT_SYMBOL(sn_acpi_slot_fixup);
  443 +
205 444 static struct acpi_driver acpi_sn_hubdev_driver = {
206 445 .name = "SGI HUBDEV Driver",
207 446 .ids = "SGIHUB,SGITIO",
... ... @@ -210,6 +449,33 @@
210 449 },
211 450 };
212 451  
  452 +
  453 +/*
  454 + * sn_acpi_bus_fixup - Perform SN specific setup of software structs
  455 + * (pcibus_bussoft, pcidev_info) and hardware
  456 + * registers, for the specified bus and devices under it.
  457 + */
  458 +void
  459 +sn_acpi_bus_fixup(struct pci_bus *bus)
  460 +{
  461 + struct pci_dev *pci_dev = NULL;
  462 + struct pcibus_bussoft *prom_bussoft_ptr;
  463 +
  464 + if (!bus->parent) { /* If root bus */
  465 + prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
  466 + if (prom_bussoft_ptr == NULL) {
  467 + printk(KERN_ERR
  468 + "%s: 0x%04x:0x%02x Unable to "
  469 + "obtain prom_bussoft_ptr\n",
  470 + __FUNCTION__, pci_domain_nr(bus), bus->number);
  471 + return;
  472 + }
  473 + sn_common_bus_fixup(bus, prom_bussoft_ptr);
  474 + }
  475 + list_for_each_entry(pci_dev, &bus->devices, bus_list) {
  476 + sn_acpi_slot_fixup(pci_dev);
  477 + }
  478 +}
213 479  
214 480 /*
215 481 * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
arch/ia64/sn/kernel/io_common.c
... ... @@ -26,14 +26,10 @@
26 26 #include <linux/acpi.h>
27 27 #include <asm/sn/sn2/sn_hwperf.h>
28 28 #include <asm/sn/acpi.h>
  29 +#include "acpi/acglobal.h"
29 30  
30 31 extern void sn_init_cpei_timer(void);
31 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 33 extern void sn_io_acpi_init(void);
38 34 extern void sn_io_init(void);
39 35  
40 36  
... ... @@ -48,17 +44,11 @@
48 44  
49 45 int sn_ioif_inited; /* SN I/O infrastructure initialized? */
50 46  
  47 +int sn_acpi_rev; /* SN ACPI revision */
  48 +EXPORT_SYMBOL_GPL(sn_acpi_rev);
  49 +
51 50 struct sn_pcibus_provider *sn_pci_provider[PCIIO_ASIC_MAX_TYPES]; /* indexed by asic type */
52 51  
53   -int sn_acpi_base_support(void)
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   -
62 52 /*
63 53 * Hooks and struct for unsupported pci providers
64 54 */
... ... @@ -108,25 +98,6 @@
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 101 * sn_pcidev_info_get() - Retrieve the pcidev_info struct for the specified
131 102 * device.
132 103 */
133 104  
134 105  
135 106  
136 107  
137 108  
138 109  
139 110  
... ... @@ -258,50 +229,25 @@
258 229 }
259 230  
260 231 /*
261   - * sn_pci_fixup_slot() - This routine sets up a slot's resources consistent
262   - * with the Linux PCI abstraction layer. Resources
263   - * acquired from our PCI provider include PIO maps
264   - * to BAR space and interrupt objects.
  232 + * sn_pci_fixup_slot()
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 237 int segment = pci_domain_nr(dev->bus);
269   - int status = 0;
270 238 struct pcibus_bussoft *bs;
271   - struct pci_bus *host_pci_bus;
272   - struct pci_dev *host_pci_dev;
273   - struct pcidev_info *pcidev_info;
274   - struct sn_irq_info *sn_irq_info;
275   - unsigned int bus_no, devfn;
  239 + struct pci_bus *host_pci_bus;
  240 + struct pci_dev *host_pci_dev;
  241 + unsigned int bus_no, devfn;
276 242  
277 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 244  
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   -
294 245 /* Add pcidev_info to list in pci_controller.platform_data */
295 246 list_add_tail(&pcidev_info->pdi_list,
296 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 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 253 bus_no = (pcidev_info->pdi_slot_host_handle >> 32) & 0xff;
... ... @@ -498,11 +444,6 @@
498 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 447 void __devinit
507 448 sn_pci_fixup_bus(struct pci_bus *bus)
508 449 {
... ... @@ -528,6 +469,15 @@
528 469 if (!ia64_platform_is("sn2") || IS_RUNNING_ON_FAKE_PROM())
529 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 482 * prime sn_pci_provider[]. Individial provider init routines will
533 483 * override their respective default entries.
... ... @@ -618,7 +568,6 @@
618 568  
619 569 fs_initcall(sn_io_late_init);
620 570  
621   -EXPORT_SYMBOL(sn_pci_fixup_slot);
622 571 EXPORT_SYMBOL(sn_pci_unfixup_slot);
623 572 EXPORT_SYMBOL(sn_bus_store_sysdata);
624 573 EXPORT_SYMBOL(sn_bus_free_sysdata);
arch/ia64/sn/kernel/io_init.c
... ... @@ -56,7 +56,26 @@
56 56 return ret_stuff.v0;
57 57 }
58 58  
  59 +/*
  60 + * Retrieve the pci device information given the bus and device|function number.
  61 + */
  62 +static inline u64
  63 +sal_get_pcidev_info(u64 segment, u64 bus_number, u64 devfn, u64 pci_dev,
  64 + u64 sn_irq_info)
  65 +{
  66 + struct ia64_sal_retval ret_stuff;
  67 + ret_stuff.status = 0;
  68 + ret_stuff.v0 = 0;
59 69  
  70 + SAL_CALL_NOLOCK(ret_stuff,
  71 + (u64) SN_SAL_IOIF_GET_PCIDEV_INFO,
  72 + (u64) segment, (u64) bus_number, (u64) devfn,
  73 + (u64) pci_dev,
  74 + sn_irq_info, 0, 0);
  75 + return ret_stuff.v0;
  76 +}
  77 +
  78 +
60 79 /*
61 80 * sn_fixup_ionodes() - This routine initializes the HUB data structure for
62 81 * each node in the system. This function is only
63 82  
64 83  
65 84  
... ... @@ -172,19 +191,41 @@
172 191 }
173 192  
174 193 /*
175   - * sn_more_slot_fixup() - We are not running with an ACPI capable PROM,
  194 + * sn_io_slot_fixup() - We are not running with an ACPI capable PROM,
176 195 * and need to convert the pci_dev->resource
177 196 * 'start' and 'end' addresses to mapped addresses,
178 197 * and setup the pci_controller->window array entries.
179 198 */
180 199 void
181   -sn_more_slot_fixup(struct pci_dev *dev, struct pcidev_info *pcidev_info)
  200 +sn_io_slot_fixup(struct pci_dev *dev)
182 201 {
183 202 unsigned int count = 0;
184 203 int idx;
185 204 s64 pci_addrs[PCI_ROM_RESOURCE + 1];
186 205 unsigned long addr, end, size, start;
  206 + struct pcidev_info *pcidev_info;
  207 + struct sn_irq_info *sn_irq_info;
  208 + int status;
187 209  
  210 + pcidev_info = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
  211 + if (!pcidev_info)
  212 + panic("%s: Unable to alloc memory for pcidev_info", __FUNCTION__);
  213 +
  214 + sn_irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
  215 + if (!sn_irq_info)
  216 + panic("%s: Unable to alloc memory for sn_irq_info", __FUNCTION__);
  217 +
  218 + /* Call to retrieve pci device information needed by kernel. */
  219 + status = sal_get_pcidev_info((u64) pci_domain_nr(dev),
  220 + (u64) dev->bus->number,
  221 + dev->devfn,
  222 + (u64) __pa(pcidev_info),
  223 + (u64) __pa(sn_irq_info));
  224 +
  225 + if (status)
  226 + BUG(); /* Cannot get platform pci device information */
  227 +
  228 +
188 229 /* Copy over PIO Mapped Addresses */
189 230 for (idx = 0; idx <= PCI_ROM_RESOURCE; idx++) {
190 231  
191 232  
... ... @@ -219,8 +260,12 @@
219 260 */
220 261 if (count > 0)
221 262 sn_pci_window_fixup(dev, count, pci_addrs);
  263 +
  264 + sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
222 265 }
223 266  
  267 +EXPORT_SYMBOL(sn_io_slot_fixup);
  268 +
224 269 /*
225 270 * sn_pci_controller_fixup() - This routine sets up a bus's resources
226 271 * consistent with the Linux PCI abstraction layer.
227 272  
... ... @@ -272,10 +317,7 @@
272 317 {
273 318 struct pci_dev *pci_dev = NULL;
274 319 struct pcibus_bussoft *prom_bussoft_ptr;
275   - extern void sn_common_bus_fixup(struct pci_bus *,
276   - struct pcibus_bussoft *);
277 320  
278   -
279 321 if (!bus->parent) { /* If root bus */
280 322 prom_bussoft_ptr = PCI_CONTROLLER(bus)->platform_data;
281 323 if (prom_bussoft_ptr == NULL) {
... ... @@ -291,7 +333,7 @@
291 333 prom_bussoft_ptr->bs_legacy_mem);
292 334 }
293 335 list_for_each_entry(pci_dev, &bus->devices, bus_list) {
294   - sn_pci_fixup_slot(pci_dev);
  336 + sn_io_slot_fixup(pci_dev);
295 337 }
296 338  
297 339 }
arch/ia64/sn/pci/pcibr/pcibr_provider.c
... ... @@ -20,7 +20,8 @@
20 20 #include "xtalk/hubdev.h"
21 21  
22 22 int
23   -sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp)
  23 +sal_pcibr_slot_enable(struct pcibus_info *soft, int device, void *resp,
  24 + char **ssdt)
24 25 {
25 26 struct ia64_sal_retval ret_stuff;
26 27 u64 busnum;
... ... @@ -32,7 +33,8 @@
32 33 segment = soft->pbi_buscommon.bs_persist_segment;
33 34 busnum = soft->pbi_buscommon.bs_persist_busnum;
34 35 SAL_CALL_NOLOCK(ret_stuff, (u64) SN_SAL_IOIF_SLOT_ENABLE, segment,
35   - busnum, (u64) device, (u64) resp, 0, 0, 0);
  36 + busnum, (u64) device, (u64) resp, (u64)ia64_tpa(ssdt),
  37 + 0, 0);
36 38  
37 39 return (int)ret_stuff.v0;
38 40 }
include/asm-ia64/sn/acpi.h
... ... @@ -11,9 +11,8 @@
11 11  
12 12 #include "acpi/acglobal.h"
13 13  
14   -#define SN_ACPI_BASE_SUPPORT() sn_acpi_base_support()
15   -
16   -extern int sn_acpi_base_support(void);
  14 +extern int sn_acpi_rev;
  15 +#define SN_ACPI_BASE_SUPPORT() (sn_acpi_rev >= 0x20101)
17 16  
18 17 #endif /* _ASM_IA64_SN_ACPI_H */
include/asm-ia64/sn/pcibr_provider.h
... ... @@ -142,7 +142,7 @@
142 142 extern void pcibr_ate_free(struct pcibus_info *, int);
143 143 extern void ate_write(struct pcibus_info *, int, int, u64);
144 144 extern int sal_pcibr_slot_enable(struct pcibus_info *soft, int device,
145   - void *resp);
  145 + void *resp, char **ssdt);
146 146 extern int sal_pcibr_slot_disable(struct pcibus_info *soft, int device,
147 147 int action, void *resp);
148 148 extern u16 sn_ioboard_to_pci_bus(struct pci_bus *pci_bus);
include/asm-ia64/sn/pcidev.h
... ... @@ -70,10 +70,16 @@
70 70 struct sn_irq_info *sn_irq_info);
71 71 extern void sn_irq_unfixup(struct pci_dev *pci_dev);
72 72 extern struct pcidev_info * sn_pcidev_info_get(struct pci_dev *);
  73 +extern void sn_bus_fixup(struct pci_bus *);
  74 +extern void sn_acpi_bus_fixup(struct pci_bus *);
  75 +extern void sn_common_bus_fixup(struct pci_bus *, struct pcibus_bussoft *);
73 76 extern void sn_bus_store_sysdata(struct pci_dev *dev);
74 77 extern void sn_bus_free_sysdata(void);
75 78 extern void sn_generate_path(struct pci_bus *pci_bus, char *address);
76   -extern void sn_pci_fixup_slot(struct pci_dev *dev);
  79 +extern void sn_io_slot_fixup(struct pci_dev *);
  80 +extern void sn_acpi_slot_fixup(struct pci_dev *);
  81 +extern void sn_pci_fixup_slot(struct pci_dev *dev, struct pcidev_info *,
  82 + struct sn_irq_info *);
77 83 extern void sn_pci_unfixup_slot(struct pci_dev *dev);
78 84 extern void sn_irq_lh_init(void);
79 85 #endif /* _ASM_IA64_SN_PCI_PCIDEV_H */