ACPICA: Utilities: Add _CLS processing
authorSuravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Wed, 1 Jul 2015 06:44:04 +0000 (14:44 +0800)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 1 Jul 2015 21:17:53 +0000 (23:17 +0200)
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/9a2b638a
Acked-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Signed-off-by: Suravee Suthikulpanit <Suravee.Suthikulpanit@amd.com>
Signed-off-by: Lv Zheng <lv.zheng@intel.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
drivers/acpi/acpica/acinterp.h
drivers/acpi/acpica/acutils.h
drivers/acpi/acpica/exutils.c
drivers/acpi/acpica/nsxfname.c
drivers/acpi/acpica/utids.c
include/acpi/acnames.h
include/acpi/actypes.h

index 1886bde54b5d323e0d9543dbac41245d7b8e1075..7ac98000b46b61dd417fe260315000092b2be861 100644 (file)
@@ -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);
 
 /*
index d49f5c7a20d90197ece8b625dd2fcd22fca4c4b1..6391c9706e8492a8bd9ab38f8a135ac2ecd55079 100644 (file)
@@ -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
  */
index 3f4225e95d9311ffe5a915f5081f686b0619ca4f..30c3f464fda5bcae5e98c7dd323fb963acea217d 100644 (file)
@@ -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
index d66c326485d82e769d5c93d4692ac0b02ca277f1..dc0836a9cf179640248dc4b2db60ef41e8227067 100644 (file)
@@ -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 @@ cleanup:
        if (cid_list) {
                ACPI_FREE(cid_list);
        }
+       if (cls) {
+               ACPI_FREE(cls);
+       }
        return (status);
 }
 
index 27431cfc1c4476c6128c90f240bb8d090831486c..3afe07f19b9f2d7d300b534ff76ece9817e7febf 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * 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 @@ cleanup:
        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);
+}
index 273de709495c1db522d46dad7f339677fc8df756..b52c0dc4b4925a1d29c6c8b2d55a1ed0c40b2b75 100644 (file)
@@ -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"
index ff0b53e128eed154070f2682d4c74565a80078e5..d791b986002a5edcf9b6777c60ced22aaf8eb999 100644 (file)
@@ -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) */