Commit cc914a55 authored by Ben Greear's avatar Ben Greear Committed by Kalle Valo
Browse files

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: default avatarBen Greear <greearb@candelatech.com>
[sven.eckelmann@openmesh.com: rebase, cleanup, drop 160Mhz workaround cleanup]
Signed-off-by: default avatarSven Eckelmann <sven.eckelmann@openmesh.com>
[kvalo@qca.qualcomm.com: use hw_params, rename the title]
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent e509e594
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -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,
	},
};

+6 −0
Original line number Diff line number Diff line
@@ -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;
+26 −0
Original line number Diff line number Diff line
@@ -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;
}

+6 −1
Original line number Diff line number Diff line
@@ -6734,6 +6734,11 @@ 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;
}

+3 −0
Original line number Diff line number Diff line
@@ -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 {