2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
9 #include <asm/sn/types.h>
10 #include <asm/sn/addrs.h>
11 #include <asm/sn/pcidev.h>
12 #include <asm/sn/pcibus_provider_defs.h>
13 #include <asm/sn/sn_sal.h>
14 #include "xtalk/hubdev.h"
15 #include <linux/acpi.h>
16 #include <linux/slab.h>
17 #include <linux/export.h>
21 * The code in this file will only be executed when running with
22 * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
27 * This value must match the UUID the PROM uses
28 * (io/acpi/defblk.c) when building a vendor descriptor.
30 struct acpi_vendor_uuid sn_uuid
= {
32 .data
= { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
33 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
36 struct sn_pcidev_match
{
43 * Perform the early IO init in PROM.
46 sal_ioif_init(u64
*result
)
48 struct ia64_sal_retval isrv
= {0,0,0,0};
51 SN_SAL_IOIF_INIT
, 0, 0, 0, 0, 0, 0, 0);
57 * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
58 * for all SGIHUB and SGITIO acpi devices defined in the
59 * DSDT. It obtains the hubdev_info pointer from the
60 * ACPI vendor resource, which the PROM setup, and sets up the
61 * hubdev_info in the pda.
64 static acpi_status __init
65 sn_acpi_hubdev_init(acpi_handle handle
, u32 depth
, void *context
, void **ret
)
67 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
68 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
70 struct hubdev_info
*hubdev
;
71 struct hubdev_info
*hubdev_ptr
;
74 struct acpi_resource
*resource
;
76 struct acpi_resource_vendor_typed
*vendor
;
77 extern void sn_common_hubdev_init(struct hubdev_info
*);
79 status
= acpi_get_vendor_resource(handle
, METHOD_NAME__CRS
,
81 if (ACPI_FAILURE(status
)) {
82 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
84 "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
85 "(0x%x) failed for: %s\n", status
,
86 (char *)name_buffer
.pointer
);
87 kfree(name_buffer
.pointer
);
88 return AE_OK
; /* Continue walking namespace */
91 resource
= buffer
.pointer
;
92 vendor
= &resource
->data
.vendor_typed
;
93 if ((vendor
->byte_length
- sizeof(struct acpi_vendor_uuid
)) !=
94 sizeof(struct hubdev_info
*)) {
95 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
97 "sn_acpi_hubdev_init: Invalid vendor data length: "
99 vendor
->byte_length
, (char *)name_buffer
.pointer
);
100 kfree(name_buffer
.pointer
);
104 memcpy(&addr
, vendor
->byte_data
, sizeof(struct hubdev_info
*));
105 hubdev_ptr
= __va((struct hubdev_info
*) addr
);
107 nasid
= hubdev_ptr
->hdi_nasid
;
108 i
= nasid_to_cnodeid(nasid
);
109 hubdev
= (struct hubdev_info
*)(NODEPDA(i
)->pdinfo
);
110 *hubdev
= *hubdev_ptr
;
111 sn_common_hubdev_init(hubdev
);
114 kfree(buffer
.pointer
);
115 return AE_OK
; /* Continue walking namespace */
119 * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
120 * the ACPI Vendor resource for this bus.
122 static struct pcibus_bussoft
*
123 sn_get_bussoft_ptr(struct pci_bus
*bus
)
126 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
127 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
129 struct pcibus_bussoft
*prom_bussoft_ptr
;
130 struct acpi_resource
*resource
;
132 struct acpi_resource_vendor_typed
*vendor
;
135 handle
= acpi_device_handle(PCI_CONTROLLER(bus
)->companion
);
136 status
= acpi_get_vendor_resource(handle
, METHOD_NAME__CRS
,
138 if (ACPI_FAILURE(status
)) {
139 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
140 printk(KERN_ERR
"%s: "
141 "acpi_get_vendor_resource() failed (0x%x) for: %s\n",
142 __func__
, status
, (char *)name_buffer
.pointer
);
143 kfree(name_buffer
.pointer
);
146 resource
= buffer
.pointer
;
147 vendor
= &resource
->data
.vendor_typed
;
149 if ((vendor
->byte_length
- sizeof(struct acpi_vendor_uuid
)) !=
150 sizeof(struct pcibus_bussoft
*)) {
152 "%s: Invalid vendor data length %d\n",
153 __func__
, vendor
->byte_length
);
154 kfree(buffer
.pointer
);
157 memcpy(&addr
, vendor
->byte_data
, sizeof(struct pcibus_bussoft
*));
158 prom_bussoft_ptr
= __va((struct pcibus_bussoft
*) addr
);
159 kfree(buffer
.pointer
);
161 return prom_bussoft_ptr
;
165 * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
166 * pointers from the vendor resource using the
167 * provided acpi handle, and copy the structures
168 * into the argument buffers.
171 sn_extract_device_info(acpi_handle handle
, struct pcidev_info
**pcidev_info
,
172 struct sn_irq_info
**sn_irq_info
)
175 struct acpi_buffer buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
176 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
177 struct sn_irq_info
*irq_info
, *irq_info_prom
;
178 struct pcidev_info
*pcidev_ptr
, *pcidev_prom_ptr
;
179 struct acpi_resource
*resource
;
182 struct acpi_resource_vendor_typed
*vendor
;
185 * The pointer to this device's pcidev_info structure in
186 * the PROM, is in the vendor resource.
188 status
= acpi_get_vendor_resource(handle
, METHOD_NAME__CRS
,
190 if (ACPI_FAILURE(status
)) {
191 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
193 "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
194 __func__
, status
, (char *)name_buffer
.pointer
);
195 kfree(name_buffer
.pointer
);
199 resource
= buffer
.pointer
;
200 vendor
= &resource
->data
.vendor_typed
;
201 if ((vendor
->byte_length
- sizeof(struct acpi_vendor_uuid
)) !=
202 sizeof(struct pci_devdev_info
*)) {
203 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
205 "%s: Invalid vendor data length: %d for: %s\n",
206 __func__
, vendor
->byte_length
,
207 (char *)name_buffer
.pointer
);
208 kfree(name_buffer
.pointer
);
213 pcidev_ptr
= kzalloc(sizeof(struct pcidev_info
), GFP_KERNEL
);
215 panic("%s: Unable to alloc memory for pcidev_info", __func__
);
217 memcpy(&addr
, vendor
->byte_data
, sizeof(struct pcidev_info
*));
218 pcidev_prom_ptr
= __va(addr
);
219 memcpy(pcidev_ptr
, pcidev_prom_ptr
, sizeof(struct pcidev_info
));
221 /* Get the IRQ info */
222 irq_info
= kzalloc(sizeof(struct sn_irq_info
), GFP_KERNEL
);
224 panic("%s: Unable to alloc memory for sn_irq_info", __func__
);
226 if (pcidev_ptr
->pdi_sn_irq_info
) {
227 irq_info_prom
= __va(pcidev_ptr
->pdi_sn_irq_info
);
228 memcpy(irq_info
, irq_info_prom
, sizeof(struct sn_irq_info
));
231 *pcidev_info
= pcidev_ptr
;
232 *sn_irq_info
= irq_info
;
235 kfree(buffer
.pointer
);
240 get_host_devfn(acpi_handle device_handle
, acpi_handle rootbus_handle
)
242 unsigned long long adr
;
249 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
251 acpi_get_name(device_handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
254 * Do an upward search to find the root bus device, and
255 * obtain the host devfn from the previous child device.
257 child
= device_handle
;
259 status
= acpi_get_parent(child
, &parent
);
260 if (ACPI_FAILURE(status
)) {
261 printk(KERN_ERR
"%s: acpi_get_parent() failed "
262 "(0x%x) for: %s\n", __func__
, status
,
263 (char *)name_buffer
.pointer
);
264 panic("%s: Unable to find host devfn\n", __func__
);
266 if (parent
== rootbus_handle
)
271 printk(KERN_ERR
"%s: Unable to find root bus for: %s\n",
272 __func__
, (char *)name_buffer
.pointer
);
276 status
= acpi_evaluate_integer(child
, METHOD_NAME__ADR
, NULL
, &adr
);
277 if (ACPI_FAILURE(status
)) {
278 printk(KERN_ERR
"%s: Unable to get _ADR (0x%x) for: %s\n",
279 __func__
, status
, (char *)name_buffer
.pointer
);
280 panic("%s: Unable to find host devfn\n", __func__
);
283 kfree(name_buffer
.pointer
);
285 slot
= (adr
>> 16) & 0xffff;
286 function
= adr
& 0xffff;
287 devfn
= PCI_DEVFN(slot
, function
);
292 * find_matching_device - Callback routine to find the ACPI device
293 * that matches up with our pci_dev device.
294 * Matching is done on bus number and devfn.
295 * To find the bus number for a particular
296 * ACPI device, we must look at the _BBN method
300 find_matching_device(acpi_handle handle
, u32 lvl
, void *context
, void **rv
)
302 unsigned long long bbn
= -1;
303 unsigned long long adr
;
304 acpi_handle parent
= NULL
;
309 struct sn_pcidev_match
*info
= context
;
310 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
312 status
= acpi_evaluate_integer(handle
, METHOD_NAME__ADR
, NULL
,
314 if (ACPI_SUCCESS(status
)) {
315 status
= acpi_get_parent(handle
, &parent
);
316 if (ACPI_FAILURE(status
)) {
317 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
319 "%s: acpi_get_parent() failed (0x%x) for: %s\n",
320 __func__
, status
, (char *)name_buffer
.pointer
);
321 kfree(name_buffer
.pointer
);
324 status
= acpi_evaluate_integer(parent
, METHOD_NAME__BBN
,
326 if (ACPI_FAILURE(status
)) {
327 acpi_get_name(handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
329 "%s: Failed to find _BBN in parent of: %s\n",
330 __func__
, (char *)name_buffer
.pointer
);
331 kfree(name_buffer
.pointer
);
335 slot
= (adr
>> 16) & 0xffff;
336 function
= adr
& 0xffff;
337 devfn
= PCI_DEVFN(slot
, function
);
338 if ((info
->devfn
== devfn
) && (info
->bus
== bbn
)) {
339 /* We have a match! */
340 info
->handle
= handle
;
348 * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
349 * device matching the specified pci_dev,
350 * and return the pcidev info and irq info.
353 sn_acpi_get_pcidev_info(struct pci_dev
*dev
, struct pcidev_info
**pcidev_info
,
354 struct sn_irq_info
**sn_irq_info
)
356 unsigned int host_devfn
;
357 struct sn_pcidev_match pcidev_match
;
358 acpi_handle rootbus_handle
;
359 unsigned long long segment
;
361 struct acpi_buffer name_buffer
= { ACPI_ALLOCATE_BUFFER
, NULL
};
363 rootbus_handle
= acpi_device_handle(PCI_CONTROLLER(dev
)->companion
);
364 status
= acpi_evaluate_integer(rootbus_handle
, METHOD_NAME__SEG
, NULL
,
366 if (ACPI_SUCCESS(status
)) {
367 if (segment
!= pci_domain_nr(dev
)) {
368 acpi_get_name(rootbus_handle
, ACPI_FULL_PATHNAME
,
371 "%s: Segment number mismatch, 0x%llx vs 0x%x for: %s\n",
372 __func__
, segment
, pci_domain_nr(dev
),
373 (char *)name_buffer
.pointer
);
374 kfree(name_buffer
.pointer
);
378 acpi_get_name(rootbus_handle
, ACPI_FULL_PATHNAME
, &name_buffer
);
379 printk(KERN_ERR
"%s: Unable to get __SEG from: %s\n",
380 __func__
, (char *)name_buffer
.pointer
);
381 kfree(name_buffer
.pointer
);
386 * We want to search all devices in this segment/domain
387 * of the ACPI namespace for the matching ACPI device,
388 * which holds the pcidev_info pointer in its vendor resource.
390 pcidev_match
.bus
= dev
->bus
->number
;
391 pcidev_match
.devfn
= dev
->devfn
;
392 pcidev_match
.handle
= NULL
;
394 acpi_walk_namespace(ACPI_TYPE_DEVICE
, rootbus_handle
, ACPI_UINT32_MAX
,
395 find_matching_device
, NULL
, &pcidev_match
, NULL
);
397 if (!pcidev_match
.handle
) {
399 "%s: Could not find matching ACPI device for %s.\n",
400 __func__
, pci_name(dev
));
404 if (sn_extract_device_info(pcidev_match
.handle
, pcidev_info
, sn_irq_info
))
407 /* Build up the pcidev_info.pdi_slot_host_handle */
408 host_devfn
= get_host_devfn(pcidev_match
.handle
, rootbus_handle
);
409 (*pcidev_info
)->pdi_slot_host_handle
=
410 ((unsigned long) pci_domain_nr(dev
) << 40) |
417 * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
418 * Perform any SN specific slot fixup.
419 * At present there does not appear to be
420 * any generic way to handle a ROM image
421 * that has been shadowed by the PROM, so
422 * we pass a pointer to it within the
423 * pcidev_info structure.
427 sn_acpi_slot_fixup(struct pci_dev
*dev
)
430 struct pcidev_info
*pcidev_info
= NULL
;
431 struct sn_irq_info
*sn_irq_info
= NULL
;
432 size_t image_size
, size
;
434 if (sn_acpi_get_pcidev_info(dev
, &pcidev_info
, &sn_irq_info
)) {
435 panic("%s: Failure obtaining pcidev_info for %s\n",
436 __func__
, pci_name(dev
));
439 if (pcidev_info
->pdi_pio_mapped_addr
[PCI_ROM_RESOURCE
]) {
441 * A valid ROM image exists and has been shadowed by the
442 * PROM. Setup the pci_dev ROM resource with the address
443 * of the shadowed copy, and the actual length of the ROM image.
445 size
= pci_resource_len(dev
, PCI_ROM_RESOURCE
);
446 addr
= ioremap(pcidev_info
->pdi_pio_mapped_addr
[PCI_ROM_RESOURCE
],
448 image_size
= pci_get_rom_size(dev
, addr
, size
);
449 dev
->resource
[PCI_ROM_RESOURCE
].start
= (unsigned long) addr
;
450 dev
->resource
[PCI_ROM_RESOURCE
].end
=
451 (unsigned long) addr
+ image_size
- 1;
452 dev
->resource
[PCI_ROM_RESOURCE
].flags
|= IORESOURCE_ROM_BIOS_COPY
;
454 sn_pci_fixup_slot(dev
, pcidev_info
, sn_irq_info
);
457 EXPORT_SYMBOL(sn_acpi_slot_fixup
);
461 * sn_acpi_bus_fixup - Perform SN specific setup of software structs
462 * (pcibus_bussoft, pcidev_info) and hardware
463 * registers, for the specified bus and devices under it.
466 sn_acpi_bus_fixup(struct pci_bus
*bus
)
468 struct pci_dev
*pci_dev
= NULL
;
469 struct pcibus_bussoft
*prom_bussoft_ptr
;
471 if (!bus
->parent
) { /* If root bus */
472 prom_bussoft_ptr
= sn_get_bussoft_ptr(bus
);
473 if (prom_bussoft_ptr
== NULL
) {
475 "%s: 0x%04x:0x%02x Unable to "
476 "obtain prom_bussoft_ptr\n",
477 __func__
, pci_domain_nr(bus
), bus
->number
);
480 sn_common_bus_fixup(bus
, prom_bussoft_ptr
);
482 list_for_each_entry(pci_dev
, &bus
->devices
, bus_list
) {
483 sn_acpi_slot_fixup(pci_dev
);
488 * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
489 * nodes and root buses in the DSDT. As a result, bus scanning
490 * will be initiated by the Linux ACPI code.
494 sn_io_acpi_init(void)
499 /* SN Altix does not follow the IOSAPIC IRQ routing model */
500 acpi_irq_model
= ACPI_IRQ_MODEL_PLATFORM
;
502 /* Setup hubdev_info for all SGIHUB/SGITIO devices */
503 acpi_get_devices("SGIHUB", sn_acpi_hubdev_init
, NULL
, NULL
);
504 acpi_get_devices("SGITIO", sn_acpi_hubdev_init
, NULL
, NULL
);
506 status
= sal_ioif_init(&result
);
507 if (status
|| result
)
508 panic("sal_ioif_init failed: [%lx] %s\n",
509 status
, ia64_sal_strerror(status
));