diff options
Diffstat (limited to 'package/kernel/mac80211/patches')
11 files changed, 2637 insertions, 0 deletions
diff --git a/package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch b/package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch new file mode 100644 index 0000000000..cd8ab3dc4e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0037-wifi-ath11k-allow-system-suspend-to-survive-ath11k.patch @@ -0,0 +1,43 @@ +From 7c15430822e71e90203d87e6d0cfe83fa058b0dc Mon Sep 17 00:00:00 2001 +From: Len Brown <len.brown@intel.com> +Date: Wed, 1 Feb 2023 12:32:01 -0600 +Subject: [PATCH] wifi: ath11k: allow system suspend to survive ath11k + +When ath11k runs into internal errors upon suspend, +it returns an error code to pci_pm_suspend, which +aborts the entire system suspend. + +The driver should not abort system suspend, but should +keep its internal errors to itself, and allow the system +to suspend. Otherwise, a user can suspend a laptop +by closing the lid and sealing it into a case, assuming +that is will suspend, rather than heating up and draining +the battery when in transit. + +In practice, the ath11k device seems to have plenty of transient +errors, and subsequent suspend cycles after this failure +often succeed. + +https://bugzilla.kernel.org/show_bug.cgi?id=216968 + +Fixes: d1b0c33850d29 ("ath11k: implement suspend for QCA6390 PCI devices") + +Signed-off-by: Len Brown <len.brown@intel.com> +Cc: stable@vger.kernel.org +Signed-off-by: Kalle Valo <kvalo@kernel.org> +Link: https://lore.kernel.org/r/20230201183201.14431-1-len.brown@intel.com +--- + drivers/net/wireless/ath/ath11k/pci.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/ath/ath11k/pci.c ++++ b/drivers/net/wireless/ath/ath11k/pci.c +@@ -981,7 +981,7 @@ static __maybe_unused int ath11k_pci_pm_ + if (ret) + ath11k_warn(ab, "failed to suspend core: %d\n", ret); + +- return ret; ++ return 0; + } + + static __maybe_unused int ath11k_pci_pm_resume(struct device *dev) diff --git a/package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch b/package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch new file mode 100644 index 0000000000..42bf170a03 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0038-wifi-ath11k-modify-accessor-macros-to-match-index-si.patch @@ -0,0 +1,61 @@ +From a96f10422e74cde27c100b321b127ec32ae75747 Mon Sep 17 00:00:00 2001 +From: Muna Sinada <quic_msinada@quicinc.com> +Date: Fri, 24 Feb 2023 12:28:03 +0200 +Subject: [PATCH] wifi: ath11k: modify accessor macros to match index size + +HE PHY is only 11 bytes, therefore it should be using byte indexes +instead of dword. Change corresponding macros to reflect this. + +Signed-off-by: Muna Sinada <quic_msinada@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/1666128501-12364-2-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/wmi.h | 24 +++++++++++++----------- + 1 file changed, 13 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2859,30 +2859,32 @@ struct rx_reorder_queue_remove_params { + #define WMI_VDEV_PARAM_TXBF_SU_TX_BFER BIT(2) + #define WMI_VDEV_PARAM_TXBF_MU_TX_BFER BIT(3) + +-#define HECAP_PHYDWORD_0 0 +-#define HECAP_PHYDWORD_1 1 +-#define HECAP_PHYDWORD_2 2 ++#define HE_PHYCAP_BYTE_0 0 ++#define HE_PHYCAP_BYTE_1 1 ++#define HE_PHYCAP_BYTE_2 2 ++#define HE_PHYCAP_BYTE_3 3 ++#define HE_PHYCAP_BYTE_4 4 + +-#define HECAP_PHY_SU_BFER BIT(31) ++#define HECAP_PHY_SU_BFER BIT(7) + #define HECAP_PHY_SU_BFEE BIT(0) + #define HECAP_PHY_MU_BFER BIT(1) +-#define HECAP_PHY_UL_MUMIMO BIT(22) +-#define HECAP_PHY_UL_MUOFDMA BIT(23) ++#define HECAP_PHY_UL_MUMIMO BIT(6) ++#define HECAP_PHY_UL_MUOFDMA BIT(7) + + #define HECAP_PHY_SUBFMR_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HECAP_PHYDWORD_0]) ++ FIELD_GET(HECAP_PHY_SU_BFER, hecap_phy[HE_PHYCAP_BYTE_3]) + + #define HECAP_PHY_SUBFME_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HECAP_PHYDWORD_1]) ++ FIELD_GET(HECAP_PHY_SU_BFEE, hecap_phy[HE_PHYCAP_BYTE_4]) + + #define HECAP_PHY_MUBFMR_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HECAP_PHYDWORD_1]) ++ FIELD_GET(HECAP_PHY_MU_BFER, hecap_phy[HE_PHYCAP_BYTE_4]) + + #define HECAP_PHY_ULMUMIMO_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HECAP_PHYDWORD_0]) ++ FIELD_GET(HECAP_PHY_UL_MUMIMO, hecap_phy[HE_PHYCAP_BYTE_2]) + + #define HECAP_PHY_ULOFDMA_GET(hecap_phy) \ +- FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HECAP_PHYDWORD_0]) ++ FIELD_GET(HECAP_PHY_UL_MUOFDMA, hecap_phy[HE_PHYCAP_BYTE_2]) + + #define HE_MODE_SU_TX_BFEE BIT(0) + #define HE_MODE_SU_TX_BFER BIT(1) diff --git a/package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch b/package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch new file mode 100644 index 0000000000..298ce1a612 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0039-wifi-ath11k-push-MU-MIMO-params-from-hostapd-to-hard.patch @@ -0,0 +1,300 @@ +From 38dfe775d0abf511341f37c1cb77b919a3ad410b Mon Sep 17 00:00:00 2001 +From: Muna Sinada <quic_msinada@quicinc.com> +Date: Fri, 24 Feb 2023 12:28:04 +0200 +Subject: [PATCH] wifi: ath11k: push MU-MIMO params from hostapd to hardware + +In the previous behaviour only HE IE in management frames are changed +regarding MU-MIMO configurations and not in hardware. Adding push of +MU-MIMO configurations to the hardware as well. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Co-developed-by: Anilkumar Kolli <quic_akolli@quicinc.com> +Signed-off-by: Anilkumar Kolli <quic_akolli@quicinc.com> +Signed-off-by: Muna Sinada <quic_msinada@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/1666128501-12364-3-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 200 ++++++++++++++++---------- + drivers/net/wireless/ath/ath11k/wmi.h | 3 + + 2 files changed, 130 insertions(+), 73 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -2699,6 +2699,117 @@ static int ath11k_setup_peer_smps(struct + ath11k_smps_map[smps]); + } + ++static bool ath11k_mac_set_he_txbf_conf(struct ath11k_vif *arvif) ++{ ++ struct ath11k *ar = arvif->ar; ++ u32 param, value; ++ int ret; ++ ++ if (!arvif->vif->bss_conf.he_support) ++ return true; ++ ++ param = WMI_VDEV_PARAM_SET_HEMU_MODE; ++ value = 0; ++ if (arvif->vif->bss_conf.he_su_beamformer) { ++ value |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE); ++ if (arvif->vif->bss_conf.he_mu_beamformer && ++ arvif->vdev_type == WMI_VDEV_TYPE_AP) ++ value |= FIELD_PREP(HE_MODE_MU_TX_BFER, HE_MU_BFER_ENABLE); ++ } ++ ++ if (arvif->vif->type != NL80211_IFTYPE_MESH_POINT) { ++ value |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | ++ FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); ++ ++ if (arvif->vif->bss_conf.he_full_ul_mumimo) ++ value |= FIELD_PREP(HE_MODE_UL_MUMIMO, HE_UL_MUMIMO_ENABLE); ++ ++ if (arvif->vif->bss_conf.he_su_beamformee) ++ value |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); ++ } ++ ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, value); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to set vdev %d HE MU mode: %d\n", ++ arvif->vdev_id, ret); ++ return false; ++ } ++ ++ param = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; ++ value = FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) | ++ FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE, ++ HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE); ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, ++ param, value); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to set vdev %d sounding mode: %d\n", ++ arvif->vdev_id, ret); ++ return false; ++ } ++ return true; ++} ++ ++static bool ath11k_mac_vif_recalc_sta_he_txbf(struct ath11k *ar, ++ struct ieee80211_vif *vif, ++ struct ieee80211_sta_he_cap *he_cap) ++{ ++ struct ath11k_vif *arvif = (void *)vif->drv_priv; ++ struct ieee80211_he_cap_elem he_cap_elem = {0}; ++ struct ieee80211_sta_he_cap *cap_band = NULL; ++ struct cfg80211_chan_def def; ++ u32 param = WMI_VDEV_PARAM_SET_HEMU_MODE; ++ u32 hemode = 0; ++ int ret; ++ ++ if (!vif->bss_conf.he_support) ++ return true; ++ ++ if (vif->type != NL80211_IFTYPE_STATION) ++ return false; ++ ++ if (WARN_ON(ath11k_mac_vif_chan(vif, &def))) ++ return false; ++ ++ if (def.chan->band == NL80211_BAND_2GHZ) ++ cap_band = &ar->mac.iftype[NL80211_BAND_2GHZ][vif->type].he_cap; ++ else ++ cap_band = &ar->mac.iftype[NL80211_BAND_5GHZ][vif->type].he_cap; ++ ++ memcpy(&he_cap_elem, &cap_band->he_cap_elem, sizeof(he_cap_elem)); ++ ++ if (HECAP_PHY_SUBFME_GET(he_cap_elem.phy_cap_info)) { ++ if (HECAP_PHY_SUBFMR_GET(he_cap->he_cap_elem.phy_cap_info)) ++ hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); ++ if (HECAP_PHY_MUBFMR_GET(he_cap->he_cap_elem.phy_cap_info)) ++ hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE); ++ } ++ ++ if (vif->type != NL80211_IFTYPE_MESH_POINT) { ++ hemode |= FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | ++ FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); ++ ++ if (HECAP_PHY_ULMUMIMO_GET(he_cap_elem.phy_cap_info)) ++ if (HECAP_PHY_ULMUMIMO_GET(he_cap->he_cap_elem.phy_cap_info)) ++ hemode |= FIELD_PREP(HE_MODE_UL_MUMIMO, ++ HE_UL_MUMIMO_ENABLE); ++ ++ if (FIELD_GET(HE_MODE_MU_TX_BFEE, hemode)) ++ hemode |= FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE); ++ ++ if (FIELD_GET(HE_MODE_MU_TX_BFER, hemode)) ++ hemode |= FIELD_PREP(HE_MODE_SU_TX_BFER, HE_SU_BFER_ENABLE); ++ } ++ ++ ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, param, hemode); ++ if (ret) { ++ ath11k_warn(ar->ab, "failed to submit vdev param txbf 0x%x: %d\n", ++ hemode, ret); ++ return false; ++ } ++ ++ return true; ++} ++ + static void ath11k_bss_assoc(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *bss_conf) +@@ -2709,6 +2820,7 @@ static void ath11k_bss_assoc(struct ieee + struct ieee80211_sta *ap_sta; + struct ath11k_peer *peer; + bool is_auth = false; ++ struct ieee80211_sta_he_cap he_cap; + int ret; + + lockdep_assert_held(&ar->conf_mutex); +@@ -2726,6 +2838,9 @@ static void ath11k_bss_assoc(struct ieee + return; + } + ++ /* he_cap here is updated at assoc success for sta mode only */ ++ he_cap = ap_sta->deflink.he_cap; ++ + ath11k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg, false); + + rcu_read_unlock(); +@@ -2753,6 +2868,12 @@ static void ath11k_bss_assoc(struct ieee + return; + } + ++ if (!ath11k_mac_vif_recalc_sta_he_txbf(ar, vif, &he_cap)) { ++ ath11k_warn(ar->ab, "failed to recalc he txbf for vdev %i on bss %pM\n", ++ arvif->vdev_id, bss_conf->bssid); ++ return; ++ } ++ + WARN_ON(arvif->is_up); + + arvif->aid = vif->cfg.aid; +@@ -3202,6 +3323,8 @@ static void ath11k_mac_op_bss_info_chang + ether_addr_copy(arvif->bssid, info->bssid); + + if (changed & BSS_CHANGED_BEACON_ENABLED) { ++ if (info->enable_beacon) ++ ath11k_mac_set_he_txbf_conf(arvif); + ath11k_control_beaconing(arvif, info); + + if (arvif->is_up && vif->bss_conf.he_support && +@@ -5392,6 +5515,10 @@ static int ath11k_mac_copy_he_cap(struct + + he_cap_elem->mac_cap_info[1] &= + IEEE80211_HE_MAC_CAP1_TF_MAC_PAD_DUR_MASK; ++ he_cap_elem->phy_cap_info[0] &= ++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G; ++ he_cap_elem->phy_cap_info[0] &= ++ ~IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G; + + he_cap_elem->phy_cap_info[5] &= + ~IEEE80211_HE_PHY_CAP5_BEAMFORMEE_NUM_SND_DIM_UNDER_80MHZ_MASK; +@@ -6026,69 +6153,6 @@ ath11k_mac_setup_vdev_create_params(stru + } + } + +-static u32 +-ath11k_mac_prepare_he_mode(struct ath11k_pdev *pdev, u32 viftype) +-{ +- struct ath11k_pdev_cap *pdev_cap = &pdev->cap; +- struct ath11k_band_cap *cap_band = NULL; +- u32 *hecap_phy_ptr = NULL; +- u32 hemode = 0; +- +- if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) +- cap_band = &pdev_cap->band[NL80211_BAND_2GHZ]; +- else +- cap_band = &pdev_cap->band[NL80211_BAND_5GHZ]; +- +- hecap_phy_ptr = &cap_band->he_cap_phy_info[0]; +- +- hemode = FIELD_PREP(HE_MODE_SU_TX_BFEE, HE_SU_BFEE_ENABLE) | +- FIELD_PREP(HE_MODE_SU_TX_BFER, HECAP_PHY_SUBFMR_GET(hecap_phy_ptr)) | +- FIELD_PREP(HE_MODE_UL_MUMIMO, HECAP_PHY_ULMUMIMO_GET(hecap_phy_ptr)); +- +- /* TODO WDS and other modes */ +- if (viftype == NL80211_IFTYPE_AP) { +- hemode |= FIELD_PREP(HE_MODE_MU_TX_BFER, +- HECAP_PHY_MUBFMR_GET(hecap_phy_ptr)) | +- FIELD_PREP(HE_MODE_DL_OFDMA, HE_DL_MUOFDMA_ENABLE) | +- FIELD_PREP(HE_MODE_UL_OFDMA, HE_UL_MUOFDMA_ENABLE); +- } else { +- hemode |= FIELD_PREP(HE_MODE_MU_TX_BFEE, HE_MU_BFEE_ENABLE); +- } +- +- return hemode; +-} +- +-static int ath11k_set_he_mu_sounding_mode(struct ath11k *ar, +- struct ath11k_vif *arvif) +-{ +- u32 param_id, param_value; +- struct ath11k_base *ab = ar->ab; +- int ret = 0; +- +- param_id = WMI_VDEV_PARAM_SET_HEMU_MODE; +- param_value = ath11k_mac_prepare_he_mode(ar->pdev, arvif->vif->type); +- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, param_value); +- if (ret) { +- ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d param_value %x\n", +- arvif->vdev_id, ret, param_value); +- return ret; +- } +- param_id = WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE; +- param_value = +- FIELD_PREP(HE_VHT_SOUNDING_MODE, HE_VHT_SOUNDING_MODE_ENABLE) | +- FIELD_PREP(HE_TRIG_NONTRIG_SOUNDING_MODE, +- HE_TRIG_NONTRIG_SOUNDING_MODE_ENABLE); +- ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, +- param_id, param_value); +- if (ret) { +- ath11k_warn(ab, "failed to set vdev %d HE MU mode: %d\n", +- arvif->vdev_id, ret); +- return ret; +- } +- return ret; +-} +- + static void ath11k_mac_op_update_vif_offload(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) + { +@@ -6757,7 +6821,6 @@ ath11k_mac_vdev_start_restart(struct ath + struct ath11k_base *ab = ar->ab; + struct wmi_vdev_start_req_arg arg = {}; + const struct cfg80211_chan_def *chandef = &ctx->def; +- int he_support = arvif->vif->bss_conf.he_support; + int ret = 0; + + lockdep_assert_held(&ar->conf_mutex); +@@ -6798,15 +6861,6 @@ ath11k_mac_vdev_start_restart(struct ath + spin_lock_bh(&ab->base_lock); + arg.regdomain = ar->ab->dfs_region; + spin_unlock_bh(&ab->base_lock); +- +- if (he_support) { +- ret = ath11k_set_he_mu_sounding_mode(ar, arvif); +- if (ret) { +- ath11k_warn(ar->ab, "failed to set he mode vdev %i\n", +- arg.vdev_id); +- return ret; +- } +- } + } + + arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2897,8 +2897,11 @@ struct rx_reorder_queue_remove_params { + #define HE_DL_MUOFDMA_ENABLE 1 + #define HE_UL_MUOFDMA_ENABLE 1 + #define HE_DL_MUMIMO_ENABLE 1 ++#define HE_UL_MUMIMO_ENABLE 1 + #define HE_MU_BFEE_ENABLE 1 + #define HE_SU_BFEE_ENABLE 1 ++#define HE_MU_BFER_ENABLE 1 ++#define HE_SU_BFER_ENABLE 1 + + #define HE_VHT_SOUNDING_MODE_ENABLE 1 + #define HE_SU_MU_SOUNDING_MODE_ENABLE 1 diff --git a/package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch b/package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch new file mode 100644 index 0000000000..6bc9880e10 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0040-wifi-ath11k-move-HE-MCS-mapper-to-a-separate-functio.patch @@ -0,0 +1,67 @@ +From 8077c1bbbc28e527fb29143c46f32c6a9d6cadf0 Mon Sep 17 00:00:00 2001 +From: Muna Sinada <quic_msinada@quicinc.com> +Date: Fri, 24 Feb 2023 12:28:04 +0200 +Subject: [PATCH] wifi: ath11k: move HE MCS mapper to a separate function + +Move HE MCS mapper to a separate function and call new function +in ath11k_mac_copy_he_cap(). + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Muna Sinada <quic_msinada@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/1666128501-12364-4-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 34 +++++++++++++++++---------- + 1 file changed, 22 insertions(+), 12 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5483,6 +5483,27 @@ static __le16 ath11k_mac_setup_he_6ghz_c + return cpu_to_le16(bcap->he_6ghz_capa); + } + ++static void ath11k_mac_set_hemcsmap(struct ath11k *ar, ++ struct ath11k_pdev_cap *cap, ++ struct ieee80211_sta_he_cap *he_cap, ++ int band) ++{ ++ struct ath11k_band_cap *band_cap = &cap->band[band]; ++ ++ he_cap->he_mcs_nss_supp.rx_mcs_80 = ++ cpu_to_le16(band_cap->he_mcs & 0xffff); ++ he_cap->he_mcs_nss_supp.tx_mcs_80 = ++ cpu_to_le16(band_cap->he_mcs & 0xffff); ++ he_cap->he_mcs_nss_supp.rx_mcs_160 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ he_cap->he_mcs_nss_supp.tx_mcs_160 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ he_cap->he_mcs_nss_supp.rx_mcs_80p80 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ he_cap->he_mcs_nss_supp.tx_mcs_80p80 = ++ cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++} ++ + static int ath11k_mac_copy_he_cap(struct ath11k *ar, + struct ath11k_pdev_cap *cap, + struct ieee80211_sband_iftype_data *data, +@@ -5544,18 +5565,7 @@ static int ath11k_mac_copy_he_cap(struct + break; + } + +- he_cap->he_mcs_nss_supp.rx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); +- he_cap->he_mcs_nss_supp.tx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); +- he_cap->he_mcs_nss_supp.rx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- he_cap->he_mcs_nss_supp.tx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- he_cap->he_mcs_nss_supp.rx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); +- he_cap->he_mcs_nss_supp.tx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ ath11k_mac_set_hemcsmap(ar, cap, he_cap, band); + + memset(he_cap->ppe_thres, 0, sizeof(he_cap->ppe_thres)); + if (he_cap_elem->phy_cap_info[6] & diff --git a/package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch b/package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch new file mode 100644 index 0000000000..5cb7801b29 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0041-wifi-ath11k-generate-rx-and-tx-mcs-maps-for-supporte.patch @@ -0,0 +1,64 @@ +From ebf82988f844dd98e6b007cffcc5e95986056995 Mon Sep 17 00:00:00 2001 +From: Muna Sinada <quic_msinada@quicinc.com> +Date: Fri, 24 Feb 2023 12:28:04 +0200 +Subject: [PATCH] wifi: ath11k: generate rx and tx mcs maps for supported HE + mcs + +Generate rx and tx mcs maps in ath11k_mac_set_hemcsmap() and set them +in supported mcs/nss for HE capabilities. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.4.0.1-00356-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Muna Sinada <quic_msinada@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/1666128501-12364-5-git-send-email-quic_msinada@quicinc.com +--- + drivers/net/wireless/ath/ath11k/mac.c | 30 ++++++++++++++++++++------- + 1 file changed, 23 insertions(+), 7 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -5488,20 +5488,36 @@ static void ath11k_mac_set_hemcsmap(stru + struct ieee80211_sta_he_cap *he_cap, + int band) + { +- struct ath11k_band_cap *band_cap = &cap->band[band]; ++ u16 txmcs_map, rxmcs_map; ++ u32 i; + ++ rxmcs_map = 0; ++ txmcs_map = 0; ++ for (i = 0; i < 8; i++) { ++ if (i < ar->num_tx_chains && ++ (ar->cfg_tx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ txmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ txmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ ++ if (i < ar->num_rx_chains && ++ (ar->cfg_rx_chainmask >> cap->tx_chain_mask_shift) & BIT(i)) ++ rxmcs_map |= IEEE80211_HE_MCS_SUPPORT_0_11 << (i * 2); ++ else ++ rxmcs_map |= IEEE80211_HE_MCS_NOT_SUPPORTED << (i * 2); ++ } + he_cap->he_mcs_nss_supp.rx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); ++ cpu_to_le16(rxmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_80 = +- cpu_to_le16(band_cap->he_mcs & 0xffff); ++ cpu_to_le16(txmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.rx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(rxmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_160 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(txmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.rx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(rxmcs_map & 0xffff); + he_cap->he_mcs_nss_supp.tx_mcs_80p80 = +- cpu_to_le16((band_cap->he_mcs >> 16) & 0xffff); ++ cpu_to_le16(txmcs_map & 0xffff); + } + + static int ath11k_mac_copy_he_cap(struct ath11k *ar, diff --git a/package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch b/package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch new file mode 100644 index 0000000000..8d41657311 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0042-wifi-ath11k-Add-tx-ack-signal-support-for-management.patch @@ -0,0 +1,150 @@ +From 01c6c9fccbd51c1d9eab0f5794b0271b026178df Mon Sep 17 00:00:00 2001 +From: Abinaya Kalaiselvan <quic_akalaise@quicinc.com> +Date: Mon, 19 Dec 2022 11:08:44 +0530 +Subject: [PATCH] wifi: ath11k: Add tx ack signal support for management + packets + +Add support to notify tx ack signal values for management +packets to userspace through nl80211 interface. + +Advertise NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT flag +to enable this feature and it will be used for data +packets as well. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Abinaya Kalaiselvan <quic_akalaise@quicinc.com> +Signed-off-by: Maharaja Kennadyrajan <quic_mkenna@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/20221219053844.4084486-1-quic_mkenna@quicinc.com +--- + drivers/net/wireless/ath/ath11k/hw.c | 1 + + drivers/net/wireless/ath/ath11k/mac.c | 5 +++++ + drivers/net/wireless/ath/ath11k/wmi.c | 27 ++++++++++++++++----------- + drivers/net/wireless/ath/ath11k/wmi.h | 3 +++ + 4 files changed, 25 insertions(+), 11 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/hw.c ++++ b/drivers/net/wireless/ath/ath11k/hw.c +@@ -201,6 +201,7 @@ static void ath11k_init_wmi_config_ipq80 + config->twt_ap_pdev_count = ab->num_radios; + config->twt_ap_sta_count = 1000; + config->flag1 |= WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64; ++ config->flag1 |= WMI_RSRC_CFG_FLAG1_ACK_RSSI; + } + + static int ath11k_hw_mac_id_to_pdev_id_ipq8074(struct ath11k_hw_params *hw, +--- a/drivers/net/wireless/ath/ath11k/mac.c ++++ b/drivers/net/wireless/ath/ath11k/mac.c +@@ -9174,6 +9174,11 @@ static int __ath11k_mac_register(struct + goto err_free_if_combs; + } + ++ if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, ++ ar->ab->wmi_ab.svc_map)) ++ wiphy_ext_feature_set(ar->hw->wiphy, ++ NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT); ++ + ar->hw->queues = ATH11K_HW_MAX_QUEUES; + ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; + ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -5229,8 +5229,8 @@ static int ath11k_pull_mgmt_rx_params_tl + return 0; + } + +-static int wmi_process_mgmt_tx_comp(struct ath11k *ar, u32 desc_id, +- u32 status) ++static int wmi_process_mgmt_tx_comp(struct ath11k *ar, ++ struct wmi_mgmt_tx_compl_event *tx_compl_param) + { + struct sk_buff *msdu; + struct ieee80211_tx_info *info; +@@ -5238,24 +5238,29 @@ static int wmi_process_mgmt_tx_comp(stru + int num_mgmt; + + spin_lock_bh(&ar->txmgmt_idr_lock); +- msdu = idr_find(&ar->txmgmt_idr, desc_id); ++ msdu = idr_find(&ar->txmgmt_idr, tx_compl_param->desc_id); + + if (!msdu) { + ath11k_warn(ar->ab, "received mgmt tx compl for invalid msdu_id: %d\n", +- desc_id); ++ tx_compl_param->desc_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); + return -ENOENT; + } + +- idr_remove(&ar->txmgmt_idr, desc_id); ++ idr_remove(&ar->txmgmt_idr, tx_compl_param->desc_id); + spin_unlock_bh(&ar->txmgmt_idr_lock); + + skb_cb = ATH11K_SKB_CB(msdu); + dma_unmap_single(ar->ab->dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); + + info = IEEE80211_SKB_CB(msdu); +- if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && !status) ++ if ((!(info->flags & IEEE80211_TX_CTL_NO_ACK)) && ++ !tx_compl_param->status) { + info->flags |= IEEE80211_TX_STAT_ACK; ++ if (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI, ++ ar->ab->wmi_ab.svc_map)) ++ info->status.ack_signal = tx_compl_param->ack_rssi; ++ } + + ieee80211_tx_status_irqsafe(ar->hw, msdu); + +@@ -5267,7 +5272,7 @@ static int wmi_process_mgmt_tx_comp(stru + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi mgmt tx comp pending %d desc id %d\n", +- num_mgmt, desc_id); ++ num_mgmt, tx_compl_param->desc_id); + + if (!num_mgmt) + wake_up(&ar->txmgmt_empty_waitq); +@@ -5300,6 +5305,7 @@ static int ath11k_pull_mgmt_tx_compl_par + param->pdev_id = ev->pdev_id; + param->desc_id = ev->desc_id; + param->status = ev->status; ++ param->ack_rssi = ev->ack_rssi; + + kfree(tb); + return 0; +@@ -7070,13 +7076,12 @@ static void ath11k_mgmt_tx_compl_event(s + goto exit; + } + +- wmi_process_mgmt_tx_comp(ar, tx_compl_param.desc_id, +- tx_compl_param.status); ++ wmi_process_mgmt_tx_comp(ar, &tx_compl_param); + + ath11k_dbg(ab, ATH11K_DBG_MGMT, +- "mgmt tx compl ev pdev_id %d, desc_id %d, status %d", ++ "mgmt tx compl ev pdev_id %d, desc_id %d, status %d ack_rssi %d", + tx_compl_param.pdev_id, tx_compl_param.desc_id, +- tx_compl_param.status); ++ tx_compl_param.status, tx_compl_param.ack_rssi); + + exit: + rcu_read_unlock(); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -2311,6 +2311,7 @@ struct wmi_init_cmd { + } __packed; + + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) ++#define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) + + struct wmi_resource_config { + u32 tlv_header; +@@ -4550,6 +4551,8 @@ struct wmi_mgmt_tx_compl_event { + u32 desc_id; + u32 status; + u32 pdev_id; ++ u32 ppdu_id; ++ u32 ack_rssi; + } __packed; + + struct wmi_scan_event { diff --git a/package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch b/package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch new file mode 100644 index 0000000000..5bc195528e --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0043-wifi-ath11k-use-proper-regulatory-reference-for-band.patch @@ -0,0 +1,216 @@ +From 25e289e1f52e1f4fb1d07622c6a24f8d8a8e420d Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh <quic_adisi@quicinc.com> +Date: Wed, 1 Mar 2023 16:20:58 +0200 +Subject: [PATCH] wifi: ath11k: use proper regulatory reference for bands + +Currently, during regulatory event, 2 GHz/5 GHz is referred +to as 2G/5G including variable names. However, there is no +such entity as 2G or 5G. + +Re-name such occurences to its proper name. No functional changes. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/20230110121024.14051-2-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/reg.c | 20 ++++----- + drivers/net/wireless/ath/ath11k/wmi.c | 58 ++++++++++++++------------- + drivers/net/wireless/ath/ath11k/wmi.h | 28 ++++++------- + 3 files changed, 54 insertions(+), 52 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -619,7 +619,7 @@ ath11k_reg_build_regd(struct ath11k_base + u32 flags; + char alpha2[3]; + +- num_rules = reg_info->num_5g_reg_rules + reg_info->num_2g_reg_rules; ++ num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules; + + if (!num_rules) + goto ret; +@@ -644,20 +644,20 @@ ath11k_reg_build_regd(struct ath11k_base + alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region), + reg_info->dfs_region, num_rules); + /* Update reg_rules[] below. Firmware is expected to +- * send these rules in order(2G rules first and then 5G) ++ * send these rules in order(2 GHz rules first and then 5 GHz) + */ + for (; i < num_rules; i++) { +- if (reg_info->num_2g_reg_rules && +- (i < reg_info->num_2g_reg_rules)) { +- reg_rule = reg_info->reg_rules_2g_ptr + i; ++ if (reg_info->num_2ghz_reg_rules && ++ (i < reg_info->num_2ghz_reg_rules)) { ++ reg_rule = reg_info->reg_rules_2ghz_ptr + i; + max_bw = min_t(u16, reg_rule->max_bw, +- reg_info->max_bw_2g); ++ reg_info->max_bw_2ghz); + flags = 0; +- } else if (reg_info->num_5g_reg_rules && +- (j < reg_info->num_5g_reg_rules)) { +- reg_rule = reg_info->reg_rules_5g_ptr + j++; ++ } else if (reg_info->num_5ghz_reg_rules && ++ (j < reg_info->num_5ghz_reg_rules)) { ++ reg_rule = reg_info->reg_rules_5ghz_ptr + j++; + max_bw = min_t(u16, reg_rule->max_bw, +- reg_info->max_bw_5g); ++ reg_info->max_bw_5ghz); + + /* FW doesn't pass NL80211_RRF_AUTO_BW flag for + * BW Auto correction, we can enable this by default +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -4959,7 +4959,7 @@ static int ath11k_pull_reg_chan_list_upd + const void **tb; + const struct wmi_reg_chan_list_cc_event *chan_list_event_hdr; + struct wmi_regulatory_rule_struct *wmi_reg_rule; +- u32 num_2g_reg_rules, num_5g_reg_rules; ++ u32 num_2ghz_reg_rules, num_5ghz_reg_rules; + int ret; + + ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory channel list\n"); +@@ -4978,10 +4978,10 @@ static int ath11k_pull_reg_chan_list_upd + return -EPROTO; + } + +- reg_info->num_2g_reg_rules = chan_list_event_hdr->num_2g_reg_rules; +- reg_info->num_5g_reg_rules = chan_list_event_hdr->num_5g_reg_rules; ++ reg_info->num_2ghz_reg_rules = chan_list_event_hdr->num_2ghz_reg_rules; ++ reg_info->num_5ghz_reg_rules = chan_list_event_hdr->num_5ghz_reg_rules; + +- if (!(reg_info->num_2g_reg_rules + reg_info->num_5g_reg_rules)) { ++ if (!(reg_info->num_2ghz_reg_rules + reg_info->num_5ghz_reg_rules)) { + ath11k_warn(ab, "No regulatory rules available in the event info\n"); + kfree(tb); + return -EINVAL; +@@ -5008,46 +5008,48 @@ static int ath11k_pull_reg_chan_list_upd + else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_FAIL) + reg_info->status_code = REG_SET_CC_STATUS_FAIL; + +- reg_info->min_bw_2g = chan_list_event_hdr->min_bw_2g; +- reg_info->max_bw_2g = chan_list_event_hdr->max_bw_2g; +- reg_info->min_bw_5g = chan_list_event_hdr->min_bw_5g; +- reg_info->max_bw_5g = chan_list_event_hdr->max_bw_5g; ++ reg_info->min_bw_2ghz = chan_list_event_hdr->min_bw_2ghz; ++ reg_info->max_bw_2ghz = chan_list_event_hdr->max_bw_2ghz; ++ reg_info->min_bw_5ghz = chan_list_event_hdr->min_bw_5ghz; ++ reg_info->max_bw_5ghz = chan_list_event_hdr->max_bw_5ghz; + +- num_2g_reg_rules = reg_info->num_2g_reg_rules; +- num_5g_reg_rules = reg_info->num_5g_reg_rules; ++ num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules; ++ num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules; + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s:cc %s dsf %d BW: min_2g %d max_2g %d min_5g %d max_5g %d", ++ "%s:cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", + __func__, reg_info->alpha2, reg_info->dfs_region, +- reg_info->min_bw_2g, reg_info->max_bw_2g, +- reg_info->min_bw_5g, reg_info->max_bw_5g); ++ reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, ++ reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s: num_2g_reg_rules %d num_5g_reg_rules %d", __func__, +- num_2g_reg_rules, num_5g_reg_rules); ++ "%s: num_2ghz_reg_rules %d num_5ghz_reg_rules %d", __func__, ++ num_2ghz_reg_rules, num_5ghz_reg_rules); + + wmi_reg_rule = + (struct wmi_regulatory_rule_struct *)((u8 *)chan_list_event_hdr + + sizeof(*chan_list_event_hdr) + + sizeof(struct wmi_tlv)); + +- if (num_2g_reg_rules) { +- reg_info->reg_rules_2g_ptr = create_reg_rules_from_wmi(num_2g_reg_rules, +- wmi_reg_rule); +- if (!reg_info->reg_rules_2g_ptr) { ++ if (num_2ghz_reg_rules) { ++ reg_info->reg_rules_2ghz_ptr = ++ create_reg_rules_from_wmi(num_2ghz_reg_rules, ++ wmi_reg_rule); ++ if (!reg_info->reg_rules_2ghz_ptr) { + kfree(tb); +- ath11k_warn(ab, "Unable to Allocate memory for 2g rules\n"); ++ ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); + return -ENOMEM; + } + } + +- if (num_5g_reg_rules) { +- wmi_reg_rule += num_2g_reg_rules; +- reg_info->reg_rules_5g_ptr = create_reg_rules_from_wmi(num_5g_reg_rules, +- wmi_reg_rule); +- if (!reg_info->reg_rules_5g_ptr) { ++ if (num_5ghz_reg_rules) { ++ wmi_reg_rule += num_2ghz_reg_rules; ++ reg_info->reg_rules_5ghz_ptr = ++ create_reg_rules_from_wmi(num_5ghz_reg_rules, ++ wmi_reg_rule); ++ if (!reg_info->reg_rules_5ghz_ptr) { + kfree(tb); +- ath11k_warn(ab, "Unable to Allocate memory for 5g rules\n"); ++ ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); + return -ENOMEM; + } + } +@@ -6619,8 +6621,8 @@ fallback: + WARN_ON(1); + mem_free: + if (reg_info) { +- kfree(reg_info->reg_rules_2g_ptr); +- kfree(reg_info->reg_rules_5g_ptr); ++ kfree(reg_info->reg_rules_2ghz_ptr); ++ kfree(reg_info->reg_rules_5ghz_ptr); + kfree(reg_info); + } + return ret; +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -4129,14 +4129,14 @@ struct cur_regulatory_info { + u8 alpha2[REG_ALPHA2_LEN + 1]; + u32 dfs_region; + u32 phybitmap; +- u32 min_bw_2g; +- u32 max_bw_2g; +- u32 min_bw_5g; +- u32 max_bw_5g; +- u32 num_2g_reg_rules; +- u32 num_5g_reg_rules; +- struct cur_reg_rule *reg_rules_2g_ptr; +- struct cur_reg_rule *reg_rules_5g_ptr; ++ u32 min_bw_2ghz; ++ u32 max_bw_2ghz; ++ u32 min_bw_5ghz; ++ u32 max_bw_5ghz; ++ u32 num_2ghz_reg_rules; ++ u32 num_5ghz_reg_rules; ++ struct cur_reg_rule *reg_rules_2ghz_ptr; ++ struct cur_reg_rule *reg_rules_5ghz_ptr; + }; + + struct wmi_reg_chan_list_cc_event { +@@ -4148,12 +4148,12 @@ struct wmi_reg_chan_list_cc_event { + u32 domain_code; + u32 dfs_region; + u32 phybitmap; +- u32 min_bw_2g; +- u32 max_bw_2g; +- u32 min_bw_5g; +- u32 max_bw_5g; +- u32 num_2g_reg_rules; +- u32 num_5g_reg_rules; ++ u32 min_bw_2ghz; ++ u32 max_bw_2ghz; ++ u32 min_bw_5ghz; ++ u32 max_bw_5ghz; ++ u32 num_2ghz_reg_rules; ++ u32 num_5ghz_reg_rules; + } __packed; + + struct wmi_regulatory_rule_struct { diff --git a/package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch b/package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch new file mode 100644 index 0000000000..e165c09dc4 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0044-wifi-ath11k-add-support-to-parse-new-WMI-event-for-6.patch @@ -0,0 +1,844 @@ +From 91fa00fa69224aae5afb720c5e68b22e4c4f7333 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh <quic_adisi@quicinc.com> +Date: Wed, 1 Mar 2023 16:20:59 +0200 +Subject: [PATCH] wifi: ath11k: add support to parse new WMI event for 6 GHz + +In order to support different power levels of 6 GHz AP and client, +new WMI event for regulatory - WMI_REG_CHAN_LIST_CC_EXT_EVENTID is +added in firmware. This event provides new parameters required for +6 GHz regulatory rules. + +Add support for parsing 2.4 GHz, 5 GHz and 6 GHz reg rules and other +parameters from WMI_REG_CHAN_LIST_CC_EXT_EVENTID. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Lavanya Suresh <quic_lavaks@quicinc.com> +Signed-off-by: Wen Gong <quic_wgong@quicinc.com> +Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/20230110121024.14051-3-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/reg.c | 37 ++- + drivers/net/wireless/ath/ath11k/wmi.c | 418 +++++++++++++++++++++++++- + drivers/net/wireless/ath/ath11k/wmi.h | 163 +++++++++- + 3 files changed, 584 insertions(+), 34 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -613,7 +613,7 @@ ath11k_reg_build_regd(struct ath11k_base + { + struct ieee80211_regdomain *tmp_regd, *default_regd, *new_regd = NULL; + struct cur_reg_rule *reg_rule; +- u8 i = 0, j = 0; ++ u8 i = 0, j = 0, k = 0; + u8 num_rules; + u16 max_bw; + u32 flags; +@@ -621,6 +621,12 @@ ath11k_reg_build_regd(struct ath11k_base + + num_rules = reg_info->num_5ghz_reg_rules + reg_info->num_2ghz_reg_rules; + ++ /* FIXME: Currently taking reg rules for 6 GHz only from Indoor AP mode list. ++ * This can be updated after complete 6 GHz regulatory support is added. ++ */ ++ if (reg_info->is_ext_reg_event) ++ num_rules += reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP]; ++ + if (!num_rules) + goto ret; + +@@ -666,6 +672,14 @@ ath11k_reg_build_regd(struct ath11k_base + * per other BW rule flags we pass from here + */ + flags = NL80211_RRF_AUTO_BW; ++ } else if (reg_info->is_ext_reg_event && ++ reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] && ++ (k < reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP])) { ++ reg_rule = reg_info->reg_rules_6ghz_ap_ptr[WMI_REG_INDOOR_AP] + ++ k++; ++ max_bw = min_t(u16, reg_rule->max_bw, ++ reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP]); ++ flags = NL80211_RRF_AUTO_BW; + } else { + break; + } +@@ -693,12 +707,21 @@ ath11k_reg_build_regd(struct ath11k_base + continue; + } + +- ath11k_dbg(ab, ATH11K_DBG_REG, +- "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", +- i + 1, reg_rule->start_freq, reg_rule->end_freq, +- max_bw, reg_rule->ant_gain, reg_rule->reg_power, +- tmp_regd->reg_rules[i].dfs_cac_ms, +- flags); ++ if (reg_info->is_ext_reg_event) { ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d) (%d, %d)\n", ++ i + 1, reg_rule->start_freq, reg_rule->end_freq, ++ max_bw, reg_rule->ant_gain, reg_rule->reg_power, ++ tmp_regd->reg_rules[i].dfs_cac_ms, flags, ++ reg_rule->psd_flag, reg_rule->psd_eirp); ++ } else { ++ ath11k_dbg(ab, ATH11K_DBG_REG, ++ "\t%d. (%d - %d @ %d) (%d, %d) (%d ms) (FLAGS %d)\n", ++ i + 1, reg_rule->start_freq, reg_rule->end_freq, ++ max_bw, reg_rule->ant_gain, reg_rule->reg_power, ++ tmp_regd->reg_rules[i].dfs_cac_ms, ++ flags); ++ } + } + + tmp_regd->n_reg_rules = i; +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -105,6 +105,8 @@ static const struct wmi_tlv_policy wmi_t + = { .min_len = sizeof(struct wmi_vdev_stopped_event) }, + [WMI_TAG_REG_CHAN_LIST_CC_EVENT] + = { .min_len = sizeof(struct wmi_reg_chan_list_cc_event) }, ++ [WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT] ++ = { .min_len = sizeof(struct wmi_reg_chan_list_cc_ext_event) }, + [WMI_TAG_MGMT_RX_HDR] + = { .min_len = sizeof(struct wmi_mgmt_rx_hdr) }, + [WMI_TAG_MGMT_TX_COMPL_EVENT] +@@ -3974,6 +3976,10 @@ ath11k_wmi_copy_resource_config(struct w + wmi_cfg->sched_params = tg_cfg->sched_params; + wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count; + wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count; ++ wmi_cfg->host_service_flags &= ++ ~(1 << WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); ++ wmi_cfg->host_service_flags |= (tg_cfg->is_reg_cc_ext_event_supported << ++ WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT); + } + + static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi, +@@ -4192,6 +4198,10 @@ int ath11k_wmi_cmd_init(struct ath11k_ba + + ab->hw_params.hw_ops->wmi_init_config(ab, &config); + ++ if (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT, ++ ab->wmi_ab.svc_map)) ++ config.is_reg_cc_ext_event_supported = 1; ++ + memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config)); + + init_param.res_cfg = &wmi_sc->wlan_resource_config; +@@ -4995,18 +5005,11 @@ static int ath11k_pull_reg_chan_list_upd + reg_info->phy_id = chan_list_event_hdr->phy_id; + reg_info->ctry_code = chan_list_event_hdr->country_id; + reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code; +- if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_PASS) +- reg_info->status_code = REG_SET_CC_STATUS_PASS; +- else if (chan_list_event_hdr->status_code == WMI_REG_CURRENT_ALPHA2_NOT_FOUND) +- reg_info->status_code = REG_CURRENT_ALPHA2_NOT_FOUND; +- else if (chan_list_event_hdr->status_code == WMI_REG_INIT_ALPHA2_NOT_FOUND) +- reg_info->status_code = REG_INIT_ALPHA2_NOT_FOUND; +- else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_CHANGE_NOT_ALLOWED) +- reg_info->status_code = REG_SET_CC_CHANGE_NOT_ALLOWED; +- else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_NO_MEMORY) +- reg_info->status_code = REG_SET_CC_STATUS_NO_MEMORY; +- else if (chan_list_event_hdr->status_code == WMI_REG_SET_CC_STATUS_FAIL) +- reg_info->status_code = REG_SET_CC_STATUS_FAIL; ++ ++ reg_info->status_code = ++ ath11k_wmi_cc_setting_code_to_reg(chan_list_event_hdr->status_code); ++ ++ reg_info->is_ext_reg_event = false; + + reg_info->min_bw_2ghz = chan_list_event_hdr->min_bw_2ghz; + reg_info->max_bw_2ghz = chan_list_event_hdr->max_bw_2ghz; +@@ -5060,6 +5063,372 @@ static int ath11k_pull_reg_chan_list_upd + return 0; + } + ++static struct cur_reg_rule ++*create_ext_reg_rules_from_wmi(u32 num_reg_rules, ++ struct wmi_regulatory_ext_rule *wmi_reg_rule) ++{ ++ struct cur_reg_rule *reg_rule_ptr; ++ u32 count; ++ ++ reg_rule_ptr = kcalloc(num_reg_rules, sizeof(*reg_rule_ptr), GFP_ATOMIC); ++ ++ if (!reg_rule_ptr) ++ return NULL; ++ ++ for (count = 0; count < num_reg_rules; count++) { ++ reg_rule_ptr[count].start_freq = ++ u32_get_bits(wmi_reg_rule[count].freq_info, ++ REG_RULE_START_FREQ); ++ reg_rule_ptr[count].end_freq = ++ u32_get_bits(wmi_reg_rule[count].freq_info, ++ REG_RULE_END_FREQ); ++ reg_rule_ptr[count].max_bw = ++ u32_get_bits(wmi_reg_rule[count].bw_pwr_info, ++ REG_RULE_MAX_BW); ++ reg_rule_ptr[count].reg_power = ++ u32_get_bits(wmi_reg_rule[count].bw_pwr_info, ++ REG_RULE_REG_PWR); ++ reg_rule_ptr[count].ant_gain = ++ u32_get_bits(wmi_reg_rule[count].bw_pwr_info, ++ REG_RULE_ANT_GAIN); ++ reg_rule_ptr[count].flags = ++ u32_get_bits(wmi_reg_rule[count].flag_info, ++ REG_RULE_FLAGS); ++ reg_rule_ptr[count].psd_flag = ++ u32_get_bits(wmi_reg_rule[count].psd_power_info, ++ REG_RULE_PSD_INFO); ++ reg_rule_ptr[count].psd_eirp = ++ u32_get_bits(wmi_reg_rule[count].psd_power_info, ++ REG_RULE_PSD_EIRP); ++ } ++ ++ return reg_rule_ptr; ++} ++ ++static u8 ++ath11k_invalid_5ghz_reg_ext_rules_from_wmi(u32 num_reg_rules, ++ const struct wmi_regulatory_ext_rule *rule) ++{ ++ u8 num_invalid_5ghz_rules = 0; ++ u32 count, start_freq; ++ ++ for (count = 0; count < num_reg_rules; count++) { ++ start_freq = u32_get_bits(rule[count].freq_info, ++ REG_RULE_START_FREQ); ++ ++ if (start_freq >= ATH11K_MIN_6G_FREQ) ++ num_invalid_5ghz_rules++; ++ } ++ ++ return num_invalid_5ghz_rules; ++} ++ ++static int ath11k_pull_reg_chan_list_ext_update_ev(struct ath11k_base *ab, ++ struct sk_buff *skb, ++ struct cur_regulatory_info *reg_info) ++{ ++ const void **tb; ++ const struct wmi_reg_chan_list_cc_ext_event *ext_chan_list_event_hdr; ++ struct wmi_regulatory_ext_rule *ext_wmi_reg_rule; ++ u32 num_2ghz_reg_rules, num_5ghz_reg_rules; ++ u32 num_6ghz_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 num_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 total_reg_rules = 0; ++ int ret, i, j, num_invalid_5ghz_ext_rules = 0; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "processing regulatory ext channel list\n"); ++ ++ tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); ++ if (IS_ERR(tb)) { ++ ret = PTR_ERR(tb); ++ ath11k_warn(ab, "failed to parse tlv: %d\n", ret); ++ return ret; ++ } ++ ++ ext_chan_list_event_hdr = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]; ++ if (!ext_chan_list_event_hdr) { ++ ath11k_warn(ab, "failed to fetch reg chan list ext update ev\n"); ++ kfree(tb); ++ return -EPROTO; ++ } ++ ++ reg_info->num_2ghz_reg_rules = ++ ext_chan_list_event_hdr->num_2ghz_reg_rules; ++ reg_info->num_5ghz_reg_rules = ++ ext_chan_list_event_hdr->num_5ghz_reg_rules; ++ reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_lpi; ++ reg_info->num_6ghz_rules_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_sp; ++ reg_info->num_6ghz_rules_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_vlp; ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_client_lpi[i]; ++ reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_client_sp[i]; ++ reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->num_6ghz_reg_rules_client_vlp[i]; ++ } ++ ++ num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules; ++ num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules; ++ ++ total_reg_rules += num_2ghz_reg_rules; ++ total_reg_rules += num_5ghz_reg_rules; ++ ++ if ((num_2ghz_reg_rules > MAX_REG_RULES) || ++ (num_5ghz_reg_rules > MAX_REG_RULES)) { ++ ath11k_warn(ab, "Num reg rules for 2.4 GHz/5 GHz exceeds max limit (num_2ghz_reg_rules: %d num_5ghz_reg_rules: %d max_rules: %d)\n", ++ num_2ghz_reg_rules, num_5ghz_reg_rules, MAX_REG_RULES); ++ kfree(tb); ++ return -EINVAL; ++ } ++ ++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { ++ num_6ghz_reg_rules_ap[i] = reg_info->num_6ghz_rules_ap[i]; ++ ++ if (num_6ghz_reg_rules_ap[i] > MAX_6GHZ_REG_RULES) { ++ ath11k_warn(ab, "Num 6 GHz reg rules for AP mode(%d) exceeds max limit (num_6ghz_reg_rules_ap: %d, max_rules: %d)\n", ++ i, num_6ghz_reg_rules_ap[i], MAX_6GHZ_REG_RULES); ++ kfree(tb); ++ return -EINVAL; ++ } ++ ++ total_reg_rules += num_6ghz_reg_rules_ap[i]; ++ } ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ num_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i]; ++ total_reg_rules += num_6ghz_client[WMI_REG_INDOOR_AP][i]; ++ ++ num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i]; ++ total_reg_rules += num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i]; ++ ++ num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i]; ++ total_reg_rules += num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i]; ++ ++ if ((num_6ghz_client[WMI_REG_INDOOR_AP][i] > MAX_6GHZ_REG_RULES) || ++ (num_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] > ++ MAX_6GHZ_REG_RULES) || ++ (num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] > ++ MAX_6GHZ_REG_RULES)) { ++ ath11k_warn(ab, ++ "Num 6 GHz client reg rules exceeds max limit, for client(type: %d)\n", ++ i); ++ kfree(tb); ++ return -EINVAL; ++ } ++ } ++ ++ if (!total_reg_rules) { ++ ath11k_warn(ab, "No reg rules available\n"); ++ kfree(tb); ++ return -EINVAL; ++ } ++ ++ memcpy(reg_info->alpha2, &ext_chan_list_event_hdr->alpha2, ++ REG_ALPHA2_LEN); ++ ++ reg_info->dfs_region = ext_chan_list_event_hdr->dfs_region; ++ reg_info->phybitmap = ext_chan_list_event_hdr->phybitmap; ++ reg_info->num_phy = ext_chan_list_event_hdr->num_phy; ++ reg_info->phy_id = ext_chan_list_event_hdr->phy_id; ++ reg_info->ctry_code = ext_chan_list_event_hdr->country_id; ++ reg_info->reg_dmn_pair = ext_chan_list_event_hdr->domain_code; ++ ++ reg_info->status_code = ++ ath11k_wmi_cc_setting_code_to_reg(ext_chan_list_event_hdr->status_code); ++ ++ reg_info->is_ext_reg_event = true; ++ ++ reg_info->min_bw_2ghz = ext_chan_list_event_hdr->min_bw_2ghz; ++ reg_info->max_bw_2ghz = ext_chan_list_event_hdr->max_bw_2ghz; ++ reg_info->min_bw_5ghz = ext_chan_list_event_hdr->min_bw_5ghz; ++ reg_info->max_bw_5ghz = ext_chan_list_event_hdr->max_bw_5ghz; ++ ++ reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->min_bw_6ghz_ap_lpi; ++ reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->max_bw_6ghz_ap_lpi; ++ reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->min_bw_6ghz_ap_sp; ++ reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->max_bw_6ghz_ap_sp; ++ reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->min_bw_6ghz_ap_vlp; ++ reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->max_bw_6ghz_ap_vlp; ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->min_bw_6ghz_client_lpi[i]; ++ reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->max_bw_6ghz_client_lpi[i]; ++ reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->min_bw_6ghz_client_sp[i]; ++ reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->max_bw_6ghz_client_sp[i]; ++ reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->min_bw_6ghz_client_vlp[i]; ++ reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->max_bw_6ghz_client_vlp[i]; ++ } ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "%s:cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", ++ __func__, reg_info->alpha2, reg_info->dfs_region, ++ reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, ++ reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "num_2ghz_reg_rules %d num_5ghz_reg_rules %d", ++ num_2ghz_reg_rules, num_5ghz_reg_rules); ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "num_6ghz_reg_rules_ap_lpi: %d num_6ghz_reg_rules_ap_sp: %d num_6ghz_reg_rules_ap_vlp: %d", ++ num_6ghz_reg_rules_ap[WMI_REG_INDOOR_AP], ++ num_6ghz_reg_rules_ap[WMI_REG_STANDARD_POWER_AP], ++ num_6ghz_reg_rules_ap[WMI_REG_VERY_LOW_POWER_AP]); ++ ++ j = WMI_REG_DEFAULT_CLIENT; ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz Regular client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d", ++ num_6ghz_client[WMI_REG_INDOOR_AP][j], ++ num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j], ++ num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]); ++ ++ j = WMI_REG_SUBORDINATE_CLIENT; ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz Subordinate client: num_6ghz_reg_rules_lpi: %d num_6ghz_reg_rules_sp: %d num_6ghz_reg_rules_vlp: %d", ++ num_6ghz_client[WMI_REG_INDOOR_AP][j], ++ num_6ghz_client[WMI_REG_STANDARD_POWER_AP][j], ++ num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]); ++ ++ ext_wmi_reg_rule = ++ (struct wmi_regulatory_ext_rule *)((u8 *)ext_chan_list_event_hdr ++ + sizeof(*ext_chan_list_event_hdr) ++ + sizeof(struct wmi_tlv)); ++ if (num_2ghz_reg_rules) { ++ reg_info->reg_rules_2ghz_ptr = ++ create_ext_reg_rules_from_wmi(num_2ghz_reg_rules, ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_2ghz_ptr) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ ext_wmi_reg_rule += num_2ghz_reg_rules; ++ ++ /* Firmware might include 6 GHz reg rule in 5 GHz rule list ++ * for few countries along with separate 6 GHz rule. ++ * Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list ++ * causes intersect check to be true, and same rules will be ++ * shown multiple times in iw cmd. ++ * Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list ++ */ ++ num_invalid_5ghz_ext_rules = ++ ath11k_invalid_5ghz_reg_ext_rules_from_wmi(num_5ghz_reg_rules, ++ ext_wmi_reg_rule); ++ ++ if (num_invalid_5ghz_ext_rules) { ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules", ++ reg_info->alpha2, reg_info->num_5ghz_reg_rules, ++ num_invalid_5ghz_ext_rules); ++ ++ num_5ghz_reg_rules = num_5ghz_reg_rules - num_invalid_5ghz_ext_rules; ++ reg_info->num_5ghz_reg_rules = num_5ghz_reg_rules; ++ } ++ ++ if (num_5ghz_reg_rules) { ++ reg_info->reg_rules_5ghz_ptr = ++ create_ext_reg_rules_from_wmi(num_5ghz_reg_rules, ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_5ghz_ptr) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); ++ return -ENOMEM; ++ } ++ } ++ ++ /* We have adjusted the number of 5 GHz reg rules above. But still those ++ * many rules needs to be adjusted in ext_wmi_reg_rule. ++ * ++ * NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases. ++ */ ++ ext_wmi_reg_rule += (num_5ghz_reg_rules + num_invalid_5ghz_ext_rules); ++ ++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) { ++ reg_info->reg_rules_6ghz_ap_ptr[i] = ++ create_ext_reg_rules_from_wmi(num_6ghz_reg_rules_ap[i], ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_6ghz_ap_ptr[i]) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 6 GHz AP rules\n"); ++ return -ENOMEM; ++ } ++ ++ ext_wmi_reg_rule += num_6ghz_reg_rules_ap[i]; ++ } ++ ++ for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) { ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->reg_rules_6ghz_client_ptr[j][i] = ++ create_ext_reg_rules_from_wmi(num_6ghz_client[j][i], ++ ext_wmi_reg_rule); ++ ++ if (!reg_info->reg_rules_6ghz_client_ptr[j][i]) { ++ kfree(tb); ++ ath11k_warn(ab, "Unable to Allocate memory for 6 GHz client rules\n"); ++ return -ENOMEM; ++ } ++ ++ ext_wmi_reg_rule += num_6ghz_client[j][i]; ++ } ++ } ++ ++ reg_info->client_type = ext_chan_list_event_hdr->client_type; ++ reg_info->rnr_tpe_usable = ext_chan_list_event_hdr->rnr_tpe_usable; ++ reg_info->unspecified_ap_usable = ++ ext_chan_list_event_hdr->unspecified_ap_usable; ++ reg_info->domain_code_6ghz_ap[WMI_REG_INDOOR_AP] = ++ ext_chan_list_event_hdr->domain_code_6ghz_ap_lpi; ++ reg_info->domain_code_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = ++ ext_chan_list_event_hdr->domain_code_6ghz_ap_sp; ++ reg_info->domain_code_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = ++ ext_chan_list_event_hdr->domain_code_6ghz_ap_vlp; ++ ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { ++ reg_info->domain_code_6ghz_client[WMI_REG_INDOOR_AP][i] = ++ ext_chan_list_event_hdr->domain_code_6ghz_client_lpi[i]; ++ reg_info->domain_code_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = ++ ext_chan_list_event_hdr->domain_code_6ghz_client_sp[i]; ++ reg_info->domain_code_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = ++ ext_chan_list_event_hdr->domain_code_6ghz_client_vlp[i]; ++ } ++ ++ reg_info->domain_code_6ghz_super_id = ++ ext_chan_list_event_hdr->domain_code_6ghz_super_id; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "6 GHz client_type: %d domain_code_6ghz_super_id: %d", ++ reg_info->client_type, reg_info->domain_code_6ghz_super_id); ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory ext channel list\n"); ++ ++ kfree(tb); ++ return 0; ++} ++ + static int ath11k_pull_peer_del_resp_ev(struct ath11k_base *ab, struct sk_buff *skb, + struct wmi_peer_delete_resp_event *peer_del_resp) + { +@@ -6507,12 +6876,14 @@ static bool ath11k_reg_is_world_alpha(ch + return false; + } + +-static int ath11k_reg_chan_list_event(struct ath11k_base *ab, struct sk_buff *skb) ++static int ath11k_reg_chan_list_event(struct ath11k_base *ab, ++ struct sk_buff *skb, ++ enum wmi_reg_chan_list_cmd_type id) + { + struct cur_regulatory_info *reg_info = NULL; + struct ieee80211_regdomain *regd = NULL; + bool intersect = false; +- int ret = 0, pdev_idx; ++ int ret = 0, pdev_idx, i, j; + struct ath11k *ar; + + reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC); +@@ -6521,7 +6892,11 @@ static int ath11k_reg_chan_list_event(st + goto fallback; + } + +- ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info); ++ if (id == WMI_REG_CHAN_LIST_CC_ID) ++ ret = ath11k_pull_reg_chan_list_update_ev(ab, skb, reg_info); ++ else ++ ret = ath11k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info); ++ + if (ret) { + ath11k_warn(ab, "failed to extract regulatory info from received event\n"); + goto fallback; +@@ -6623,6 +6998,14 @@ mem_free: + if (reg_info) { + kfree(reg_info->reg_rules_2ghz_ptr); + kfree(reg_info->reg_rules_5ghz_ptr); ++ if (reg_info->is_ext_reg_event) { ++ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) ++ kfree(reg_info->reg_rules_6ghz_ap_ptr[i]); ++ ++ for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) ++ for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) ++ kfree(reg_info->reg_rules_6ghz_client_ptr[j][i]); ++ } + kfree(reg_info); + } + return ret; +@@ -8054,7 +8437,10 @@ static void ath11k_wmi_tlv_op_rx(struct + ath11k_service_ready_ext2_event(ab, skb); + break; + case WMI_REG_CHAN_LIST_CC_EVENTID: +- ath11k_reg_chan_list_event(ab, skb); ++ ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_ID); ++ break; ++ case WMI_REG_CHAN_LIST_CC_EXT_EVENTID: ++ ath11k_reg_chan_list_event(ab, skb, WMI_REG_CHAN_LIST_CC_EXT_ID); + break; + case WMI_READY_EVENTID: + ath11k_ready_event(ab, skb); +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -797,6 +797,7 @@ enum wmi_tlv_event_id { + WMI_RMC_NEW_LEADER_EVENTID = WMI_TLV_CMD(WMI_GRP_RMC), + WMI_REG_CHAN_LIST_CC_EVENTID = WMI_TLV_CMD(WMI_GRP_REGULATORY), + WMI_11D_NEW_COUNTRY_EVENTID, ++ WMI_REG_CHAN_LIST_CC_EXT_EVENTID, + WMI_NDI_CAP_RSP_EVENTID = WMI_TLV_CMD(WMI_GRP_PROTOTYPE), + WMI_NDP_INITIATOR_RSP_EVENTID, + WMI_NDP_RESPONDER_RSP_EVENTID, +@@ -1865,6 +1866,8 @@ enum wmi_tlv_tag { + WMI_TAG_PDEV_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_COLOR_ENABLE_BITMAP_CMD, + WMI_TAG_PDEV_NON_SRG_OBSS_BSSID_ENABLE_BITMAP_CMD, ++ WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9, ++ WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT, + WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8, + WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD, + WMI_TAG_MAX +@@ -2097,6 +2100,7 @@ enum wmi_tlv_service { + + /* The second 128 bits */ + WMI_MAX_EXT_SERVICE = 256, ++ WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281, + WMI_TLV_SERVICE_BIOS_SAR_SUPPORT = 326, + + /* The third 128 bits */ +@@ -2313,6 +2317,8 @@ struct wmi_init_cmd { + #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5) + #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18) + ++#define WMI_CFG_HOST_SERVICE_FLAG_REG_CC_EXT 4 ++ + struct wmi_resource_config { + u32 tlv_header; + u32 num_vdevs; +@@ -2372,6 +2378,15 @@ struct wmi_resource_config { + u32 sched_params; + u32 twt_ap_pdev_count; + u32 twt_ap_sta_count; ++ u32 max_nlo_ssids; ++ u32 num_pkt_filters; ++ u32 num_max_sta_vdevs; ++ u32 max_bssid_indicator; ++ u32 ul_resp_config; ++ u32 msdu_flow_override_config0; ++ u32 msdu_flow_override_config1; ++ u32 flags2; ++ u32 host_service_flags; + } __packed; + + struct wmi_service_ready_event { +@@ -2854,6 +2869,8 @@ struct rx_reorder_queue_remove_params { + #define REG_RULE_MAX_BW 0x0000ffff + #define REG_RULE_REG_PWR 0x00ff0000 + #define REG_RULE_ANT_GAIN 0xff000000 ++#define REG_RULE_PSD_INFO BIT(0) ++#define REG_RULE_PSD_EIRP 0xff0000 + + #define WMI_VDEV_PARAM_TXBF_SU_TX_BFEE BIT(0) + #define WMI_VDEV_PARAM_TXBF_MU_TX_BFEE BIT(1) +@@ -4049,6 +4066,7 @@ struct wmi_he_rate_set { + + #define MAX_REG_RULES 10 + #define REG_ALPHA2_LEN 2 ++#define MAX_6GHZ_REG_RULES 5 + + enum wmi_start_event_param { + WMI_VDEV_START_RESP_EVENT = 0, +@@ -4079,16 +4097,6 @@ enum wmi_vdev_start_resp_status_code { + WMI_VDEV_START_RESPONSE_INVALID_REGDOMAIN = 4, + }; + +-; +-enum cc_setting_code { +- REG_SET_CC_STATUS_PASS = 0, +- REG_CURRENT_ALPHA2_NOT_FOUND = 1, +- REG_INIT_ALPHA2_NOT_FOUND = 2, +- REG_SET_CC_CHANGE_NOT_ALLOWED = 3, +- REG_SET_CC_STATUS_NO_MEMORY = 4, +- REG_SET_CC_STATUS_FAIL = 5, +-}; +- + /* Regaulatory Rule Flags Passed by FW */ + #define REGULATORY_CHAN_DISABLED BIT(0) + #define REGULATORY_CHAN_NO_IR BIT(1) +@@ -4102,13 +4110,72 @@ enum cc_setting_code { + #define REGULATORY_CHAN_NO_20MHZ BIT(11) + #define REGULATORY_CHAN_NO_10MHZ BIT(12) + +-enum { ++enum wmi_reg_chan_list_cmd_type { ++ WMI_REG_CHAN_LIST_CC_ID = 0, ++ WMI_REG_CHAN_LIST_CC_EXT_ID = 1, ++}; ++ ++enum wmi_reg_cc_setting_code { + WMI_REG_SET_CC_STATUS_PASS = 0, + WMI_REG_CURRENT_ALPHA2_NOT_FOUND = 1, + WMI_REG_INIT_ALPHA2_NOT_FOUND = 2, + WMI_REG_SET_CC_CHANGE_NOT_ALLOWED = 3, + WMI_REG_SET_CC_STATUS_NO_MEMORY = 4, + WMI_REG_SET_CC_STATUS_FAIL = 5, ++ ++ /* add new setting code above, update in ++ * @enum cc_setting_code as well. ++ * Also handle it in ath11k_wmi_cc_setting_code_to_reg() ++ */ ++}; ++ ++enum cc_setting_code { ++ REG_SET_CC_STATUS_PASS = 0, ++ REG_CURRENT_ALPHA2_NOT_FOUND = 1, ++ REG_INIT_ALPHA2_NOT_FOUND = 2, ++ REG_SET_CC_CHANGE_NOT_ALLOWED = 3, ++ REG_SET_CC_STATUS_NO_MEMORY = 4, ++ REG_SET_CC_STATUS_FAIL = 5, ++ ++ /* add new setting code above, update in ++ * @enum wmi_reg_cc_setting_code as well. ++ */ ++}; ++ ++static inline enum cc_setting_code ++ath11k_wmi_cc_setting_code_to_reg(enum wmi_reg_cc_setting_code status_code) ++{ ++ switch (status_code) { ++ case WMI_REG_SET_CC_STATUS_PASS: ++ return REG_SET_CC_STATUS_PASS; ++ case WMI_REG_CURRENT_ALPHA2_NOT_FOUND: ++ return REG_CURRENT_ALPHA2_NOT_FOUND; ++ case WMI_REG_INIT_ALPHA2_NOT_FOUND: ++ return REG_INIT_ALPHA2_NOT_FOUND; ++ case WMI_REG_SET_CC_CHANGE_NOT_ALLOWED: ++ return REG_SET_CC_CHANGE_NOT_ALLOWED; ++ case WMI_REG_SET_CC_STATUS_NO_MEMORY: ++ return REG_SET_CC_STATUS_NO_MEMORY; ++ case WMI_REG_SET_CC_STATUS_FAIL: ++ return REG_SET_CC_STATUS_FAIL; ++ } ++ ++ return REG_SET_CC_STATUS_FAIL; ++} ++ ++enum wmi_reg_6ghz_ap_type { ++ WMI_REG_INDOOR_AP = 0, ++ WMI_REG_STANDARD_POWER_AP = 1, ++ WMI_REG_VERY_LOW_POWER_AP = 2, ++ ++ WMI_REG_CURRENT_MAX_AP_TYPE, ++ WMI_REG_MAX_AP_TYPE = 7, ++}; ++ ++enum wmi_reg_6ghz_client_type { ++ WMI_REG_DEFAULT_CLIENT = 0, ++ WMI_REG_SUBORDINATE_CLIENT = 1, ++ WMI_REG_MAX_CLIENT_TYPE = 2, + }; + + struct cur_reg_rule { +@@ -4118,6 +4185,8 @@ struct cur_reg_rule { + u8 reg_power; + u8 ant_gain; + u16 flags; ++ bool psd_flag; ++ s8 psd_eirp; + }; + + struct cur_regulatory_info { +@@ -4137,6 +4206,22 @@ struct cur_regulatory_info { + u32 num_5ghz_reg_rules; + struct cur_reg_rule *reg_rules_2ghz_ptr; + struct cur_reg_rule *reg_rules_5ghz_ptr; ++ bool is_ext_reg_event; ++ enum wmi_reg_6ghz_client_type client_type; ++ bool rnr_tpe_usable; ++ bool unspecified_ap_usable; ++ u8 domain_code_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u8 domain_code_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 domain_code_6ghz_super_id; ++ u32 min_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 max_bw_6ghz_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 min_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 max_bw_6ghz_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ u32 num_6ghz_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ u32 num_6ghz_rules_client[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; ++ struct cur_reg_rule *reg_rules_6ghz_ap_ptr[WMI_REG_CURRENT_MAX_AP_TYPE]; ++ struct cur_reg_rule *reg_rules_6ghz_client_ptr ++ [WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE]; + }; + + struct wmi_reg_chan_list_cc_event { +@@ -4163,6 +4248,61 @@ struct wmi_regulatory_rule_struct { + u32 flag_info; + }; + ++#define WMI_REG_CLIENT_MAX 4 ++ ++struct wmi_reg_chan_list_cc_ext_event { ++ u32 status_code; ++ u32 phy_id; ++ u32 alpha2; ++ u32 num_phy; ++ u32 country_id; ++ u32 domain_code; ++ u32 dfs_region; ++ u32 phybitmap; ++ u32 min_bw_2ghz; ++ u32 max_bw_2ghz; ++ u32 min_bw_5ghz; ++ u32 max_bw_5ghz; ++ u32 num_2ghz_reg_rules; ++ u32 num_5ghz_reg_rules; ++ u32 client_type; ++ u32 rnr_tpe_usable; ++ u32 unspecified_ap_usable; ++ u32 domain_code_6ghz_ap_lpi; ++ u32 domain_code_6ghz_ap_sp; ++ u32 domain_code_6ghz_ap_vlp; ++ u32 domain_code_6ghz_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 domain_code_6ghz_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 domain_code_6ghz_client_vlp[WMI_REG_CLIENT_MAX]; ++ u32 domain_code_6ghz_super_id; ++ u32 min_bw_6ghz_ap_sp; ++ u32 max_bw_6ghz_ap_sp; ++ u32 min_bw_6ghz_ap_lpi; ++ u32 max_bw_6ghz_ap_lpi; ++ u32 min_bw_6ghz_ap_vlp; ++ u32 max_bw_6ghz_ap_vlp; ++ u32 min_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 max_bw_6ghz_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 min_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 max_bw_6ghz_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 min_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX]; ++ u32 max_bw_6ghz_client_vlp[WMI_REG_CLIENT_MAX]; ++ u32 num_6ghz_reg_rules_ap_sp; ++ u32 num_6ghz_reg_rules_ap_lpi; ++ u32 num_6ghz_reg_rules_ap_vlp; ++ u32 num_6ghz_reg_rules_client_sp[WMI_REG_CLIENT_MAX]; ++ u32 num_6ghz_reg_rules_client_lpi[WMI_REG_CLIENT_MAX]; ++ u32 num_6ghz_reg_rules_client_vlp[WMI_REG_CLIENT_MAX]; ++} __packed; ++ ++struct wmi_regulatory_ext_rule { ++ u32 tlv_header; ++ u32 freq_info; ++ u32 bw_pwr_info; ++ u32 flag_info; ++ u32 psd_power_info; ++} __packed; ++ + struct wmi_vdev_delete_resp_event { + u32 vdev_id; + } __packed; +@@ -5358,6 +5498,7 @@ struct target_resource_config { + u32 sched_params; + u32 twt_ap_pdev_count; + u32 twt_ap_sta_count; ++ u8 is_reg_cc_ext_event_supported; + }; + + enum wmi_debug_log_param { diff --git a/package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch b/package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch new file mode 100644 index 0000000000..b88e51928f --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0045-wifi-ath11k-add-debug-prints-in-regulatory-WMI-event.patch @@ -0,0 +1,567 @@ +From e238e62ba8868a784e485eb94451c87cd1b85cee Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh <quic_adisi@quicinc.com> +Date: Wed, 1 Mar 2023 16:20:59 +0200 +Subject: [PATCH] wifi: ath11k: add debug prints in regulatory WMI event + processing + +Add some more debug prints in processing regulatory WMI event in order to +increase more debuggability. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 +Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 + +Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/20230110121024.14051-4-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/reg.c | 2 +- + drivers/net/wireless/ath/ath11k/wmi.c | 207 ++++++++++++++++++-------- + drivers/net/wireless/ath/ath11k/wmi.h | 142 ++++++++++++++++++ + 3 files changed, 291 insertions(+), 60 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/reg.c ++++ b/drivers/net/wireless/ath/ath11k/reg.c +@@ -646,7 +646,7 @@ ath11k_reg_build_regd(struct ath11k_base + tmp_regd->dfs_region = ath11k_map_fw_dfs_region(reg_info->dfs_region); + + ath11k_dbg(ab, ATH11K_DBG_REG, +- "\r\nCountry %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n", ++ "Country %s, CFG Regdomain %s FW Regdomain %d, num_reg_rules %d\n", + alpha2, ath11k_reg_get_regdom_str(tmp_regd->dfs_region), + reg_info->dfs_region, num_rules); + /* Update reg_rules[] below. Firmware is expected to +--- a/drivers/net/wireless/ath/ath11k/wmi.c ++++ b/drivers/net/wireless/ath/ath11k/wmi.c +@@ -4925,6 +4925,26 @@ static int ath11k_pull_vdev_start_resp_t + return 0; + } + ++static void ath11k_print_reg_rule(struct ath11k_base *ab, const char *band, ++ u32 num_reg_rules, ++ struct cur_reg_rule *reg_rule_ptr) ++{ ++ struct cur_reg_rule *reg_rule = reg_rule_ptr; ++ u32 count; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, "number of reg rules in %s band: %d\n", ++ band, num_reg_rules); ++ ++ for (count = 0; count < num_reg_rules; count++) { ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "reg rule %d: (%d - %d @ %d) (%d, %d) (FLAGS %d)\n", ++ count + 1, reg_rule->start_freq, reg_rule->end_freq, ++ reg_rule->max_bw, reg_rule->ant_gain, ++ reg_rule->reg_power, reg_rule->flags); ++ reg_rule++; ++ } ++} ++ + static struct cur_reg_rule + *create_reg_rules_from_wmi(u32 num_reg_rules, + struct wmi_regulatory_rule_struct *wmi_reg_rule) +@@ -5006,6 +5026,10 @@ static int ath11k_pull_reg_chan_list_upd + reg_info->ctry_code = chan_list_event_hdr->country_id; + reg_info->reg_dmn_pair = chan_list_event_hdr->domain_code; + ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "status_code %s", ++ ath11k_cc_status_to_str(reg_info->status_code)); ++ + reg_info->status_code = + ath11k_wmi_cc_setting_code_to_reg(chan_list_event_hdr->status_code); + +@@ -5020,13 +5044,13 @@ static int ath11k_pull_reg_chan_list_upd + num_5ghz_reg_rules = reg_info->num_5ghz_reg_rules; + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s:cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", +- __func__, reg_info->alpha2, reg_info->dfs_region, ++ "cc %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", ++ reg_info->alpha2, reg_info->dfs_region, + reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, + reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s: num_2ghz_reg_rules %d num_5ghz_reg_rules %d", __func__, ++ "num_2ghz_reg_rules %d num_5ghz_reg_rules %d", + num_2ghz_reg_rules, num_5ghz_reg_rules); + + wmi_reg_rule = +@@ -5043,6 +5067,10 @@ static int ath11k_pull_reg_chan_list_upd + ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "2 GHz", ++ num_2ghz_reg_rules, ++ reg_info->reg_rules_2ghz_ptr); + } + + if (num_5ghz_reg_rules) { +@@ -5055,6 +5083,10 @@ static int ath11k_pull_reg_chan_list_upd + ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "5 GHz", ++ num_5ghz_reg_rules, ++ reg_info->reg_rules_5ghz_ptr); + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory channel list\n"); +@@ -5128,7 +5160,7 @@ static int ath11k_pull_reg_chan_list_ext + struct cur_regulatory_info *reg_info) + { + const void **tb; +- const struct wmi_reg_chan_list_cc_ext_event *ext_chan_list_event_hdr; ++ const struct wmi_reg_chan_list_cc_ext_event *ev; + struct wmi_regulatory_ext_rule *ext_wmi_reg_rule; + u32 num_2ghz_reg_rules, num_5ghz_reg_rules; + u32 num_6ghz_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE]; +@@ -5145,31 +5177,29 @@ static int ath11k_pull_reg_chan_list_ext + return ret; + } + +- ext_chan_list_event_hdr = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]; +- if (!ext_chan_list_event_hdr) { ++ ev = tb[WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT]; ++ if (!ev) { + ath11k_warn(ab, "failed to fetch reg chan list ext update ev\n"); + kfree(tb); + return -EPROTO; + } + +- reg_info->num_2ghz_reg_rules = +- ext_chan_list_event_hdr->num_2ghz_reg_rules; +- reg_info->num_5ghz_reg_rules = +- ext_chan_list_event_hdr->num_5ghz_reg_rules; ++ reg_info->num_2ghz_reg_rules = ev->num_2ghz_reg_rules; ++ reg_info->num_5ghz_reg_rules = ev->num_5ghz_reg_rules; + reg_info->num_6ghz_rules_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_lpi; ++ ev->num_6ghz_reg_rules_ap_lpi; + reg_info->num_6ghz_rules_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_sp; ++ ev->num_6ghz_reg_rules_ap_sp; + reg_info->num_6ghz_rules_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_ap_vlp; ++ ev->num_6ghz_reg_rules_ap_vlp; + + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->num_6ghz_rules_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_client_lpi[i]; ++ ev->num_6ghz_reg_rules_client_lpi[i]; + reg_info->num_6ghz_rules_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_client_sp[i]; ++ ev->num_6ghz_reg_rules_client_sp[i]; + reg_info->num_6ghz_rules_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->num_6ghz_reg_rules_client_vlp[i]; ++ ev->num_6ghz_reg_rules_client_vlp[i]; + } + + num_2ghz_reg_rules = reg_info->num_2ghz_reg_rules; +@@ -5231,57 +5261,79 @@ static int ath11k_pull_reg_chan_list_ext + return -EINVAL; + } + +- memcpy(reg_info->alpha2, &ext_chan_list_event_hdr->alpha2, +- REG_ALPHA2_LEN); ++ memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN); ++ ++ reg_info->dfs_region = ev->dfs_region; ++ reg_info->phybitmap = ev->phybitmap; ++ reg_info->num_phy = ev->num_phy; ++ reg_info->phy_id = ev->phy_id; ++ reg_info->ctry_code = ev->country_id; ++ reg_info->reg_dmn_pair = ev->domain_code; + +- reg_info->dfs_region = ext_chan_list_event_hdr->dfs_region; +- reg_info->phybitmap = ext_chan_list_event_hdr->phybitmap; +- reg_info->num_phy = ext_chan_list_event_hdr->num_phy; +- reg_info->phy_id = ext_chan_list_event_hdr->phy_id; +- reg_info->ctry_code = ext_chan_list_event_hdr->country_id; +- reg_info->reg_dmn_pair = ext_chan_list_event_hdr->domain_code; ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "status_code %s", ++ ath11k_cc_status_to_str(reg_info->status_code)); + + reg_info->status_code = +- ath11k_wmi_cc_setting_code_to_reg(ext_chan_list_event_hdr->status_code); ++ ath11k_wmi_cc_setting_code_to_reg(ev->status_code); + + reg_info->is_ext_reg_event = true; + +- reg_info->min_bw_2ghz = ext_chan_list_event_hdr->min_bw_2ghz; +- reg_info->max_bw_2ghz = ext_chan_list_event_hdr->max_bw_2ghz; +- reg_info->min_bw_5ghz = ext_chan_list_event_hdr->min_bw_5ghz; +- reg_info->max_bw_5ghz = ext_chan_list_event_hdr->max_bw_5ghz; ++ reg_info->min_bw_2ghz = ev->min_bw_2ghz; ++ reg_info->max_bw_2ghz = ev->max_bw_2ghz; ++ reg_info->min_bw_5ghz = ev->min_bw_5ghz; ++ reg_info->max_bw_5ghz = ev->max_bw_5ghz; + + reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->min_bw_6ghz_ap_lpi; ++ ev->min_bw_6ghz_ap_lpi; + reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->max_bw_6ghz_ap_lpi; ++ ev->max_bw_6ghz_ap_lpi; + reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->min_bw_6ghz_ap_sp; ++ ev->min_bw_6ghz_ap_sp; + reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->max_bw_6ghz_ap_sp; ++ ev->max_bw_6ghz_ap_sp; + reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->min_bw_6ghz_ap_vlp; ++ ev->min_bw_6ghz_ap_vlp; + reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->max_bw_6ghz_ap_vlp; ++ ev->max_bw_6ghz_ap_vlp; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz AP BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n", ++ reg_info->min_bw_6ghz_ap[WMI_REG_INDOOR_AP], ++ reg_info->max_bw_6ghz_ap[WMI_REG_INDOOR_AP], ++ reg_info->min_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP], ++ reg_info->max_bw_6ghz_ap[WMI_REG_STANDARD_POWER_AP], ++ reg_info->min_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP], ++ reg_info->max_bw_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP]); + + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->min_bw_6ghz_client_lpi[i]; ++ ev->min_bw_6ghz_client_lpi[i]; + reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->max_bw_6ghz_client_lpi[i]; ++ ev->max_bw_6ghz_client_lpi[i]; + reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->min_bw_6ghz_client_sp[i]; ++ ev->min_bw_6ghz_client_sp[i]; + reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->max_bw_6ghz_client_sp[i]; ++ ev->max_bw_6ghz_client_sp[i]; + reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->min_bw_6ghz_client_vlp[i]; ++ ev->min_bw_6ghz_client_vlp[i]; + reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->max_bw_6ghz_client_vlp[i]; ++ ev->max_bw_6ghz_client_vlp[i]; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz %s BW: LPI (%d - %d), SP (%d - %d), VLP (%d - %d)\n", ++ ath11k_6ghz_client_type_to_str(i), ++ reg_info->min_bw_6ghz_client[WMI_REG_INDOOR_AP][i], ++ reg_info->max_bw_6ghz_client[WMI_REG_INDOOR_AP][i], ++ reg_info->min_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i], ++ reg_info->max_bw_6ghz_client[WMI_REG_STANDARD_POWER_AP][i], ++ reg_info->min_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i], ++ reg_info->max_bw_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i]); + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, +- "%s:cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", +- __func__, reg_info->alpha2, reg_info->dfs_region, ++ "cc_ext %s dsf %d BW: min_2ghz %d max_2ghz %d min_5ghz %d max_5ghz %d", ++ reg_info->alpha2, reg_info->dfs_region, + reg_info->min_bw_2ghz, reg_info->max_bw_2ghz, + reg_info->min_bw_5ghz, reg_info->max_bw_5ghz); + +@@ -5310,9 +5362,8 @@ static int ath11k_pull_reg_chan_list_ext + num_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][j]); + + ext_wmi_reg_rule = +- (struct wmi_regulatory_ext_rule *)((u8 *)ext_chan_list_event_hdr +- + sizeof(*ext_chan_list_event_hdr) +- + sizeof(struct wmi_tlv)); ++ (struct wmi_regulatory_ext_rule *)((u8 *)ev + sizeof(*ev) + ++ sizeof(struct wmi_tlv)); + if (num_2ghz_reg_rules) { + reg_info->reg_rules_2ghz_ptr = + create_ext_reg_rules_from_wmi(num_2ghz_reg_rules, +@@ -5323,6 +5374,10 @@ static int ath11k_pull_reg_chan_list_ext + ath11k_warn(ab, "Unable to Allocate memory for 2 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "2 GHz", ++ num_2ghz_reg_rules, ++ reg_info->reg_rules_2ghz_ptr); + } + + ext_wmi_reg_rule += num_2ghz_reg_rules; +@@ -5358,6 +5413,10 @@ static int ath11k_pull_reg_chan_list_ext + ath11k_warn(ab, "Unable to Allocate memory for 5 GHz rules\n"); + return -ENOMEM; + } ++ ++ ath11k_print_reg_rule(ab, "5 GHz", ++ num_5ghz_reg_rules, ++ reg_info->reg_rules_5ghz_ptr); + } + + /* We have adjusted the number of 5 GHz reg rules above. But still those +@@ -5378,10 +5437,17 @@ static int ath11k_pull_reg_chan_list_ext + return -ENOMEM; + } + ++ ath11k_print_reg_rule(ab, ath11k_6ghz_ap_type_to_str(i), ++ num_6ghz_reg_rules_ap[i], ++ reg_info->reg_rules_6ghz_ap_ptr[i]); ++ + ext_wmi_reg_rule += num_6ghz_reg_rules_ap[i]; + } + + for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++) { ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz AP type %s", ath11k_6ghz_ap_type_to_str(j)); ++ + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->reg_rules_6ghz_client_ptr[j][i] = + create_ext_reg_rules_from_wmi(num_6ghz_client[j][i], +@@ -5393,35 +5459,58 @@ static int ath11k_pull_reg_chan_list_ext + return -ENOMEM; + } + ++ ath11k_print_reg_rule(ab, ++ ath11k_6ghz_client_type_to_str(i), ++ num_6ghz_client[j][i], ++ reg_info->reg_rules_6ghz_client_ptr[j][i]); ++ + ext_wmi_reg_rule += num_6ghz_client[j][i]; + } + } + +- reg_info->client_type = ext_chan_list_event_hdr->client_type; +- reg_info->rnr_tpe_usable = ext_chan_list_event_hdr->rnr_tpe_usable; ++ reg_info->client_type = ev->client_type; ++ reg_info->rnr_tpe_usable = ev->rnr_tpe_usable; + reg_info->unspecified_ap_usable = +- ext_chan_list_event_hdr->unspecified_ap_usable; ++ ev->unspecified_ap_usable; + reg_info->domain_code_6ghz_ap[WMI_REG_INDOOR_AP] = +- ext_chan_list_event_hdr->domain_code_6ghz_ap_lpi; ++ ev->domain_code_6ghz_ap_lpi; + reg_info->domain_code_6ghz_ap[WMI_REG_STANDARD_POWER_AP] = +- ext_chan_list_event_hdr->domain_code_6ghz_ap_sp; ++ ev->domain_code_6ghz_ap_sp; + reg_info->domain_code_6ghz_ap[WMI_REG_VERY_LOW_POWER_AP] = +- ext_chan_list_event_hdr->domain_code_6ghz_ap_vlp; ++ ev->domain_code_6ghz_ap_vlp; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz reg info client type %s rnr_tpe_usable %d unspecified_ap_usable %d AP sub domain: lpi %s, sp %s, vlp %s\n", ++ ath11k_6ghz_client_type_to_str(reg_info->client_type), ++ reg_info->rnr_tpe_usable, ++ reg_info->unspecified_ap_usable, ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_lpi), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_sp), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_ap_vlp)); + + for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++) { + reg_info->domain_code_6ghz_client[WMI_REG_INDOOR_AP][i] = +- ext_chan_list_event_hdr->domain_code_6ghz_client_lpi[i]; ++ ev->domain_code_6ghz_client_lpi[i]; + reg_info->domain_code_6ghz_client[WMI_REG_STANDARD_POWER_AP][i] = +- ext_chan_list_event_hdr->domain_code_6ghz_client_sp[i]; ++ ev->domain_code_6ghz_client_sp[i]; + reg_info->domain_code_6ghz_client[WMI_REG_VERY_LOW_POWER_AP][i] = +- ext_chan_list_event_hdr->domain_code_6ghz_client_vlp[i]; ++ ev->domain_code_6ghz_client_vlp[i]; ++ ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz client type %s client sub domain: lpi %s, sp %s, vlp %s\n", ++ ath11k_6ghz_client_type_to_str(i), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_lpi[i]), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_sp[i]), ++ ath11k_sub_reg_6ghz_to_str(ev->domain_code_6ghz_client_vlp[i]) ++ ); + } + +- reg_info->domain_code_6ghz_super_id = +- ext_chan_list_event_hdr->domain_code_6ghz_super_id; ++ reg_info->domain_code_6ghz_super_id = ev->domain_code_6ghz_super_id; + +- ath11k_dbg(ab, ATH11K_DBG_WMI, "6 GHz client_type: %d domain_code_6ghz_super_id: %d", +- reg_info->client_type, reg_info->domain_code_6ghz_super_id); ++ ath11k_dbg(ab, ATH11K_DBG_WMI, ++ "6 GHz client_type %s 6 GHz super domain %s", ++ ath11k_6ghz_client_type_to_str(reg_info->client_type), ++ ath11k_super_reg_6ghz_to_str(reg_info->domain_code_6ghz_super_id)); + + ath11k_dbg(ab, ATH11K_DBG_WMI, "processed regulatory ext channel list\n"); + +--- a/drivers/net/wireless/ath/ath11k/wmi.h ++++ b/drivers/net/wireless/ath/ath11k/wmi.h +@@ -4139,6 +4139,7 @@ enum cc_setting_code { + + /* add new setting code above, update in + * @enum wmi_reg_cc_setting_code as well. ++ * Also handle it in ath11k_cc_status_to_str() + */ + }; + +@@ -4163,21 +4164,162 @@ ath11k_wmi_cc_setting_code_to_reg(enum w + return REG_SET_CC_STATUS_FAIL; + } + ++static inline const char *ath11k_cc_status_to_str(enum cc_setting_code code) ++{ ++ switch (code) { ++ case REG_SET_CC_STATUS_PASS: ++ return "REG_SET_CC_STATUS_PASS"; ++ case REG_CURRENT_ALPHA2_NOT_FOUND: ++ return "REG_CURRENT_ALPHA2_NOT_FOUND"; ++ case REG_INIT_ALPHA2_NOT_FOUND: ++ return "REG_INIT_ALPHA2_NOT_FOUND"; ++ case REG_SET_CC_CHANGE_NOT_ALLOWED: ++ return "REG_SET_CC_CHANGE_NOT_ALLOWED"; ++ case REG_SET_CC_STATUS_NO_MEMORY: ++ return "REG_SET_CC_STATUS_NO_MEMORY"; ++ case REG_SET_CC_STATUS_FAIL: ++ return "REG_SET_CC_STATUS_FAIL"; ++ } ++ ++ return "Unknown CC status"; ++} ++ + enum wmi_reg_6ghz_ap_type { + WMI_REG_INDOOR_AP = 0, + WMI_REG_STANDARD_POWER_AP = 1, + WMI_REG_VERY_LOW_POWER_AP = 2, + ++ /* add AP type above, handle in ath11k_6ghz_ap_type_to_str() ++ */ + WMI_REG_CURRENT_MAX_AP_TYPE, + WMI_REG_MAX_AP_TYPE = 7, + }; + ++static inline const char * ++ath11k_6ghz_ap_type_to_str(enum wmi_reg_6ghz_ap_type type) ++{ ++ switch (type) { ++ case WMI_REG_INDOOR_AP: ++ return "INDOOR AP"; ++ case WMI_REG_STANDARD_POWER_AP: ++ return "STANDARD POWER AP"; ++ case WMI_REG_VERY_LOW_POWER_AP: ++ return "VERY LOW POWER AP"; ++ case WMI_REG_CURRENT_MAX_AP_TYPE: ++ return "CURRENT_MAX_AP_TYPE"; ++ case WMI_REG_MAX_AP_TYPE: ++ return "MAX_AP_TYPE"; ++ } ++ ++ return "unknown 6 GHz AP type"; ++} ++ + enum wmi_reg_6ghz_client_type { + WMI_REG_DEFAULT_CLIENT = 0, + WMI_REG_SUBORDINATE_CLIENT = 1, + WMI_REG_MAX_CLIENT_TYPE = 2, ++ ++ /* add client type above, handle it in ++ * ath11k_6ghz_client_type_to_str() ++ */ ++}; ++ ++static inline const char * ++ath11k_6ghz_client_type_to_str(enum wmi_reg_6ghz_client_type type) ++{ ++ switch (type) { ++ case WMI_REG_DEFAULT_CLIENT: ++ return "DEFAULT CLIENT"; ++ case WMI_REG_SUBORDINATE_CLIENT: ++ return "SUBORDINATE CLIENT"; ++ case WMI_REG_MAX_CLIENT_TYPE: ++ return "MAX_CLIENT_TYPE"; ++ } ++ ++ return "unknown 6 GHz client type"; ++} ++ ++enum reg_subdomains_6ghz { ++ EMPTY_6GHZ = 0x0, ++ FCC1_CLIENT_LPI_REGULAR_6GHZ = 0x01, ++ FCC1_CLIENT_SP_6GHZ = 0x02, ++ FCC1_AP_LPI_6GHZ = 0x03, ++ FCC1_CLIENT_LPI_SUBORDINATE = FCC1_AP_LPI_6GHZ, ++ FCC1_AP_SP_6GHZ = 0x04, ++ ETSI1_LPI_6GHZ = 0x10, ++ ETSI1_VLP_6GHZ = 0x11, ++ ETSI2_LPI_6GHZ = 0x12, ++ ETSI2_VLP_6GHZ = 0x13, ++ APL1_LPI_6GHZ = 0x20, ++ APL1_VLP_6GHZ = 0x21, ++ ++ /* add sub-domain above, handle it in ++ * ath11k_sub_reg_6ghz_to_str() ++ */ ++}; ++ ++static inline const char * ++ath11k_sub_reg_6ghz_to_str(enum reg_subdomains_6ghz sub_id) ++{ ++ switch (sub_id) { ++ case EMPTY_6GHZ: ++ return "N/A"; ++ case FCC1_CLIENT_LPI_REGULAR_6GHZ: ++ return "FCC1_CLIENT_LPI_REGULAR_6GHZ"; ++ case FCC1_CLIENT_SP_6GHZ: ++ return "FCC1_CLIENT_SP_6GHZ"; ++ case FCC1_AP_LPI_6GHZ: ++ return "FCC1_AP_LPI_6GHZ/FCC1_CLIENT_LPI_SUBORDINATE"; ++ case FCC1_AP_SP_6GHZ: ++ return "FCC1_AP_SP_6GHZ"; ++ case ETSI1_LPI_6GHZ: ++ return "ETSI1_LPI_6GHZ"; ++ case ETSI1_VLP_6GHZ: ++ return "ETSI1_VLP_6GHZ"; ++ case ETSI2_LPI_6GHZ: ++ return "ETSI2_LPI_6GHZ"; ++ case ETSI2_VLP_6GHZ: ++ return "ETSI2_VLP_6GHZ"; ++ case APL1_LPI_6GHZ: ++ return "APL1_LPI_6GHZ"; ++ case APL1_VLP_6GHZ: ++ return "APL1_VLP_6GHZ"; ++ } ++ ++ return "unknown sub reg id"; ++} ++ ++enum reg_super_domain_6ghz { ++ FCC1_6GHZ = 0x01, ++ ETSI1_6GHZ = 0x02, ++ ETSI2_6GHZ = 0x03, ++ APL1_6GHZ = 0x04, ++ FCC1_6GHZ_CL = 0x05, ++ ++ /* add super domain above, handle it in ++ * ath11k_super_reg_6ghz_to_str() ++ */ + }; + ++static inline const char * ++ath11k_super_reg_6ghz_to_str(enum reg_super_domain_6ghz domain_id) ++{ ++ switch (domain_id) { ++ case FCC1_6GHZ: ++ return "FCC1_6GHZ"; ++ case ETSI1_6GHZ: ++ return "ETSI1_6GHZ"; ++ case ETSI2_6GHZ: ++ return "ETSI2_6GHZ"; ++ case APL1_6GHZ: ++ return "APL1_6GHZ"; ++ case FCC1_6GHZ_CL: ++ return "FCC1_6GHZ_CL"; ++ } ++ ++ return "unknown domain id"; ++} ++ + struct cur_reg_rule { + u16 start_freq; + u16 end_freq; diff --git a/package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch b/package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch new file mode 100644 index 0000000000..bd16178564 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0046-wifi-ath11k-Replace-fake-flex-array-with-flexible-ar.patch @@ -0,0 +1,246 @@ +From 3b1088a09ec9438523c251d8435e78988824bc0d Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" <gustavoars@kernel.org> +Date: Tue, 7 Mar 2023 16:22:39 -0600 +Subject: [PATCH] wifi: ath11k: Replace fake flex-array with flexible-array + member +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Zero-length arrays as fake flexible arrays are deprecated and we are +moving towards adopting C99 flexible-array members instead. + +Address 25 of the following warnings found with GCC-13 and +-fstrict-flex-arrays=3 enabled: +drivers/net/wireless/ath/ath11k/debugfs_htt_stats.c:30:51: warning: array subscript <unknown> is outside array bounds of ‘const u32[0]’ {aka ‘const unsigned int[]’} [-Warray-bounds=] + +This helps with the ongoing efforts to tighten the FORTIFY_SOURCE +routines on memcpy() and help us make progress towards globally +enabling -fstrict-flex-arrays=3 [1]. + +Link: https://github.com/KSPP/linux/issues/21 +Link: https://github.com/KSPP/linux/issues/266 +Link: https://gcc.gnu.org/pipermail/gcc-patches/2022-October/602902.html [1] +Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org> +Reviewed-by: Simon Horman <simon.horman@corigine.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/ZAe5L5DtmsQxzqRH@work +--- + .../wireless/ath/ath11k/debugfs_htt_stats.h | 73 +++++++++++-------- + 1 file changed, 43 insertions(+), 30 deletions(-) + +--- a/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h ++++ b/drivers/net/wireless/ath/ath11k/debugfs_htt_stats.h +@@ -143,7 +143,8 @@ enum htt_tx_pdev_underrun_enum { + /* Bytes stored in little endian order */ + /* Length should be multiple of DWORD */ + struct htt_stats_string_tlv { +- u32 data[0]; /* Can be variable length */ ++ /* Can be variable length */ ++ DECLARE_FLEX_ARRAY(u32, data); + } __packed; + + #define HTT_STATS_MAC_ID GENMASK(7, 0) +@@ -205,27 +206,32 @@ struct htt_tx_pdev_stats_cmn_tlv { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_urrn_tlv_v { +- u32 urrn_stats[0]; /* HTT_TX_PDEV_MAX_URRN_STATS */ ++ /* HTT_TX_PDEV_MAX_URRN_STATS */ ++ DECLARE_FLEX_ARRAY(u32, urrn_stats); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_flush_tlv_v { +- u32 flush_errs[0]; /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ ++ /* HTT_TX_PDEV_MAX_FLUSH_REASON_STATS */ ++ DECLARE_FLEX_ARRAY(u32, flush_errs); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_sifs_tlv_v { +- u32 sifs_status[0]; /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ ++ /* HTT_TX_PDEV_MAX_SIFS_BURST_STATS */ ++ DECLARE_FLEX_ARRAY(u32, sifs_status); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_phy_err_tlv_v { +- u32 phy_errs[0]; /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ ++ /* HTT_TX_PDEV_MAX_PHY_ERR_STATS */ ++ DECLARE_FLEX_ARRAY(u32, phy_errs); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_pdev_stats_sifs_hist_tlv_v { +- u32 sifs_hist_status[0]; /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ ++ /* HTT_TX_PDEV_SIFS_BURST_HIST_STATS */ ++ DECLARE_FLEX_ARRAY(u32, sifs_hist_status); + }; + + struct htt_tx_pdev_stats_tx_ppdu_stats_tlv_v { +@@ -590,20 +596,20 @@ struct htt_tx_hwq_difs_latency_stats_tlv + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_hwq_cmd_result_stats_tlv_v { +- /* Histogram of sched cmd result */ +- u32 cmd_result[0]; /* HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ ++ /* Histogram of sched cmd result, HTT_TX_HWQ_MAX_CMD_RESULT_STATS */ ++ DECLARE_FLEX_ARRAY(u32, cmd_result); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_hwq_cmd_stall_stats_tlv_v { +- /* Histogram of various pause conitions */ +- u32 cmd_stall_status[0]; /* HTT_TX_HWQ_MAX_CMD_STALL_STATS */ ++ /* Histogram of various pause conitions, HTT_TX_HWQ_MAX_CMD_STALL_STATS */ ++ DECLARE_FLEX_ARRAY(u32, cmd_stall_status); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_hwq_fes_result_stats_tlv_v { +- /* Histogram of number of user fes result */ +- u32 fes_result[0]; /* HTT_TX_HWQ_MAX_FES_RESULT_STATS */ ++ /* Histogram of number of user fes result, HTT_TX_HWQ_MAX_FES_RESULT_STATS */ ++ DECLARE_FLEX_ARRAY(u32, fes_result); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size +@@ -635,8 +641,8 @@ struct htt_tx_hwq_tried_mpdu_cnt_hist_tl + * #define WAL_TXOP_USED_HISTOGRAM_INTERVAL 1000 ( 1 ms ) + */ + struct htt_tx_hwq_txop_used_cnt_hist_tlv_v { +- /* Histogram of txop used cnt */ +- u32 txop_used_cnt_hist[0]; /* HTT_TX_HWQ_TXOP_USED_CNT_HIST */ ++ /* Histogram of txop used cnt, HTT_TX_HWQ_TXOP_USED_CNT_HIST */ ++ DECLARE_FLEX_ARRAY(u32, txop_used_cnt_hist); + }; + + /* == TX SELFGEN STATS == */ +@@ -804,17 +810,20 @@ struct htt_tx_pdev_mpdu_stats_tlv { + /* == TX SCHED STATS == */ + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_cmd_posted_tlv_v { +- u32 sched_cmd_posted[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ DECLARE_FLEX_ARRAY(u32, sched_cmd_posted); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_cmd_reaped_tlv_v { +- u32 sched_cmd_reaped[0]; /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ /* HTT_TX_PDEV_SCHED_TX_MODE_MAX */ ++ DECLARE_FLEX_ARRAY(u32, sched_cmd_reaped); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_sched_order_su_tlv_v { +- u32 sched_order_su[0]; /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ ++ /* HTT_TX_PDEV_NUM_SCHED_ORDER_LOG */ ++ DECLARE_FLEX_ARRAY(u32, sched_order_su); + }; + + enum htt_sched_txq_sched_ineligibility_tlv_enum { +@@ -842,7 +851,7 @@ enum htt_sched_txq_sched_ineligibility_t + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sched_txq_sched_ineligibility_tlv_v { + /* indexed by htt_sched_txq_sched_ineligibility_tlv_enum */ +- u32 sched_ineligibility[0]; ++ DECLARE_FLEX_ARRAY(u32, sched_ineligibility); + }; + + #define HTT_TX_PDEV_STATS_SCHED_PER_TXQ_MAC_ID GENMASK(7, 0) +@@ -888,18 +897,20 @@ struct htt_stats_tx_sched_cmn_tlv { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_tqm_gen_mpdu_stats_tlv_v { +- u32 gen_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ ++ /* HTT_TX_TQM_MAX_GEN_MPDU_END_REASON */ ++ DECLARE_FLEX_ARRAY(u32, gen_mpdu_end_reason); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_tqm_list_mpdu_stats_tlv_v { +- u32 list_mpdu_end_reason[0]; /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ ++ /* HTT_TX_TQM_MAX_LIST_MPDU_END_REASON */ ++ DECLARE_FLEX_ARRAY(u32, list_mpdu_end_reason); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_tx_tqm_list_mpdu_cnt_tlv_v { +- u32 list_mpdu_cnt_hist[0]; +- /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ ++ /* HTT_TX_TQM_MAX_LIST_MPDU_CNT_HISTOGRAM_BINS */ ++ DECLARE_FLEX_ARRAY(u32, list_mpdu_cnt_hist); + }; + + struct htt_tx_tqm_pdev_stats_tlv_v { +@@ -1098,7 +1109,7 @@ struct htt_tx_de_compl_stats_tlv { + * ENTRIES_PER_BIN_COUNT) + */ + struct htt_tx_de_fw2wbm_ring_full_hist_tlv { +- u32 fw2wbm_ring_full_hist[0]; ++ DECLARE_FLEX_ARRAY(u32, fw2wbm_ring_full_hist); + }; + + struct htt_tx_de_cmn_stats_tlv { +@@ -1151,7 +1162,7 @@ struct htt_ring_if_cmn_tlv { + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_sfm_client_user_tlv_v { + /* Number of DWORDS used per user and per client */ +- u32 dwords_used_by_user_n[0]; ++ DECLARE_FLEX_ARRAY(u32, dwords_used_by_user_n); + }; + + struct htt_sfm_client_tlv { +@@ -1436,12 +1447,14 @@ struct htt_rx_soc_fw_stats_tlv { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_empty_tlv_v { +- u32 refill_ring_empty_cnt[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ ++ /* HTT_RX_STATS_REFILL_MAX_RING */ ++ DECLARE_FLEX_ARRAY(u32, refill_ring_empty_cnt); + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_num_refill_tlv_v { +- u32 refill_ring_num_refill[0]; /* HTT_RX_STATS_REFILL_MAX_RING */ ++ /* HTT_RX_STATS_REFILL_MAX_RING */ ++ DECLARE_FLEX_ARRAY(u32, refill_ring_num_refill); + }; + + /* RXDMA error code from WBM released packets */ +@@ -1473,7 +1486,7 @@ enum htt_rx_rxdma_error_code_enum { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_num_rxdma_err_tlv_v { +- u32 rxdma_err[0]; /* HTT_RX_RXDMA_MAX_ERR_CODE */ ++ DECLARE_FLEX_ARRAY(u32, rxdma_err); /* HTT_RX_RXDMA_MAX_ERR_CODE */ + }; + + /* REO error code from WBM released packets */ +@@ -1505,7 +1518,7 @@ enum htt_rx_reo_error_code_enum { + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_soc_fw_refill_ring_num_reo_err_tlv_v { +- u32 reo_err[0]; /* HTT_RX_REO_MAX_ERR_CODE */ ++ DECLARE_FLEX_ARRAY(u32, reo_err); /* HTT_RX_REO_MAX_ERR_CODE */ + }; + + /* == RX PDEV STATS == */ +@@ -1622,13 +1635,13 @@ struct htt_rx_pdev_fw_stats_phy_err_tlv + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_pdev_fw_ring_mpdu_err_tlv_v { + /* Num error MPDU for each RxDMA error type */ +- u32 fw_ring_mpdu_err[0]; /* HTT_RX_STATS_RXDMA_MAX_ERR */ ++ DECLARE_FLEX_ARRAY(u32, fw_ring_mpdu_err); /* HTT_RX_STATS_RXDMA_MAX_ERR */ + }; + + /* NOTE: Variable length TLV, use length spec to infer array size */ + struct htt_rx_pdev_fw_mpdu_drop_tlv_v { + /* Num MPDU dropped */ +- u32 fw_mpdu_drop[0]; /* HTT_RX_STATS_FW_DROP_REASON_MAX */ ++ DECLARE_FLEX_ARRAY(u32, fw_mpdu_drop); /* HTT_RX_STATS_FW_DROP_REASON_MAX */ + }; + + #define HTT_PDEV_CCA_STATS_TX_FRAME_INFO_PRESENT (0x1) diff --git a/package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch b/package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch new file mode 100644 index 0000000000..eec11f50e3 --- /dev/null +++ b/package/kernel/mac80211/patches/ath11k/0047-wifi-ath11k-fix-deinitialization-of-firmware-resourc.patch @@ -0,0 +1,79 @@ +From 5a78ac33e3cb8822da64dd1af196e83664b332b0 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh <quic_adisi@quicinc.com> +Date: Thu, 9 Mar 2023 15:23:08 +0530 +Subject: [PATCH] wifi: ath11k: fix deinitialization of firmware resources + +Currently, in ath11k_ahb_fw_resources_init(), iommu domain +mapping is done only for the chipsets having fixed firmware +memory. Also, for such chipsets, mapping is done only if it +does not have TrustZone support. + +During deinitialization, only if TrustZone support is not there, +iommu is unmapped back. However, for non fixed firmware memory +chipsets, TrustZone support is not there and this makes the +condition check to true and it tries to unmap the memory which +was not mapped during initialization. + +This leads to the following trace - + +[ 83.198790] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000008 +[ 83.259537] Modules linked in: ath11k_ahb ath11k qmi_helpers +.. snip .. +[ 83.280286] pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) +[ 83.287228] pc : __iommu_unmap+0x30/0x140 +[ 83.293907] lr : iommu_unmap+0x5c/0xa4 +[ 83.298072] sp : ffff80000b3abad0 +.. snip .. +[ 83.369175] Call trace: +[ 83.376282] __iommu_unmap+0x30/0x140 +[ 83.378541] iommu_unmap+0x5c/0xa4 +[ 83.382360] ath11k_ahb_fw_resource_deinit.part.12+0x2c/0xac [ath11k_ahb] +[ 83.385666] ath11k_ahb_free_resources+0x140/0x17c [ath11k_ahb] +[ 83.392521] ath11k_ahb_shutdown+0x34/0x40 [ath11k_ahb] +[ 83.398248] platform_shutdown+0x20/0x2c +[ 83.403455] device_shutdown+0x16c/0x1c4 +[ 83.407621] kernel_restart_prepare+0x34/0x3c +[ 83.411529] kernel_restart+0x14/0x74 +[ 83.415781] __do_sys_reboot+0x1c4/0x22c +[ 83.419427] __arm64_sys_reboot+0x1c/0x24 +[ 83.423420] invoke_syscall+0x44/0xfc +[ 83.427326] el0_svc_common.constprop.3+0xac/0xe8 +[ 83.430974] do_el0_svc+0xa0/0xa8 +[ 83.435659] el0_svc+0x1c/0x44 +[ 83.438957] el0t_64_sync_handler+0x60/0x144 +[ 83.441910] el0t_64_sync+0x15c/0x160 +[ 83.446343] Code: aa0103f4 f9400001 f90027a1 d2800001 (f94006a0) +[ 83.449903] ---[ end trace 0000000000000000 ]--- + +This can be reproduced by probing an AHB chipset which is not +having a fixed memory region. During reboot (or rmmod) trace +can be seen. + +Fix this issue by adding a condition check on firmware fixed memory +hw_param as done in the counter initialization function. + +Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1 + +Fixes: f9eec4947add ("ath11k: Add support for targets without trustzone") +Signed-off-by: Aditya Kumar Singh <quic_adisi@quicinc.com> +Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> +Link: https://lore.kernel.org/r/20230309095308.24937-1-quic_adisi@quicinc.com +--- + drivers/net/wireless/ath/ath11k/ahb.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +--- a/drivers/net/wireless/ath/ath11k/ahb.c ++++ b/drivers/net/wireless/ath/ath11k/ahb.c +@@ -1078,6 +1078,12 @@ static int ath11k_ahb_fw_resource_deinit + struct iommu_domain *iommu; + size_t unmapped_size; + ++ /* Chipsets not requiring MSA would have not initialized ++ * MSA resources, return success in such cases. ++ */ ++ if (!ab->hw_params.fixed_fw_mem) ++ return 0; ++ + if (ab_ahb->fw.use_tz) + return 0; + |