Commit f65358e5 authored by Suravee Suthikulpanit's avatar Suravee Suthikulpanit Committed by Rafael J. Wysocki

ACPICA: Utilities: Add _CLS processing

ACPICA commit 9a2b638acb3a7215209432e070c6bd0312374229

ACPI Device object often contains a _CLS object to supply PCI-defined class
code for the device. This patch introduces logic to process the _CLS
object. Suravee Suthikulpanit, Lv Zheng.

Link: https://github.com/acpica/acpica/commit/9a2b638aAcked-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: default avatarHanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: default avatarSuravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: default avatarLv Zheng <lv.zheng@intel.com>
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent cbc82340
......@@ -468,6 +468,8 @@ void acpi_ex_eisa_id_to_string(char *dest, u64 compressed_id);
void acpi_ex_integer_to_string(char *dest, u64 value);
void acpi_ex_pci_cls_to_string(char *dest, u8 class_code[3]);
u8 acpi_is_valid_space_id(u8 space_id);
/*
......
......@@ -430,6 +430,10 @@ acpi_status
acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id_list ** return_cid_list);
acpi_status
acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id **return_id);
/*
* utlock - reader/writer locks
*/
......
......@@ -378,6 +378,38 @@ void acpi_ex_integer_to_string(char *out_string, u64 value)
}
}
/*******************************************************************************
*
* FUNCTION: acpi_ex_pci_cls_to_string
*
* PARAMETERS: out_string - Where to put the converted string (7 bytes)
* PARAMETERS: class_code - PCI class code to be converted (3 bytes)
*
* RETURN: None
*
* DESCRIPTION: Convert 3-bytes PCI class code to string representation.
* Return buffer must be large enough to hold the string. The
* string returned is always exactly of length
* ACPI_PCICLS_STRING_SIZE (includes null terminator).
*
******************************************************************************/
void acpi_ex_pci_cls_to_string(char *out_string, u8 class_code[3])
{
ACPI_FUNCTION_ENTRY();
/* All 3 bytes are hexadecimal */
out_string[0] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 4);
out_string[1] = acpi_ut_hex_to_ascii_char((u64)class_code[0], 0);
out_string[2] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 4);
out_string[3] = acpi_ut_hex_to_ascii_char((u64)class_code[1], 0);
out_string[4] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 4);
out_string[5] = acpi_ut_hex_to_ascii_char((u64)class_code[2], 0);
out_string[6] = 0;
}
/*******************************************************************************
*
* FUNCTION: acpi_is_valid_space_id
......
......@@ -260,7 +260,7 @@ static char *acpi_ns_copy_device_id(struct acpi_pnp_device_id *dest,
* control methods (Such as in the case of a device.)
*
* For Device and Processor objects, run the Device _HID, _UID, _CID, _SUB,
* _STA, _ADR, _sx_w, and _sx_d methods.
* _CLS, _STA, _ADR, _sx_w, and _sx_d methods.
*
* Note: Allocates the return buffer, must be freed by the caller.
*
......@@ -276,11 +276,12 @@ acpi_get_object_info(acpi_handle handle,
struct acpi_pnp_device_id *hid = NULL;
struct acpi_pnp_device_id *uid = NULL;
struct acpi_pnp_device_id *sub = NULL;
struct acpi_pnp_device_id *cls = NULL;
char *next_id_string;
acpi_object_type type;
acpi_name name;
u8 param_count = 0;
u8 valid = 0;
u16 valid = 0;
u32 info_size;
u32 i;
acpi_status status;
......@@ -320,7 +321,7 @@ acpi_get_object_info(acpi_handle handle,
if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) {
/*
* Get extra info for ACPI Device/Processor objects only:
* Run the Device _HID, _UID, _SUB, and _CID methods.
* Run the Device _HID, _UID, _SUB, _CID, and _CLS methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info->Valid bitfield is used
......@@ -363,6 +364,14 @@ acpi_get_object_info(acpi_handle handle,
sizeof(struct acpi_pnp_device_id_list));
valid |= ACPI_VALID_CID;
}
/* Execute the Device._CLS method */
status = acpi_ut_execute_CLS(node, &cls);
if (ACPI_SUCCESS(status)) {
info_size += cls->length;
valid |= ACPI_VALID_CLS;
}
}
/*
......@@ -486,6 +495,11 @@ acpi_get_object_info(acpi_handle handle,
}
}
if (cls) {
next_id_string = acpi_ns_copy_device_id(&info->class_code,
cls, next_id_string);
}
/* Copy the fixed-length data */
info->info_size = info_size;
......@@ -510,6 +524,9 @@ acpi_get_object_info(acpi_handle handle,
if (cid_list) {
ACPI_FREE(cid_list);
}
if (cls) {
ACPI_FREE(cls);
}
return (status);
}
......
/******************************************************************************
*
* Module Name: utids - support for device Ids - HID, UID, CID
* Module Name: utids - support for device Ids - HID, UID, CID, SUB, CLS
*
*****************************************************************************/
......@@ -416,3 +416,92 @@ acpi_ut_execute_CID(struct acpi_namespace_node *device_node,
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
/*******************************************************************************
*
* FUNCTION: acpi_ut_execute_CLS
*
* PARAMETERS: device_node - Node for the device
* return_id - Where the _CLS is returned
*
* RETURN: Status
*
* DESCRIPTION: Executes the _CLS control method that returns PCI-defined
* class code of the device. The _CLS value is always a package
* containing PCI class information as a list of integers.
* The returned string has format "BBSSPP", where:
* BB = Base-class code
* SS = Sub-class code
* PP = Programming Interface code
*
******************************************************************************/
acpi_status
acpi_ut_execute_CLS(struct acpi_namespace_node *device_node,
struct acpi_pnp_device_id **return_id)
{
union acpi_operand_object *obj_desc;
union acpi_operand_object **cls_objects;
u32 count;
struct acpi_pnp_device_id *cls;
u32 length;
acpi_status status;
u8 class_code[3] = { 0, 0, 0 };
ACPI_FUNCTION_TRACE(ut_execute_CLS);
status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CLS,
ACPI_BTYPE_PACKAGE, &obj_desc);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/* Get the size of the String to be returned, includes null terminator */
length = ACPI_PCICLS_STRING_SIZE;
cls_objects = obj_desc->package.elements;
count = obj_desc->package.count;
if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
if (count > 0
&& cls_objects[0]->common.type == ACPI_TYPE_INTEGER) {
class_code[0] = (u8)cls_objects[0]->integer.value;
}
if (count > 1
&& cls_objects[1]->common.type == ACPI_TYPE_INTEGER) {
class_code[1] = (u8)cls_objects[1]->integer.value;
}
if (count > 2
&& cls_objects[2]->common.type == ACPI_TYPE_INTEGER) {
class_code[2] = (u8)cls_objects[2]->integer.value;
}
}
/* Allocate a buffer for the CLS */
cls =
ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pnp_device_id) +
(acpi_size) length);
if (!cls) {
status = AE_NO_MEMORY;
goto cleanup;
}
/* Area for the string starts after PNP_DEVICE_ID struct */
cls->string =
ACPI_ADD_PTR(char, cls, sizeof(struct acpi_pnp_device_id));
/* Simply copy existing string */
acpi_ex_pci_cls_to_string(cls->string, class_code);
cls->length = length;
*return_id = cls;
cleanup:
/* On exit, we must delete the return object */
acpi_ut_remove_reference(obj_desc);
return_ACPI_STATUS(status);
}
......@@ -51,6 +51,7 @@
#define METHOD_NAME__BBN "_BBN"
#define METHOD_NAME__CBA "_CBA"
#define METHOD_NAME__CID "_CID"
#define METHOD_NAME__CLS "_CLS"
#define METHOD_NAME__CRS "_CRS"
#define METHOD_NAME__DDN "_DDN"
#define METHOD_NAME__HID "_HID"
......
......@@ -1141,6 +1141,10 @@ u32 (*acpi_interface_handler) (acpi_string interface_name, u32 supported);
#define ACPI_UUID_LENGTH 16
/* Length of 3-byte PCI class code values when converted back to a string */
#define ACPI_PCICLS_STRING_SIZE 7 /* Includes null terminator */
/* Structures used for device/processor HID, UID, CID, and SUB */
struct acpi_pnp_device_id {
......@@ -1163,7 +1167,7 @@ struct acpi_device_info {
u32 name; /* ACPI object Name */
acpi_object_type type; /* ACPI object Type */
u8 param_count; /* If a method, required parameter count */
u8 valid; /* Indicates which optional fields are valid */
u16 valid; /* Indicates which optional fields are valid */
u8 flags; /* Miscellaneous info */
u8 highest_dstates[4]; /* _sx_d values: 0xFF indicates not valid */
u8 lowest_dstates[5]; /* _sx_w values: 0xFF indicates not valid */
......@@ -1172,6 +1176,7 @@ struct acpi_device_info {
struct acpi_pnp_device_id hardware_id; /* _HID value */
struct acpi_pnp_device_id unique_id; /* _UID value */
struct acpi_pnp_device_id subsystem_id; /* _SUB value */
struct acpi_pnp_device_id class_code; /* _CLS value */
struct acpi_pnp_device_id_list compatible_id_list; /* _CID list <must be last> */
};
......@@ -1181,14 +1186,15 @@ struct acpi_device_info {
/* Flags for Valid field above (acpi_get_object_info) */
#define ACPI_VALID_STA 0x01
#define ACPI_VALID_ADR 0x02
#define ACPI_VALID_HID 0x04
#define ACPI_VALID_UID 0x08
#define ACPI_VALID_SUB 0x10
#define ACPI_VALID_CID 0x20
#define ACPI_VALID_SXDS 0x40
#define ACPI_VALID_SXWS 0x80
#define ACPI_VALID_STA 0x0001
#define ACPI_VALID_ADR 0x0002
#define ACPI_VALID_HID 0x0004
#define ACPI_VALID_UID 0x0008
#define ACPI_VALID_SUB 0x0010
#define ACPI_VALID_CID 0x0020
#define ACPI_VALID_CLS 0x0040
#define ACPI_VALID_SXDS 0x0100
#define ACPI_VALID_SXWS 0x0200
/* Flags for _STA return value (current_status above) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment