Commit 335a9276 authored by Aloka Dixit's avatar Aloka Dixit Committed by Kalle Valo
Browse files

wifi: ath11k: MBSSID beacon support



- Split ath11k_mac_setup_bcn_tmpl() to move the beacon retrieval and
  WMI command to a new function, ath11k_mac_setup_bcn_tmpl_legacy().
  In the original function add checks to use the transmitting interface
  when MBSSID is enabled.
- Set rsnie_present and wpaie_present fields for the non-transmitting
  interfaces when MBSSID is enabled.

Tested-on: IPQ8074 hw2.0 AHB WLAN.HK.2.7.0.1-01744-QCAHKSWPL_SILICONZ-1

Signed-off-by: default avatarAloka Dixit <quic_alokad@quicinc.com>
Co-developed-by: default avatarJohn Crispin <john@phrozen.org>
Signed-off-by: default avatarJohn Crispin <john@phrozen.org>
Signed-off-by: default avatarKalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/20230405221648.17950-7-quic_alokad@quicinc.com
parent cb9bea77
Loading
Loading
Loading
Loading
+111 −5
Original line number Diff line number Diff line
@@ -1351,6 +1351,84 @@ static int ath11k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
	return ret;
}

static void ath11k_mac_setup_nontx_vif_rsnie(struct ath11k_vif *arvif,
					     bool tx_arvif_rsnie_present,
					     const u8 *profile, u8 profile_len)
{
	if (cfg80211_find_ie(WLAN_EID_RSN, profile, profile_len)) {
		arvif->rsnie_present = true;
	} else if (tx_arvif_rsnie_present) {
		int i;
		u8 nie_len;
		const u8 *nie = cfg80211_find_ext_ie(WLAN_EID_EXT_NON_INHERITANCE,
						     profile, profile_len);
		if (!nie)
			return;

		nie_len = nie[1];
		nie += 2;
		for (i = 0; i < nie_len; i++) {
			if (nie[i] == WLAN_EID_RSN) {
				arvif->rsnie_present = false;
				break;
			}
		}
	}
}

static bool ath11k_mac_set_nontx_vif_params(struct ath11k_vif *tx_arvif,
					    struct ath11k_vif *arvif,
					    struct sk_buff *bcn)
{
	struct ieee80211_mgmt *mgmt;
	const u8 *ies, *profile, *next_profile;
	int ies_len;

	ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
	mgmt = (struct ieee80211_mgmt *)bcn->data;
	ies += sizeof(mgmt->u.beacon);
	ies_len = skb_tail_pointer(bcn) - ies;

	ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, ies, ies_len);
	arvif->rsnie_present = tx_arvif->rsnie_present;

	while (ies) {
		u8 mbssid_len;

		ies_len -= (2 + ies[1]);
		mbssid_len = ies[1] - 1;
		profile = &ies[3];

		while (mbssid_len) {
			u8 profile_len;

			profile_len = profile[1];
			next_profile = profile + (2 + profile_len);
			mbssid_len -= (2 + profile_len);

			profile += 2;
			profile_len -= (2 + profile[1]);
			profile += (2 + profile[1]); /* nontx capabilities */
			profile_len -= (2 + profile[1]);
			profile += (2 + profile[1]); /* SSID */
			if (profile[2] == arvif->vif->bss_conf.bssid_index) {
				profile_len -= 5;
				profile = profile + 5;
				ath11k_mac_setup_nontx_vif_rsnie(arvif,
								 tx_arvif->rsnie_present,
								 profile,
								 profile_len);
				return true;
			}
			profile = next_profile;
		}
		ies = cfg80211_find_ie(WLAN_EID_MULTIPLE_BSSID, profile,
				       ies_len);
	}

	return false;
}

static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
				      struct sk_buff *bcn)
{
@@ -1374,18 +1452,26 @@ static void ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
		arvif->wpaie_present = false;
}

static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif)
{
	struct ath11k *ar = arvif->ar;
	struct ath11k_base *ab = ar->ab;
	struct ath11k_vif *tx_arvif = arvif;
	struct ieee80211_hw *hw = ar->hw;
	struct ieee80211_vif *vif = arvif->vif;
	struct ieee80211_mutable_offsets offs = {};
	struct sk_buff *bcn;
	int ret;

	if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
		return 0;
	if (arvif->vif->mbssid_tx_vif) {
		tx_arvif = (void *)arvif->vif->mbssid_tx_vif->drv_priv;
		if (tx_arvif != arvif) {
			ar = tx_arvif->ar;
			ab = ar->ab;
			hw = ar->hw;
			vif = tx_arvif->vif;
		}
	}

	bcn = ieee80211_beacon_get_template(hw, vif, &offs, 0);
	if (!bcn) {
@@ -1393,9 +1479,12 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
		return -EPERM;
	}

	ath11k_mac_set_vif_params(arvif, bcn);
	ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
	if (tx_arvif == arvif)
		ath11k_mac_set_vif_params(tx_arvif, bcn);
	else if (!ath11k_mac_set_nontx_vif_params(tx_arvif, arvif, bcn))
		return -EINVAL;

	ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
	kfree_skb(bcn);

	if (ret)
@@ -1405,6 +1494,23 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
	return ret;
}

static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
{
	struct ieee80211_vif *vif = arvif->vif;

	if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
		return 0;

	/* Target does not expect beacon templates for the already up
	 * non-transmitting interfaces, and results in a crash if sent.
	 */
	if (vif->mbssid_tx_vif &&
	    arvif != (void *)vif->mbssid_tx_vif->drv_priv && arvif->is_up)
		return 0;

	return ath11k_mac_setup_bcn_tmpl_mbssid(arvif);
}

void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
{
	struct ieee80211_vif *vif = arvif->vif;
+1 −0
Original line number Diff line number Diff line
@@ -1737,6 +1737,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
	}

	cmd->buf_len = bcn->len;
	cmd->mbssid_ie_offset = offs->mbssid_off;

	ptr = skb->data + sizeof(*cmd);