diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath12k/acpi.c')
-rw-r--r-- | drivers/net/wireless/ath/ath12k/acpi.c | 202 |
1 files changed, 158 insertions, 44 deletions
diff --git a/drivers/net/wireless/ath/ath12k/acpi.c b/drivers/net/wireless/ath/ath12k/acpi.c index 0555d35aab47..d81367ce6929 100644 --- a/drivers/net/wireless/ath/ath12k/acpi.c +++ b/drivers/net/wireless/ath/ath12k/acpi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2021 The Linux Foundation. All rights reserved. - * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "core.h" @@ -12,7 +12,7 @@ static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func) { union acpi_object *obj; acpi_handle root_handle; - int ret; + int ret, i; root_handle = ACPI_HANDLE(ab->dev); if (!root_handle) { @@ -29,9 +29,48 @@ static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func) } if (obj->type == ACPI_TYPE_INTEGER) { - ab->acpi.func_bit = obj->integer.value; + switch (func) { + case ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS: + ab->acpi.func_bit = obj->integer.value; + break; + case ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG: + ab->acpi.bit_flag = obj->integer.value; + break; + } + } else if (obj->type == ACPI_TYPE_STRING) { + switch (func) { + case ATH12K_ACPI_DSM_FUNC_BDF_EXT: + if (obj->string.length <= ATH12K_ACPI_BDF_ANCHOR_STRING_LEN || + obj->string.length > ATH12K_ACPI_BDF_MAX_LEN || + memcmp(obj->string.pointer, ATH12K_ACPI_BDF_ANCHOR_STRING, + ATH12K_ACPI_BDF_ANCHOR_STRING_LEN)) { + ath12k_warn(ab, "invalid ACPI DSM BDF size: %d\n", + obj->string.length); + ret = -EINVAL; + goto out; + } + + memcpy(ab->acpi.bdf_string, obj->string.pointer, + obj->buffer.length); + + break; + } } else if (obj->type == ACPI_TYPE_BUFFER) { switch (func) { + case ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS: + if (obj->buffer.length < ATH12K_ACPI_DSM_FUNC_MIN_BITMAP_SIZE || + obj->buffer.length > ATH12K_ACPI_DSM_FUNC_MAX_BITMAP_SIZE) { + ath12k_warn(ab, "invalid ACPI DSM func size: %d\n", + obj->buffer.length); + ret = -EINVAL; + goto out; + } + + ab->acpi.func_bit = 0; + for (i = 0; i < obj->buffer.length; i++) + ab->acpi.func_bit += obj->buffer.pointer[i] << (i * 8); + + break; case ATH12K_ACPI_DSM_FUNC_TAS_CFG: if (obj->buffer.length != ATH12K_ACPI_DSM_TAS_CFG_SIZE) { ath12k_warn(ab, "invalid ACPI DSM TAS config size: %d\n", @@ -247,24 +286,118 @@ static int ath12k_acpi_set_tas_params(struct ath12k_base *ab) return 0; } +bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab) +{ + return ab->acpi.acpi_disable_rfkill; +} + +bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab) +{ + return ab->acpi.acpi_disable_11be; +} + +void ath12k_acpi_set_dsm_func(struct ath12k_base *ab) +{ + int ret; + u8 *buf; + + if (!ab->hw_params->acpi_guid) + /* not supported with this hardware */ + return; + + if (ab->acpi.acpi_tas_enable) { + ret = ath12k_acpi_set_tas_params(ab); + if (ret) { + ath12k_warn(ab, "failed to send ACPI TAS parameters: %d\n", ret); + return; + } + } + + if (ab->acpi.acpi_bios_sar_enable) { + ret = ath12k_acpi_set_bios_sar_params(ab); + if (ret) { + ath12k_warn(ab, "failed to send ACPI BIOS SAR: %d\n", ret); + return; + } + } + + if (ab->acpi.acpi_cca_enable) { + buf = ab->acpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET; + ret = ath12k_wmi_set_bios_cmd(ab, + WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE, + buf, + ATH12K_ACPI_CCA_THR_OFFSET_LEN); + if (ret) { + ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n", + ret); + return; + } + } + + if (ab->acpi.acpi_band_edge_enable) { + ret = ath12k_wmi_set_bios_cmd(ab, + WMI_BIOS_PARAM_TYPE_BANDEDGE, + ab->acpi.band_edge_power, + sizeof(ab->acpi.band_edge_power)); + if (ret) { + ath12k_warn(ab, + "failed to set ACPI DSM band edge channel power: %d\n", + ret); + return; + } + } +} + int ath12k_acpi_start(struct ath12k_base *ab) { acpi_status status; - u8 *buf; int ret; + ab->acpi.acpi_tas_enable = false; + ab->acpi.acpi_disable_11be = false; + ab->acpi.acpi_disable_rfkill = false; + ab->acpi.acpi_bios_sar_enable = false; + ab->acpi.acpi_cca_enable = false; + ab->acpi.acpi_band_edge_enable = false; + ab->acpi.acpi_enable_bdf = false; + ab->acpi.bdf_string[0] = '\0'; + if (!ab->hw_params->acpi_guid) /* not supported with this hardware */ return 0; - ab->acpi.acpi_tas_enable = false; - ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS); if (ret) { ath12k_dbg(ab, ATH12K_DBG_BOOT, "failed to get ACPI DSM data: %d\n", ret); return ret; } + if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_DISABLE_FLAG)) { + ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG); + if (ret) { + ath12k_warn(ab, "failed to get ACPI DISABLE FLAG: %d\n", ret); + return ret; + } + + if (ATH12K_ACPI_CHEK_BIT_VALID(ab->acpi, + ATH12K_ACPI_DSM_DISABLE_11BE_BIT)) + ab->acpi.acpi_disable_11be = true; + + if (!ATH12K_ACPI_CHEK_BIT_VALID(ab->acpi, + ATH12K_ACPI_DSM_DISABLE_RFKILL_BIT)) + ab->acpi.acpi_disable_rfkill = true; + } + + if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_BDF_EXT)) { + ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BDF_EXT); + if (ret || ab->acpi.bdf_string[0] == '\0') { + ath12k_warn(ab, "failed to get ACPI BDF EXT: %d\n", ret); + return ret; + } + + ab->acpi.acpi_enable_bdf = true; + } + if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG)) { ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_CFG); if (ret) { @@ -308,20 +441,6 @@ int ath12k_acpi_start(struct ath12k_base *ab) ab->acpi.acpi_bios_sar_enable = true; } - if (ab->acpi.acpi_tas_enable) { - ret = ath12k_acpi_set_tas_params(ab); - if (ret) { - ath12k_warn(ab, "failed to send ACPI parameters: %d\n", ret); - return ret; - } - } - - if (ab->acpi.acpi_bios_sar_enable) { - ret = ath12k_acpi_set_bios_sar_params(ab); - if (ret) - return ret; - } - if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, ATH12K_ACPI_FUNC_BIT_CCA)) { ret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_CCA); if (ret) { @@ -332,18 +451,8 @@ int ath12k_acpi_start(struct ath12k_base *ab) if (ab->acpi.cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION && ab->acpi.cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] == - ATH12K_ACPI_CCA_THR_ENABLE_FLAG) { - buf = ab->acpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET; - ret = ath12k_wmi_set_bios_cmd(ab, - WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE, - buf, - ATH12K_ACPI_CCA_THR_OFFSET_LEN); - if (ret) { - ath12k_warn(ab, "failed to set ACPI DSM CCA threshold: %d\n", - ret); - return ret; - } - } + ATH12K_ACPI_CCA_THR_ENABLE_FLAG) + ab->acpi.acpi_cca_enable = true; } if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acpi, @@ -356,18 +465,8 @@ int ath12k_acpi_start(struct ath12k_base *ab) } if (ab->acpi.band_edge_power[0] == ATH12K_ACPI_BAND_EDGE_VERSION && - ab->acpi.band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG) { - ret = ath12k_wmi_set_bios_cmd(ab, - WMI_BIOS_PARAM_TYPE_BANDEDGE, - ab->acpi.band_edge_power, - sizeof(ab->acpi.band_edge_power)); - if (ret) { - ath12k_warn(ab, - "failed to set ACPI DSM band edge channel power: %d\n", - ret); - return ret; - } - } + ab->acpi.band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG) + ab->acpi.acpi_band_edge_enable = true; } status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev), @@ -383,6 +482,21 @@ int ath12k_acpi_start(struct ath12k_base *ab) return 0; } +int ath12k_acpi_check_bdf_variant_name(struct ath12k_base *ab) +{ + size_t max_len = sizeof(ab->qmi.target.bdf_ext); + + if (!ab->acpi.acpi_enable_bdf) + return -ENODATA; + + if (strscpy(ab->qmi.target.bdf_ext, ab->acpi.bdf_string + 4, max_len) < 0) + ath12k_dbg(ab, ATH12K_DBG_BOOT, + "acpi bdf variant longer than the buffer (variant: %s)\n", + ab->acpi.bdf_string); + + return 0; +} + void ath12k_acpi_stop(struct ath12k_base *ab) { if (!ab->acpi.started) |