Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc1efd73 authored by Sebastian Gottschall's avatar Sebastian Gottschall Committed by Kalle Valo
Browse files

ath10k: add VHT160 support



This patch adds full VHT160 support for QCA9984 chipsets Tested on Netgear
R7800. 80+80 is possible, but disabled so far since it seems to contain
glitches like missing vht station flags (this may be firmware or mac80211
related).

Signed-off-by: default avatarSebastian Gottschall <s.gottschall@dd-wrt.com>
[kvalo@qca.qualcomm.com: refactoring and fix few warnings]
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 06efdbe7
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -702,6 +702,10 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
		/* 80MHZ */
		case 2:
			status->vht_flag |= RX_VHT_FLAG_80MHZ;
			break;
		case 3:
			status->vht_flag |= RX_VHT_FLAG_160MHZ;
			break;
		}

		status->flag |= RX_FLAG_VHT;
@@ -926,7 +930,7 @@ static void ath10k_process_rx(struct ath10k *ar,
	*status = *rx_status;

	ath10k_dbg(ar, ATH10K_DBG_DATA,
		   "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
		   "rx skb %pK len %u peer %pM %s %s sn %u %s%s%s%s%s%s %srate_idx %u vht_nss %u freq %u band %u flag 0x%llx fcs-err %i mic-err %i amsdu-more %i\n",
		   skb,
		   skb->len,
		   ieee80211_get_SA(hdr),
@@ -940,6 +944,7 @@ static void ath10k_process_rx(struct ath10k *ar,
		   status->flag & RX_FLAG_VHT ? "vht" : "",
		   status->flag & RX_FLAG_40MHZ ? "40" : "",
		   status->vht_flag & RX_VHT_FLAG_80MHZ ? "80" : "",
		   status->vht_flag & RX_VHT_FLAG_160MHZ ? "160" : "",
		   status->flag & RX_FLAG_SHORT_GI ? "sgi " : "",
		   status->rate_idx,
		   status->vht_nss,
+33 −2
Original line number Diff line number Diff line
@@ -569,10 +569,14 @@ chan_to_phymode(const struct cfg80211_chan_def *chandef)
		case NL80211_CHAN_WIDTH_80:
			phymode = MODE_11AC_VHT80;
			break;
		case NL80211_CHAN_WIDTH_160:
			phymode = MODE_11AC_VHT160;
			break;
		case NL80211_CHAN_WIDTH_80P80:
			phymode = MODE_11AC_VHT80_80;
			break;
		case NL80211_CHAN_WIDTH_5:
		case NL80211_CHAN_WIDTH_10:
		case NL80211_CHAN_WIDTH_80P80:
		case NL80211_CHAN_WIDTH_160:
			phymode = MODE_UNKNOWN;
			break;
		}
@@ -971,6 +975,7 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id)
	arg.vdev_id = vdev_id;
	arg.channel.freq = channel->center_freq;
	arg.channel.band_center_freq1 = chandef->center_freq1;
	arg.channel.band_center_freq2 = chandef->center_freq2;

	/* TODO setup this dynamically, what in case we
	   don't have any vifs? */
@@ -1417,6 +1422,7 @@ static int ath10k_vdev_start_restart(struct ath10k_vif *arvif,

	arg.channel.freq = chandef->chan->center_freq;
	arg.channel.band_center_freq1 = chandef->center_freq1;
	arg.channel.band_center_freq2 = chandef->center_freq2;
	arg.channel.mode = chan_to_phymode(chandef);

	arg.channel.min_power = 0;
@@ -2480,6 +2486,9 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
		arg->peer_flags |= ar->wmi.peer_flags->bw80;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
		arg->peer_flags |= ar->wmi.peer_flags->bw160;

	arg->peer_vht_rates.rx_max_rate =
		__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
	arg->peer_vht_rates.rx_mcs_set =
@@ -2536,6 +2545,18 @@ static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
						    struct ieee80211_sta *sta)
{
	if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
		switch (sta->vht_cap.cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
			return MODE_11AC_VHT160;
		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ:
			return MODE_11AC_VHT80_80;
		default:
			/* not sure if this is a valid case? */
			return MODE_11AC_VHT160;
		}
	}

	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
		return MODE_11AC_VHT80;

@@ -4321,6 +4342,13 @@ 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_160_80PLUS80MHZ))
		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)))
@@ -6979,6 +7007,9 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
			bw = WMI_PEER_CHWIDTH_80MHZ;
			break;
		case IEEE80211_STA_RX_BW_160:
			bw = WMI_PEER_CHWIDTH_160MHZ;
			break;
		default:
			ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
				    sta->bandwidth, sta->addr);
			bw = WMI_PEER_CHWIDTH_20MHZ;
+1 −0
Original line number Diff line number Diff line
@@ -3637,6 +3637,7 @@ static const struct wmi_peer_flags_map wmi_tlv_peer_flags_map = {
	.vht = WMI_TLV_PEER_VHT,
	.bw80 = WMI_TLV_PEER_80MHZ,
	.pmf = WMI_TLV_PEER_PMF,
	.bw160 = WMI_TLV_PEER_160MHZ,
};

/************/
+1 −0
Original line number Diff line number Diff line
@@ -543,6 +543,7 @@ enum wmi_tlv_peer_flags {
	WMI_TLV_PEER_VHT = 0x02000000,
	WMI_TLV_PEER_80MHZ = 0x04000000,
	WMI_TLV_PEER_PMF = 0x08000000,
	WMI_TLV_PEER_160MHZ = 0x20000000,
};

enum wmi_tlv_tag {
+8 −1
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@
#include "wmi-ops.h"
#include "p2p.h"
#include "hw.h"
#include "hif.h"

#define ATH10K_WMI_BARRIER_ECHO_ID 0xBA991E9
#define ATH10K_WMI_BARRIER_TIMEOUT_HZ (3 * HZ)
@@ -1574,6 +1575,7 @@ static const struct wmi_peer_flags_map wmi_peer_flags_map = {
	.bw80 = WMI_PEER_80MHZ,
	.vht_2g = WMI_PEER_VHT_2G,
	.pmf = WMI_PEER_PMF,
	.bw160 = WMI_PEER_160MHZ,
};

static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
@@ -1591,6 +1593,7 @@ static const struct wmi_peer_flags_map wmi_10x_peer_flags_map = {
	.spatial_mux = WMI_10X_PEER_SPATIAL_MUX,
	.vht = WMI_10X_PEER_VHT,
	.bw80 = WMI_10X_PEER_80MHZ,
	.bw160 = WMI_10X_PEER_160MHZ,
};

static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
@@ -1610,6 +1613,7 @@ static const struct wmi_peer_flags_map wmi_10_2_peer_flags_map = {
	.bw80 = WMI_10_2_PEER_80MHZ,
	.vht_2g = WMI_10_2_PEER_VHT_2G,
	.pmf = WMI_10_2_PEER_PMF,
	.bw160 = WMI_10_2_PEER_160MHZ,
};

void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
@@ -1634,6 +1638,9 @@ void ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,

	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;
	ch->min_power = arg->min_power;
	ch->max_power = arg->max_power;
Loading