Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwpci.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Module Name: hwpci - Obtain PCI bus, device, and function numbers
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2012, 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 {
61 
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,
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 
123  acpi_handle root_pci_device, acpi_handle pci_region)
124 {
126  struct acpi_pci_device *list_head = NULL;
127 
128  ACPI_FUNCTION_TRACE(hw_derive_pci_id);
129 
130  if (!pci_id) {
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 
170 static acpi_status
171 acpi_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;
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 
232 static acpi_status
233 acpi_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 
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_ACPI_STATUS(status);
263  }
264 
265  info = info->next;
266  }
267 
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 
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 
290 static 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 
323 static acpi_status
324 acpi_hw_get_pci_device_info(struct acpi_pci_id *pci_id,
326  u16 *bus_number, u8 *is_bridge)
327 {
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 
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,
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,
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,
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 }