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>
This commit is contained in:
parent
d1fdda83f7
commit
b7a6980630
|
@ -48,6 +48,11 @@
|
||||||
#define _COMPONENT ACPI_EVENTS
|
#define _COMPONENT ACPI_EVENTS
|
||||||
ACPI_MODULE_NAME("evrgnini")
|
ACPI_MODULE_NAME("evrgnini")
|
||||||
|
|
||||||
|
/* Local prototypes */
|
||||||
|
static u8 acpi_ev_match_pci_root_bridge(char *id);
|
||||||
|
|
||||||
|
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node);
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_ev_system_memory_region_setup
|
* FUNCTION: acpi_ev_system_memory_region_setup
|
||||||
|
@ -62,6 +67,7 @@ ACPI_MODULE_NAME("evrgnini")
|
||||||
* DESCRIPTION: Setup a system_memory operation region
|
* DESCRIPTION: Setup a system_memory operation region
|
||||||
*
|
*
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
acpi_status
|
acpi_status
|
||||||
acpi_ev_system_memory_region_setup(acpi_handle handle,
|
acpi_ev_system_memory_region_setup(acpi_handle handle,
|
||||||
u32 function,
|
u32 function,
|
||||||
|
@ -168,9 +174,9 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
|
||||||
union acpi_operand_object *handler_obj;
|
union acpi_operand_object *handler_obj;
|
||||||
struct acpi_namespace_node *parent_node;
|
struct acpi_namespace_node *parent_node;
|
||||||
struct acpi_namespace_node *pci_root_node;
|
struct acpi_namespace_node *pci_root_node;
|
||||||
|
struct acpi_namespace_node *pci_device_node;
|
||||||
union acpi_operand_object *region_obj =
|
union acpi_operand_object *region_obj =
|
||||||
(union acpi_operand_object *)handle;
|
(union acpi_operand_object *)handle;
|
||||||
struct acpi_device_id object_hID;
|
|
||||||
|
|
||||||
ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
|
ACPI_FUNCTION_TRACE(ev_pci_config_region_setup);
|
||||||
|
|
||||||
|
@ -215,45 +221,30 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
|
||||||
|
|
||||||
pci_root_node = parent_node;
|
pci_root_node = parent_node;
|
||||||
while (pci_root_node != acpi_gbl_root_node) {
|
while (pci_root_node != acpi_gbl_root_node) {
|
||||||
status =
|
|
||||||
acpi_ut_execute_HID(pci_root_node, &object_hID);
|
|
||||||
if (ACPI_SUCCESS(status)) {
|
|
||||||
/*
|
|
||||||
* Got a valid _HID string, check if this is a PCI root.
|
|
||||||
* New for ACPI 3.0: check for a PCI Express root also.
|
|
||||||
*/
|
|
||||||
if (!
|
|
||||||
(ACPI_STRNCMP
|
|
||||||
(object_hID.value, PCI_ROOT_HID_STRING,
|
|
||||||
sizeof(PCI_ROOT_HID_STRING)))
|
|
||||||
||
|
|
||||||
!(ACPI_STRNCMP
|
|
||||||
(object_hID.value,
|
|
||||||
PCI_EXPRESS_ROOT_HID_STRING,
|
|
||||||
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
|
|
||||||
|
|
||||||
/* Install a handler for this PCI root bridge */
|
/* Get the _HID/_CID in order to detect a root_bridge */
|
||||||
|
|
||||||
status =
|
if (acpi_ev_is_pci_root_bridge(pci_root_node)) {
|
||||||
acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
|
|
||||||
if (ACPI_FAILURE(status)) {
|
/* Install a handler for this PCI root bridge */
|
||||||
if (status == AE_SAME_HANDLER) {
|
|
||||||
/*
|
status = acpi_install_address_space_handler((acpi_handle) pci_root_node, ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
|
||||||
* It is OK if the handler is already installed on the root
|
if (ACPI_FAILURE(status)) {
|
||||||
* bridge. Still need to return a context object for the
|
if (status == AE_SAME_HANDLER) {
|
||||||
* new PCI_Config operation region, however.
|
/*
|
||||||
*/
|
* It is OK if the handler is already installed on the root
|
||||||
status = AE_OK;
|
* bridge. Still need to return a context object for the
|
||||||
} else {
|
* new PCI_Config operation region, however.
|
||||||
ACPI_EXCEPTION((AE_INFO,
|
*/
|
||||||
status,
|
status = AE_OK;
|
||||||
"Could not install PciConfig handler for Root Bridge %4.4s",
|
} else {
|
||||||
acpi_ut_get_node_name
|
ACPI_EXCEPTION((AE_INFO, status,
|
||||||
(pci_root_node)));
|
"Could not install PciConfig handler for Root Bridge %4.4s",
|
||||||
}
|
acpi_ut_get_node_name
|
||||||
|
(pci_root_node)));
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_root_node = acpi_ns_get_parent_node(pci_root_node);
|
pci_root_node = acpi_ns_get_parent_node(pci_root_node);
|
||||||
|
@ -282,14 +273,25 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
|
||||||
/*
|
/*
|
||||||
* For PCI_Config space access, we need the segment, bus,
|
* For PCI_Config space access, we need the segment, bus,
|
||||||
* device and function numbers. Acquire them here.
|
* device and function numbers. Acquire them here.
|
||||||
|
*
|
||||||
|
* Find the parent device object. (This allows the operation region to be
|
||||||
|
* within a subscope under the device, such as a control method.)
|
||||||
*/
|
*/
|
||||||
|
pci_device_node = region_obj->region.node;
|
||||||
|
while (pci_device_node && (pci_device_node->type != ACPI_TYPE_DEVICE)) {
|
||||||
|
pci_device_node = acpi_ns_get_parent_node(pci_device_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pci_device_node) {
|
||||||
|
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the PCI device and function numbers from the _ADR object
|
* Get the PCI device and function numbers from the _ADR object
|
||||||
* contained in the parent's scope.
|
* contained in the parent's scope.
|
||||||
*/
|
*/
|
||||||
status =
|
status =
|
||||||
acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, parent_node,
|
acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, pci_device_node,
|
||||||
&pci_value);
|
&pci_value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -327,6 +329,91 @@ acpi_ev_pci_config_region_setup(acpi_handle handle,
|
||||||
return_ACPI_STATUS(AE_OK);
|
return_ACPI_STATUS(AE_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ev_match_pci_root_bridge
|
||||||
|
*
|
||||||
|
* PARAMETERS: Id - The HID/CID in string format
|
||||||
|
*
|
||||||
|
* RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
static u8 acpi_ev_match_pci_root_bridge(char *id)
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if this is a PCI root.
|
||||||
|
* ACPI 3.0+: check for a PCI Express root also.
|
||||||
|
*/
|
||||||
|
if (!(ACPI_STRNCMP(id,
|
||||||
|
PCI_ROOT_HID_STRING,
|
||||||
|
sizeof(PCI_ROOT_HID_STRING))) ||
|
||||||
|
!(ACPI_STRNCMP(id,
|
||||||
|
PCI_EXPRESS_ROOT_HID_STRING,
|
||||||
|
sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) {
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
*
|
||||||
|
* FUNCTION: acpi_ev_is_pci_root_bridge
|
||||||
|
*
|
||||||
|
* PARAMETERS: Node - Device node being examined
|
||||||
|
*
|
||||||
|
* RETURN: TRUE if device is a PCI/PCI-Express Root Bridge
|
||||||
|
*
|
||||||
|
* DESCRIPTION: Determine if the input device represents a PCI Root Bridge by
|
||||||
|
* examining the _HID and _CID for the device.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node)
|
||||||
|
{
|
||||||
|
acpi_status status;
|
||||||
|
struct acpi_device_id hid;
|
||||||
|
struct acpi_compatible_id_list *cid;
|
||||||
|
acpi_native_uint i;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the _HID and check for a PCI Root Bridge
|
||||||
|
*/
|
||||||
|
status = acpi_ut_execute_HID(node, &hid);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acpi_ev_match_pci_root_bridge(hid.value)) {
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The _HID did not match.
|
||||||
|
* Get the _CID and check for a PCI Root Bridge
|
||||||
|
*/
|
||||||
|
status = acpi_ut_execute_CID(node, &cid);
|
||||||
|
if (ACPI_FAILURE(status)) {
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check all _CIDs in the returned list */
|
||||||
|
|
||||||
|
for (i = 0; i < cid->count; i++) {
|
||||||
|
if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) {
|
||||||
|
ACPI_FREE(cid);
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ACPI_FREE(cid);
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
*
|
*
|
||||||
* FUNCTION: acpi_ev_pci_bar_region_setup
|
* FUNCTION: acpi_ev_pci_bar_region_setup
|
||||||
|
|
Loading…
Reference in New Issue