2023-04-05 22:17:50

by Aloka Dixit

[permalink] [raw]
Subject: [PATCH v3 6/7] 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: Aloka Dixit <[email protected]>
Co-developed-by: John Crispin <[email protected]>
Signed-off-by: John Crispin <[email protected]>
---
v3: Squashed some hunks from patches 09/10 and 10/10 from v2 to create
this which logically adds support for MBSSID, beacon related
as well as vif parameters for non-transmitting profiles.
Renamed ath11k_mac_setup_bcn_tmpl_nontx_vif_rsnie() as
ath11k_mac_setup_nontx_vif_rsnie() as this function does
not set anything in the beacon template.
v2: Rebase only.

drivers/net/wireless/ath/ath11k/mac.c | 116 ++++++++++++++++++++++++--
drivers/net/wireless/ath/ath11k/wmi.c | 1 +
2 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index a10f4a6a1120..ee910fd756f2 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -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;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 039df4847108..16bc4d16c7d2 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1730,6 +1730,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);

--
2.39.0