Skip to content

Commit

Permalink
ath10k: configure rxnss_override for QCA9984
Browse files Browse the repository at this point in the history
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 <[email protected]>
[[email protected]: rebase, cleanup, drop 160Mhz workaround cleanup]
Signed-off-by: Sven Eckelmann <[email protected]>
[[email protected]: use hw_params, rename the title]
Signed-off-by: Kalle Valo <[email protected]>
  • Loading branch information
greearb authored and kvalo committed Jun 21, 2017
1 parent e509e59 commit cc914a5
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 1 deletion.
28 changes: 28 additions & 0 deletions drivers/net/wireless/ath/ath10k/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -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,
},
};

Expand Down
6 changes: 6 additions & 0 deletions drivers/net/wireless/ath/ath10k/hw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
26 changes: 26 additions & 0 deletions drivers/net/wireless/ath/ath10k/mac.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
7 changes: 6 additions & 1 deletion drivers/net/wireless/ath/ath10k/wmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/wireless/ath/ath10k/wmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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 {
Expand Down

0 comments on commit cc914a5

Please sign in to comment.