--- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5999,9 +5999,94 @@ ath11k_mac_get_single_legacy_rate(struct return 0; } -static int ath11k_mac_set_fixed_rate_params(struct ath11k_vif *arvif, - u32 rate, u8 nss, u8 sgi, u8 ldpc, - u8 he_gi, u8 he_ltf) +static int +ath11k_mac_set_fixed_rate_GI_LTF(struct ath11k_vif *arvif, u8 he_gi, u8 he_ltf) +{ + struct ath11k *ar = arvif->ar; + int ret; + + /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */ + if (he_gi && he_gi != 0xFF) + he_gi += 1; + + ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + WMI_VDEV_PARAM_SGI, he_gi); + if (ret) { + ath11k_warn(ar->ab, "failed to set HE GI:%d, error:%d\n", + he_gi, ret); + return ret; + } + /* start from 1 */ + if (he_ltf != 0xFF) + he_ltf += 1; + + ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + WMI_VDEV_PARAM_HE_LTF, he_ltf); + if (ret) { + ath11k_warn(ar->ab, "failed to set HE LTF:%d, error:%d\n", + he_ltf, ret); + return ret; + } + return 0; +} + +static int +ath11k_mac_set_auto_rate_GI_LTF(struct ath11k_vif *arvif, u16 he_gi, u8 he_ltf) +{ + struct ath11k *ar = arvif->ar; + int ret; + u32 he_ar_gi_ltf = 0; + + if (he_gi != 0xFF) { + switch (he_gi) { + case NL80211_RATE_INFO_HE_GI_0_8: + he_gi = WMI_AUTORATE_800NS_GI; + break; + case NL80211_RATE_INFO_HE_GI_1_6: + he_gi = WMI_AUTORATE_1600NS_GI; + break; + case NL80211_RATE_INFO_HE_GI_3_2: + he_gi = WMI_AUTORATE_3200NS_GI; + break; + default: + ath11k_warn(ar->ab, "Invalid GI\n"); + return 1; + } + } + + if (he_ltf != 0xFF) { + switch (he_ltf) { + case NL80211_RATE_INFO_HE_1XLTF: + he_ltf = WMI_HE_AUTORATE_LTF_1X; + break; + case NL80211_RATE_INFO_HE_2XLTF: + he_ltf = WMI_HE_AUTORATE_LTF_2X; + break; + case NL80211_RATE_INFO_HE_4XLTF: + he_ltf = WMI_HE_AUTORATE_LTF_4X; + break; + default: + ath11k_warn(ar->ab, "Invalid LTF\n"); + return 1; + } + } + + he_ar_gi_ltf = he_gi | he_ltf; + ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, + WMI_VDEV_PARAM_AUTORATE_MISC_CFG, + he_ar_gi_ltf); + if (ret) { + ath11k_warn(ar->ab, + "failed to set HE autorate GI:%u, LTF:%u params, error:%d\n", + he_gi, he_ltf, ret); + return ret; + } + return 0; +} + +static int ath11k_mac_set_rate_params(struct ath11k_vif *arvif, + u32 rate, u8 nss, u8 sgi, u8 ldpc, + u8 he_gi, u8 he_ltf, bool he_fixed_rate) { struct ath11k *ar = arvif->ar; u32 vdev_param; @@ -6009,8 +6094,13 @@ static int ath11k_mac_set_fixed_rate_par lockdep_assert_held(&ar->conf_mutex); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac set fixed rate params vdev %i rate 0x%02hhx nss %hhu sgi %hhu\n", - arvif->vdev_id, rate, nss, sgi); + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "mac set rate params vdev %i, rate:0x%02x, nss:0x%02x, sgi:0x%02x, ldpc:0x%02x\n", + arvif->vdev_id, rate, nss, sgi, ldpc); + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, + "he_gi:0x%02x, he_ltf:0x%02x, he_fixed_rate:%d\n", he_gi, + he_ltf, he_fixed_rate); if (!arvif->vif->bss_conf.he_support) { vdev_param = WMI_VDEV_PARAM_FIXED_RATE; @@ -6033,39 +6123,23 @@ static int ath11k_mac_set_fixed_rate_par vdev_param = WMI_VDEV_PARAM_LDPC; ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, - vdev_param, ldpc); + vdev_param, ldpc); if (ret) { ath11k_warn(ar->ab, "failed to set ldpc param %d: %d\n", - ldpc, ret); + ldpc, ret); return ret; } if (arvif->vif->bss_conf.he_support) { - if (he_gi != 0xFF) { - vdev_param = WMI_VDEV_PARAM_SGI; - /* 0.8 = 0, 1.6 = 2 and 3.2 = 3. */ - if (he_gi) - he_gi += 1; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, - vdev_param, he_gi); - if (ret) { - ath11k_warn(ar->ab, "failed to set hegi param %d: %d\n", - sgi, ret); - return ret; - } - } - if (he_ltf != 0xFF) { - vdev_param = WMI_VDEV_PARAM_HE_LTF; - /* start from 1 */ - he_ltf += 1; - ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, - vdev_param, he_ltf); - if (ret) { - ath11k_warn(ar->ab, "failed to set heltf param %d: %d\n", - he_ltf, ret); - return ret; - } + if (he_fixed_rate) { + ret = ath11k_mac_set_fixed_rate_GI_LTF(arvif, he_gi, + he_ltf); + } else { + ret = ath11k_mac_set_auto_rate_GI_LTF(arvif, he_gi, + he_ltf); } + if (ret) + return ret; } else { vdev_param = WMI_VDEV_PARAM_SGI; ret = ath11k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id, @@ -6228,6 +6302,7 @@ ath11k_mac_op_set_bitrate_mask(struct ie int single_nss; int ret; int num_rates; + bool he_fixed_rate = false; if (ath11k_mac_vif_chan(vif, &def)) return -EPERM; @@ -6268,6 +6343,12 @@ ath11k_mac_op_set_bitrate_mask(struct ie &single_nss)) { rate = WMI_FIXED_RATE_NONE; nss = single_nss; + mutex_lock(&ar->conf_mutex); + arvif->bitrate_mask = *mask; + ieee80211_iterate_stations_atomic(ar->hw, + ath11k_mac_set_bitrate_mask_iter, + arvif); + mutex_unlock(&ar->conf_mutex); } else { rate = WMI_FIXED_RATE_NONE; @@ -6315,6 +6396,8 @@ ath11k_mac_op_set_bitrate_mask(struct ie num_rates = ath11k_mac_bitrate_mask_num_he_rates(ar, band, mask); + if (num_rates == 1) + he_fixed_rate = true; if (!ath11k_mac_he_mcs_range_present(ar, band, mask) && num_rates > 1) { @@ -6324,6 +6407,9 @@ ath11k_mac_op_set_bitrate_mask(struct ie } mutex_lock(&ar->conf_mutex); + ieee80211_iterate_stations_atomic(ar->hw, + ath11k_mac_disable_peer_fixed_rate, + arvif); arvif->bitrate_mask = *mask; ieee80211_iterate_stations_atomic(ar->hw, @@ -6335,10 +6421,10 @@ ath11k_mac_op_set_bitrate_mask(struct ie mutex_lock(&ar->conf_mutex); - ret = ath11k_mac_set_fixed_rate_params(arvif, rate, nss, sgi, ldpc, - he_gi, he_ltf); + ret = ath11k_mac_set_rate_params(arvif, rate, nss, sgi, ldpc, he_gi, + he_ltf, he_fixed_rate); if (ret) { - ath11k_warn(ar->ab, "failed to set fixed rate params on vdev %i: %d\n", + ath11k_warn(ar->ab, "failed to set rate params on vdev %i: %d\n", arvif->vdev_id, ret); } --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -110,6 +110,23 @@ enum { }; #define WMI_BA_MODE_BUFFER_SIZE_256 3 + +/* Parameters used for WMI_VDEV_PARAM_AUTORATE_MISC_CFG command. + * Used only for HE auto rate mode. + */ +enum { +/* HE LTF related configuration */ + WMI_HE_AUTORATE_LTF_1X = (1 << 0), + WMI_HE_AUTORATE_LTF_2X = (1 << 1), + WMI_HE_AUTORATE_LTF_4X = (1 << 2), + +/* HE GI related configuration */ + WMI_AUTORATE_400NS_GI = (1 << 8), + WMI_AUTORATE_800NS_GI = (1 << 9), + WMI_AUTORATE_1600NS_GI = (1 << 10), + WMI_AUTORATE_3200NS_GI = (1 << 11), +}; + /* * wmi command groups. */ @@ -1018,6 +1035,7 @@ enum wmi_tlv_vdev_param { WMI_VDEV_PARAM_FILS_MAX_CHANNEL_GUARD_TIME, WMI_VDEV_PARAM_HE_LTF = 0x74, WMI_VDEV_PARAM_BA_MODE = 0x7e, + WMI_VDEV_PARAM_AUTORATE_MISC_CFG = 0x80, WMI_VDEV_PARAM_SET_HE_SOUNDING_MODE = 0x87, WMI_VDEV_PARAM_PROTOTYPE = 0x8000, WMI_VDEV_PARAM_BSS_COLOR,