io_acpi_init.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511
  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. #include <asm/sn/types.h>
  9. #include <asm/sn/addrs.h>
  10. #include <asm/sn/pcidev.h>
  11. #include <asm/sn/pcibus_provider_defs.h>
  12. #include <asm/sn/sn_sal.h>
  13. #include "xtalk/hubdev.h"
  14. #include <linux/acpi.h>
  15. #include <linux/slab.h>
  16. #include <linux/export.h>
  17. /*
  18. * The code in this file will only be executed when running with
  19. * a PROM that has ACPI IO support. (i.e., SN_ACPI_BASE_SUPPORT() == 1)
  20. */
  21. /*
  22. * This value must match the UUID the PROM uses
  23. * (io/acpi/defblk.c) when building a vendor descriptor.
  24. */
  25. struct acpi_vendor_uuid sn_uuid = {
  26. .subtype = 0,
  27. .data = { 0x2c, 0xc6, 0xa6, 0xfe, 0x9c, 0x44, 0xda, 0x11,
  28. 0xa2, 0x7c, 0x08, 0x00, 0x69, 0x13, 0xea, 0x51 },
  29. };
  30. struct sn_pcidev_match {
  31. u8 bus;
  32. unsigned int devfn;
  33. acpi_handle handle;
  34. };
  35. /*
  36. * Perform the early IO init in PROM.
  37. */
  38. static long
  39. sal_ioif_init(u64 *result)
  40. {
  41. struct ia64_sal_retval isrv = {0,0,0,0};
  42. SAL_CALL_NOLOCK(isrv,
  43. SN_SAL_IOIF_INIT, 0, 0, 0, 0, 0, 0, 0);
  44. *result = isrv.v0;
  45. return isrv.status;
  46. }
  47. /*
  48. * sn_acpi_hubdev_init() - This function is called by acpi_ns_get_device_callback()
  49. * for all SGIHUB and SGITIO acpi devices defined in the
  50. * DSDT. It obtains the hubdev_info pointer from the
  51. * ACPI vendor resource, which the PROM setup, and sets up the
  52. * hubdev_info in the pda.
  53. */
  54. static acpi_status __init
  55. sn_acpi_hubdev_init(acpi_handle handle, u32 depth, void *context, void **ret)
  56. {
  57. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  58. struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  59. u64 addr;
  60. struct hubdev_info *hubdev;
  61. struct hubdev_info *hubdev_ptr;
  62. int i;
  63. u64 nasid;
  64. struct acpi_resource *resource;
  65. acpi_status status;
  66. struct acpi_resource_vendor_typed *vendor;
  67. extern void sn_common_hubdev_init(struct hubdev_info *);
  68. status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
  69. &sn_uuid, &buffer);
  70. if (ACPI_FAILURE(status)) {
  71. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  72. printk(KERN_ERR
  73. "sn_acpi_hubdev_init: acpi_get_vendor_resource() "
  74. "(0x%x) failed for: %s\n", status,
  75. (char *)name_buffer.pointer);
  76. kfree(name_buffer.pointer);
  77. return AE_OK; /* Continue walking namespace */
  78. }
  79. resource = buffer.pointer;
  80. vendor = &resource->data.vendor_typed;
  81. if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
  82. sizeof(struct hubdev_info *)) {
  83. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  84. printk(KERN_ERR
  85. "sn_acpi_hubdev_init: Invalid vendor data length: "
  86. "%d for: %s\n",
  87. vendor->byte_length, (char *)name_buffer.pointer);
  88. kfree(name_buffer.pointer);
  89. goto exit;
  90. }
  91. memcpy(&addr, vendor->byte_data, sizeof(struct hubdev_info *));
  92. hubdev_ptr = __va((struct hubdev_info *) addr);
  93. nasid = hubdev_ptr->hdi_nasid;
  94. i = nasid_to_cnodeid(nasid);
  95. hubdev = (struct hubdev_info *)(NODEPDA(i)->pdinfo);
  96. *hubdev = *hubdev_ptr;
  97. sn_common_hubdev_init(hubdev);
  98. exit:
  99. kfree(buffer.pointer);
  100. return AE_OK; /* Continue walking namespace */
  101. }
  102. /*
  103. * sn_get_bussoft_ptr() - The pcibus_bussoft pointer is found in
  104. * the ACPI Vendor resource for this bus.
  105. */
  106. static struct pcibus_bussoft *
  107. sn_get_bussoft_ptr(struct pci_bus *bus)
  108. {
  109. u64 addr;
  110. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  111. struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  112. acpi_handle handle;
  113. struct pcibus_bussoft *prom_bussoft_ptr;
  114. struct acpi_resource *resource;
  115. acpi_status status;
  116. struct acpi_resource_vendor_typed *vendor;
  117. handle = PCI_CONTROLLER(bus)->acpi_handle;
  118. status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
  119. &sn_uuid, &buffer);
  120. if (ACPI_FAILURE(status)) {
  121. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  122. printk(KERN_ERR "%s: "
  123. "acpi_get_vendor_resource() failed (0x%x) for: %s\n",
  124. __func__, status, (char *)name_buffer.pointer);
  125. kfree(name_buffer.pointer);
  126. return NULL;
  127. }
  128. resource = buffer.pointer;
  129. vendor = &resource->data.vendor_typed;
  130. if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
  131. sizeof(struct pcibus_bussoft *)) {
  132. printk(KERN_ERR
  133. "%s: Invalid vendor data length %d\n",
  134. __func__, vendor->byte_length);
  135. kfree(buffer.pointer);
  136. return NULL;
  137. }
  138. memcpy(&addr, vendor->byte_data, sizeof(struct pcibus_bussoft *));
  139. prom_bussoft_ptr = __va((struct pcibus_bussoft *) addr);
  140. kfree(buffer.pointer);
  141. return prom_bussoft_ptr;
  142. }
  143. /*
  144. * sn_extract_device_info - Extract the pcidev_info and the sn_irq_info
  145. * pointers from the vendor resource using the
  146. * provided acpi handle, and copy the structures
  147. * into the argument buffers.
  148. */
  149. static int
  150. sn_extract_device_info(acpi_handle handle, struct pcidev_info **pcidev_info,
  151. struct sn_irq_info **sn_irq_info)
  152. {
  153. u64 addr;
  154. struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  155. struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  156. struct sn_irq_info *irq_info, *irq_info_prom;
  157. struct pcidev_info *pcidev_ptr, *pcidev_prom_ptr;
  158. struct acpi_resource *resource;
  159. int ret = 0;
  160. acpi_status status;
  161. struct acpi_resource_vendor_typed *vendor;
  162. /*
  163. * The pointer to this device's pcidev_info structure in
  164. * the PROM, is in the vendor resource.
  165. */
  166. status = acpi_get_vendor_resource(handle, METHOD_NAME__CRS,
  167. &sn_uuid, &buffer);
  168. if (ACPI_FAILURE(status)) {
  169. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  170. printk(KERN_ERR
  171. "%s: acpi_get_vendor_resource() failed (0x%x) for: %s\n",
  172. __func__, status, (char *)name_buffer.pointer);
  173. kfree(name_buffer.pointer);
  174. return 1;
  175. }
  176. resource = buffer.pointer;
  177. vendor = &resource->data.vendor_typed;
  178. if ((vendor->byte_length - sizeof(struct acpi_vendor_uuid)) !=
  179. sizeof(struct pci_devdev_info *)) {
  180. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  181. printk(KERN_ERR
  182. "%s: Invalid vendor data length: %d for: %s\n",
  183. __func__, vendor->byte_length,
  184. (char *)name_buffer.pointer);
  185. kfree(name_buffer.pointer);
  186. ret = 1;
  187. goto exit;
  188. }
  189. pcidev_ptr = kzalloc(sizeof(struct pcidev_info), GFP_KERNEL);
  190. if (!pcidev_ptr)
  191. panic("%s: Unable to alloc memory for pcidev_info", __func__);
  192. memcpy(&addr, vendor->byte_data, sizeof(struct pcidev_info *));
  193. pcidev_prom_ptr = __va(addr);
  194. memcpy(pcidev_ptr, pcidev_prom_ptr, sizeof(struct pcidev_info));
  195. /* Get the IRQ info */
  196. irq_info = kzalloc(sizeof(struct sn_irq_info), GFP_KERNEL);
  197. if (!irq_info)
  198. panic("%s: Unable to alloc memory for sn_irq_info", __func__);
  199. if (pcidev_ptr->pdi_sn_irq_info) {
  200. irq_info_prom = __va(pcidev_ptr->pdi_sn_irq_info);
  201. memcpy(irq_info, irq_info_prom, sizeof(struct sn_irq_info));
  202. }
  203. *pcidev_info = pcidev_ptr;
  204. *sn_irq_info = irq_info;
  205. exit:
  206. kfree(buffer.pointer);
  207. return ret;
  208. }
  209. static unsigned int
  210. get_host_devfn(acpi_handle device_handle, acpi_handle rootbus_handle)
  211. {
  212. unsigned long long adr;
  213. acpi_handle child;
  214. unsigned int devfn;
  215. int function;
  216. acpi_handle parent;
  217. int slot;
  218. acpi_status status;
  219. struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  220. acpi_get_name(device_handle, ACPI_FULL_PATHNAME, &name_buffer);
  221. /*
  222. * Do an upward search to find the root bus device, and
  223. * obtain the host devfn from the previous child device.
  224. */
  225. child = device_handle;
  226. while (child) {
  227. status = acpi_get_parent(child, &parent);
  228. if (ACPI_FAILURE(status)) {
  229. printk(KERN_ERR "%s: acpi_get_parent() failed "
  230. "(0x%x) for: %s\n", __func__, status,
  231. (char *)name_buffer.pointer);
  232. panic("%s: Unable to find host devfn\n", __func__);
  233. }
  234. if (parent == rootbus_handle)
  235. break;
  236. child = parent;
  237. }
  238. if (!child) {
  239. printk(KERN_ERR "%s: Unable to find root bus for: %s\n",
  240. __func__, (char *)name_buffer.pointer);
  241. BUG();
  242. }
  243. status = acpi_evaluate_integer(child, METHOD_NAME__ADR, NULL, &adr);
  244. if (ACPI_FAILURE(status)) {
  245. printk(KERN_ERR "%s: Unable to get _ADR (0x%x) for: %s\n",
  246. __func__, status, (char *)name_buffer.pointer);
  247. panic("%s: Unable to find host devfn\n", __func__);
  248. }
  249. kfree(name_buffer.pointer);
  250. slot = (adr >> 16) & 0xffff;
  251. function = adr & 0xffff;
  252. devfn = PCI_DEVFN(slot, function);
  253. return devfn;
  254. }
  255. /*
  256. * find_matching_device - Callback routine to find the ACPI device
  257. * that matches up with our pci_dev device.
  258. * Matching is done on bus number and devfn.
  259. * To find the bus number for a particular
  260. * ACPI device, we must look at the _BBN method
  261. * of its parent.
  262. */
  263. static acpi_status
  264. find_matching_device(acpi_handle handle, u32 lvl, void *context, void **rv)
  265. {
  266. unsigned long long bbn = -1;
  267. unsigned long long adr;
  268. acpi_handle parent = NULL;
  269. acpi_status status;
  270. unsigned int devfn;
  271. int function;
  272. int slot;
  273. struct sn_pcidev_match *info = context;
  274. struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  275. status = acpi_evaluate_integer(handle, METHOD_NAME__ADR, NULL,
  276. &adr);
  277. if (ACPI_SUCCESS(status)) {
  278. status = acpi_get_parent(handle, &parent);
  279. if (ACPI_FAILURE(status)) {
  280. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  281. printk(KERN_ERR
  282. "%s: acpi_get_parent() failed (0x%x) for: %s\n",
  283. __func__, status, (char *)name_buffer.pointer);
  284. kfree(name_buffer.pointer);
  285. return AE_OK;
  286. }
  287. status = acpi_evaluate_integer(parent, METHOD_NAME__BBN,
  288. NULL, &bbn);
  289. if (ACPI_FAILURE(status)) {
  290. acpi_get_name(handle, ACPI_FULL_PATHNAME, &name_buffer);
  291. printk(KERN_ERR
  292. "%s: Failed to find _BBN in parent of: %s\n",
  293. __func__, (char *)name_buffer.pointer);
  294. kfree(name_buffer.pointer);
  295. return AE_OK;
  296. }
  297. slot = (adr >> 16) & 0xffff;
  298. function = adr & 0xffff;
  299. devfn = PCI_DEVFN(slot, function);
  300. if ((info->devfn == devfn) && (info->bus == bbn)) {
  301. /* We have a match! */
  302. info->handle = handle;
  303. return 1;
  304. }
  305. }
  306. return AE_OK;
  307. }
  308. /*
  309. * sn_acpi_get_pcidev_info - Search ACPI namespace for the acpi
  310. * device matching the specified pci_dev,
  311. * and return the pcidev info and irq info.
  312. */
  313. int
  314. sn_acpi_get_pcidev_info(struct pci_dev *dev, struct pcidev_info **pcidev_info,
  315. struct sn_irq_info **sn_irq_info)
  316. {
  317. unsigned int host_devfn;
  318. struct sn_pcidev_match pcidev_match;
  319. acpi_handle rootbus_handle;
  320. unsigned long long segment;
  321. acpi_status status;
  322. struct acpi_buffer name_buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  323. rootbus_handle = PCI_CONTROLLER(dev)->acpi_handle;
  324. status = acpi_evaluate_integer(rootbus_handle, METHOD_NAME__SEG, NULL,
  325. &segment);
  326. if (ACPI_SUCCESS(status)) {
  327. if (segment != pci_domain_nr(dev)) {
  328. acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME,
  329. &name_buffer);
  330. printk(KERN_ERR
  331. "%s: Segment number mismatch, 0x%llx vs 0x%x for: %s\n",
  332. __func__, segment, pci_domain_nr(dev),
  333. (char *)name_buffer.pointer);
  334. kfree(name_buffer.pointer);
  335. return 1;
  336. }
  337. } else {
  338. acpi_get_name(rootbus_handle, ACPI_FULL_PATHNAME, &name_buffer);
  339. printk(KERN_ERR "%s: Unable to get __SEG from: %s\n",
  340. __func__, (char *)name_buffer.pointer);
  341. kfree(name_buffer.pointer);
  342. return 1;
  343. }
  344. /*
  345. * We want to search all devices in this segment/domain
  346. * of the ACPI namespace for the matching ACPI device,
  347. * which holds the pcidev_info pointer in its vendor resource.
  348. */
  349. pcidev_match.bus = dev->bus->number;
  350. pcidev_match.devfn = dev->devfn;
  351. pcidev_match.handle = NULL;
  352. acpi_walk_namespace(ACPI_TYPE_DEVICE, rootbus_handle, ACPI_UINT32_MAX,
  353. find_matching_device, NULL, &pcidev_match, NULL);
  354. if (!pcidev_match.handle) {
  355. printk(KERN_ERR
  356. "%s: Could not find matching ACPI device for %s.\n",
  357. __func__, pci_name(dev));
  358. return 1;
  359. }
  360. if (sn_extract_device_info(pcidev_match.handle, pcidev_info, sn_irq_info))
  361. return 1;
  362. /* Build up the pcidev_info.pdi_slot_host_handle */
  363. host_devfn = get_host_devfn(pcidev_match.handle, rootbus_handle);
  364. (*pcidev_info)->pdi_slot_host_handle =
  365. ((unsigned long) pci_domain_nr(dev) << 40) |
  366. /* bus == 0 */
  367. host_devfn;
  368. return 0;
  369. }
  370. /*
  371. * sn_acpi_slot_fixup - Obtain the pcidev_info and sn_irq_info.
  372. * Perform any SN specific slot fixup.
  373. * At present there does not appear to be
  374. * any generic way to handle a ROM image
  375. * that has been shadowed by the PROM, so
  376. * we pass a pointer to it within the
  377. * pcidev_info structure.
  378. */
  379. void
  380. sn_acpi_slot_fixup(struct pci_dev *dev)
  381. {
  382. void __iomem *addr;
  383. struct pcidev_info *pcidev_info = NULL;
  384. struct sn_irq_info *sn_irq_info = NULL;
  385. size_t image_size, size;
  386. if (sn_acpi_get_pcidev_info(dev, &pcidev_info, &sn_irq_info)) {
  387. panic("%s: Failure obtaining pcidev_info for %s\n",
  388. __func__, pci_name(dev));
  389. }
  390. if (pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE]) {
  391. /*
  392. * A valid ROM image exists and has been shadowed by the
  393. * PROM. Setup the pci_dev ROM resource with the address
  394. * of the shadowed copy, and the actual length of the ROM image.
  395. */
  396. size = pci_resource_len(dev, PCI_ROM_RESOURCE);
  397. addr = ioremap(pcidev_info->pdi_pio_mapped_addr[PCI_ROM_RESOURCE],
  398. size);
  399. image_size = pci_get_rom_size(dev, addr, size);
  400. dev->resource[PCI_ROM_RESOURCE].start = (unsigned long) addr;
  401. dev->resource[PCI_ROM_RESOURCE].end =
  402. (unsigned long) addr + image_size - 1;
  403. dev->resource[PCI_ROM_RESOURCE].flags |= IORESOURCE_ROM_BIOS_COPY;
  404. }
  405. sn_pci_fixup_slot(dev, pcidev_info, sn_irq_info);
  406. }
  407. EXPORT_SYMBOL(sn_acpi_slot_fixup);
  408. /*
  409. * sn_acpi_bus_fixup - Perform SN specific setup of software structs
  410. * (pcibus_bussoft, pcidev_info) and hardware
  411. * registers, for the specified bus and devices under it.
  412. */
  413. void
  414. sn_acpi_bus_fixup(struct pci_bus *bus)
  415. {
  416. struct pci_dev *pci_dev = NULL;
  417. struct pcibus_bussoft *prom_bussoft_ptr;
  418. if (!bus->parent) { /* If root bus */
  419. prom_bussoft_ptr = sn_get_bussoft_ptr(bus);
  420. if (prom_bussoft_ptr == NULL) {
  421. printk(KERN_ERR
  422. "%s: 0x%04x:0x%02x Unable to "
  423. "obtain prom_bussoft_ptr\n",
  424. __func__, pci_domain_nr(bus), bus->number);
  425. return;
  426. }
  427. sn_common_bus_fixup(bus, prom_bussoft_ptr);
  428. }
  429. list_for_each_entry(pci_dev, &bus->devices, bus_list) {
  430. sn_acpi_slot_fixup(pci_dev);
  431. }
  432. }
  433. /*
  434. * sn_io_acpi_init - PROM has ACPI support for IO, defining at a minimum the
  435. * nodes and root buses in the DSDT. As a result, bus scanning
  436. * will be initiated by the Linux ACPI code.
  437. */
  438. void __init
  439. sn_io_acpi_init(void)
  440. {
  441. u64 result;
  442. long status;
  443. /* SN Altix does not follow the IOSAPIC IRQ routing model */
  444. acpi_irq_model = ACPI_IRQ_MODEL_PLATFORM;
  445. /* Setup hubdev_info for all SGIHUB/SGITIO devices */
  446. acpi_get_devices("SGIHUB", sn_acpi_hubdev_init, NULL, NULL);
  447. acpi_get_devices("SGITIO", sn_acpi_hubdev_init, NULL, NULL);
  448. status = sal_ioif_init(&result);
  449. if (status || result)
  450. panic("sal_ioif_init failed: [%lx] %s\n",
  451. status, ia64_sal_strerror(status));
  452. }