Commit 046d2e7c authored by Sriram R's avatar Sriram R Committed by Johannes Berg
Browse files

mac80211: prepare sta handling for MLO support



Currently in mac80211 each STA object is represented
using sta_info datastructure with the associated
STA specific information and drivers access ieee80211_sta
part of it.

With MLO (Multi Link Operation) support being added
in 802.11be standard, though the association is logically
with a single Multi Link capable STA, at the physical level
communication can happen via different advertised
links (uniquely identified by Channel, operating class,
BSSID) and hence the need to handle multiple link
STA parameters within a composite sta_info object
called the MLD STA. The different link STA part of
MLD STA are identified using the link address which can
be same or different as the MLD STA address and unique
link id based on the link vif.

To support extension of such a model, the sta_info
datastructure is modified to hold multiple link STA
objects with link specific params currently within
sta_info moved to this new structure. Similarly this is
done for ieee80211_sta as well which will be accessed
within mac80211 as well as by drivers, hence trivial
driver changes are expected to support this.

For current non MLO supported drivers, only one link STA
is present and link information is accessed via 'deflink'
member.

For MLO drivers, we still need to define the APIs etc. to
get the correct link ID and access the correct part of
the station info.

Currently in mac80211, all link STA info are accessed directly
via deflink. These will be updated to access via link pointers
indexed by link id with MLO support patches, with link id
being 0 for non MLO supported cases.

Except for couple of macro related changes, below spatch takes
care of updating mac80211 and driver code to access to the
link STA info via deflink.

  @ieee80211_sta@
  struct ieee80211_sta *s;
  struct sta_info *si;
  identifier var = {supp_rates, ht_cap, vht_cap, he_cap, he_6ghz_capa, eht_cap, rx_nss, bandwidth, txpwr};
  @@

  (
    s->
  -    var
  +    deflink.var
  |
   si->sta.
  -    var
  +    deflink.var
  )

  @sta_info@
  struct sta_info *si;
  identifier var = {gtk, pcpu_rx_stats, rx_stats, rx_stats_avg, status_stats, tx_stats, cur_max_bandwidth};
  @@

  (
    si->
  -    var
  +    deflink.var
  )

Signed-off-by: default avatarSriram R <quic_srirrama@quicinc.com>
Link: https://lore.kernel.org/r/1649086883-13246-1-git-send-email-quic_srirrama@quicinc.com


