Message ID | 20230905024904.3882-4-quic_lingbok@quicinc.com |
---|---|
State | Superseded |
Headers | show |
Series | wifi: ath12k: implement some functionalities through reading ACPI Table | expand |
On 9/4/2023 7:49 PM, Lingbo Kong wrote: > ath12k need to adjust CCA threshold values to meet the regulatory > requirement. ath12k can retrieve CCA threshold configuration by invoking > ACPI _DSM method. > > 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@quicinc.com> > --- > drivers/net/wireless/ath/ath12k/acpi.c | 30 +++++++++++++++++++ > drivers/net/wireless/ath/ath12k/acpi.h | 8 +++++ > drivers/net/wireless/ath/ath12k/core.h | 1 + > drivers/net/wireless/ath/ath12k/wmi.c | 41 ++++++++++++++++++++++++++ > drivers/net/wireless/ath/ath12k/wmi.h | 7 +++-- > 5 files changed, 85 insertions(+), 2 deletions(-) > > diff --git a/drivers/net/wireless/ath/ath12k/acpi.c b/drivers/net/wireless/ath/ath12k/acpi.c > index ae1ce7b99d2d..a9931e17bd17 100644 > --- a/drivers/net/wireless/ath/ath12k/acpi.c > +++ b/drivers/net/wireless/ath/ath12k/acpi.c > @@ -72,6 +72,16 @@ static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func) > memcpy(&ab->acdata->geo_offset_data, obj->buffer.pointer, > obj->buffer.length); > break; > + case ATH12K_ACPI_DSM_FUNC_INDEX_CCA: > + if (obj->buffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) { > + ath12k_err(ab, "Invalid CCA data size %d\n", > + obj->buffer.length); > + ret = -EINVAL; > + goto out; > + } > + memcpy(&ab->acdata->cca_data, obj->buffer.pointer, > + obj->buffer.length); > + break; > } > } else { > ath12k_err(ab, > @@ -281,6 +291,26 @@ int ath12k_get_acpi_all_data(struct ath12k_base *ab) > goto err_free_acdata; > } > > + if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acdata, ATH12K_ACPI_FUNC_BIT_CCA)) { > + ret = ath12k_acpi_dsm_get_data(ab, > + ATH12K_ACPI_DSM_FUNC_INDEX_CCA); > + if (ret) { > + ath12k_err(ab, "failed to get cca threshold configuration %d\n", ret); > + goto err_free_acdata; > + } > + > + if (ab->acdata->cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION && > + ab->acdata->cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] == > + ATH12K_ACPI_CCA_THR_ENABLE_FLAG) { > + ret = ath12k_wmi_pdev_set_cca_thr_table_param(ab, > + ab->acdata->cca_data); > + if (ret) { > + ath12k_err(ab, "set cca threshold 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 59f87cb258c6..acdf8d851fba 100644 > --- a/drivers/net/wireless/ath/ath12k/acpi.h > +++ b/drivers/net/wireless/ath/ath12k/acpi.h > @@ -13,14 +13,17 @@ > #define ATH12K_ACPI_DSM_FUNC_INDEX_TAS_DATA 9 > #define ATH12K_ACPI_DSM_FUNC_INDEX_BIOS_SAR 4 > #define ATH12K_ACPI_DSM_FUNC_INDEX_GEO_OFFSET 5 > +#define ATH12K_ACPI_DSM_FUNC_INDEX_CCA 6 > > #define ATH12K_ACPI_DSM_TAS_CFG_SIZE 108 > #define ATH12K_ACPI_DSM_TAS_DATA_SIZE 69 > #define ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE 34 > #define ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE 19 > +#define ATH12K_ACPI_DSM_CCA_DATA_SIZE 41 > > #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) > > @@ -37,6 +40,11 @@ > #define ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG 0x1 > #define ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET 1 > #define ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN 18 > +#define ATH12K_ACPI_CCA_THR_VERSION 0x1 > +#define ATH12K_ACPI_CCA_THR_ENABLE_FLAG 0x1 > +#define ATH12K_ACPI_CCA_THR_OFFSET_LEN 36 > +#define ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET 5 for all of these macros it seems like you have duplication of knowledge. here you have two macros that describe the layout, and you have a separate macro above that describes the entire data size. IMO it would be "better" if the data size was based upon the layout macros rather than being an independent quantity: #define ATH12K_ACPI_DSM_CCA_DATA_SIZE (ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET + ATH12K_ACPI_CCA_THR_OFFSET_LEN) consider this advice to apply to the previous patches in this patchset > + > > int ath12k_get_acpi_all_data(struct ath12k_base *ab); > void acpi_dsm_notify(acpi_handle handle, u32 event, void *data); > diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h > index 6fe4f0ddee4a..d57e2013b0fe 100644 > --- a/drivers/net/wireless/ath/ath12k/core.h > +++ b/drivers/net/wireless/ath/ath12k/core.h > @@ -780,6 +780,7 @@ struct ath12k_base { > u8 tas_sar_power_table[ATH12K_ACPI_DSM_TAS_DATA_SIZE]; > 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]; > } *acdata; > > /* must be last */ > diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c > index f090ccea5f64..3f66807b7961 100644 > --- a/drivers/net/wireless/ath/ath12k/wmi.c > +++ b/drivers/net/wireless/ath/ath12k/wmi.c > @@ -7072,3 +7072,44 @@ int ath12k_wmi_pdev_set_bios_geo_table_param(struct ath12k_base *ab, > > return ret; > } > + > +int ath12k_wmi_pdev_set_cca_thr_table_param(struct ath12k_base *ab, > + u8 *pcca_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, cca_thr_len_aligned; > + u8 *pcca_value = pcca_table + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET; > + > + cca_thr_len_aligned = roundup(ATH12K_ACPI_CCA_THR_OFFSET_LEN, sizeof(u32)); > + len = sizeof(*cmd) + TLV_HDR_SIZE + cca_thr_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 = > + cpu_to_le32(ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD_PARAMS, > + sizeof(*cmd))); remove cpu_to_le32() > + cmd->pdev_id = cpu_to_le32(WMI_PDEV_ID_SOC); > + cmd->param_type_id = cpu_to_le32(WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE); > + cmd->length = ATH12K_ACPI_CCA_THR_OFFSET_LEN; > + > + buf_ptr = skb->data + sizeof(*cmd); > + tlv = (struct wmi_tlv *)buf_ptr; > + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, cca_thr_len_aligned); > + buf_ptr += TLV_HDR_SIZE; > + memcpy(buf_ptr, pcca_value, ATH12K_ACPI_CCA_THR_OFFSET_LEN); > + > + 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 8a774655fe9f..7607cd7ab699 100644 > --- a/drivers/net/wireless/ath/ath12k/wmi.h > +++ b/drivers/net/wireless/ath/ath12k/wmi.h > @@ -4805,8 +4805,9 @@ struct wmi_pdev_set_bios_interface_cmd { > } __packed; > > enum bios_param_type { > - WMI_BIOS_PARAM_TAS_CONFIG_TYPE = 1, > - WMI_BIOS_PARAM_TAS_DATA_TYPE = 2, > + 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_MAX, > }; > > @@ -4952,4 +4953,6 @@ int ath12k_wmi_pdev_set_bios_sar_table_param(struct ath12k_base *ab, > u8 *psar_table); > 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); > #endif
diff --git a/drivers/net/wireless/ath/ath12k/acpi.c b/drivers/net/wireless/ath/ath12k/acpi.c index ae1ce7b99d2d..a9931e17bd17 100644 --- a/drivers/net/wireless/ath/ath12k/acpi.c +++ b/drivers/net/wireless/ath/ath12k/acpi.c @@ -72,6 +72,16 @@ static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func) memcpy(&ab->acdata->geo_offset_data, obj->buffer.pointer, obj->buffer.length); break; + case ATH12K_ACPI_DSM_FUNC_INDEX_CCA: + if (obj->buffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) { + ath12k_err(ab, "Invalid CCA data size %d\n", + obj->buffer.length); + ret = -EINVAL; + goto out; + } + memcpy(&ab->acdata->cca_data, obj->buffer.pointer, + obj->buffer.length); + break; } } else { ath12k_err(ab, @@ -281,6 +291,26 @@ int ath12k_get_acpi_all_data(struct ath12k_base *ab) goto err_free_acdata; } + if (ATH12K_ACPI_FUNC_BIT_VALID(ab->acdata, ATH12K_ACPI_FUNC_BIT_CCA)) { + ret = ath12k_acpi_dsm_get_data(ab, + ATH12K_ACPI_DSM_FUNC_INDEX_CCA); + if (ret) { + ath12k_err(ab, "failed to get cca threshold configuration %d\n", ret); + goto err_free_acdata; + } + + if (ab->acdata->cca_data[0] == ATH12K_ACPI_CCA_THR_VERSION && + ab->acdata->cca_data[ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET] == + ATH12K_ACPI_CCA_THR_ENABLE_FLAG) { + ret = ath12k_wmi_pdev_set_cca_thr_table_param(ab, + ab->acdata->cca_data); + if (ret) { + ath12k_err(ab, "set cca threshold 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 59f87cb258c6..acdf8d851fba 100644 --- a/drivers/net/wireless/ath/ath12k/acpi.h +++ b/drivers/net/wireless/ath/ath12k/acpi.h @@ -13,14 +13,17 @@ #define ATH12K_ACPI_DSM_FUNC_INDEX_TAS_DATA 9 #define ATH12K_ACPI_DSM_FUNC_INDEX_BIOS_SAR 4 #define ATH12K_ACPI_DSM_FUNC_INDEX_GEO_OFFSET 5 +#define ATH12K_ACPI_DSM_FUNC_INDEX_CCA 6 #define ATH12K_ACPI_DSM_TAS_CFG_SIZE 108 #define ATH12K_ACPI_DSM_TAS_DATA_SIZE 69 #define ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE 34 #define ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE 19 +#define ATH12K_ACPI_DSM_CCA_DATA_SIZE 41 #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) @@ -37,6 +40,11 @@ #define ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG 0x1 #define ATH12K_ACPI_GEO_OFFSET_DATA_OFFSET 1 #define ATH12K_ACPI_BIOS_SAR_GEO_OFFSET_LEN 18 +#define ATH12K_ACPI_CCA_THR_VERSION 0x1 +#define ATH12K_ACPI_CCA_THR_ENABLE_FLAG 0x1 +#define ATH12K_ACPI_CCA_THR_OFFSET_LEN 36 +#define ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET 5 + int ath12k_get_acpi_all_data(struct ath12k_base *ab); void acpi_dsm_notify(acpi_handle handle, u32 event, void *data); diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h index 6fe4f0ddee4a..d57e2013b0fe 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -780,6 +780,7 @@ struct ath12k_base { u8 tas_sar_power_table[ATH12K_ACPI_DSM_TAS_DATA_SIZE]; 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]; } *acdata; /* must be last */ diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index f090ccea5f64..3f66807b7961 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -7072,3 +7072,44 @@ int ath12k_wmi_pdev_set_bios_geo_table_param(struct ath12k_base *ab, return ret; } + +int ath12k_wmi_pdev_set_cca_thr_table_param(struct ath12k_base *ab, + u8 *pcca_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, cca_thr_len_aligned; + u8 *pcca_value = pcca_table + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET; + + cca_thr_len_aligned = roundup(ATH12K_ACPI_CCA_THR_OFFSET_LEN, sizeof(u32)); + len = sizeof(*cmd) + TLV_HDR_SIZE + cca_thr_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 = + cpu_to_le32(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_CCA_THRESHOLD_TYPE); + cmd->length = ATH12K_ACPI_CCA_THR_OFFSET_LEN; + + buf_ptr = skb->data + sizeof(*cmd); + tlv = (struct wmi_tlv *)buf_ptr; + tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_BYTE, cca_thr_len_aligned); + buf_ptr += TLV_HDR_SIZE; + memcpy(buf_ptr, pcca_value, ATH12K_ACPI_CCA_THR_OFFSET_LEN); + + 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 8a774655fe9f..7607cd7ab699 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -4805,8 +4805,9 @@ struct wmi_pdev_set_bios_interface_cmd { } __packed; enum bios_param_type { - WMI_BIOS_PARAM_TAS_CONFIG_TYPE = 1, - WMI_BIOS_PARAM_TAS_DATA_TYPE = 2, + 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_MAX, }; @@ -4952,4 +4953,6 @@ int ath12k_wmi_pdev_set_bios_sar_table_param(struct ath12k_base *ab, u8 *psar_table); 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); #endif
ath12k need to adjust CCA threshold values to meet the regulatory requirement. ath12k can retrieve CCA threshold configuration by invoking ACPI _DSM method. 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@quicinc.com> --- drivers/net/wireless/ath/ath12k/acpi.c | 30 +++++++++++++++++++ drivers/net/wireless/ath/ath12k/acpi.h | 8 +++++ drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/wmi.c | 41 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 7 +++-- 5 files changed, 85 insertions(+), 2 deletions(-)