• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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
4  * for more details.
5  *
6  * Copyright (C) 2006 Silicon Graphics, Inc. All rights reserved.
7  */
8 
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>
18 
19 
20 /*
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)
23  */
24 
25 
26 /*
27  * This value must match the UUID the PROM uses
28  * (io/acpi/defblk.c) when building a vendor descriptor.
29  */
30 struct acpi_vendor_uuid sn_uuid = {
31 	.subtype = 0,
32 	.data	= { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
33 		    0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
34 };
35 
36 struct sn_pcidev_match {
37 	u8 bus;
38 	unsigned int devfn;
39 	acpi_handle handle;
40 };
41 
42 /*
43  * Perform the early IO init in PROM.
44  */
45 static long
sal_ioif_init(u64 * result)46 sal_ioif_init(u64 *result)
47 {
48 	struct ia64_sal_retval isrv = {0,0,0,0};
49 
50 	SAL_CALL_NOLOCK(isrv,
51 			SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
52 	*result = isrv.v0;
53 	return isrv.status;
54 }
55 
56 /*
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.
62  */
63 
64 static acpi_status __init
sn_acpi_hubdev_init(acpi_handle handle,u32 depth,void * context,void ** ret)65 sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
66 {
67 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
68 	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
69 	u64 addr;
70 	struct hubdev_info *hubdev;
71 	struct hubdev_info *hubdev_ptr;
72 	int i;
73 	u64 nasid;
74 	struct acpi_resource *resource;
75 	acpi_status status;
76 	struct acpi_resource_vendor_typed *vendor;
77 	extern void sn_common_hubdev_init(struct hubdev_info *);
78 
79 	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
80 					  &sn_uuid, &buffer);
81 	if (ACPI_FAILURE(status)) {
82 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
83 		printk(KERN_ERR
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 */
89 	}
90 
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);
96 		printk(KERN_ERR
97 		       "sn_acpi_hubdev_init: Invalid vendor data length: "
98 		       "%d for: %s\n",
99 			vendor->byte_length, (char *)name_buffer.pointer);
100 		kfree(name_buffer.pointer);
101 		goto exit;
102 	}
103 
104 	memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
105 	hubdev_ptr = __va((struct hubdev_info *) addr);
106 
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);
112 
113 exit:
114 	kfree(buffer.pointer);
115 	return AE_OK;		/* Continue walking namespace */
116 }
117 
118 /*
119  * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
120  *			  the ACPI Vendor resource for this bus.
121  */
122 static struct pcibus_bussoft *
sn_get_bussoft_ptr(struct pci_bus * bus)123 sn_get_bussoft_ptr(struct pci_bus *bus)
124 {
125 	u64 addr;
126 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
127 	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
128 	acpi_handle handle;
129 	struct pcibus_bussoft *prom_bussoft_ptr;
130 	struct acpi_resource *resource;
131 	acpi_status status;
132 	struct acpi_resource_vendor_typed *vendor;
133 
134 
135 	handle = PCI_CONTROLLER(bus)->acpi_handle;
136 	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
137 					  &sn_uuid, &buffer);
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);
144 		return NULL;
145 	}
146 	resource = buffer.pointer;
147 	vendor = &resource->data.vendor_typed;
148 
149 	if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
150 	     sizeof(struct pcibus_bussoft *)) {
151 		printk(KERN_ERR
152 		       "%s: Invalid vendor data length %d\n",
153 			__func__, vendor->byte_length);
154 		kfree(buffer.pointer);
155 		return NULL;
156 	}
157 	memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
158 	prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
159 	kfree(buffer.pointer);
160 
161 	return prom_bussoft_ptr;
162 }
163 
164 /*
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.
169  */
170 static int
sn_extract_device_info(acpi_handle handle,struct pcidev_info ** pcidev_info,struct sn_irq_info ** sn_irq_info)171 sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
172 		    struct sn_irq_info **sn_irq_info)
173 {
174 	u64 addr;
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;
180 	int ret = 0;
181 	acpi_status status;
182 	struct acpi_resource_vendor_typed *vendor;
183 
184 	/*
185 	 * The pointer to this device's pcidev_info structure in
186 	 * the PROM, is in the vendor resource.
187 	 */
188 	status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
189 					  &sn_uuid, &buffer);
190 	if (ACPI_FAILURE(status)) {
191 		acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
192 		printk(KERN_ERR
193 		       "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
194 			__func__, status, (char *)name_buffer.pointer);
195 		kfree(name_buffer.pointer);
196 		return 1;
197 	}
198 
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);
204 		printk(KERN_ERR
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);
209 		ret = 1;
210 		goto exit;
211 	}
212 
213 	pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
214 	if (!pcidev_ptr)
215 		panic("%s: Unable to alloc memory for pcidev_info", __func__);
216 
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));
220 
221 	/* Get the IRQ info */
222 	irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
223 	if (!irq_info)
224 		 panic("%s: Unable to alloc memory for sn_irq_info", __func__);
225 
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));
229 	}
230 
231 	*pcidev_info = pcidev_ptr;
232 	*sn_irq_info = irq_info;
233 
234 exit:
235 	kfree(buffer.pointer);
236 	return ret;
237 }
238 
239 static unsigned int
get_host_devfn(acpi_handle device_handle,acpi_handle rootbus_handle)240 get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
241 {
242 	unsigned long long adr;
243 	acpi_handle child;
244 	unsigned int devfn;
245 	int function;
246 	acpi_handle parent;
247 	int slot;
248 	acpi_status status;
249 	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
250 
251 	acpi_get_name(device_handle, ACPI_FULL_PATHNAME, &name_buffer);
252 
253 	/*
254 	 * Do an upward search to find the root bus device, and
255 	 * obtain the host devfn from the previous child device.
256 	 */
257 	child = device_handle;
258 	while (child) {
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__);
265 		}
266 		if (parent == rootbus_handle)
267 			break;
268 		child = parent;
269 	}
270 	if (!child) {
271 		printk(KERN_ERR "%s: Unable to find root bus for: %s\n",
272 		       __func__, (char *)name_buffer.pointer);
273 		BUG();
274 	}
275 
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__);
281 	}
282 
283 	kfree(name_buffer.pointer);
284 
285 	slot = (adr >> 16) & 0xffff;
286 	function = adr & 0xffff;
287 	devfn = PCI_DEVFN(slot, function);
288 	return devfn;
289 }
290 
291 /*
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
297  *			  of its parent.
298  */
299 static acpi_status
find_matching_device(acpi_handle handle,u32 lvl,void * context,void ** rv)300 find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
301 {
302 	unsigned long long bbn = -1;
303 	unsigned long long adr;
304 	acpi_handle parent = NULL;
305 	acpi_status status;
306 	unsigned int devfn;
307 	int function;
308 	int slot;
309 	struct sn_pcidev_match *info = context;
310 	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
311 
312         status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
313                                        &adr);
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);
318 			printk(KERN_ERR
319 			       "%s: acpi_get_parent() failed (0x%x) for: %s\n",
320 				__func__, status, (char *)name_buffer.pointer);
321 			kfree(name_buffer.pointer);
322 			return AE_OK;
323 		}
324 		status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
325 					       NULL, &bbn);
326 		if (ACPI_FAILURE(status)) {
327 			acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
328 			printk(KERN_ERR
329 			  "%s: Failed to find _BBN in parent of: %s\n",
330 					__func__, (char *)name_buffer.pointer);
331 			kfree(name_buffer.pointer);
332 			return AE_OK;
333 		}
334 
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;
341 			return 1;
342 		}
343 	}
344 	return AE_OK;
345 }
346 
347 /*
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.
351  */
352 int
sn_acpi_get_pcidev_info(struct pci_dev * dev,struct pcidev_info ** pcidev_info,struct sn_irq_info ** sn_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)
355 {
356 	unsigned int host_devfn;
357 	struct sn_pcidev_match pcidev_match;
358 	acpi_handle rootbus_handle;
359 	unsigned long long segment;
360 	acpi_status status;
361 	struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
362 
363 	rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
364         status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
365                                        &segment);
366         if (ACPI_SUCCESS(status)) {
367 		if (segment != pci_domain_nr(dev)) {
368 			acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME,
369 				&name_buffer);
370 			printk(KERN_ERR
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);
375 			return 1;
376 		}
377 	} else {
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);
382 		return 1;
383 	}
384 
385 	/*
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.
389 	 */
390 	pcidev_match.bus = dev->bus->number;
391 	pcidev_match.devfn = dev->devfn;
392 	pcidev_match.handle = NULL;
393 
394 	acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
395 			    find_matching_device, NULL, &pcidev_match, NULL);
396 
397 	if (!pcidev_match.handle) {
398 		printk(KERN_ERR
399 		       "%s: Could not find matching ACPI device for %s.\n",
400 		       __func__, pci_name(dev));
401 		return 1;
402 	}
403 
404 	if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
405 		return 1;
406 
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) |
411 					/* bus == 0 */
412 					host_devfn;
413 	return 0;
414 }
415 
416 /*
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.
424  */
425 
426 void
sn_acpi_slot_fixup(struct pci_dev * dev)427 sn_acpi_slot_fixup(struct pci_dev *dev)
428 {
429 	void __iomem *addr;
430 	struct pcidev_info *pcidev_info = NULL;
431 	struct sn_irq_info *sn_irq_info = NULL;
432 	size_t image_size, size;
433 
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));
437 	}
438 
439 	if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
440 		/*
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.
444 		 */
445 		size = pci_resource_len(dev, PCI_ROM_RESOURCE);
446 		addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
447 			       size);
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;
453 	}
454 	sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
455 }
456 
457 EXPORT_SYMBOL(sn_acpi_slot_fixup);
458 
459 
460 /*
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.
464  */
465 void
sn_acpi_bus_fixup(struct pci_bus * bus)466 sn_acpi_bus_fixup(struct pci_bus *bus)
467 {
468 	struct pci_dev *pci_dev = NULL;
469 	struct pcibus_bussoft *prom_bussoft_ptr;
470 
471 	if (!bus->parent) {	/* If root bus */
472 		prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
473 		if (prom_bussoft_ptr == NULL) {
474 			printk(KERN_ERR
475 			       "%s: 0x%04x:0x%02x Unable to "
476 			       "obtain prom_bussoft_ptr\n",
477 			       __func__, pci_domain_nr(bus), bus->number);
478 			return;
479 		}
480 		sn_common_bus_fixup(bus, prom_bussoft_ptr);
481 	}
482 	list_for_each_entry(pci_dev, &bus->devices, bus_list) {
483 		sn_acpi_slot_fixup(pci_dev);
484 	}
485 }
486 
487 /*
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.
491  */
492 
493 void __init
sn_io_acpi_init(void)494 sn_io_acpi_init(void)
495 {
496 	u64 result;
497 	long status;
498 
499 	/* SN Altix does not follow the IOSAPIC IRQ routing model */
500 	acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
501 
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);
505 
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));
510 }
511