[remove MLO-drivers notes from commit message, not clear yet; run spatch]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 5c6dd7bd
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1160,7 +1160,7 @@ static int ar5523_get_wlan_mode(struct ar5523 *ar,
		ar5523_info(ar, "STA not found!\n");
		return WLAN_MODE_11b;
	}
	sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
	sta_rate_set = sta->deflink.supp_rates[ar->hw->conf.chandef.chan->band];

	for (bit = 0; bit < band->n_bitrates; bit++) {
		if (sta_rate_set & 1) {
@@ -1198,7 +1198,7 @@ static void ar5523_create_rateset(struct ar5523 *ar,
		ar5523_info(ar, "STA not found. Cannot set rates\n");
		sta_rate_set = bss_conf->basic_rates;
	} else
		sta_rate_set = sta->supp_rates[ar->hw->conf.chandef.chan->band];
		sta_rate_set = sta->deflink.supp_rates[ar->hw->conf.chandef.chan->band];

	ar5523_dbg(ar, "sta rate_set = %08x\n", sta_rate_set);

+39 −37
Original line number Diff line number Diff line
@@ -2251,7 +2251,7 @@ static void ath10k_peer_assoc_h_rates(struct ath10k *ar,

	band = def.chan->band;
	sband = ar->hw->wiphy->bands[band];
	ratemask = sta->supp_rates[band];
	ratemask = sta->deflink.supp_rates[band];
	ratemask &= arvif->bitrate_mask.control[band].legacy;
	rates = sband->bitrates;

@@ -2296,7 +2296,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
				   struct ieee80211_sta *sta,
				   struct wmi_peer_assoc_complete_arg *arg)
{
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	struct ath10k_vif *arvif = (void *)vif->drv_priv;
	struct cfg80211_chan_def def;
	enum nl80211_band band;
@@ -2335,7 +2335,7 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
	if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
		arg->peer_flags |= ar->wmi.peer_flags->ldbc;

	if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
	if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
		arg->peer_flags |= ar->wmi.peer_flags->bw40;
		arg->peer_rate_caps |= WMI_RC_CW40_FLAG;
	}
@@ -2388,7 +2388,8 @@ static void ath10k_peer_assoc_h_ht(struct ath10k *ar,
			arg->peer_ht_rates.rates[i] = i;
	} else {
		arg->peer_ht_rates.num_rates = n;
		arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss);
		arg->peer_num_spatial_streams = min(sta->deflink.rx_nss,
						    max_nss);
	}

	ath10k_dbg(ar, ATH10K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
@@ -2545,7 +2546,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
				    struct ieee80211_sta *sta,
				    struct wmi_peer_assoc_complete_arg *arg)
{
	const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
	const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
	struct ath10k_vif *arvif = (void *)vif->drv_priv;
	struct ath10k_hw_params *hw = &ar->hw_params;
	struct cfg80211_chan_def def;
@@ -2587,10 +2588,10 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
				 (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
					ampdu_factor)) - 1);

	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
		arg->peer_flags |= ar->wmi.peer_flags->bw80;

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

	/* Calculate peer NSS capability from VHT capabilities if STA
@@ -2604,7 +2605,7 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar,
		    vht_mcs_mask[i])
			max_nss = i + 1;
	}
	arg->peer_num_spatial_streams = min(sta->rx_nss, max_nss);
	arg->peer_num_spatial_streams = min(sta->deflink.rx_nss, max_nss);
	arg->peer_vht_rates.rx_max_rate =
		__le16_to_cpu(vht_cap->vht_mcs.rx_highest);
	arg->peer_vht_rates.rx_mcs_set =
@@ -2684,15 +2685,15 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar,

static bool ath10k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
{
	return sta->supp_rates[NL80211_BAND_2GHZ] >>
	return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
	       ATH10K_MAC_FIRST_OFDM_RATE_IDX;
}

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) {
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
		switch (sta->deflink.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:
@@ -2703,13 +2704,13 @@ static enum wmi_phy_mode ath10k_mac_get_phymode_vht(struct ath10k *ar,
		}
	}

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

	if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
		return MODE_11AC_VHT40;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
		return MODE_11AC_VHT20;

	return MODE_UNKNOWN;
@@ -2736,15 +2737,15 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,

	switch (band) {
	case NL80211_BAND_2GHZ:
		if (sta->vht_cap.vht_supported &&
		if (sta->deflink.vht_cap.vht_supported &&
		    !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
				phymode = MODE_11AC_VHT40;
			else
				phymode = MODE_11AC_VHT20;
		} else if (sta->ht_cap.ht_supported &&
		} else if (sta->deflink.ht_cap.ht_supported &&
			   !ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
				phymode = MODE_11NG_HT40;
			else
				phymode = MODE_11NG_HT20;
@@ -2759,12 +2760,12 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
		/*
		 * Check VHT first.
		 */
		if (sta->vht_cap.vht_supported &&
		if (sta->deflink.vht_cap.vht_supported &&
		    !ath10k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
			phymode = ath10k_mac_get_phymode_vht(ar, sta);
		} else if (sta->ht_cap.ht_supported &&
		} else if (sta->deflink.ht_cap.ht_supported &&
			   !ath10k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
			if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
			if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
				phymode = MODE_11NA_HT40;
			else
				phymode = MODE_11NA_HT20;
@@ -3079,8 +3080,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw,
	/* ap_sta must be accessed only within rcu section which must be left
	 * before calling ath10k_setup_peer_smps() which might sleep.
	 */
	ht_cap = ap_sta->ht_cap;
	vht_cap = ap_sta->vht_cap;
	ht_cap = ap_sta->deflink.ht_cap;
	vht_cap = ap_sta->deflink.vht_cap;

	ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
	if (ret) {
@@ -3278,7 +3279,7 @@ static int ath10k_station_assoc(struct ath10k *ar,
	 */
	if (!reassoc) {
		ret = ath10k_setup_peer_smps(ar, arvif, sta->addr,
					     &sta->ht_cap);
					     &sta->deflink.ht_cap);
		if (ret) {
			ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
				    arvif->vdev_id, ret);
@@ -6787,10 +6788,10 @@ static int ath10k_sta_set_txpwr(struct ieee80211_hw *hw,
	int ret = 0;
	s16 txpwr;

	if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
	if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
		txpwr = 0;
	} else {
		txpwr = sta->txpwr.power;
		txpwr = sta->deflink.txpwr.power;
		if (!txpwr)
			return -EINVAL;
	}
@@ -6910,26 +6911,26 @@ static int ath10k_mac_validate_rate_mask(struct ath10k *ar,
					 struct ieee80211_sta *sta,
					 u32 rate_ctrl_flag, u8 nss)
{
	if (nss > sta->rx_nss) {
	if (nss > sta->deflink.rx_nss) {
		ath10k_warn(ar, "Invalid nss field, configured %u limit %u\n",
			    nss, sta->rx_nss);
			    nss, sta->deflink.rx_nss);
		return -EINVAL;
	}

	if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_VHT) {
		if (!sta->vht_cap.vht_supported) {
		if (!sta->deflink.vht_cap.vht_supported) {
			ath10k_warn(ar, "Invalid VHT rate for sta %pM\n",
				    sta->addr);
			return -EINVAL;
		}
	} else if (ATH10K_HW_PREAMBLE(rate_ctrl_flag) == WMI_RATE_PREAMBLE_HT) {
		if (!sta->ht_cap.ht_supported || sta->vht_cap.vht_supported) {
		if (!sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported) {
			ath10k_warn(ar, "Invalid HT rate for sta %pM\n",
				    sta->addr);
			return -EINVAL;
		}
	} else {
		if (sta->ht_cap.ht_supported || sta->vht_cap.vht_supported)
		if (sta->deflink.ht_cap.ht_supported || sta->deflink.vht_cap.vht_supported)
			return -EINVAL;
	}

@@ -8272,7 +8273,7 @@ static bool ath10k_mac_set_vht_bitrate_mask_fixup(struct ath10k *ar,
	u8 rate = arvif->vht_pfr;

	/* skip non vht and multiple rate peers */
	if (!sta->vht_cap.vht_supported || arvif->vht_num_rates != 1)
	if (!sta->deflink.vht_cap.vht_supported || arvif->vht_num_rates != 1)
		return false;

	err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
@@ -8313,7 +8314,7 @@ static void ath10k_mac_clr_bitrate_mask_iter(void *data,
	int err;

	/* clear vht peers only */
	if (arsta->arvif != arvif || !sta->vht_cap.vht_supported)
	if (arsta->arvif != arvif || !sta->deflink.vht_cap.vht_supported)
		return;

	err = ath10k_wmi_peer_set_param(ar, arvif->vdev_id, sta->addr,
@@ -8457,13 +8458,14 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,

	ath10k_dbg(ar, ATH10K_DBG_STA,
		   "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
		   sta->addr, changed, sta->bandwidth, sta->rx_nss,
		   sta->addr, changed, sta->deflink.bandwidth,
		   sta->deflink.rx_nss,
		   sta->smps_mode);

	if (changed & IEEE80211_RC_BW_CHANGED) {
		bw = WMI_PEER_CHWIDTH_20MHZ;

		switch (sta->bandwidth) {
		switch (sta->deflink.bandwidth) {
		case IEEE80211_STA_RX_BW_20:
			bw = WMI_PEER_CHWIDTH_20MHZ;
			break;
@@ -8478,7 +8480,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
			break;
		default:
			ath10k_warn(ar, "Invalid bandwidth %d in rc update for %pM\n",
				    sta->bandwidth, sta->addr);
				    sta->deflink.bandwidth, sta->addr);
			bw = WMI_PEER_CHWIDTH_20MHZ;
			break;
		}
@@ -8487,7 +8489,7 @@ static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
	}

	if (changed & IEEE80211_RC_NSS_CHANGED)
		arsta->nss = sta->rx_nss;
		arsta->nss = sta->deflink.rx_nss;

	if (changed & IEEE80211_RC_SMPS_CHANGED) {
		smps = WMI_PEER_SMPS_PS_NONE;
+78 −76
Original line number Diff line number Diff line
@@ -1636,7 +1636,7 @@ static void ath11k_peer_assoc_h_rates(struct ath11k *ar,

	band = def.chan->band;
	sband = ar->hw->wiphy->bands[band];
	ratemask = sta->supp_rates[band];
	ratemask = sta->deflink.supp_rates[band];
	ratemask &= arvif->bitrate_mask.control[band].legacy;
	rates = sband->bitrates;

@@ -1681,7 +1681,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
				   struct ieee80211_sta *sta,
				   struct peer_assoc_params *arg)
{
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	struct ath11k_vif *arvif = (void *)vif->drv_priv;
	struct cfg80211_chan_def def;
	enum nl80211_band band;
@@ -1718,7 +1718,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
	if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
		arg->ldpc_flag = true;

	if (sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
	if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
		arg->bw_40 = true;
		arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
	}
@@ -1776,7 +1776,7 @@ static void ath11k_peer_assoc_h_ht(struct ath11k *ar,
			arg->peer_ht_rates.rates[i] = i;
	} else {
		arg->peer_ht_rates.num_rates = n;
		arg->peer_nss = min(sta->rx_nss, max_nss);
		arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
	}

	ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
@@ -1878,7 +1878,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
				    struct ieee80211_sta *sta,
				    struct peer_assoc_params *arg)
{
	const struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
	const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
	struct ath11k_vif *arvif = (void *)vif->drv_priv;
	struct cfg80211_chan_def def;
	enum nl80211_band band;
@@ -1924,17 +1924,17 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
				 (1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
					ampdu_factor)) - 1);

	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
		arg->bw_80 = true;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
		arg->bw_160 = true;

	vht_nss =  ath11k_mac_max_vht_nss(vht_mcs_mask);

	if (vht_nss > sta->rx_nss) {
	if (vht_nss > sta->deflink.rx_nss) {
		user_rate_valid = false;
		for (nss_idx = sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
		for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
			if (vht_mcs_mask[nss_idx]) {
				user_rate_valid = true;
				break;
@@ -1944,8 +1944,8 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,

	if (!user_rate_valid) {
		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting vht range mcs value to peer supported nss %d for peer %pM\n",
			   sta->rx_nss, sta->addr);
		vht_mcs_mask[sta->rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
			   sta->deflink.rx_nss, sta->addr);
		vht_mcs_mask[sta->deflink.rx_nss - 1] = vht_mcs_mask[vht_nss - 1];
	}

	/* Calculate peer NSS capability from VHT capabilities if STA
@@ -1959,7 +1959,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
		    vht_mcs_mask[i])
			max_nss = i + 1;
	}
	arg->peer_nss = min(sta->rx_nss, max_nss);
	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
	arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
	arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
	arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
@@ -2078,7 +2078,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
{
	struct ath11k_vif *arvif = (void *)vif->drv_priv;
	struct cfg80211_chan_def def;
	const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
	enum nl80211_band band;
	u16 *he_mcs_mask;
	u8 max_nss, he_mcs;
@@ -2135,7 +2135,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
	else
		max_nss = rx_mcs_80;

	arg->peer_nss = min(sta->rx_nss, max_nss);
	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);

	memcpy_and_pad(&arg->peer_he_cap_macinfo,
		       sizeof(arg->peer_he_cap_macinfo),
@@ -2167,10 +2167,10 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
				   IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);

	if (ampdu_factor) {
		if (sta->vht_cap.vht_supported)
		if (sta->deflink.vht_cap.vht_supported)
			arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
						    ampdu_factor)) - 1;
		else if (sta->ht_cap.ht_supported)
		else if (sta->deflink.ht_cap.ht_supported)
			arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
						    ampdu_factor)) - 1;
	}
@@ -2213,9 +2213,9 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,

	he_nss =  ath11k_mac_max_he_nss(he_mcs_mask);

	if (he_nss > sta->rx_nss) {
	if (he_nss > sta->deflink.rx_nss) {
		user_rate_valid = false;
		for (nss_idx = sta->rx_nss - 1; nss_idx >= 0; nss_idx--) {
		for (nss_idx = sta->deflink.rx_nss - 1; nss_idx >= 0; nss_idx--) {
			if (he_mcs_mask[nss_idx]) {
				user_rate_valid = true;
				break;
@@ -2225,11 +2225,11 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,

	if (!user_rate_valid) {
		ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac setting he range mcs value to peer supported nss %d for peer %pM\n",
			   sta->rx_nss, sta->addr);
		he_mcs_mask[sta->rx_nss - 1] = he_mcs_mask[he_nss - 1];
			   sta->deflink.rx_nss, sta->addr);
		he_mcs_mask[sta->deflink.rx_nss - 1] = he_mcs_mask[he_nss - 1];
	}

	switch (sta->bandwidth) {
	switch (sta->deflink.bandwidth) {
	case IEEE80211_STA_RX_BW_160:
		if (he_cap->he_cap_elem.phy_cap_info[0] &
		    IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
@@ -2283,7 +2283,7 @@ static void ath11k_peer_assoc_h_he(struct ath11k *ar,
		    he_mcs_mask[i])
			max_nss = i + 1;
	}
	arg->peer_nss = min(sta->rx_nss, max_nss);
	arg->peer_nss = min(sta->deflink.rx_nss, max_nss);

	if (arg->peer_phymode == MODE_11AX_HE160 ||
	    arg->peer_phymode == MODE_11AX_HE80_80) {
@@ -2316,7 +2316,7 @@ static void ath11k_peer_assoc_h_he_6ghz(struct ath11k *ar,
					struct ieee80211_sta *sta,
					struct peer_assoc_params *arg)
{
	const struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
	const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
	struct cfg80211_chan_def def;
	enum nl80211_band band;
	u8  ampdu_factor;
@@ -2326,19 +2326,19 @@ static void ath11k_peer_assoc_h_he_6ghz(struct ath11k *ar,

	band = def.chan->band;

	if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->he_6ghz_capa.capa)
	if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->deflink.he_6ghz_capa.capa)
		return;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
		arg->bw_40 = true;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
		arg->bw_80 = true;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_160)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
		arg->bw_160 = true;

	arg->peer_he_caps_6ghz = le16_to_cpu(sta->he_6ghz_capa.capa);
	arg->peer_he_caps_6ghz = le16_to_cpu(sta->deflink.he_6ghz_capa.capa);
	arg->peer_mpdu_density =
		ath11k_parse_mpdudensity(FIELD_GET(IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START,
						   arg->peer_he_caps_6ghz));
@@ -2364,17 +2364,17 @@ static void ath11k_peer_assoc_h_he_6ghz(struct ath11k *ar,
static void ath11k_peer_assoc_h_smps(struct ieee80211_sta *sta,
				     struct peer_assoc_params *arg)
{
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
	const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
	int smps;

	if (!ht_cap->ht_supported && !sta->he_6ghz_capa.capa)
	if (!ht_cap->ht_supported && !sta->deflink.he_6ghz_capa.capa)
		return;

	if (ht_cap->ht_supported) {
		smps = ht_cap->cap & IEEE80211_HT_CAP_SM_PS;
		smps >>= IEEE80211_HT_CAP_SM_PS_SHIFT;
	} else {
		smps = le16_get_bits(sta->he_6ghz_capa.capa,
		smps = le16_get_bits(sta->deflink.he_6ghz_capa.capa,
				     IEEE80211_HE_6GHZ_CAP_SM_PS);
	}

@@ -2498,15 +2498,15 @@ static int ath11k_peer_assoc_qos_ap(struct ath11k *ar,

static bool ath11k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
{
	return sta->supp_rates[NL80211_BAND_2GHZ] >>
	return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
	       ATH11K_MAC_FIRST_OFDM_RATE_IDX;
}

static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
						    struct ieee80211_sta *sta)
{
	if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
		switch (sta->vht_cap.cap &
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
		switch (sta->deflink.vht_cap.cap &
			IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
		case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
			return MODE_11AC_VHT160;
@@ -2518,13 +2518,13 @@ static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
		}
	}

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

	if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
		return MODE_11AC_VHT40;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
		return MODE_11AC_VHT20;

	return MODE_UNKNOWN;
@@ -2533,24 +2533,24 @@ static enum wmi_phy_mode ath11k_mac_get_phymode_vht(struct ath11k *ar,
static enum wmi_phy_mode ath11k_mac_get_phymode_he(struct ath11k *ar,
						   struct ieee80211_sta *sta)
{
	if (sta->bandwidth == IEEE80211_STA_RX_BW_160) {
		if (sta->he_cap.he_cap_elem.phy_cap_info[0] &
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
		if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
		     IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
			return MODE_11AX_HE160;
		else if (sta->he_cap.he_cap_elem.phy_cap_info[0] &
		else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
			 IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
			return MODE_11AX_HE80_80;
		/* not sure if this is a valid case? */
		return MODE_11AX_HE160;
	}

	if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
		return MODE_11AX_HE80;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
		return MODE_11AX_HE40;

	if (sta->bandwidth == IEEE80211_STA_RX_BW_20)
	if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
		return MODE_11AX_HE20;

	return MODE_UNKNOWN;
@@ -2579,23 +2579,23 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,

	switch (band) {
	case NL80211_BAND_2GHZ:
		if (sta->he_cap.has_he &&
		if (sta->deflink.he_cap.has_he &&
		    !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) {
			if (sta->bandwidth == IEEE80211_STA_RX_BW_80)
			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
				phymode = MODE_11AX_HE80_2G;
			else if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
			else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
				phymode = MODE_11AX_HE40_2G;
			else
				phymode = MODE_11AX_HE20_2G;
		} else if (sta->vht_cap.vht_supported &&
		} else if (sta->deflink.vht_cap.vht_supported &&
			   !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
				phymode = MODE_11AC_VHT40;
			else
				phymode = MODE_11AC_VHT20;
		} else if (sta->ht_cap.ht_supported &&
		} else if (sta->deflink.ht_cap.ht_supported &&
			   !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
			if (sta->bandwidth == IEEE80211_STA_RX_BW_40)
			if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
				phymode = MODE_11NG_HT40;
			else
				phymode = MODE_11NG_HT20;
@@ -2608,15 +2608,15 @@ static void ath11k_peer_assoc_h_phymode(struct ath11k *ar,
	case NL80211_BAND_5GHZ:
	case NL80211_BAND_6GHZ:
		/* Check HE first */
		if (sta->he_cap.has_he &&
		if (sta->deflink.he_cap.has_he &&
		    !ath11k_peer_assoc_h_he_masked(he_mcs_mask)) {
			phymode = ath11k_mac_get_phymode_he(ar, sta);
		} else if (sta->vht_cap.vht_supported &&
		} else if (sta->deflink.vht_cap.vht_supported &&
			   !ath11k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
			phymode = ath11k_mac_get_phymode_vht(ar, sta);
		} else if (sta->ht_cap.ht_supported &&
		} else if (sta->deflink.ht_cap.ht_supported &&
			   !ath11k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
			if (sta->bandwidth >= IEEE80211_STA_RX_BW_40)
			if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
				phymode = MODE_11NA_HT40;
			else
				phymode = MODE_11NA_HT20;
@@ -2739,8 +2739,8 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
	}

	ret = ath11k_setup_peer_smps(ar, arvif, bss_conf->bssid,
				     &ap_sta->ht_cap,
				     le16_to_cpu(ap_sta->he_6ghz_capa.capa));
				     &ap_sta->deflink.ht_cap,
				     le16_to_cpu(ap_sta->deflink.he_6ghz_capa.capa));
	if (ret) {
		ath11k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
			    arvif->vdev_id, ret);
@@ -4001,7 +4001,7 @@ ath11k_mac_set_peer_vht_fixed_rate(struct ath11k_vif *arvif,
	}

	/* Avoid updating invalid nss as fixed rate*/
	if (nss > sta->rx_nss)
	if (nss > sta->deflink.rx_nss)
		return -EINVAL;

	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
@@ -4051,7 +4051,7 @@ ath11k_mac_set_peer_he_fixed_rate(struct ath11k_vif *arvif,
	}

	/* Avoid updating invalid nss as fixed rate */
	if (nss > sta->rx_nss)
	if (nss > sta->deflink.rx_nss)
		return -EINVAL;

	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
@@ -4118,12 +4118,12 @@ static int ath11k_station_assoc(struct ath11k *ar,
	 * fixed param.
	 * Note that all other rates and NSS will be disabled for this peer.
	 */
	if (sta->vht_cap.vht_supported && num_vht_rates == 1) {
	if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
		ret = ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
							 band);
		if (ret)
			return ret;
	} else if (sta->he_cap.has_he && num_he_rates == 1) {
	} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
		ret = ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
							band);
		if (ret)
@@ -4137,7 +4137,8 @@ static int ath11k_station_assoc(struct ath11k *ar,
		return 0;

	ret = ath11k_setup_peer_smps(ar, arvif, sta->addr,
				     &sta->ht_cap, le16_to_cpu(sta->he_6ghz_capa.capa));
				     &sta->deflink.ht_cap,
				     le16_to_cpu(sta->deflink.he_6ghz_capa.capa));
	if (ret) {
		ath11k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
			    arvif->vdev_id, ret);
@@ -4299,10 +4300,10 @@ static void ath11k_sta_rc_update_wk(struct work_struct *wk)
		 * TODO: Check RATEMASK_CMDID to support auto rates selection
		 * across HT/VHT and for multiple VHT MCS support.
		 */
		if (sta->vht_cap.vht_supported && num_vht_rates == 1) {
		if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
			ath11k_mac_set_peer_vht_fixed_rate(arvif, sta, mask,
							   band);
		} else if (sta->he_cap.has_he && num_he_rates == 1) {
		} else if (sta->deflink.he_cap.has_he && num_he_rates == 1) {
			ath11k_mac_set_peer_he_fixed_rate(arvif, sta, mask,
							  band);
		} else {
@@ -4624,10 +4625,10 @@ static int ath11k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
	int ret = 0;
	s16 txpwr;

	if (sta->txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
	if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
		txpwr = 0;
	} else {
		txpwr = sta->txpwr.power;
		txpwr = sta->deflink.txpwr.power;
		if (!txpwr)
			return -EINVAL;
	}
@@ -4688,7 +4689,8 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,

	ath11k_dbg(ar->ab, ATH11K_DBG_MAC,
		   "mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
		   sta->addr, changed, sta->bandwidth, sta->rx_nss,
		   sta->addr, changed, sta->deflink.bandwidth,
		   sta->deflink.rx_nss,
		   sta->smps_mode);

	spin_lock_bh(&ar->data_lock);
@@ -4696,7 +4698,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
	if (changed & IEEE80211_RC_BW_CHANGED) {
		bw = WMI_PEER_CHWIDTH_20MHZ;

		switch (sta->bandwidth) {
		switch (sta->deflink.bandwidth) {
		case IEEE80211_STA_RX_BW_20:
			bw = WMI_PEER_CHWIDTH_20MHZ;
			break;
@@ -4711,7 +4713,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
			break;
		default:
			ath11k_warn(ar->ab, "Invalid bandwidth %d in rc update for %pM\n",
				    sta->bandwidth, sta->addr);
				    sta->deflink.bandwidth, sta->addr);
			bw = WMI_PEER_CHWIDTH_20MHZ;
			break;
		}
@@ -4720,7 +4722,7 @@ static void ath11k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
	}

	if (changed & IEEE80211_RC_NSS_CHANGED)
		arsta->nss = sta->rx_nss;
		arsta->nss = sta->deflink.rx_nss;

	if (changed & IEEE80211_RC_SMPS_CHANGED) {
		smps = WMI_PEER_SMPS_PS_NONE;
@@ -7755,13 +7757,13 @@ ath11k_mac_validate_vht_he_fixed_rate_settings(struct ath11k *ar, enum nl80211_b
	spin_lock_bh(&ar->ab->base_lock);
	list_for_each_entry_safe(peer, tmp, &ar->ab->peers, list) {
		if (peer->sta) {
			if (vht_fixed_rate && (!peer->sta->vht_cap.vht_supported ||
					       peer->sta->rx_nss < vht_nss)) {
			if (vht_fixed_rate && (!peer->sta->deflink.vht_cap.vht_supported ||
					       peer->sta->deflink.rx_nss < vht_nss)) {
				ret = false;
				goto out;
			}
			if (he_fixed_rate && (!peer->sta->he_cap.has_he ||
					      peer->sta->rx_nss < he_nss)) {
			if (he_fixed_rate && (!peer->sta->deflink.he_cap.has_he ||
					      peer->sta->deflink.rx_nss < he_nss)) {
				ret = false;
				goto out;
			}
+2 −2
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
	if (buf == NULL)
		return -ENOMEM;

	if (!an->sta->ht_cap.ht_supported) {
	if (!an->sta->deflink.ht_cap.ht_supported) {
		len = scnprintf(buf, size, "%s\n",
				"HT not supported");
		goto exit;
@@ -186,7 +186,7 @@ static ssize_t read_file_node_recv(struct file *file, char __user *user_buf,
	band = ah->curchan->chan->band;
	rstats = &an->rx_rate_stats;

	if (!sta->ht_cap.ht_supported)
	if (!sta->deflink.ht_cap.ht_supported)
		goto legacy;

	len += scnprintf(buf + len, size - len,
+10 −10

File changed.

Preview size limit exceeded, changes collapsed.

Loading