ath10k: configure rxnss_override for QCA9984

QCA9984 hardware can do 4x4 at 80Mhz, but only 2x2 at 160Mhz.

First, report this to user-space by setting the max-tx-speed
and max-rx-speed vht capabilities.

Second, if the peer rx-speed is configured, and if we
are in 160 or 80+80 mode, and the peer rx-speed matches
the max speed for 2x2 or 1x1 at 160Mhz (long guard interval),
then use that info to set the peer_bw_rxnss_override appropriately.

Without this, a 9984 firmware will not use 2x2 ratesets when
transmitting to peer (it will be stuck at 1x1), because
the firmware would not have configured the rxnss_override.

Signed-off-by: Ben Greear <greearb@candelatech.com>
[sven.eckelmann@openmesh.com: rebase, cleanup, drop 160Mhz workaround cleanup]
Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
[kvalo@qca.qualcomm.com: use hw_params, rename the title]
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
This commit is contained in:
Ben Greear 2017-06-16 10:37:45 +03:00 committed by Kalle Valo
parent e509e59477
commit cc914a5500
5 changed files with 69 additions and 1 deletions

View File

@ -72,6 +72,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA9887_HW_1_0_VERSION,
@ -93,6 +95,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_2_1_VERSION,
@ -113,6 +117,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_2_1_VERSION,
@ -133,6 +139,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_3_0_VERSION,
@ -153,6 +161,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA6174_HW_3_2_VERSION,
@ -176,6 +186,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.target_cpu_freq = 176000000,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA99X0_HW_2_0_DEV_VERSION,
@ -202,6 +214,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 4,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA9984_HW_1_0_DEV_VERSION,
@ -229,6 +243,12 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 12,
/* Can do only 2x2 VHT160 or 80+80. 1560Mbps is 4x4 80Mhz
* or 2x2 160Mhz, long-guard-interval.
*/
.vht160_mcs_rx_highest = 1560,
.vht160_mcs_tx_highest = 1560,
},
{
.id = QCA9888_HW_2_0_DEV_VERSION,
@ -255,6 +275,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 12,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA9377_HW_1_0_DEV_VERSION,
@ -275,6 +297,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca988x_ops,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA9377_HW_1_1_DEV_VERSION,
@ -297,6 +321,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.target_cpu_freq = 176000000,
.decap_align_bytes = 4,
.spectral_bin_discard = 0,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
{
.id = QCA4019_HW_1_0_DEV_VERSION,
@ -324,6 +350,8 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
.hw_ops = &qca99x0_ops,
.decap_align_bytes = 1,
.spectral_bin_discard = 4,
.vht160_mcs_rx_highest = 0,
.vht160_mcs_tx_highest = 0,
},
};

View File

@ -535,6 +535,12 @@ struct ath10k_hw_params {
/* Number of bytes to be discarded for each FFT sample */
int spectral_bin_discard;
/* The board may have a restricted NSS for 160 or 80+80 vs what it
* can do for 80Mhz.
*/
int vht160_mcs_rx_highest;
int vht160_mcs_tx_highest;
};
struct htt_rx_desc;

View File

@ -2519,6 +2519,20 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
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);
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;
}
}
}
static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
@ -4362,6 +4376,7 @@ static int ath10k_mac_get_vht_cap_bf_sound_dim(struct ath10k *ar)
static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
{
struct ieee80211_sta_vht_cap vht_cap = {0};
struct ath10k_hw_params *hw = &ar->hw_params;
u16 mcs_map;
u32 val;
int i;
@ -4408,6 +4423,17 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
/* If we are supporting 160Mhz or 80+80, then the NIC may be able to do
* a restricted NSS for 160 or 80+80 vs what it can do for 80Mhz. Give
* user-space a clue if that is the case.
*/
if ((vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) &&
(hw->vht160_mcs_rx_highest != 0 ||
hw->vht160_mcs_tx_highest != 0)) {
vht_cap.vht_mcs.rx_highest = cpu_to_le16(hw->vht160_mcs_rx_highest);
vht_cap.vht_mcs.tx_highest = cpu_to_le16(hw->vht160_mcs_tx_highest);
}
return vht_cap;
}

View File

@ -6734,7 +6734,12 @@ 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);
cmd->peer_bw_rxnss_override = 0;
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;
}
static int

View File

@ -6028,6 +6028,8 @@ struct wmi_10_2_peer_assoc_complete_cmd {
__le32 info0; /* WMI_PEER_ASSOC_INFO0_ */
} __packed;
#define PEER_BW_RXNSS_OVERRIDE_OFFSET 31
struct wmi_10_4_peer_assoc_complete_cmd {
struct wmi_10_2_peer_assoc_complete_cmd cmd;
__le32 peer_bw_rxnss_override;
@ -6051,6 +6053,7 @@ struct wmi_peer_assoc_complete_arg {
u32 peer_vht_caps;
enum wmi_phy_mode peer_phymode;
struct wmi_vht_rate_set_arg peer_vht_rates;
u32 peer_bw_rxnss_override;
};
struct wmi_peer_add_wds_entry_cmd {