ath10k: enable VHT160 and VHT80+80 modes
Set right channel frequencies in VHT160 mode according to the VHT160 interoperability workaround added as part of IEEE Std 802.11™-2016 in "Table 9-252—VHT Operation Information subfields", band_center_freq2 corresponds to CCFS1 in Table 9-253. Previous implementation (band_center_freq2 = 0 for VHT160) is only deprecated. Enable VHT80+80 mode and set the proper peer RX nss value for VHT160 and VHT80+80 mode. Based on patches by Sebastian Gottschall: https://lkml.kernel.org/r/20180704095444.662-1-s.gottschall@dd-wrt.com https://lkml.kernel.org/r/20180704120519.6479-1-s.gottschall@dd-wrt.com Tested: qca9984 with firmware ver 10.4-3.10-00047 Co-developed-by: Sebastian Gottschall <s.gottschall@dd-wrt.com> Signed-off-by: Sebastian Gottschall <s.gottschall@dd-wrt.com> Co-developed-by: Rick Wu <rwu@codeaurora.org> Signed-off-by: Rick Wu <rwu@codeaurora.org> Signed-off-by: Lei Wang <leiwa@codeaurora.org> Signed-off-by: Sowmiya Sree Elavalagan <ssreeela@codeaurora.org> Signed-off-by: Kalle Valo <kvalo@codeaurora.org> Link: https://lore.kernel.org/r/1585574792-719-1-git-send-email-ssreeela@codeaurora.org
This commit is contained in:
parent
800113ff4b
commit
3db24065c2
@ -2505,6 +2505,30 @@ ath10k_peer_assoc_h_vht_limit(u16 tx_mcs_set,
|
||||
return tx_mcs_set;
|
||||
}
|
||||
|
||||
static u32 get_160mhz_nss_from_maxrate(int rate)
|
||||
{
|
||||
u32 nss;
|
||||
|
||||
switch (rate) {
|
||||
case 780:
|
||||
nss = 1;
|
||||
break;
|
||||
case 1560:
|
||||
nss = 2;
|
||||
break;
|
||||
case 2106:
|
||||
nss = 3; /* not support MCS9 from spec*/
|
||||
break;
|
||||
case 3120:
|
||||
nss = 4;
|
||||
break;
|
||||
default:
|
||||
nss = 1;
|
||||
}
|
||||
|
||||
return nss;
|
||||
}
|
||||
|
||||
static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
||||
struct ieee80211_vif *vif,
|
||||
struct ieee80211_sta *sta,
|
||||
@ -2512,6 +2536,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
||||
{
|
||||
const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
|
||||
struct ath10k_vif *arvif = (void *)vif->drv_priv;
|
||||
struct ath10k_hw_params *hw = &ar->hw_params;
|
||||
struct cfg80211_chan_def def;
|
||||
enum nl80211_band band;
|
||||
const u16 *vht_mcs_mask;
|
||||
@ -2578,22 +2603,38 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
|
||||
arg->peer_vht_rates.tx_mcs_set = ath10k_peer_assoc_h_vht_limit(
|
||||
__le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
|
||||
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
|
||||
sta->addr, arg->peer_max_mpdu, arg->peer_flags);
|
||||
/* Configure bandwidth-NSS mapping to FW
|
||||
* for the chip's tx chains setting on 160Mhz bw
|
||||
*/
|
||||
if (arg->peer_phymode == MODE_11AC_VHT160 ||
|
||||
arg->peer_phymode == MODE_11AC_VHT80_80) {
|
||||
u32 rx_nss;
|
||||
u32 max_rate;
|
||||
|
||||
if (arg->peer_vht_rates.rx_max_rate &&
|
||||
(sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK)) {
|
||||
switch (arg->peer_vht_rates.rx_max_rate) {
|
||||
case 1560:
|
||||
/* Must be 2x2 at 160Mhz is all it can do. */
|
||||
arg->peer_bw_rxnss_override = 2;
|
||||
break;
|
||||
case 780:
|
||||
/* Can only do 1x1 at 160Mhz (Long Guard Interval) */
|
||||
arg->peer_bw_rxnss_override = 1;
|
||||
break;
|
||||
max_rate = arg->peer_vht_rates.rx_max_rate;
|
||||
rx_nss = get_160mhz_nss_from_maxrate(max_rate);
|
||||
|
||||
if (rx_nss == 0)
|
||||
rx_nss = arg->peer_num_spatial_streams;
|
||||
else
|
||||
rx_nss = min(arg->peer_num_spatial_streams, rx_nss);
|
||||
|
||||
max_rate = hw->vht160_mcs_tx_highest;
|
||||
rx_nss = min(rx_nss, get_160mhz_nss_from_maxrate(max_rate));
|
||||
|
||||
arg->peer_bw_rxnss_override =
|
||||
FIELD_PREP(WMI_PEER_NSS_MAP_ENABLE, 1) |
|
||||
FIELD_PREP(WMI_PEER_NSS_160MHZ_MASK, (rx_nss - 1));
|
||||
|
||||
if (arg->peer_phymode == MODE_11AC_VHT80_80) {
|
||||
arg->peer_bw_rxnss_override |=
|
||||
FIELD_PREP(WMI_PEER_NSS_80_80MHZ_MASK, (rx_nss - 1));
|
||||
}
|
||||
}
|
||||
ath10k_dbg(ar, ATH10K_DBG_MAC,
|
||||
"mac vht peer %pM max_mpdu %d flags 0x%x peer_rx_nss_override 0x%x\n",
|
||||
sta->addr, arg->peer_max_mpdu,
|
||||
arg->peer_flags, arg->peer_bw_rxnss_override);
|
||||
}
|
||||
|
||||
static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
|
||||
@ -2745,9 +2786,9 @@ static int ath10k_peer_assoc_prepare(struct ath10k *ar,
|
||||
ath10k_peer_assoc_h_crypto(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_rates(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_ht(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_vht(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
|
||||
ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -4563,13 +4604,6 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
|
||||
vht_cap.cap |= val;
|
||||
}
|
||||
|
||||
/* Currently the firmware seems to be buggy, don't enable 80+80
|
||||
* mode until that's resolved.
|
||||
*/
|
||||
if ((ar->vht_cap_info & IEEE80211_VHT_CAP_SHORT_GI_160) &&
|
||||
(ar->vht_cap_info & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) == 0)
|
||||
vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
|
||||
|
||||
mcs_map = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((i < ar->num_rf_chains) && (ar->cfg_tx_chainmask & BIT(i)))
|
||||
@ -8625,7 +8659,9 @@ static const struct ieee80211_iface_combination ath10k_10_4_if_comb[] = {
|
||||
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
BIT(NL80211_CHAN_WIDTH_40) |
|
||||
BIT(NL80211_CHAN_WIDTH_80),
|
||||
BIT(NL80211_CHAN_WIDTH_80) |
|
||||
BIT(NL80211_CHAN_WIDTH_80P80) |
|
||||
BIT(NL80211_CHAN_WIDTH_160),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
@ -8643,7 +8679,9 @@ ieee80211_iface_combination ath10k_10_4_bcn_int_if_comb[] = {
|
||||
.radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
|
||||
BIT(NL80211_CHAN_WIDTH_20) |
|
||||
BIT(NL80211_CHAN_WIDTH_40) |
|
||||
BIT(NL80211_CHAN_WIDTH_80),
|
||||
BIT(NL80211_CHAN_WIDTH_80) |
|
||||
BIT(NL80211_CHAN_WIDTH_80P80) |
|
||||
BIT(NL80211_CHAN_WIDTH_160),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
|
@ -1714,12 +1714,23 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
|
||||
if (arg->chan_radar)
|
||||
flags |= WMI_CHAN_FLAG_DFS;
|
||||
|
||||
ch->band_center_freq2 = 0;
|
||||
ch->mhz = __cpu_to_le32(arg->freq);
|
||||
ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
|
||||
if (arg->mode == MODE_11AC_VHT80_80)
|
||||
ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq2);
|
||||
else
|
||||
ch->band_center_freq2 = 0;
|
||||
|
||||
if (arg->mode == MODE_11AC_VHT160) {
|
||||
if (arg->freq > arg->band_center_freq1)
|
||||
ch->band_center_freq1 =
|
||||
__cpu_to_le32(arg->band_center_freq1 + 40);
|
||||
else
|
||||
ch->band_center_freq1 =
|
||||
__cpu_to_le32(arg->band_center_freq1 - 40);
|
||||
|
||||
ch->band_center_freq2 = __cpu_to_le32(arg->band_center_freq1);
|
||||
}
|
||||
|
||||
ch->min_power = arg->min_power;
|
||||
ch->max_power = arg->max_power;
|
||||
ch->reg_power = arg->max_reg_power;
|
||||
@ -7628,12 +7639,8 @@ ath10k_wmi_peer_assoc_fill_10_4(struct ath10k *ar, void *buf,
|
||||
struct wmi_10_4_peer_assoc_complete_cmd *cmd = buf;
|
||||
|
||||
ath10k_wmi_peer_assoc_fill_10_2(ar, buf, arg);
|
||||
if (arg->peer_bw_rxnss_override)
|
||||
cmd->peer_bw_rxnss_override =
|
||||
__cpu_to_le32((arg->peer_bw_rxnss_override - 1) |
|
||||
BIT(PEER_BW_RXNSS_OVERRIDE_OFFSET));
|
||||
else
|
||||
cmd->peer_bw_rxnss_override = 0;
|
||||
cmd->peer_bw_rxnss_override =
|
||||
__cpu_to_le32(arg->peer_bw_rxnss_override);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -6508,7 +6508,10 @@ struct wmi_10_2_peer_assoc_complete_cmd {
|
||||
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
|
||||
} __packed;
|
||||
|
||||
#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
|
||||
/* NSS Mapping to FW */
|
||||
#define WMI_PEER_NSS_MAP_ENABLE BIT(31)
|
||||
#define WMI_PEER_NSS_160MHZ_MASK GENMASK(2, 0)
|
||||
#define WMI_PEER_NSS_80_80MHZ_MASK GENMASK(5, 3)
|
||||
|
||||
struct wmi_10_4_peer_assoc_complete_cmd {
|
||||
struct wmi_10_2_peer_assoc_complete_cmd cmd;
|
||||
|
Loading…
x
Reference in New Issue
Block a user