xref: /linux/drivers/acpi/acpica/hwpci.c (revision e0bf6c5ca2d3281f231c5f0c9bf145e9513644de)
1 /*******************************************************************************
2  *
3  * Module Name: hwpci - Obtain PCI bus, device, and function numbers
4  *
5  ******************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, 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