]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: rtw89: acpi: introduce method evaluation function for reuse
authorZong-Zhe Yang <kevin_yang@realtek.com>
Wed, 26 Mar 2025 02:06:36 +0000 (10:06 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 31 Mar 2025 06:23:03 +0000 (14:23 +0800)
The following implementations will evaluate different ACPI methods, but
the pre-process flow of them are the same. So, introduce a function for
these pre-process things. Besides, also change ACPI RTAG method to call
this function.

Signed-off-by: Zong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20250326020643.14487-6-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/acpi.c
drivers/net/wireless/realtek/rtw89/acpi.h

index b870a3df4072cb628a6ef854dac00629cbec0a88..97b069062ec8f39262e828c7782cb93b98f229ff 100644 (file)
@@ -12,6 +12,121 @@ static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00,
                                           0x82, 0xBD, 0xFE, 0x86,
                                           0x07, 0x80, 0x3A, 0xA7);
 
+static u32 rtw89_acpi_traversal_object(struct rtw89_dev *rtwdev,
+                                      const union acpi_object *obj, u8 *pos)
+{
+       const union acpi_object *elm;
+       unsigned int i;
+       u32 sub_len;
+       u32 len = 0;
+       u8 *tmp;
+
+       switch (obj->type) {
+       case ACPI_TYPE_INTEGER:
+               if (pos)
+                       pos[len] = obj->integer.value;
+
+               len++;
+               break;
+       case ACPI_TYPE_BUFFER:
+               if (unlikely(obj->buffer.length == 0)) {
+                       rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                                   "%s: invalid buffer type\n", __func__);
+                       goto err;
+               }
+
+               if (pos)
+                       memcpy(pos, obj->buffer.pointer, obj->buffer.length);
+
+               len += obj->buffer.length;
+               break;
+       case ACPI_TYPE_PACKAGE:
+               if (unlikely(obj->package.count == 0)) {
+                       rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                                   "%s: invalid package type\n", __func__);
+                       goto err;
+               }
+
+               for (i = 0; i < obj->package.count; i++) {
+                       elm = &obj->package.elements[i];
+                       tmp = pos ? pos + len : NULL;
+
+                       sub_len = rtw89_acpi_traversal_object(rtwdev, elm, tmp);
+                       if (unlikely(sub_len == 0))
+                               goto err;
+
+                       len += sub_len;
+               }
+               break;
+       default:
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: unhandled type: %d\n",
+                           __func__, obj->type);
+               goto err;
+       }
+
+       return len;
+
+err:
+       return 0;
+}
+
+static u32 rtw89_acpi_calculate_object_length(struct rtw89_dev *rtwdev,
+                                             const union acpi_object *obj)
+{
+       return rtw89_acpi_traversal_object(rtwdev, obj, NULL);
+}
+
+static struct rtw89_acpi_data *
+rtw89_acpi_evaluate_method(struct rtw89_dev *rtwdev, const char *method)
+{
+       struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+       struct rtw89_acpi_data *data = NULL;
+       acpi_handle root, handle;
+       union acpi_object *obj;
+       acpi_status status;
+       u32 len;
+
+       root = ACPI_HANDLE(rtwdev->dev);
+       if (!root) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                           "acpi (%s): failed to get root\n", method);
+               return NULL;
+       }
+
+       status = acpi_get_handle(root, (acpi_string)method, &handle);
+       if (ACPI_FAILURE(status)) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                           "acpi (%s): failed to get handle\n", method);
+               return NULL;
+       }
+
+       status = acpi_evaluate_object(handle, NULL, NULL, &buf);
+       if (ACPI_FAILURE(status)) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                           "acpi (%s): failed to evaluate object\n", method);
+               return NULL;
+       }
+
+       obj = buf.pointer;
+       len = rtw89_acpi_calculate_object_length(rtwdev, obj);
+       if (unlikely(len == 0)) {
+               rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+                           "acpi (%s): failed to traversal obj len\n", method);
+               goto out;
+       }
+
+       data = kzalloc(struct_size(data, buf, len), GFP_KERNEL);
+       if (!data)
+               goto out;
+
+       data->len = len;
+       rtw89_acpi_traversal_object(rtwdev, obj, data->buf);
+
+out:
+       ACPI_FREE(obj);
+       return data;
+}
+
 static
 int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj,
                             u8 *value)
@@ -152,34 +267,15 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
 int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
                             struct rtw89_acpi_rtag_result *res)
 {
-       struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
-       acpi_handle root, handle;
-       union acpi_object *obj;
-       acpi_status status;
+       const struct rtw89_acpi_data *data;
        u32 buf_len;
        int ret = 0;
 
-       root = ACPI_HANDLE(rtwdev->dev);
-       if (!root)
-               return -EOPNOTSUPP;
-
-       status = acpi_get_handle(root, (acpi_string)"RTAG", &handle);
-       if (ACPI_FAILURE(status))
-               return -EIO;
-
-       status = acpi_evaluate_object(handle, NULL, NULL, &buf);
-       if (ACPI_FAILURE(status))
+       data = rtw89_acpi_evaluate_method(rtwdev, "RTAG");
+       if (!data)
                return -EIO;
 
-       obj = buf.pointer;
-       if (obj->type != ACPI_TYPE_BUFFER) {
-               rtw89_debug(rtwdev, RTW89_DBG_ACPI,
-                           "acpi: expect buffer but type: %d\n", obj->type);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       buf_len = obj->buffer.length;
+       buf_len = data->len;
        if (buf_len != sizeof(*res)) {
                rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
                            __func__, buf_len);
@@ -187,12 +283,12 @@ int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
                goto out;
        }
 
-       *res = *(struct rtw89_acpi_rtag_result *)obj->buffer.pointer;
+       *res = *(struct rtw89_acpi_rtag_result *)data->buf;
 
        rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "antenna_gain: ", res, sizeof(*res));
 
 out:
-       ACPI_FREE(obj);
+       kfree(data);
        return ret;
 }
 
index a7f583a2164f5a25d0c860e53bec74bcb3264a6a..1f5d732c33c08932daf2cac5175999bde662818a 100644 (file)
@@ -7,6 +7,11 @@
 
 #include "core.h"
 
+struct rtw89_acpi_data {
+       u32 len;
+       u8 buf[] __counted_by(len);
+};
+
 enum rtw89_acpi_dsm_func {
        RTW89_ACPI_DSM_FUNC_IDN_BAND_SUP = 2,
        RTW89_ACPI_DSM_FUNC_6G_DIS = 3,