Currently, ath12k does not have the ability to set band edge channel power for WCN7850. In order to support this, ath12k gets band edge channel power table in ath12k_acpi_dsm_get_data() function and sets pdev_id and param_type_id, then finally sends these data and WMI_PDEV_SET_BIOS_INTERFACE_CMDID to firmware to set band edge channel power. Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0-03427-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.15378.4 Signed-off-by: Lingbo Kong <quic_lingbok@xxxxxxxxxxx> --- v5: 1.rebase to the latest tag v4: 1.revise commit log using imperative voice v3: 1.remove unnecessary cpu_to_le32() 2.adjust the order of the macros v2: no change drivers/net/wireless/ath/ath12k/acpi.c | 29 +++++++++++++++++++ drivers/net/wireless/ath/ath12k/acpi.h | 5 ++++ drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/wmi.c | 40 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 3 ++ 5 files changed, 78 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/acpi.c b/drivers/net/wireless/ath/ath12k/acpi.c index a9931e17bd17..389b900df170 100644 --- a/drivers/net/wireless/ath/ath12k/acpi.c +++ b/drivers/net/wireless/ath/ath12k/acpi.c @@ -82,6 +82,16 @@ static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func) memcpy(&ab->acdata->cca_data, obj->buffer.pointer, obj->buffer.length); break; + case ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE: + if (obj->buffer.length != ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE) { + ath12k_err(ab, "Invalid BAND EDGE data size %d\n", + obj->buffer.length); + ret = -EINVAL; + goto out; + } + memcpy(&ab->acdata->band_edge_power, obj->buffer.pointer, + obj->buffer.length); + break; } } else { ath12k_err(ab, @@ -311,6 +321,25 @@ int ath12k_get_acpi_all_data(struct ath12k_base *ab) } } + if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acdata, ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER)) { + ret = ath12k_acpi_dsm_get_data(ab, + ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE); + if (ret) { + ath12k_err(ab, "failed to get band edge channel power %d\n", ret); + goto err_free_acdata; + } + + if (ab->acdata->band_edge_power[0] == ATH12K_ACPI_BAND_EDGE_VERSION && + ab->acdata->band_edge_power[1] == ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG) { + ret = ath12k_wmi_pdev_set_band_edge_power(ab, + ab->acdata->band_edge_power); + if (ret) { + ath12k_err(ab, "set band edge channel power failed %d\n", ret); + goto err_free_acdata; + } + } + } + status = acpi_install_notify_handler(ACPI_HANDLE(ab->dev), ACPI_DEVICE_NOTIFY, acpi_dsm_notify, ab); diff --git a/drivers/net/wireless/ath/ath12k/acpi.h b/drivers/net/wireless/ath/ath12k/acpi.h index 1f05a68e490b..27f28fc13600 100644 --- a/drivers/net/wireless/ath/ath12k/acpi.h +++ b/drivers/net/wireless/ath/ath12k/acpi.h @@ -14,12 +14,14 @@ #define ATH12K_ACPI_DSM_FUNC_INDEX_CCA 6 #define ATH12K_ACPI_DSM_FUNC_INDEX_TAS_CFG 8 #define ATH12K_ACPI_DSM_FUNC_INDEX_TAS_DATA 9 +#define ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE 10 #define ATH12K_ACPI_FUNC_BIT_BIOS_SAR BIT(3) #define ATH12K_ACPI_FUNC_BIT_GEO_OFFSET BIT(4) #define ATH12K_ACPI_FUNC_BIT_CCA BIT(5) #define ATH12K_ACPI_FUNC_BIT_TAS_CFG BIT(7) #define ATH12K_ACPI_FUNC_BIT_TAS_DATA BIT(8) +#define ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER BIT(9) #define ATH12K_ACPI_NOTIFY_EVENT 0x86 #define ATH12K_ACPI_FUNC_BIT_VALID(_acdata, _func) ((((_acdata)->func_bit) & (_func)) != 0) @@ -30,6 +32,8 @@ #define ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG 0x1 #define ATH12K_ACPI_CCA_THR_VERSION 0x1 #define ATH12K_ACPI_CCA_THR_ENABLE_FLAG 0x1 +#define ATH12K_ACPI_BAND_EDGE_VERSION 0x1 +#define ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG 0x1 #define ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET 1 #define ATH12K_ACPI_DBS_BACKOFF_DATA_OFFSET 2 @@ -41,6 +45,7 @@ #define ATH12K_ACPI_CCA_THR_OFFSET_LEN 36 #define ATH12K_ACPI_DSM_TAS_DATA_SIZE 69 +#define ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE 100 #define ATH12K_ACPI_DSM_TAS_CFG_SIZE 108 #define ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE (ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET + \ diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 4b663577c2b9..350cff3c30e3 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -803,6 +803,7 @@ struct ath12k_base { u8 bios_sar_data[ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE]; u8 geo_offset_data[ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE]; u8 cca_data[ATH12K_ACPI_DSM_CCA_DATA_SIZE]; + u8 band_edge_power[ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE]; } *acdata; /* must be last */ diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index b2fbd285ab4d..942ed486b2b5 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -7184,3 +7184,43 @@ int ath12k_wmi_pdev_set_cca_thr_table_param(struct ath12k_base *ab, } return ret; } + +int ath12k_wmi_pdev_set_band_edge_power(struct ath12k_base *ab, + const u8 *pchan_table) +{ + struct ath12k_wmi_base *wmi_ab = &ab->wmi_ab; + struct wmi_pdev_set_bios_interface_cmd *cmd; + struct wmi_tlv *tlv; + struct sk_buff *skb; + int ret; + u8 *buf_ptr; + u32 len, len_aligned; + + len_aligned = roundup(ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE, sizeof(u32)); + len = sizeof(*cmd) + TLV_HDR_SIZE + len_aligned; + + skb = ath12k_wmi_alloc_skb(wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_pdev_set_bios_interface_cmd *)skb->data; + cmd->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD_PARAMS, + sizeof(*cmd)); + cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC); + cmd->param_type_id = cpu_to_le32(WMI_BIOS_PARAM_TYPE_BANDEDGE_CTL_POWER); + cmd->length = cpu_to_le32(ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE); + + buf_ptr = skb->data + sizeof(*cmd); + tlv = (struct wmi_tlv *)buf_ptr; + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, len_aligned); + buf_ptr += TLV_HDR_SIZE; + memcpy(buf_ptr, pchan_table, ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE); + + ret = ath12k_wmi_cmd_send(&wmi_ab->wmi[0], skb, WMI_PDEV_SET_BIOS_INTERFACE_CMDID); + if (ret) { + ath12k_warn(ab, "failed to send WMI_PDEV_SET_BIOS_INTERFACE_CMDID %d\n", ret); + dev_kfree_skb(skb); + } + + return ret; +} diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h index 5a3d7962b8cb..314044b0e003 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -4811,6 +4811,7 @@ enum bios_param_type { WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE = 0, WMI_BIOS_PARAM_TAS_CONFIG_TYPE = 1, WMI_BIOS_PARAM_TAS_DATA_TYPE = 2, + WMI_BIOS_PARAM_TYPE_BANDEDGE_CTL_POWER = 3, WMI_BIOS_PARAM_TYPE_MAX, }; @@ -4983,4 +4984,6 @@ int ath12k_wmi_pdev_set_bios_geo_table_param(struct ath12k_base *ab, u8 *pgeo_table); int ath12k_wmi_pdev_set_cca_thr_table_param(struct ath12k_base *ab, u8 *pcca_table); +int ath12k_wmi_pdev_set_band_edge_power(struct ath12k_base *ab, + const u8 *pchan_table); #endif -- 2.34.1