linux/drivers/acpi/acpica/hwpci.c
<<
>>
Prefs
   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
  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;
 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
 171static acpi_status
 172acpi_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
 240static acpi_status
 241acpi_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
 298static 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
 331static acpi_status
 332acpi_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