Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* Copyright(c) 2021-2023 Realtek Corporation */ #include <linux/acpi.h> #include <linux/uuid.h> #include "acpi.h" #include "debug.h" static const guid_t rtw89_guid = GUID_INIT(0xD2A8C3E8, 0x4B69, 0x4F00, 0x82, 0xBD, 0xFE, 0x86, 0x07, 0x80, 0x3A, 0xA7); static int rtw89_acpi_dsm_get_value(struct rtw89_dev *rtwdev, union acpi_object *obj, u8 *value) { if (obj->type != ACPI_TYPE_INTEGER) { rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi: expect integer but type: %d\n", obj->type); return -EINVAL; } *value = (u8)obj->integer.value; return 0; } static bool chk_acpi_policy_6ghz_sig(const struct rtw89_acpi_policy_6ghz *p) { return p->signature[0] == 0x00 && p->signature[1] == 0xE0 && p->signature[2] == 0x4C; } static int rtw89_acpi_dsm_get_policy_6ghz(struct rtw89_dev *rtwdev, union acpi_object *obj, struct rtw89_acpi_policy_6ghz **policy_6ghz) { const struct rtw89_acpi_policy_6ghz *ptr; u32 expect_len; u32 len; if (obj->type != ACPI_TYPE_BUFFER) { rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi: expect buffer but type: %d\n", obj->type); return -EINVAL; } len = obj->buffer.length; if (len < sizeof(*ptr)) { rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n", __func__, len); return -EINVAL; } ptr = (typeof(ptr))obj->buffer.pointer; if (!chk_acpi_policy_6ghz_sig(ptr)) { rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: bad signature\n", __func__); return -EINVAL; } expect_len = struct_size(ptr, country_list, ptr->country_count); if (len < expect_len) { rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: expect %u but length: %u\n", __func__, expect_len, len); return -EINVAL; } *policy_6ghz = kmemdup(ptr, expect_len, GFP_KERNEL); if (!*policy_6ghz) return -ENOMEM; rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "policy_6ghz: ", *policy_6ghz, expect_len); return 0; } int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev, enum rtw89_acpi_dsm_func func, struct rtw89_acpi_dsm_result *res) { union acpi_object *obj; int ret; obj = acpi_evaluate_dsm(ACPI_HANDLE(rtwdev->dev), &rtw89_guid, 0, func, NULL); if (!obj) { rtw89_debug(rtwdev, RTW89_DBG_ACPI, "acpi dsm fail to evaluate func: %d\n", func); return -ENOENT; } if (func == RTW89_ACPI_DSM_FUNC_6G_BP) ret = rtw89_acpi_dsm_get_policy_6ghz(rtwdev, obj, &res->u.policy_6ghz); else ret = rtw89_acpi_dsm_get_value(rtwdev, obj, &res->u.value); ACPI_FREE(obj); return ret; } |