1 /******************************************************************************* 2 * 3 * Module Name: hwpci - Obtain PCI bus, device, and function numbers 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 = NULL; 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 struct acpi_pci_device *list_head = NULL; 181 182 /* 183 * Ascend namespace branch until the root_pci_device is reached, building 184 * a list of device nodes. Loop will exit when either the PCI device is 185 * found, or the root of the namespace is reached. 186 */ 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_list_head = list_head; 202 return (AE_OK); 203 } 204 205 list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); 206 if (!list_element) { 207 208 /* Must delete the list before exit */ 209 210 acpi_hw_delete_pci_list(*return_list_head); 211 return (AE_NO_MEMORY); 212 } 213 214 /* Put new element at the head of the list */ 215 216 list_element->next = list_head; 217 list_element->device = parent_device; 218 list_head = list_element; 219 220 current_device = parent_device; 221 } 222 } 223 224 /******************************************************************************* 225 * 226 * FUNCTION: acpi_hw_process_pci_list 227 * 228 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 229 * modified by this function. 230 * list_head - Device list created by 231 * acpi_hw_build_pci_list 232 * 233 * RETURN: Status 234 * 235 * DESCRIPTION: Walk downward through the PCI device list, getting the device 236 * info for each, via the PCI configuration space and updating 237 * the PCI ID as necessary. Deletes the list during traversal. 238 * 239 ******************************************************************************/ 240 241 static acpi_status 242 acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 243 struct acpi_pci_device *list_head) 244 { 245 acpi_status status = AE_OK; 246 struct acpi_pci_device *info; 247 u16 bus_number; 248 u8 is_bridge = TRUE; 249 250 ACPI_FUNCTION_NAME(hw_process_pci_list); 251 252 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 253 "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", 254 pci_id->segment, pci_id->bus, pci_id->device, 255 pci_id->function)); 256 257 bus_number = pci_id->bus; 258 259 /* 260 * Descend down the namespace tree, collecting PCI device, function, 261 * and bus numbers. bus_number is only important for PCI bridges. 262 * Algorithm: As we descend the tree, use the last valid PCI device, 263 * function, and bus numbers that are discovered, and assign them 264 * to the PCI ID for the target device. 265 */ 266 info = list_head; 267 while (info) { 268 status = acpi_hw_get_pci_device_info(pci_id, info->device, 269 &bus_number, &is_bridge); 270 if (ACPI_FAILURE(status)) { 271 return (status); 272 } 273 274 info = info->next; 275 } 276 277 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 278 "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " 279 "Status %X BusNumber %X IsBridge %X\n", 280 pci_id->segment, pci_id->bus, pci_id->device, 281 pci_id->function, status, bus_number, is_bridge)); 282 283 return (AE_OK); 284 } 285 286 /******************************************************************************* 287 * 288 * FUNCTION: acpi_hw_delete_pci_list 289 * 290 * PARAMETERS: list_head - Device list created by 291 * acpi_hw_build_pci_list 292 * 293 * RETURN: None 294 * 295 * DESCRIPTION: Free the entire PCI list. 296 * 297 ******************************************************************************/ 298 299 static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head) 300 { 301 struct acpi_pci_device *next; 302 struct acpi_pci_device *previous; 303 304 next = list_head; 305 while (next) { 306 previous = next; 307 next = previous->next; 308 ACPI_FREE(previous); 309 } 310 } 311 312 /******************************************************************************* 313 * 314 * FUNCTION: acpi_hw_get_pci_device_info 315 * 316 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 317 * modified by this function. 318 * pci_device - Handle for the PCI device object 319 * bus_number - Where a PCI bridge bus number is returned 320 * is_bridge - Return value, indicates if this PCI 321 * device is a PCI bridge 322 * 323 * RETURN: Status 324 * 325 * DESCRIPTION: Get the device info for a single PCI device object. Get the 326 * _ADR (contains PCI device and function numbers), and for PCI 327 * bridge devices, get the bus number from PCI configuration 328 * space. 329 * 330 ******************************************************************************/ 331 332 static acpi_status 333 acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, 334 acpi_handle pci_device, 335 u16 *bus_number, u8 *is_bridge) 336 { 337 acpi_status status; 338 acpi_object_type object_type; 339 u64 return_value; 340 u64 pci_value; 341 342 /* We only care about objects of type Device */ 343 344 status = acpi_get_type(pci_device, &object_type); 345 if (ACPI_FAILURE(status)) { 346 return (status); 347 } 348 349 if (object_type != ACPI_TYPE_DEVICE) { 350 return (AE_OK); 351 } 352 353 /* We need an _ADR. Ignore device if not present */ 354 355 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, 356 pci_device, &return_value); 357 if (ACPI_FAILURE(status)) { 358 return (AE_OK); 359 } 360 361 /* 362 * From _ADR, get the PCI Device and Function and 363 * update the PCI ID. 364 */ 365 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value)); 366 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value)); 367 368 /* 369 * If the previous device was a bridge, use the previous 370 * device bus number 371 */ 372 if (*is_bridge) { 373 pci_id->bus = *bus_number; 374 } 375 376 /* 377 * Get the bus numbers from PCI Config space: 378 * 379 * First, get the PCI header_type 380 */ 381 *is_bridge = FALSE; 382 status = acpi_os_read_pci_configuration(pci_id, 383 PCI_CFG_HEADER_TYPE_REG, 384 &pci_value, 8); 385 if (ACPI_FAILURE(status)) { 386 return (status); 387 } 388 389 /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */ 390 391 pci_value &= PCI_HEADER_TYPE_MASK; 392 393 if ((pci_value != PCI_TYPE_BRIDGE) && 394 (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) { 395 return (AE_OK); 396 } 397 398 /* Bridge: Get the Primary bus_number */ 399 400 status = acpi_os_read_pci_configuration(pci_id, 401 PCI_CFG_PRIMARY_BUS_NUMBER_REG, 402 &pci_value, 8); 403 if (ACPI_FAILURE(status)) { 404 return (status); 405 } 406 407 *is_bridge = TRUE; 408 pci_id->bus = (u16)pci_value; 409 410 /* Bridge: Get the Secondary bus_number */ 411 412 status = acpi_os_read_pci_configuration(pci_id, 413 PCI_CFG_SECONDARY_BUS_NUMBER_REG, 414 &pci_value, 8); 415 if (ACPI_FAILURE(status)) { 416 return (status); 417 } 418 419 *bus_number = (u16)pci_value; 420 return (AE_OK); 421 } 422