Message ID | 20230905024904.3882-5-quic_lingbok@quicinc.com (mailing list archive) |
---|---|
State | Changes Requested |
Delegated to: | Kalle Valo |
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 retrieve band edge channel power table by invoking ACPI _DSM > method, then pass the table to firmware. > > 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 | 29 ++++++++++++++++++ > drivers/net/wireless/ath/ath12k/acpi.h | 6 +++- > drivers/net/wireless/ath/ath12k/core.h | 1 + > drivers/net/wireless/ath/ath12k/wmi.c | 41 ++++++++++++++++++++++++++ > drivers/net/wireless/ath/ath12k/wmi.h | 3 ++ > 5 files changed, 79 insertions(+), 1 deletion(-) > > 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 acdf8d851fba..1acfd7696dfc 100644 > --- a/drivers/net/wireless/ath/ath12k/acpi.h > +++ b/drivers/net/wireless/ath/ath12k/acpi.h > @@ -14,18 +14,21 @@ > #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_FUNC_INDEX_BAND_EDGE 10 > > #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_DSM_BAND_EDGE_DATA_SIZE 100 > > #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) > @@ -44,7 +47,8 @@ > #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 > - > +#define ATH12K_ACPI_BAND_EDGE_VERSION 0x1 > +#define ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG 0x1 > > 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 d57e2013b0fe..d06c3984aef9 100644 > --- a/drivers/net/wireless/ath/ath12k/core.h > +++ b/drivers/net/wireless/ath/ath12k/core.h > @@ -781,6 +781,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 3f66807b7961..345bdd50adb2 100644 > --- a/drivers/net/wireless/ath/ath12k/wmi.c > +++ b/drivers/net/wireless/ath/ath12k/wmi.c > @@ -7113,3 +7113,44 @@ 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 = > + cpu_to_le32(ath12k_wmi_tlv_cmd_hdr(WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD_PARAMS, remove cpu_to_le32() > + 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 7607cd7ab699..73d790d405cd 100644 > --- a/drivers/net/wireless/ath/ath12k/wmi.h > +++ b/drivers/net/wireless/ath/ath12k/wmi.h > @@ -4808,6 +4808,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, > }; > > @@ -4955,4 +4956,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
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 acdf8d851fba..1acfd7696dfc 100644 --- a/drivers/net/wireless/ath/ath12k/acpi.h +++ b/drivers/net/wireless/ath/ath12k/acpi.h @@ -14,18 +14,21 @@ #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_FUNC_INDEX_BAND_EDGE 10 #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_DSM_BAND_EDGE_DATA_SIZE 100 #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) @@ -44,7 +47,8 @@ #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 - +#define ATH12K_ACPI_BAND_EDGE_VERSION 0x1 +#define ATH12K_ACPI_BAND_EDGE_ENABLE_FLAG 0x1 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 d57e2013b0fe..d06c3984aef9 100644 --- a/drivers/net/wireless/ath/ath12k/core.h +++ b/drivers/net/wireless/ath/ath12k/core.h @@ -781,6 +781,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 3f66807b7961..345bdd50adb2 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -7113,3 +7113,44 @@ 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 = + 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_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 7607cd7ab699..73d790d405cd 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.h +++ b/drivers/net/wireless/ath/ath12k/wmi.h @@ -4808,6 +4808,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, }; @@ -4955,4 +4956,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
ath12k need to retrieve band edge channel power table by invoking ACPI _DSM method, then pass the table to firmware. 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 | 29 ++++++++++++++++++ drivers/net/wireless/ath/ath12k/acpi.h | 6 +++- drivers/net/wireless/ath/ath12k/core.h | 1 + drivers/net/wireless/ath/ath12k/wmi.c | 41 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/wmi.h | 3 ++ 5 files changed, 79 insertions(+), 1 deletion(-)