123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300 |
- 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
|