1/******************************************************************************* 2 * 3 * Module Name: hwpci - Obtain PCI bus, device, and function numbers 4 * 5 ******************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2013, 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 48ACPI_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 58typedef struct acpi_pci_device { 59 acpi_handle device; 60 struct acpi_pci_device *next; 61 62} acpi_pci_device; 63 64/* Local prototypes */ 65 66static acpi_status 67acpi_hw_build_pci_list(acpi_handle root_pci_device, 68 acpi_handle pci_region, 69 struct acpi_pci_device **return_list_head); 70 71static acpi_status 72acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 73 struct acpi_pci_device *list_head); 74 75static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head); 76 77static acpi_status 78acpi_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 121acpi_status 122acpi_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 145 /* Always delete the list */ 146 147 acpi_hw_delete_pci_list(list_head); 148 return_ACPI_STATUS(status); 149} 150 151/******************************************************************************* 152 * 153 * FUNCTION: acpi_hw_build_pci_list 154 * 155 * PARAMETERS: root_pci_device - A handle to a PCI device object. This 156 * object is guaranteed to be a PCI Root 157 * Bridge having a _HID value of either 158 * PNP0A03 or PNP0A08 159 * pci_region - A handle to the PCI configuration space 160 * Operation Region 161 * return_list_head - Where the PCI device list is returned 162 * 163 * RETURN: Status 164 * 165 * DESCRIPTION: Builds a list of devices from the input PCI region up to the 166 * Root PCI device for this namespace subtree. 167 * 168 ******************************************************************************/ 169 170static acpi_status 171acpi_hw_build_pci_list(acpi_handle root_pci_device, 172 acpi_handle pci_region, 173 struct acpi_pci_device **return_list_head) 174{ 175 acpi_handle current_device; 176 acpi_handle parent_device; 177 acpi_status status; 178 struct acpi_pci_device *list_element; 179 struct acpi_pci_device *list_head = NULL; 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 current_device = pci_region; 187 while (1) { 188 status = acpi_get_parent(current_device, &parent_device); 189 if (ACPI_FAILURE(status)) { 190 return (status); 191 } 192 193 /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ 194 195 if (parent_device == root_pci_device) { 196 *return_list_head = list_head; 197 return (AE_OK); 198 } 199 200 list_element = ACPI_ALLOCATE(sizeof(struct acpi_pci_device)); 201 if (!list_element) { 202 return (AE_NO_MEMORY); 203 } 204 205 /* Put new element at the head of the list */ 206 207 list_element->next = list_head; 208 list_element->device = parent_device; 209 list_head = list_element; 210 211 current_device = parent_device; 212 } 213} 214 215/******************************************************************************* 216 * 217 * FUNCTION: acpi_hw_process_pci_list 218 * 219 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 220 * modified by this function. 221 * list_head - Device list created by 222 * acpi_hw_build_pci_list 223 * 224 * RETURN: Status 225 * 226 * DESCRIPTION: Walk downward through the PCI device list, getting the device 227 * info for each, via the PCI configuration space and updating 228 * the PCI ID as necessary. Deletes the list during traversal. 229 * 230 ******************************************************************************/ 231 232static acpi_status 233acpi_hw_process_pci_list(struct acpi_pci_id *pci_id, 234 struct acpi_pci_device *list_head) 235{ 236 acpi_status status = AE_OK; 237 struct acpi_pci_device *info; 238 u16 bus_number; 239 u8 is_bridge = TRUE; 240 241 ACPI_FUNCTION_NAME(hw_process_pci_list); 242 243 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 244 "Input PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X\n", 245 pci_id->segment, pci_id->bus, pci_id->device, 246 pci_id->function)); 247 248 bus_number = pci_id->bus; 249 250 /* 251 * Descend down the namespace tree, collecting PCI device, function, 252 * and bus numbers. bus_number is only important for PCI bridges. 253 * Algorithm: As we descend the tree, use the last valid PCI device, 254 * function, and bus numbers that are discovered, and assign them 255 * to the PCI ID for the target device. 256 */ 257 info = list_head; 258 while (info) { 259 status = acpi_hw_get_pci_device_info(pci_id, info->device, 260 &bus_number, &is_bridge); 261 if (ACPI_FAILURE(status)) { 262 return (status); 263 } 264 265 info = info->next; 266 } 267 268 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 269 "Output PciId: Seg %4.4X Bus %4.4X Dev %4.4X Func %4.4X " 270 "Status %X BusNumber %X IsBridge %X\n", 271 pci_id->segment, pci_id->bus, pci_id->device, 272 pci_id->function, status, bus_number, is_bridge)); 273 274 return (AE_OK); 275} 276 277/******************************************************************************* 278 * 279 * FUNCTION: acpi_hw_delete_pci_list 280 * 281 * PARAMETERS: list_head - Device list created by 282 * acpi_hw_build_pci_list 283 * 284 * RETURN: None 285 * 286 * DESCRIPTION: Free the entire PCI list. 287 * 288 ******************************************************************************/ 289 290static void acpi_hw_delete_pci_list(struct acpi_pci_device *list_head) 291{ 292 struct acpi_pci_device *next; 293 struct acpi_pci_device *previous; 294 295 next = list_head; 296 while (next) { 297 previous = next; 298 next = previous->next; 299 ACPI_FREE(previous); 300 } 301} 302 303/******************************************************************************* 304 * 305 * FUNCTION: acpi_hw_get_pci_device_info 306 * 307 * PARAMETERS: pci_id - Initial values for the PCI ID. May be 308 * modified by this function. 309 * pci_device - Handle for the PCI device object 310 * bus_number - Where a PCI bridge bus number is returned 311 * is_bridge - Return value, indicates if this PCI 312 * device is a PCI bridge 313 * 314 * RETURN: Status 315 * 316 * DESCRIPTION: Get the device info for a single PCI device object. Get the 317 * _ADR (contains PCI device and function numbers), and for PCI 318 * bridge devices, get the bus number from PCI configuration 319 * space. 320 * 321 ******************************************************************************/ 322 323static acpi_status 324acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id, 325 acpi_handle pci_device, 326 u16 *bus_number, u8 *is_bridge) 327{ 328 acpi_status status; 329 acpi_object_type object_type; 330 u64 return_value; 331 u64 pci_value; 332 333 /* We only care about objects of type Device */ 334 335 status = acpi_get_type(pci_device, &object_type); 336 if (ACPI_FAILURE(status)) { 337 return (status); 338 } 339 340 if (object_type != ACPI_TYPE_DEVICE) { 341 return (AE_OK); 342 } 343 344 /* We need an _ADR. Ignore device if not present */ 345 346 status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, 347 pci_device, &return_value); 348 if (ACPI_FAILURE(status)) { 349 return (AE_OK); 350 } 351 352 /* 353 * From _ADR, get the PCI Device and Function and 354 * update the PCI ID. 355 */ 356 pci_id->device = ACPI_HIWORD(ACPI_LODWORD(return_value)); 357 pci_id->function = ACPI_LOWORD(ACPI_LODWORD(return_value)); 358 359 /* 360 * If the previous device was a bridge, use the previous 361 * device bus number 362 */ 363 if (*is_bridge) { 364 pci_id->bus = *bus_number; 365 } 366 367 /* 368 * Get the bus numbers from PCI Config space: 369 * 370 * First, get the PCI header_type 371 */ 372 *is_bridge = FALSE; 373 status = acpi_os_read_pci_configuration(pci_id, 374 PCI_CFG_HEADER_TYPE_REG, 375 &pci_value, 8); 376 if (ACPI_FAILURE(status)) { 377 return (status); 378 } 379 380 /* We only care about bridges (1=pci_bridge, 2=card_bus_bridge) */ 381 382 pci_value &= PCI_HEADER_TYPE_MASK; 383 384 if ((pci_value != PCI_TYPE_BRIDGE) && 385 (pci_value != PCI_TYPE_CARDBUS_BRIDGE)) { 386 return (AE_OK); 387 } 388 389 /* Bridge: Get the Primary bus_number */ 390 391 status = acpi_os_read_pci_configuration(pci_id, 392 PCI_CFG_PRIMARY_BUS_NUMBER_REG, 393 &pci_value, 8); 394 if (ACPI_FAILURE(status)) { 395 return (status); 396 } 397 398 *is_bridge = TRUE; 399 pci_id->bus = (u16)pci_value; 400 401 /* Bridge: Get the Secondary bus_number */ 402 403 status = acpi_os_read_pci_configuration(pci_id, 404 PCI_CFG_SECONDARY_BUS_NUMBER_REG, 405 &pci_value, 8); 406 if (ACPI_FAILURE(status)) { 407 return (status); 408 } 409 410 *bus_number = (u16)pci_value; 411 return (AE_OK); 412} 413