diff options
author | Bob Moore <robert.moore@intel.com> | 2007-02-02 11:48:21 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2007-02-02 21:14:27 -0500 |
commit | b7a69806308600711589e4ca306d18dd029ef0cf (patch) | |
tree | 0084a0784d14e2c753eb878b2c731c6d42249319 /drivers/acpi | |
parent | d1fdda83f7c567f376ddd4305833de09f7919ca9 (diff) |
ACPICA: _CID support for PCI Root Bridge detection.
Implemented _CID support for PCI Root Bridge detection. If the _HID
does not match the predefined root bridge IDs, the _CID list (if present)
is now obtained and also checked for an ID match
Signed-off-by: Alexey Starikovskiy <alexey.y.starikovskiy@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/events/evrgnini.c | 163 |
1 files changed, 125 insertions, 38 deletions
diff --git a/drivers/acpi/events/evrgnini.c b/drivers/acpi/events/evrgnini.c index 790d49b8212b..617660228801 100644 --- a/drivers/acpi/events/evrgnini.c +++ b/drivers/acpi/events/evrgnini.c | |||
@@ -48,6 +48,11 @@ | |||
48 | #define _COMPONENT ACPI_EVENTS | 48 | #define _COMPONENT ACPI_EVENTS |
49 | ACPI_MODULE_NAME("evrgnini") | 49 | ACPI_MODULE_NAME("evrgnini") |
50 | 50 | ||
51 | /* Local prototypes */ | ||
52 | static u8 acpi_ev_match_pci_root_bridge(char *id); | ||
53 | |||
54 | static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); | ||
55 | |||
51 | /******************************************************************************* | 56 | /******************************************************************************* |
52 | * | 57 | * |
53 | * FUNCTION: acpi_ev_system_memory_region_setup | 58 | * FUNCTION: acpi_ev_system_memory_region_setup |
@@ -62,6 +67,7 @@ ACPI_MODULE_NAME("evrgnini") | |||
62 | * DESCRIPTION: Setup a system_memory operation region | 67 | * DESCRIPTION: Setup a system_memory operation region |
63 | * | 68 | * |
64 | ******************************************************************************/ | 69 | ******************************************************************************/ |
70 | |||
65 | acpi_status | 71 | acpi_status |
66 | acpi_ev_system_memory_region_setup(acpi_handle handle, | 72 | acpi_ev_system_memory_region_setup(acpi_handle handle, |
67 | u32 function, | 73 | u32 function, |
@@ -168,9 +174,9 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
168 | union acpi_operand_object *handler_obj; | 174 | union acpi_operand_object *handler_obj; |
169 | struct acpi_namespace_node *parent_node; | 175 | struct acpi_namespace_node *parent_node; |
170 | struct acpi_namespace_node *pci_root_node; | 176 | struct acpi_namespace_node *pci_root_node; |
177 | struct acpi_namespace_node *pci_device_node; | ||
171 | union acpi_operand_object *region_obj = | 178 | union acpi_operand_object *region_obj = |
172 | (union acpi_operand_object *)handle; | 179 | (union acpi_operand_object *)handle; |
173 | struct acpi_device_id object_hID; | ||
174 | 180 | ||
175 | ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); | 181 | ACPI_FUNCTION_TRACE(ev_pci_config_region_setup); |
176 | 182 | ||
@@ -215,45 +221,30 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
215 | 221 | ||
216 | pci_root_node = parent_node; | 222 | pci_root_node = parent_node; |
217 | while (pci_root_node != acpi_gbl_root_node) { | 223 | while (pci_root_node != acpi_gbl_root_node) { |
218 | status = | ||
219 | acpi_ut_execute_HID(pci_root_node, &object_hID); | ||
220 | if (ACPI_SUCCESS(status)) { | ||
221 | /* | ||
222 | * Got a valid _HID string, check if this is a PCI root. | ||
223 | * New for ACPI 3.0: check for a PCI Express root also. | ||
224 | */ | ||
225 | if (! | ||
226 | (ACPI_STRNCMP | ||
227 | (object_hID.value, PCI_ROOT_HID_STRING, | ||
228 | sizeof(PCI_ROOT_HID_STRING))) | ||
229 | || | ||
230 | !(ACPI_STRNCMP | ||
231 | (object_hID.value, | ||
232 | PCI_EXPRESS_ROOT_HID_STRING, | ||
233 | sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { | ||
234 | |||
235 | /* Install a handler for this PCI root bridge */ | ||
236 | 224 | ||
237 | status = | 225 | /* Get the _HID/_CID in order to detect a root_bridge */ |
238 | acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); | 226 | |
239 | if (ACPI_FAILURE(status)) { | 227 | if (acpi_ev_is_pci_root_bridge(pci_root_node)) { |
240 | if (status == AE_SAME_HANDLER) { | 228 | |
241 | /* | 229 | /* Install a handler for this PCI root bridge */ |
242 | * It is OK if the handler is already installed on the root | 230 | |
243 | * bridge. Still need to return a context object for the | 231 | status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL); |
244 | * new PCI_Config operation region, however. | 232 | if (ACPI_FAILURE(status)) { |
245 | */ | 233 | if (status == AE_SAME_HANDLER) { |
246 | status = AE_OK; | 234 | /* |
247 | } else { | 235 | * It is OK if the handler is already installed on the root |
248 | ACPI_EXCEPTION((AE_INFO, | 236 | * bridge. Still need to return a context object for the |
249 | status, | 237 | * new PCI_Config operation region, however. |
250 | "Could not install PciConfig handler for Root Bridge %4.4s", | 238 | */ |
251 | acpi_ut_get_node_name | 239 | status = AE_OK; |
252 | (pci_root_node))); | 240 | } else { |
253 | } | 241 | ACPI_EXCEPTION((AE_INFO, status, |
242 | "Could not install PciConfig handler for Root Bridge %4.4s", | ||
243 | acpi_ut_get_node_name | ||
244 | (pci_root_node))); | ||
254 | } | 245 | } |
255 | break; | ||
256 | } | 246 | } |
247 | break; | ||
257 | } | 248 | } |
258 | 249 | ||
259 | pci_root_node = acpi_ns_get_parent_node(pci_root_node); | 250 | pci_root_node = acpi_ns_get_parent_node(pci_root_node); |
@@ -282,14 +273,25 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
282 | /* | 273 | /* |
283 | * For PCI_Config space access, we need the segment, bus, | 274 | * For PCI_Config space access, we need the segment, bus, |
284 | * device and function numbers. Acquire them here. | 275 | * device and function numbers. Acquire them here. |
276 | * | ||
277 | * Find the parent device object. (This allows the operation region to be | ||
278 | * within a subscope under the device, such as a control method.) | ||
285 | */ | 279 | */ |
280 | pci_device_node = region_obj->region.node; | ||
281 | while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) { | ||
282 | pci_device_node = acpi_ns_get_parent_node(pci_device_node); | ||
283 | } | ||
284 | |||
285 | if (!pci_device_node) { | ||
286 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
287 | } | ||
286 | 288 | ||
287 | /* | 289 | /* |
288 | * Get the PCI device and function numbers from the _ADR object | 290 | * Get the PCI device and function numbers from the _ADR object |
289 | * contained in the parent's scope. | 291 | * contained in the parent's scope. |
290 | */ | 292 | */ |
291 | status = | 293 | status = |
292 | acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node, | 294 | acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node, |
293 | &pci_value); | 295 | &pci_value); |
294 | 296 | ||
295 | /* | 297 | /* |
@@ -329,6 +331,91 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, | |||
329 | 331 | ||
330 | /******************************************************************************* | 332 | /******************************************************************************* |
331 | * | 333 | * |
334 | * FUNCTION: acpi_ev_match_pci_root_bridge | ||
335 | * | ||
336 | * PARAMETERS: Id - The HID/CID in string format | ||
337 | * | ||
338 | * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge | ||
339 | * | ||
340 | * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. | ||
341 | * | ||
342 | ******************************************************************************/ | ||
343 | |||
344 | static u8 acpi_ev_match_pci_root_bridge(char *id) | ||
345 | { | ||
346 | |||
347 | /* | ||
348 | * Check if this is a PCI root. | ||
349 | * ACPI 3.0+: check for a PCI Express root also. | ||
350 | */ | ||
351 | if (!(ACPI_STRNCMP(id, | ||
352 | PCI_ROOT_HID_STRING, | ||
353 | sizeof(PCI_ROOT_HID_STRING))) || | ||
354 | !(ACPI_STRNCMP(id, | ||
355 | PCI_EXPRESS_ROOT_HID_STRING, | ||
356 | sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { | ||
357 | return (TRUE); | ||
358 | } | ||
359 | |||
360 | return (FALSE); | ||
361 | } | ||
362 | |||
363 | /******************************************************************************* | ||
364 | * | ||
365 | * FUNCTION: acpi_ev_is_pci_root_bridge | ||
366 | * | ||
367 | * PARAMETERS: Node - Device node being examined | ||
368 | * | ||
369 | * RETURN: TRUE if device is a PCI/PCI-Express Root Bridge | ||
370 | * | ||
371 | * DESCRIPTION: Determine if the input device represents a PCI Root Bridge by | ||
372 | * examining the _HID and _CID for the device. | ||
373 | * | ||
374 | ******************************************************************************/ | ||
375 | |||
376 | static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) | ||
377 | { | ||
378 | acpi_status status; | ||
379 | struct acpi_device_id hid; | ||
380 | struct acpi_compatible_id_list *cid; | ||
381 | acpi_native_uint i; | ||
382 | |||
383 | /* | ||
384 | * Get the _HID and check for a PCI Root Bridge | ||
385 | */ | ||
386 | status = acpi_ut_execute_HID(node, &hid); | ||
387 | if (ACPI_FAILURE(status)) { | ||
388 | return (FALSE); | ||
389 | } | ||
390 | |||
391 | if (acpi_ev_match_pci_root_bridge(hid.value)) { | ||
392 | return (TRUE); | ||
393 | } | ||
394 | |||
395 | /* | ||
396 | * The _HID did not match. | ||
397 | * Get the _CID and check for a PCI Root Bridge | ||
398 | */ | ||
399 | status = acpi_ut_execute_CID(node, &cid); | ||
400 | if (ACPI_FAILURE(status)) { | ||
401 | return (FALSE); | ||
402 | } | ||
403 | |||
404 | /* Check all _CIDs in the returned list */ | ||
405 | |||
406 | for (i = 0; i < cid->count; i++) { | ||
407 | if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { | ||
408 | ACPI_FREE(cid); | ||
409 | return (TRUE); | ||
410 | } | ||
411 | } | ||
412 | |||
413 | ACPI_FREE(cid); | ||
414 | return (FALSE); | ||
415 | } | ||
416 | |||
417 | /******************************************************************************* | ||
418 | * | ||
332 | * FUNCTION: acpi_ev_pci_bar_region_setup | 419 | * FUNCTION: acpi_ev_pci_bar_region_setup |
333 | * | 420 | * |
334 | * PARAMETERS: Handle - Region we are interested in | 421 | * PARAMETERS: Handle - Region we are interested in |