1 /******************************************************************************* 2 * 3 * Module Name: hwpci - Obtain PCI bus, device, and function numbers 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 47 #define _COMPONENT ACPI_NAMESPACE 48 ACPI_MODULE_NAME("hwpci") 49 50 /* PCI configuration space values */ 51 #define PCI_CFG_HEADER_TYPE_REG 0x0E 52 #define PCI_CFG_PRIMARY_BUS_NUMBER_REG 0x18 53 #define PCI_CFG_SECONDARY_BUS_NUMBER_REG 0x19 54 /* PCI header values */ 55 #define PCI_HEADER_TYPE_MASK 0x7F 56 #define PCI_TYPE_BRIDGE 0x01 57 #define PCI_TYPE_CARDBUS_BRIDGE 0x02 58 typedef struct acpi_pci_device { 59 acpi_handle device; 60 struct acpi_pci_device *next; 61 62 } acpi_pci_device; 63 64 /* Local prototypes */ 65 66 static acpi_status 67 acpi_hw_build_pci_list(acpi_handle root_pci_device, 68 acpi_handle pci_region, 69 struct acpi_pci_device **return_list_head); 70 71 static acpi_status 72 acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 73 struct acpi_pci_device *list_head); 74 75 static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head); 76 77 static acpi_status 78 acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, 79 acpi_handle pci_device, 80 u16 *bus_number, u8 *is_bridge); 81 82 /******************************************************************************* 83 * 84 * FUNCTION: acpi_hw_derive_pci_id 85 * 86 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 87 * modified by this function. 88 * root_pci_device - A handle to a PCI device object. This 89 * object must be a PCI Root Bridge having a 90 * _HID value of either PNP0A03 or PNP0A08 91 * pci_region - A handle to a PCI configuration space 92 * Operation Region being initialized 93 * 94 * RETURN: Status 95 * 96 * DESCRIPTION: This function derives a full PCI ID for a PCI device, 97 * consisting of a Segment number, Bus number, Device number, 98 * and function code. 99 * 100 * The PCI hardware dynamically configures PCI bus numbers 101 * depending on the bus topology discovered during system 102 * initialization. This function is invoked during configuration 103 * of a PCI_Config Operation Region in order to (possibly) update 104 * the Bus/Device/Function numbers in the pci_id with the actual 105 * values as determined by the hardware and operating system 106 * configuration. 107 * 108 * The pci_id parameter is initially populated during the Operation 109 * Region initialization. This function is then called, and is 110 * will make any necessary modifications to the Bus, Device, or 111 * Function number PCI ID subfields as appropriate for the 112 * current hardware and OS configuration. 113 * 114 * NOTE: Created 08/2010. Replaces the previous OSL acpi_os_derive_pci_id 115 * interface since this feature is OS-independent. This module 116 * specifically avoids any use of recursion by building a local 117 * temporary device list. 118 * 119 ******************************************************************************/ 120 121 acpi_status 122 acpi_hw_derive_pci_id(struct acpi_pci_id *pci_id, 123 acpi_handle root_pci_device, acpi_handle pci_region) 124 { 125 acpi_status status; 126 struct acpi_pci_device *list_head; 127 128 ACPI_FUNCTION_TRACE(hw_derive_pci_id); 129 130 if (!pci_id) { 131 return_ACPI_STATUS(AE_BAD_PARAMETER); 132 } 133 134 /* Build a list of PCI devices, from pci_region up to root_pci_device */ 135 136 status = 137 acpi_hw_build_pci_list(root_pci_device, pci_region, &list_head); 138 if (ACPI_SUCCESS(status)) { 139 140 /* Walk the list, updating the PCI device/function/bus numbers */ 141 142 status = acpi_hw_process_pci_list(pci_id, list_head); 143 144 /* Delete the list */ 145 146 acpi_hw_delete_pci_list(list_head); 147 } 148 149 return_ACPI_STATUS(status); 150 } 151 152 /******************************************************************************* 153 * 154 * FUNCTION: acpi_hw_build_pci_list 155 * 156 * PARAMETERS: root_pci_device - A handle to a PCI device object. This 157 * object is guaranteed to be a PCI Root 158 * Bridge having a _HID value of either 159 * PNP0A03 or PNP0A08 160 * pci_region - A handle to the PCI configuration space 161 * Operation Region 162 * return_list_head - Where the PCI device list is returned 163 * 164 * RETURN: Status 165 * 166 * DESCRIPTION: Builds a list of devices from the input PCI region up to the 167 * Root PCI device for this namespace subtree. 168 * 169 ******************************************************************************/ 170 171 static acpi_status 172 acpi_hw_build_pci_list(acpi_handle root_pci_device, 173 acpi_handle pci_region, 174 struct acpi_pci_device **return_list_head) 175 { 176 acpi_handle current_device; 177 acpi_handle parent_device; 178 acpi_status status; 179 struct acpi_pci_device *list_element; 180 181 /* 182 * Ascend namespace branch until the root_pci_device is reached, building 183 * a list of device nodes. Loop will exit when either the PCI device is 184 * found, or the root of the namespace is reached. 185 */ 186 *return_list_head = NULL; 187 current_device = pci_region; 188 while (1) { 189 status = acpi_get_parent(current_device, &parent_device); 190 if (ACPI_FAILURE(status)) { 191 192 /* Must delete the list before exit */ 193 194 acpi_hw_delete_pci_list(*return_list_head); 195 return (status); 196 } 197 198 /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ 199 200 if (parent_device == root_pci_device) { 201 return (AE_OK); 202 } 203 204 list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); 205 if (!list_element) { 206 207 /* Must delete the list before exit */ 208 209 acpi_hw_delete_pci_list(*return_list_head); 210 return (AE_NO_MEMORY); 211 } 212 213 /* Put new element at the head of the list */ 214 215 list_element->next = *return_list_head; 216 list_element->device = parent_device; 217 *return_list_head = list_element; 218 219 current_device = parent_device; 220 } 221 } 222 223 /******************************************************************************* 224 * 225 * FUNCTION: acpi_hw_process_pci_list 226 * 227 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 228 * modified by this function. 229 * list_head - Device list created by 230 * acpi_hw_build_pci_list 231 * 232 * RETURN: Status 233 * 234 * DESCRIPTION: Walk downward through the PCI device list, getting the device 235 * info for each, via the PCI configuration space and updating 236 * the PCI ID as necessary. Deletes the list during traversal. 237 * 238 ******************************************************************************/ 239 240 static acpi_status 241 acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 242 struct acpi_pci_device *list_head) 243 { 244 acpi_status status = AE_OK; 245 struct acpi_pci_device *info; 246 u16 bus_number; 247 u8 is_bridge = TRUE; 248 249 ACPI_FUNCTION_NAME(hw_process_pci_list); 250 251 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 252 "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", 253 pci_id->segment, pci_id->bus, pci_id->device, 254 pci_id->function)); 255 256 bus_number = pci_id->bus; 257 258 /* 259 * Descend down the namespace tree, collecting PCI device, function, 260 * and bus numbers. bus_number is only important for PCI bridges. 261 * Algorithm: As we descend the tree, use the last valid PCI device, 262 * function, and bus numbers that are discovered, and assign them 263 * to the PCI ID for the target device. 264 */ 265 info = list_head; 266 while (info) { 267 status = acpi_hw_get_pci_device_info(pci_id, info->device, 268 &bus_number, &is_bridge); 269 if (ACPI_FAILURE(status)) { 270 return (status); 271 } 272 273 info = info->next; 274 } 275 276 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 277 "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " 278 "Status %X BusNumber %X IsBridge %X\n", 279 pci_id->segment, pci_id->bus, pci_id->device, 280 pci_id->function, status, bus_number, is_bridge)); 281 282 return (AE_OK); 283 } 284 285 /******************************************************************************* 286 * 287 * FUNCTION: acpi_hw_delete_pci_list 288 * 289 * PARAMETERS: list_head - Device list created by 290 * acpi_hw_build_pci_list 291 * 292 * RETURN: None 293 * 294 * DESCRIPTION: Free the entire PCI list. 295 * 296 ******************************************************************************/ 297 298 static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head) 299 { 300 struct acpi_pci_device *next; 301 struct acpi_pci_device *previous; 302 303 next = list_head; 304 while (next) { 305 previous = next; 306 next = previous->next; 307 ACPI_FREE(previous); 308 } 309 } 310 311 /******************************************************************************* 312 * 313 * FUNCTION: acpi_hw_get_pci_device_info 314 * 315 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 316 * modified by this function. 317 * pci_device - Handle for the PCI device object 318 * bus_number - Where a PCI bridge bus number is returned 319 * is_bridge - Return value, indicates if this PCI 320 * device is a PCI bridge 321 * 322 * RETURN: Status 323 * 324 * DESCRIPTION: Get the device info for a single PCI device object. Get the 325 * _ADR (contains PCI device and function numbers), and for PCI 326 * bridge devices, get the bus number from PCI configuration 327 * space. 328 * 329 ******************************************************************************/ 330 331 static acpi_status 332 acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, 333 acpi_handle pci_device, 334 u16 *bus_number, u8 *is_bridge) 335 { 336 acpi_status status; 337 acpi_object_type object_type; 338 u64 return_value; 339 u64 pci_value; 340 341 /* We only care about objects of type Device */ 342 343 status = acpi_get_type(pci_device, &object_type); 344 if (ACPI_FAILURE(status)) { 345 return (status); 346 } 347 348 if (object_type != ACPI_TYPE_DEVICE) { 349 return (AE_OK); 350 } 351 352 /* We need an _ADR. Ignore device if not present */ 353 354 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, 355 pci_device, &return_value); 356 if (ACPI_FAILURE(status)) { 357 return (AE_OK); 358 } 359 360 /* 361 * From _ADR, get the PCI Device and Function and 362 * update the PCI ID. 363 */ 364 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value)); 365 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value)); 366 367 /* 368 * If the previous device was a bridge, use the previous 369 * device bus number 370 */ 371 if (*is_bridge) { 372 pci_id->bus = *bus_number; 373 } 374 375 /* 376 * Get the bus numbers from PCI Config space: 377 * 378 * First, get the PCI header_type 379 */ 380 *is_bridge = FALSE; 381 status = acpi_os_read_pci_configuration(pci_id, 382 PCI_CFG_HEADER_TYPE_REG, 383 &pci_value, 8); 384 if (ACPI_FAILURE(status)) { 385 return (status); 386 } 387 388 /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */ 389 390 pci_value &= PCI_HEADER_TYPE_MASK; 391 392 if ((pci_value != PCI_TYPE_BRIDGE) && 393 (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) { 394 return (AE_OK); 395 } 396 397 /* Bridge: Get the Primary bus_number */ 398 399 status = acpi_os_read_pci_configuration(pci_id, 400 PCI_CFG_PRIMARY_BUS_NUMBER_REG, 401 &pci_value, 8); 402 if (ACPI_FAILURE(status)) { 403 return (status); 404 } 405 406 *is_bridge = TRUE; 407 pci_id->bus = (u16)pci_value; 408 409 /* Bridge: Get the Secondary bus_number */ 410 411 status = acpi_os_read_pci_configuration(pci_id, 412 PCI_CFG_SECONDARY_BUS_NUMBER_REG, 413 &pci_value, 8); 414 if (ACPI_FAILURE(status)) { 415 return (status); 416 } 417 418 *bus_number = (u16)pci_value; 419 return (AE_OK); 420 } 421