hwpci.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /*******************************************************************************
  3. *
  4. * Module Name: hwpci - Obtain PCI bus, device, and function numbers
  5. *
  6. ******************************************************************************/
  7. #include <acpi/acpi.h>
  8. #include "accommon.h"
  9. #define _COMPONENT ACPI_NAMESPACE
  10. ACPI_MODULE_NAME("hwpci")
  11. /* PCI configuration space values */
  12. #define PCI_CFG_HEADER_TYPE_REG 0x0E
  13. #define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18
  14. #define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19
  15. /* PCI header values */
  16. #define PCI_HEADER_TYPE_MASK 0x7F
  17. #define PCI_TYPE_BRIDGE 0x01
  18. #define PCI_TYPE_CARDBUS_BRIDGE 0x02
  19. typedef struct acpi_pci_device {
  20. acpi_handle device;
  21. struct acpi_pci_device *next;
  22. } acpi_pci_device;
  23. /* Local prototypes */
  24. static acpi_status
  25. acpi_hw_build_pci_list(acpi_handle root_pci_device,
  26. acpi_handle pci_region,
  27. struct acpi_pci_device **return_list_head);
  28. static acpi_status
  29. acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
  30. struct acpi_pci_device *list_head);
  31. static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head);
  32. static acpi_status
  33. acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
  34. acpi_handle pci_device,
  35. u16 *bus_number, u8 *is_bridge);
  36. /*******************************************************************************
  37. *
  38. * FUNCTION: acpi_hw_derive_pci_id
  39. *
  40. * PARAMETERS: pci_id - Initial values for the PCI ID. May be
  41. * modified by this function.
  42. * root_pci_device - A handle to a PCI device object. This
  43. * object must be a PCI Root Bridge having a
  44. * _HID value of either PNP0A03 or PNP0A08
  45. * pci_region - A handle to a PCI configuration space
  46. * Operation Region being initialized
  47. *
  48. * RETURN: Status
  49. *
  50. * DESCRIPTION: This function derives a full PCI ID for a PCI device,
  51. * consisting of a Segment number, Bus number, Device number,
  52. * and function code.
  53. *
  54. * The PCI hardware dynamically configures PCI bus numbers
  55. * depending on the bus topology discovered during system
  56. * initialization. This function is invoked during configuration
  57. * of a PCI_Config Operation Region in order to (possibly) update
  58. * the Bus/Device/Function numbers in the pci_id with the actual
  59. * values as determined by the hardware and operating system
  60. * configuration.
  61. *
  62. * The pci_id parameter is initially populated during the Operation
  63. * Region initialization. This function is then called, and is
  64. * will make any necessary modifications to the Bus, Device, or
  65. * Function number PCI ID subfields as appropriate for the
  66. * current hardware and OS configuration.
  67. *
  68. * NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id
  69. * interface since this feature is OS-independent. This module
  70. * specifically avoids any use of recursion by building a local
  71. * temporary device list.
  72. *
  73. ******************************************************************************/
  74. acpi_status
  75. acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id,
  76. acpi_handle root_pci_device, acpi_handle pci_region)
  77. {
  78. acpi_status status;
  79. struct acpi_pci_device *list_head;
  80. ACPI_FUNCTION_TRACE(hw_derive_pci_id);
  81. if (!pci_id) {
  82. return_ACPI_STATUS(AE_BAD_PARAMETER);
  83. }
  84. /* Build a list of PCI devices, from pci_region up to root_pci_device */
  85. status =
  86. acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head);
  87. if (ACPI_SUCCESS(status)) {
  88. /* Walk the list, updating the PCI device/function/bus numbers */
  89. status = acpi_hw_process_pci_list(pci_id, list_head);
  90. /* Delete the list */
  91. acpi_hw_delete_pci_list(list_head);
  92. }
  93. return_ACPI_STATUS(status);
  94. }
  95. /*******************************************************************************
  96. *
  97. * FUNCTION: acpi_hw_build_pci_list
  98. *
  99. * PARAMETERS: root_pci_device - A handle to a PCI device object. This
  100. * object is guaranteed to be a PCI Root
  101. * Bridge having a _HID value of either
  102. * PNP0A03 or PNP0A08
  103. * pci_region - A handle to the PCI configuration space
  104. * Operation Region
  105. * return_list_head - Where the PCI device list is returned
  106. *
  107. * RETURN: Status
  108. *
  109. * DESCRIPTION: Builds a list of devices from the input PCI region up to the
  110. * Root PCI device for this namespace subtree.
  111. *
  112. ******************************************************************************/
  113. static acpi_status
  114. acpi_hw_build_pci_list(acpi_handle root_pci_device,
  115. acpi_handle pci_region,
  116. struct acpi_pci_device **return_list_head)
  117. {
  118. acpi_handle current_device;
  119. acpi_handle parent_device;
  120. acpi_status status;
  121. struct acpi_pci_device *list_element;
  122. /*
  123. * Ascend namespace branch until the root_pci_device is reached, building
  124. * a list of device nodes. Loop will exit when either the PCI device is
  125. * found, or the root of the namespace is reached.
  126. */
  127. *return_list_head = NULL;
  128. current_device = pci_region;
  129. while (1) {
  130. status = acpi_get_parent(current_device, &parent_device);
  131. if (ACPI_FAILURE(status)) {
  132. /* Must delete the list before exit */
  133. acpi_hw_delete_pci_list(*return_list_head);
  134. return (status);
  135. }
  136. /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */
  137. if (parent_device == root_pci_device) {
  138. return (AE_OK);
  139. }
  140. list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device));
  141. if (!list_element) {
  142. /* Must delete the list before exit */
  143. acpi_hw_delete_pci_list(*return_list_head);
  144. return (AE_NO_MEMORY);
  145. }
  146. /* Put new element at the head of the list */
  147. list_element->next = *return_list_head;
  148. list_element->device = parent_device;
  149. *return_list_head = list_element;
  150. current_device = parent_device;
  151. }
  152. }
  153. /*******************************************************************************
  154. *
  155. * FUNCTION: acpi_hw_process_pci_list
  156. *
  157. * PARAMETERS: pci_id - Initial values for the PCI ID. May be
  158. * modified by this function.
  159. * list_head - Device list created by
  160. * acpi_hw_build_pci_list
  161. *
  162. * RETURN: Status
  163. *
  164. * DESCRIPTION: Walk downward through the PCI device list, getting the device
  165. * info for each, via the PCI configuration space and updating
  166. * the PCI ID as necessary. Deletes the list during traversal.
  167. *
  168. ******************************************************************************/
  169. static acpi_status
  170. acpi_hw_process_pci_list(struct acpi_pci_id *pci_id,
  171. struct acpi_pci_device *list_head)
  172. {
  173. acpi_status status = AE_OK;
  174. struct acpi_pci_device *info;
  175. u16 bus_number;
  176. u8 is_bridge = TRUE;
  177. ACPI_FUNCTION_NAME(hw_process_pci_list);
  178. ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  179. "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n",
  180. pci_id->segment, pci_id->bus, pci_id->device,
  181. pci_id->function));
  182. bus_number = pci_id->bus;
  183. /*
  184. * Descend down the namespace tree, collecting PCI device, function,
  185. * and bus numbers. bus_number is only important for PCI bridges.
  186. * Algorithm: As we descend the tree, use the last valid PCI device,
  187. * function, and bus numbers that are discovered, and assign them
  188. * to the PCI ID for the target device.
  189. */
  190. info = list_head;
  191. while (info) {
  192. status = acpi_hw_get_pci_device_info(pci_id, info->device,
  193. &bus_number, &is_bridge);
  194. if (ACPI_FAILURE(status)) {
  195. return (status);
  196. }
  197. info = info->next;
  198. }
  199. ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,
  200. "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X "
  201. "Status %X BusNumber %X IsBridge %X\n",
  202. pci_id->segment, pci_id->bus, pci_id->device,
  203. pci_id->function, status, bus_number, is_bridge));
  204. return (AE_OK);
  205. }
  206. /*******************************************************************************
  207. *
  208. * FUNCTION: acpi_hw_delete_pci_list
  209. *
  210. * PARAMETERS: list_head - Device list created by
  211. * acpi_hw_build_pci_list
  212. *
  213. * RETURN: None
  214. *
  215. * DESCRIPTION: Free the entire PCI list.
  216. *
  217. ******************************************************************************/
  218. static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head)
  219. {
  220. struct acpi_pci_device *next;
  221. struct acpi_pci_device *previous;
  222. next = list_head;
  223. while (next) {
  224. previous = next;
  225. next = previous->next;
  226. ACPI_FREE(previous);
  227. }
  228. }
  229. /*******************************************************************************
  230. *
  231. * FUNCTION: acpi_hw_get_pci_device_info
  232. *
  233. * PARAMETERS: pci_id - Initial values for the PCI ID. May be
  234. * modified by this function.
  235. * pci_device - Handle for the PCI device object
  236. * bus_number - Where a PCI bridge bus number is returned
  237. * is_bridge - Return value, indicates if this PCI
  238. * device is a PCI bridge
  239. *
  240. * RETURN: Status
  241. *
  242. * DESCRIPTION: Get the device info for a single PCI device object. Get the
  243. * _ADR (contains PCI device and function numbers), and for PCI
  244. * bridge devices, get the bus number from PCI configuration
  245. * space.
  246. *
  247. ******************************************************************************/
  248. static acpi_status
  249. acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
  250. acpi_handle pci_device,
  251. u16 *bus_number, u8 *is_bridge)
  252. {
  253. acpi_status status;
  254. acpi_object_type object_type;
  255. u64 return_value;
  256. u64 pci_value;
  257. /* We only care about objects of type Device */
  258. status = acpi_get_type(pci_device, &object_type);
  259. if (ACPI_FAILURE(status)) {
  260. return (status);
  261. }
  262. if (object_type != ACPI_TYPE_DEVICE) {
  263. return (AE_OK);
  264. }
  265. /* We need an _ADR. Ignore device if not present */
  266. status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR,
  267. pci_device, &return_value);
  268. if (ACPI_FAILURE(status)) {
  269. return (AE_OK);
  270. }
  271. /*
  272. * From _ADR, get the PCI Device and Function and
  273. * update the PCI ID.
  274. */
  275. pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value));
  276. pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value));
  277. /*
  278. * If the previous device was a bridge, use the previous
  279. * device bus number
  280. */
  281. if (*is_bridge) {
  282. pci_id->bus = *bus_number;
  283. }
  284. /*
  285. * Get the bus numbers from PCI Config space:
  286. *
  287. * First, get the PCI header_type
  288. */
  289. *is_bridge = FALSE;
  290. status = acpi_os_read_pci_configuration(pci_id,
  291. PCI_CFG_HEADER_TYPE_REG,
  292. &pci_value, 8);
  293. if (ACPI_FAILURE(status)) {
  294. return (status);
  295. }
  296. /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */
  297. pci_value &= PCI_HEADER_TYPE_MASK;
  298. if ((pci_value != PCI_TYPE_BRIDGE) &&
  299. (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) {
  300. return (AE_OK);
  301. }
  302. /* Bridge: Get the Primary bus_number */
  303. status = acpi_os_read_pci_configuration(pci_id,
  304. PCI_CFG_PRIMARY_BUS_NUMBER_REG,
  305. &pci_value, 8);
  306. if (ACPI_FAILURE(status)) {
  307. return (status);
  308. }
  309. *is_bridge = TRUE;
  310. pci_id->bus = (u16)pci_value;
  311. /* Bridge: Get the Secondary bus_number */
  312. status = acpi_os_read_pci_configuration(pci_id,
  313. PCI_CFG_SECONDARY_BUS_NUMBER_REG,
  314. &pci_value, 8);
  315. if (ACPI_FAILURE(status)) {
  316. return (status);
  317. }
  318. *bus_number = (u16)pci_value;
  319. return (AE_OK);
  320. }