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