--- /dev/null
+From d38fdb272c4471c5958eaee9ab7d42353871c7a3 Mon Sep 17 00:00:00 2001
+From: Koen Vandeputte <koen.vandeputte@citymesh.com>
+Date: Tue, 25 Mar 2025 14:14:48 +0100
+Subject: [PATCH 1/2] ath10k-ct: add Coverage Class setting ipq40xx and qca99xx
+ WiFi (WIP)
+
+ath10k-ct: add Coverage Class setting ipq40xx and qca99xx WiFi (WIP)
+
+Since QCA wireless firmware version 10.4 the Coverage Class can be set
+for ipq40xx and qca99xx circuits via the wmi interface.
+A timeout value adjusts protocol timing for the extra radio propagation
+time that is inherent to transmission over larger than local distances.
+
+In due time an upstream patch in mac80211 can be anticipated.
+This patch enables use of ipq40xx SoC based devices in OpenWrt in the
+mean time when Coverage Class setting is required.
+
+Authors:
+Sebastian Gottschall <s.gottschall@dd-wrt.com>
+William Wortel <wwortel@dorpstraat.com>
+
+Signed-off-by: William Wortel <wwortel@dorpstraat.com>
+Signed-off-by: Koen Vandeputte <koen.vandeputte@citymesh.com>
+---
+ ath10k-5.15/core.c | 2 +-
+ ath10k-5.15/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-5.15/wmi.c | 4 ++++
+ ath10k-5.15/wmi.h | 3 +++
+ ath10k-5.17/core.c | 2 +-
+ ath10k-5.17/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-5.17/wmi.c | 4 ++++
+ ath10k-5.17/wmi.h | 3 +++
+ ath10k-5.19/core.c | 2 +-
+ ath10k-5.19/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-5.19/wmi.c | 4 ++++
+ ath10k-5.19/wmi.h | 3 +++
+ ath10k-6.10/core.c | 2 +-
+ ath10k-6.10/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.10/wmi.c | 4 ++++
+ ath10k-6.10/wmi.h | 3 +++
+ ath10k-6.11/core.c | 2 +-
+ ath10k-6.11/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.11/wmi.c | 4 ++++
+ ath10k-6.11/wmi.h | 3 +++
+ ath10k-6.14/core.c | 2 +-
+ ath10k-6.14/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.14/wmi.c | 4 ++++
+ ath10k-6.14/wmi.h | 3 +++
+ ath10k-6.2/core.c | 2 +-
+ ath10k-6.2/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.2/wmi.c | 4 ++++
+ ath10k-6.2/wmi.h | 3 +++
+ ath10k-6.4/core.c | 2 +-
+ ath10k-6.4/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.4/wmi.c | 4 ++++
+ ath10k-6.4/wmi.h | 3 +++
+ ath10k-6.7/core.c | 2 +-
+ ath10k-6.7/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.7/wmi.c | 4 ++++
+ ath10k-6.7/wmi.h | 3 +++
+ ath10k-6.9/core.c | 2 +-
+ ath10k-6.9/hw.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++
+ ath10k-6.9/wmi.c | 4 ++++
+ ath10k-6.9/wmi.h | 3 +++
+ 40 files changed, 590 insertions(+), 10 deletions(-)
+
+diff --git a/ath10k-5.15/core.c b/ath10k-5.15/core.c
+index c4c96ed..a7d5b0b 100644
+--- a/ath10k-5.15/core.c
++++ b/ath10k-5.15/core.c
+@@ -2970,7 +2970,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-5.15/hw.c b/ath10k-5.15/hw.c
+index 93c3e30..e87fbf6 100644
+--- a/ath10k-5.15/hw.c
++++ b/ath10k-5.15/hw.c
+@@ -584,6 +584,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1172,6 +1222,7 @@ static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd)
+ }
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
+ .rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+diff --git a/ath10k-5.15/wmi.c b/ath10k-5.15/wmi.c
+index c2450df..41e2610 100644
+--- a/ath10k-5.15/wmi.c
++++ b/ath10k-5.15/wmi.c
+@@ -1164,6 +1164,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1260,6 +1261,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1357,6 +1359,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1617,6 +1620,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-5.15/wmi.h b/ath10k-5.15/wmi.h
+index 832a485..3ea179b 100644
+--- a/ath10k-5.15/wmi.h
++++ b/ath10k-5.15/wmi.h
+@@ -3937,6 +3937,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4257,6 +4258,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-5.17/core.c b/ath10k-5.17/core.c
+index b50cb9a..868e14f 100644
+--- a/ath10k-5.17/core.c
++++ b/ath10k-5.17/core.c
+@@ -3035,7 +3035,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-5.17/hw.c b/ath10k-5.17/hw.c
+index 93c3e30..2234b27 100644
+--- a/ath10k-5.17/hw.c
++++ b/ath10k-5.17/hw.c
+@@ -584,6 +584,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1172,6 +1222,7 @@ static bool ath10k_qca99x0_rx_desc_msdu_limit_error(struct htt_rx_desc *rxd)
+ }
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .rx_desc_get_l3_pad_bytes = ath10k_qca99x0_rx_desc_get_l3_pad_bytes,
+ .rx_desc_get_msdu_limit_error = ath10k_qca99x0_rx_desc_msdu_limit_error,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+diff --git a/ath10k-5.17/wmi.c b/ath10k-5.17/wmi.c
+index 5bddfff..1b16957 100644
+--- a/ath10k-5.17/wmi.c
++++ b/ath10k-5.17/wmi.c
+@@ -1164,6 +1164,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1260,6 +1261,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1357,6 +1359,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1617,6 +1620,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-5.17/wmi.h b/ath10k-5.17/wmi.h
+index ecb8fe4..8f963bd 100644
+--- a/ath10k-5.17/wmi.h
++++ b/ath10k-5.17/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-5.19/core.c b/ath10k-5.19/core.c
+index 4589f04..bc28e2c 100644
+--- a/ath10k-5.19/core.c
++++ b/ath10k-5.19/core.c
+@@ -3091,7 +3091,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-5.19/hw.c b/ath10k-5.19/hw.c
+index c0c4dbd..1df6e63 100644
+--- a/ath10k-5.19/hw.c
++++ b/ath10k-5.19/hw.c
+@@ -585,6 +585,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1161,6 +1211,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-5.19/wmi.c b/ath10k-5.19/wmi.c
+index 949205d..03d1d16 100644
+--- a/ath10k-5.19/wmi.c
++++ b/ath10k-5.19/wmi.c
+@@ -1164,6 +1164,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1260,6 +1261,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1357,6 +1359,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1617,6 +1620,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-5.19/wmi.h b/ath10k-5.19/wmi.h
+index ecb8fe4..8f963bd 100644
+--- a/ath10k-5.19/wmi.h
++++ b/ath10k-5.19/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.10/core.c b/ath10k-6.10/core.c
+index 6d1465a..1906c70 100644
+--- a/ath10k-6.10/core.c
++++ b/ath10k-6.10/core.c
+@@ -3103,7 +3103,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.10/hw.c b/ath10k-6.10/hw.c
+index 4621a60..b0b1ee5 100644
+--- a/ath10k-6.10/hw.c
++++ b/ath10k-6.10/hw.c
+@@ -586,6 +586,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1162,6 +1212,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.10/wmi.c b/ath10k-6.10/wmi.c
+index fdd8364..67b7922 100644
+--- a/ath10k-6.10/wmi.c
++++ b/ath10k-6.10/wmi.c
+@@ -1165,6 +1165,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1261,6 +1262,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1358,6 +1360,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1618,6 +1621,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.10/wmi.h b/ath10k-6.10/wmi.h
+index bdc0560..d1b6132 100644
+--- a/ath10k-6.10/wmi.h
++++ b/ath10k-6.10/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.11/core.c b/ath10k-6.11/core.c
+index c715fb6..23f4a56 100644
+--- a/ath10k-6.11/core.c
++++ b/ath10k-6.11/core.c
+@@ -3120,7 +3120,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.11/hw.c b/ath10k-6.11/hw.c
+index 4621a60..b0b1ee5 100644
+--- a/ath10k-6.11/hw.c
++++ b/ath10k-6.11/hw.c
+@@ -586,6 +586,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1162,6 +1212,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.11/wmi.c b/ath10k-6.11/wmi.c
+index c09a64d..0b3cf6a 100644
+--- a/ath10k-6.11/wmi.c
++++ b/ath10k-6.11/wmi.c
+@@ -1165,6 +1165,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1261,6 +1262,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1358,6 +1360,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1618,6 +1621,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.11/wmi.h b/ath10k-6.11/wmi.h
+index b06283d..5953fcd 100644
+--- a/ath10k-6.11/wmi.h
++++ b/ath10k-6.11/wmi.h
+@@ -3974,6 +3974,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4294,6 +4295,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.14/core.c b/ath10k-6.14/core.c
+index c715fb6..23f4a56 100644
+--- a/ath10k-6.14/core.c
++++ b/ath10k-6.14/core.c
+@@ -3120,7 +3120,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.14/hw.c b/ath10k-6.14/hw.c
+index 4621a60..b0b1ee5 100644
+--- a/ath10k-6.14/hw.c
++++ b/ath10k-6.14/hw.c
+@@ -586,6 +586,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1162,6 +1212,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.14/wmi.c b/ath10k-6.14/wmi.c
+index 1498322..fa0ad46 100644
+--- a/ath10k-6.14/wmi.c
++++ b/ath10k-6.14/wmi.c
+@@ -1165,6 +1165,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1261,6 +1262,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1358,6 +1360,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1618,6 +1621,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.14/wmi.h b/ath10k-6.14/wmi.h
+index b06283d..5953fcd 100644
+--- a/ath10k-6.14/wmi.h
++++ b/ath10k-6.14/wmi.h
+@@ -3974,6 +3974,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4294,6 +4295,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.2/core.c b/ath10k-6.2/core.c
+index 8ffce87..8c6df8a 100644
+--- a/ath10k-6.2/core.c
++++ b/ath10k-6.2/core.c
+@@ -3110,7 +3110,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.2/hw.c b/ath10k-6.2/hw.c
+index 30384b8..8c43969 100644
+--- a/ath10k-6.2/hw.c
++++ b/ath10k-6.2/hw.c
+@@ -585,6 +585,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1161,6 +1211,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.2/wmi.c b/ath10k-6.2/wmi.c
+index fd271fc..52b3667 100644
+--- a/ath10k-6.2/wmi.c
++++ b/ath10k-6.2/wmi.c
+@@ -1164,6 +1164,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1260,6 +1261,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1357,6 +1359,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1617,6 +1620,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.2/wmi.h b/ath10k-6.2/wmi.h
+index 5b6414a..941cd3b 100644
+--- a/ath10k-6.2/wmi.h
++++ b/ath10k-6.2/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.4/core.c b/ath10k-6.4/core.c
+index 8ffce87..8c6df8a 100644
+--- a/ath10k-6.4/core.c
++++ b/ath10k-6.4/core.c
+@@ -3110,7 +3110,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.4/hw.c b/ath10k-6.4/hw.c
+index 30384b8..8c43969 100644
+--- a/ath10k-6.4/hw.c
++++ b/ath10k-6.4/hw.c
+@@ -585,6 +585,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1161,6 +1211,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.4/wmi.c b/ath10k-6.4/wmi.c
+index 149bca3..fd5a018 100644
+--- a/ath10k-6.4/wmi.c
++++ b/ath10k-6.4/wmi.c
+@@ -1164,6 +1164,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1260,6 +1261,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1357,6 +1359,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1617,6 +1620,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.4/wmi.h b/ath10k-6.4/wmi.h
+index 5b6414a..941cd3b 100644
+--- a/ath10k-6.4/wmi.h
++++ b/ath10k-6.4/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.7/core.c b/ath10k-6.7/core.c
+index 1977de2..3746420 100644
+--- a/ath10k-6.7/core.c
++++ b/ath10k-6.7/core.c
+@@ -3101,7 +3101,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.7/hw.c b/ath10k-6.7/hw.c
+index 30384b8..8c43969 100644
+--- a/ath10k-6.7/hw.c
++++ b/ath10k-6.7/hw.c
+@@ -585,6 +585,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1161,6 +1211,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.7/wmi.c b/ath10k-6.7/wmi.c
+index 7bdf12f..d928c63 100644
+--- a/ath10k-6.7/wmi.c
++++ b/ath10k-6.7/wmi.c
+@@ -1164,6 +1164,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1260,6 +1261,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1357,6 +1359,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1617,6 +1620,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.7/wmi.h b/ath10k-6.7/wmi.h
+index 7fa5a5e..ef867ed 100644
+--- a/ath10k-6.7/wmi.h
++++ b/ath10k-6.7/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+diff --git a/ath10k-6.9/core.c b/ath10k-6.9/core.c
+index 17b6a64..0ede88f 100644
+--- a/ath10k-6.9/core.c
++++ b/ath10k-6.9/core.c
+@@ -3121,7 +3121,7 @@ static void ath10k_core_set_coverage_class_work(struct work_struct *work)
+ set_coverage_class_work);
+
+ if (ar->hw_params.hw_ops->set_coverage_class)
+- ar->hw_params.hw_ops->set_coverage_class(ar, -1);
++ ar->hw_params.hw_ops->set_coverage_class(ar, ar->fw_coverage.coverage_class);
+ }
+
+ static int ath10k_core_init_firmware_features(struct ath10k *ar)
+diff --git a/ath10k-6.9/hw.c b/ath10k-6.9/hw.c
+index 4621a60..b0b1ee5 100644
+--- a/ath10k-6.9/hw.c
++++ b/ath10k-6.9/hw.c
+@@ -586,6 +586,56 @@ void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ survey->time_busy = CCNT_TO_MSEC(ar, rcc);
+ }
+
++/* Wireless firmware version 10.4 supports setting Coverage Class by
+++ * setting via wmi tx_ack_timeout; chipsets a.o. ipq40xx, qca99xx
+++*/
++static void ath10k_hw_qca99xx_set_coverage_class(struct ath10k *ar,
++ s16 value)
++{
++ u32 timeout;
++ int ret;
++
++ mutex_lock(&ar->conf_mutex);
++
++ /* Only execute if the core is started. */
++ if ((ar->state != ATH10K_STATE_ON) &&
++ (ar->state != ATH10K_STATE_RESTARTED)) {
++ ath10k_warn(ar, "ath10k core not yet started");
++ goto unlock;
++ }
++
++ if (value < 0)
++ value = ar->fw_coverage.coverage_class;
++
++ /* WIP: it appears that one wmi timeout unit accounts for 3 C.Class units
++ * so we need an integer divide by three; feedback welcome for distances
++ * 10-20 km; tested at 7 km */
++ if (value > 0) {
++ timeout = 0x40 + (value / 3) + 0x01;
++
++ /* Limit to 0xff as the destination register is u8 */
++ if (timeout > 0xff)
++ timeout = 0xff;
++ }
++ else
++ timeout = 0x40;
++
++ /* set Coverage Class via wmi */
++ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_ack_timeout,
++ timeout);
++ if (ret) {
++ ath10k_warn(ar, "failed to set tx-acktimeout: %d, timeout: 0x%x\n"
++ , ret, timeout);
++ }
++
++unlock:
++ spin_lock_bh(&ar->data_lock);
++ ar->fw_coverage.coverage_class = value;
++ spin_unlock_bh(&ar->data_lock);
++
++ mutex_unlock(&ar->conf_mutex);
++}
++
+ /* The stock firmware does not support setting the coverage class. Instead this
+ * function monitors and modifies the corresponding MAC registers.
+ */
+@@ -1162,6 +1212,7 @@ const struct ath10k_hw_ops qca988x_ops = {
+ };
+
+ const struct ath10k_hw_ops qca99x0_ops = {
++ .set_coverage_class = ath10k_hw_qca99xx_set_coverage_class,
+ .is_rssi_enable = ath10k_htt_tx_rssi_enable,
+ };
+
+diff --git a/ath10k-6.9/wmi.c b/ath10k-6.9/wmi.c
+index fdd8364..67b7922 100644
+--- a/ath10k-6.9/wmi.c
++++ b/ath10k-6.9/wmi.c
+@@ -1165,6 +1165,7 @@ static struct wmi_pdev_param_map wmi_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+@@ -1261,6 +1262,7 @@ static struct wmi_pdev_param_map wmi_10x_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+@@ -1358,6 +1360,7 @@ static struct wmi_pdev_param_map wmi_10_2_4_pdev_param_map = {
+ .arp_srcaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .arp_dstaddr = WMI_PDEV_PARAM_UNSUPPORTED,
+ .enable_btcoex = WMI_PDEV_PARAM_UNSUPPORTED,
++ .tx_ack_timeout = WMI_PDEV_PARAM_UNSUPPORTED,
+ };
+
+ /* firmware 10.2 specific mappings */
+@@ -1618,6 +1621,7 @@ static struct wmi_pdev_param_map wmi_10_4_pdev_param_map = {
+ .arp_srcaddr = WMI_10_4_PDEV_PARAM_ARP_SRCADDR,
+ .arp_dstaddr = WMI_10_4_PDEV_PARAM_ARP_DSTADDR,
+ .enable_btcoex = WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ .tx_ack_timeout = WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT,
+ };
+
+ static const u8 wmi_key_cipher_suites[] = {
+diff --git a/ath10k-6.9/wmi.h b/ath10k-6.9/wmi.h
+index bdc0560..d1b6132 100644
+--- a/ath10k-6.9/wmi.h
++++ b/ath10k-6.9/wmi.h
+@@ -3939,6 +3939,7 @@ struct wmi_pdev_param_map {
+ u32 rfkill_config;
+ u32 rfkill_enable;
+ u32 peer_stats_info_enable;
++ u32 tx_ack_timeout;
+ };
+
+ #define WMI_PDEV_PARAM_UNSUPPORTED 0
+@@ -4259,6 +4260,8 @@ enum wmi_10_4_pdev_param {
+ WMI_10_4_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+ WMI_10_4_PDEV_PARAM_ATF_SSID_GROUP_POLICY,
+ WMI_10_4_PDEV_PARAM_ENABLE_BTCOEX,
++ /* TX acknowledge timeout. Advised range: 0x40 - 0xFF microsec. */
++ WMI_10_4_PDEV_PARAM_TX_ACK_TIMEOUT = 0x68,
+ };
+
+ struct wmi_pdev_set_param_cmd {
+--
+2.43.0
+