wlan-ap-Telecominfraproject/feeds/wifi-ax/mac80211/patches/qca/205-0001-nl80211-add-basic-multiple-bssid-support.patch
John Crispin 528a778e38 open-converged-wireless: Import 21.02 based uCentral tree
Signed-off-by: John Crispin <john@phrozen.org>
2021-03-25 12:19:47 +01:00

1275 lines
43 KiB
Diff

From 75684a3621171f759a2ba0c44ae0f405178df56f Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Tue, 25 Aug 2020 00:10:23 -0700
Subject: [PATCH 1/9] nl80211: add basic multiple bssid support
This patch adds support for passing the multiple bssid config to the
kernel when adding an interface. If the BSS is non-transmitting it needs
to be indicated. A non-transmitting BSSID will have a parent interface,
which needs to be transmitting. The multiple bssid elements are passed
as an array.
Signed-off-by: John Crispin <john@phrozen.org>
---
include/net/cfg80211.h | 35 +++++++++++++++++++++++++++++++
include/uapi/linux/nl80211.h | 22 ++++++++++++++++++++
net/wireless/nl80211.c | 40 ++++++++++++++++++++++++++++++++++++
3 files changed, 97 insertions(+)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index b9f7a81293c1..f509b770175f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -455,6 +455,21 @@ struct ieee80211_supported_band {
const struct ieee80211_sband_iftype_data *iftype_data;
};
+/**
+ * struct ieee80211_multiple_bssid - AP settings for multi bssid
+ *
+ * @index: the index of this AP in the multi bssid group.
+ * @count: the total number of multi bssid peer APs.
+ * @parent: a non-transmitted bssid has a transmitted parent
+ * @non_transmitted: Is this a non-transmitted bssid
+ */
+struct ieee80211_multiple_bssid {
+ u8 index;
+ u8 count;
+ u32 parent;
+ bool non_transmitted;
+};
+
/**
* ieee80211_get_sband_iftype_data - return sband data for a given iftype
* @sband: the sband to search for the STA on
@@ -599,6 +614,7 @@ static inline void wiphy_read_of_freq_limits(struct wiphy *wiphy)
* belonging to that MU-MIMO groupID; %NULL if not changed
* @vht_mumimo_follow_addr: MU-MIMO follow address, used for monitoring
* MU-MIMO packets going to the specified station; %NULL if not changed
+ * @multiple_bssid: AP settings for multiple bssid
*/
struct vif_params {
u32 flags;
@@ -606,6 +622,7 @@ struct vif_params {
u8 macaddr[ETH_ALEN];
const u8 *vht_mumimo_groups;
const u8 *vht_mumimo_follow_addr;
+ struct ieee80211_multiple_bssid multiple_bssid;
};
/**
@@ -986,6 +1003,19 @@ struct cfg80211_crypto_settings {
u8 sae_pwd_len;
};
+/**
+ * struct cfg80211_multiple_bssid_data - multiple_bssid data
+ * @ies: array of extra information element(s) to add into Beacon frames for multiple
+ * bssid or %NULL
+ * @len: array of lengths of multiple_bssid.ies in octets
+ * @cnt: number of entries in multiple_bssid.ies
+ */
+struct cfg80211_multiple_bssid_data {
+ u8 *ies[NL80211_MULTIPLE_BSSID_IES_MAX];
+ size_t len[NL80211_MULTIPLE_BSSID_IES_MAX];
+ int cnt;
+};
+
/**
* struct cfg80211_beacon_data - beacon data
* @head: head portion of beacon (before TIM IE)
@@ -1012,6 +1042,7 @@ struct cfg80211_crypto_settings {
* Token (measurement type 11)
* @lci_len: LCI data length
* @civicloc_len: Civic location data length
+ * @multiple_bssid: multiple_bssid data
*/
struct cfg80211_beacon_data {
const u8 *head, *tail;
@@ -1030,6 +1061,8 @@ struct cfg80211_beacon_data {
size_t probe_resp_len;
size_t lci_len;
size_t civicloc_len;
+
+ struct cfg80211_multiple_bssid_data multiple_bssid;
};
struct mac_address {
@@ -1134,6 +1167,7 @@ enum cfg80211_ap_settings_flags {
* @he_oper: HE operation IE (or %NULL if HE isn't enabled)
* @fils_discovery: FILS discovery transmission parameters
* @unsol_bcast_probe_resp: Unsolicited broadcast probe response parameter
+ * @multiple_bssid: AP settings for multiple bssid
*/
struct cfg80211_ap_settings {
struct cfg80211_chan_def chandef;
@@ -1166,6 +1200,7 @@ struct cfg80211_ap_settings {
struct cfg80211_he_bss_color he_bss_color;
struct cfg80211_fils_discovery fils_discovery;
struct cfg80211_unsol_bcast_probe_resp unsol_bcast_probe_resp;
+ struct ieee80211_multiple_bssid multiple_bssid;
};
/**
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 30e2b3726a52..d09aab5377a1 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2522,6 +2522,20 @@ enum nl80211_commands {
* unsolicited broadcast probe response. It is a nested attribute, see
* &enum nl80211_unsol_bcast_probe_resp_attributes.
*
+ * @NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING: Set the Non-Transmitted flag for this
+ * BSSIDs beacon.
+ *
+ * @NL80211_ATTR_MULTIPLE_BSSID_PARENT: If this is a Non-Transmitted BSSID, define
+ * the parent (transmitting) interface.
+ *
+ * @NL80211_ATTR_MULTIPLE_BSSID_INDEX: The index of this BSS inside the multi bssid
+ * element.
+ *
+ * @NL80211_ATTR_MULTIPLE_BSSID_COUNT: The number of BSSs inside the multi bssid element.
+ *
+ * @NL80211_ATTR_MULTIPLE_BSSID_IES: The Elements that describe our multiple BSS group.
+ * these get passed separately as the kernel might need to split them up for EMA VAP.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3010,6 +3024,12 @@ enum nl80211_attrs {
NL80211_ATTR_UNSOL_BCAST_PROBE_RESP,
+ NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING,
+ NL80211_ATTR_MULTIPLE_BSSID_PARENT,
+ NL80211_ATTR_MULTIPLE_BSSID_INDEX,
+ NL80211_ATTR_MULTIPLE_BSSID_COUNT,
+ NL80211_ATTR_MULTIPLE_BSSID_IES,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -3071,6 +3091,8 @@ enum nl80211_attrs {
#define NL80211_CQM_TXE_MAX_INTVL 1800
+#define NL80211_MULTIPLE_BSSID_IES_MAX 8
+
/**
* enum nl80211_iftype - (virtual) interface types
*
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index d63aeb9dfe64..17e0d3ec622b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -758,6 +758,11 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
NLA_POLICY_NESTED(fils_discovery_policy),
[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
NLA_POLICY_NESTED(unsol_bcast_probe_resp_policy),
+ [NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING] = { .type = NLA_FLAG },
+ [NL80211_ATTR_MULTIPLE_BSSID_PARENT] = { .type = NLA_U32 },
+ [NL80211_ATTR_MULTIPLE_BSSID_INDEX] = { .type = NLA_U8 },
+ [NL80211_ATTR_MULTIPLE_BSSID_COUNT] = { .type = NLA_U8 },
+ [NL80211_ATTR_MULTIPLE_BSSID_IES] = { .type = NLA_NESTED },
};
/* policy for the key attributes */
@@ -3857,6 +3862,14 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
return err;
}
+ if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING])
+ params.multiple_bssid.non_transmitted =
+ nla_get_flag(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING]);
+
+ if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT])
+ params.multiple_bssid.parent =
+ nla_get_u8(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT]);
+
if (!cfg80211_iftype_allowed(&rdev->wiphy, type, params.use_4addr, 0))
return -EOPNOTSUPP;
@@ -4802,6 +4815,21 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
bcn->ftm_responder = -1;
}
+ if (attrs[NL80211_ATTR_MULTIPLE_BSSID_IES]) {
+ struct nlattr *nl_ie;
+ int rem_ie;
+
+ nla_for_each_nested(nl_ie, attrs[NL80211_ATTR_MULTIPLE_BSSID_IES], rem_ie) {
+ if (bcn->multiple_bssid.cnt > NL80211_MULTIPLE_BSSID_IES_MAX)
+ return -EINVAL;
+ if (nla_type(nl_ie) != bcn->multiple_bssid.cnt + 1)
+ return -EINVAL;
+ bcn->multiple_bssid.ies[bcn->multiple_bssid.cnt] = nla_data(nl_ie);
+ bcn->multiple_bssid.len[bcn->multiple_bssid.cnt] = nla_len(nl_ie);
+ bcn->multiple_bssid.cnt++;
+ }
+ }
+
return 0;
}
@@ -5237,6 +5265,18 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
return err;
}
+ if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_INDEX])
+ params.multiple_bssid.index = nla_get_u8(
+ info->attrs[NL80211_ATTR_MULTIPLE_BSSID_INDEX]);
+
+ if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_COUNT])
+ params.multiple_bssid.count = nla_get_u8(
+ info->attrs[NL80211_ATTR_MULTIPLE_BSSID_COUNT]);
+
+ if (params.multiple_bssid.non_transmitted &&
+ !info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT])
+ return -EOPNOTSUPP;
+
nl80211_calculate_ap_params(&params);
if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
--
2.25.0
From 91823121198609ce8d289a06893bc11d3f6733d2 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 26 Aug 2020 10:49:48 -0700
Subject: [PATCH 2/9] mac80211: add multiple bssid support to interface
handling
When bringing up multi bssid APs we need to track the parent-child relation
of non-transmitting and transmitting VAPs. This patch checks the above by
using a linked list to track the relations. The patch also ensures that
when a non-transmitting interface is closed the transmitting one is also
closed.
Fixed Null pointer dereference.
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Pradeep Kumar Chitrapu <pradeepc@codeaurora.org>
---
include/net/mac80211.h | 13 +++++++++-
net/mac80211/cfg.c | 54 ++++++++++++++++++++++++++++++++++++++++++
net/mac80211/debugfs.c | 1 +
net/mac80211/iface.c | 7 ++++++
4 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b2278cdb2c08..d5209130009c 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1682,6 +1682,9 @@ enum ieee80211_vif_flags {
* @txq: the multicast data TX queue (if driver uses the TXQ abstraction)
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
* protected by fq->lock.
+ * @multiple_bssid.parent: a non-transmitted bssid has a transmitted parent.
+ * @multiple_bssid.list: linked list for tracking parent - child relations.
+ * @multiple_bssid.non_transmitted: Is this a non-transmitted bssi
*/
struct ieee80211_vif {
enum nl80211_iftype type;
@@ -1709,6 +1712,11 @@ struct ieee80211_vif {
bool rx_mcast_action_reg;
bool txqs_stopped[IEEE80211_NUM_ACS];
+ struct {
+ struct ieee80211_vif *parent;
+ struct list_head list;
+ bool non_transmitted;
+ } multiple_bssid;
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
@@ -2367,7 +2375,7 @@ struct ieee80211_txq {
* @IEEE80211_HW_TX_STATUS_NO_AMPDU_LEN: Driver does not report accurate A-MPDU
* length in tx status information
*
- * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID
+ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID: Hardware supports multi BSSID in STA mode
*
* @IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID: Hardware supports multi BSSID
* only for HE APs. Applies if @IEEE80211_HW_SUPPORTS_MULTI_BSSID is set.
@@ -2378,6 +2386,8 @@ struct ieee80211_txq {
*
* @IEEE80211_HW_SUPPORTS_NSS_OFFLOAD: Hardware/driver supports NSS offload
*
+ * @IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP: Hardware supports multi BSSID in AP mode
+ *
* @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
*/
enum ieee80211_hw_flags {
@@ -2431,6 +2441,7 @@ enum ieee80211_hw_flags {
IEEE80211_HW_SUPPORTS_ONLY_HE_MULTI_BSSID,
IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
IEEE80211_HW_SUPPORTS_NSS_OFFLOAD,
+ IEEE80211_HW_SUPPORTS_MULTI_BSSID_AP,
/* keep last, obviously */
NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 4e8a8ac9c84b..62b53ee9c77a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -111,6 +111,36 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
return 0;
}
+static int ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sdata,
+ struct vif_params *params)
+{
+ struct ieee80211_local *local = sdata->local;
+ struct wiphy *wiphy = local->hw.wiphy;
+ struct net_device *parent;
+ struct ieee80211_sub_if_data *psdata;
+
+ if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP))
+ return 0;
+
+ if (params->multiple_bssid.non_transmitted) {
+ parent = __dev_get_by_index(wiphy_net(wiphy),
+ params->multiple_bssid.parent);
+ if (!parent || !parent->ieee80211_ptr)
+ return -EINVAL;
+ psdata = IEEE80211_WDEV_TO_SUB_IF(parent->ieee80211_ptr);
+ if (psdata->vif.multiple_bssid.non_transmitted)
+ return -EINVAL;
+ sdata->vif.multiple_bssid.parent = &psdata->vif;
+ list_add(&sdata->vif.multiple_bssid.list,
+ &psdata->vif.multiple_bssid.list);
+ sdata->vif.multiple_bssid.non_transmitted = true;
+ } else {
+ INIT_LIST_HEAD(&sdata->vif.multiple_bssid.list);
+ }
+
+ return 0;
+}
+
static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
const char *name,
unsigned char name_assign_type,
@@ -136,11 +166,35 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
}
}
+ if (type == NL80211_IFTYPE_AP) {
+ err = ieee80211_set_multiple_bssid_options(sdata, params);
+ if (err) {
+ ieee80211_if_remove(sdata);
+ return NULL;
+ }
+ }
+
return wdev;
}
static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
{
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_vif *child, *tmp;
+
+ sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ if (sdata && sdata->vif.type == NL80211_IFTYPE_AP) {
+ if (!sdata->vif.multiple_bssid.non_transmitted) {
+ if (!list_empty(&sdata->vif.multiple_bssid.list))
+ list_for_each_entry_safe(child, tmp,
+ &sdata->vif.multiple_bssid.list,
+ multiple_bssid.list)
+ dev_close(vif_to_sdata(child)->wdev.netdev);
+ } else {
+ list_del(&sdata->vif.multiple_bssid.list);
+ }
+ }
+
ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));
return 0;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 60274d0c83c1..0c8c785a8df9 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -409,6 +409,7 @@ static const char *hw_flag_names[] = {
FLAG(SUPPORTS_ONLY_HE_MULTI_BSSID),
FLAG(AMPDU_KEYBORDER_SUPPORT),
FLAG(SUPPORTS_NSS_OFFLOAD),
+ FLAG(SUPPORTS_MULTI_BSSID_AP),
#undef FLAG
};
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index c2a5779839ed..55c9395f4f92 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -810,6 +810,13 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
bool cancel_scan;
struct cfg80211_nan_func *func;
+ if (sdata->vif.type == NL80211_IFTYPE_AP &&
+ sdata->vif.multiple_bssid.non_transmitted)
+ /* make sure the parent is already down */
+ if (sdata->vif.multiple_bssid.parent &&
+ ieee80211_sdata_running(vif_to_sdata(sdata->vif.multiple_bssid.parent)))
+ dev_close(vif_to_sdata(sdata->vif.multiple_bssid.parent)->wdev.netdev);
+
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
--
2.25.0
From 83a12da29048b00c3160a12b1b73aadff43a6481 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 26 Aug 2020 10:54:07 -0700
Subject: [PATCH 3/9] mac80211: add multiple bssid support to beacon handling
With beacon_data now holding the additional information about the multiple
bssid elements, we need to honour these in the various beacon handling
code paths.
Signed-off-by: John Crispin <john@phrozen.org>
---
include/net/mac80211.h | 2 ++
net/mac80211/cfg.c | 59 ++++++++++++++++++++++++++++++++++++--
net/mac80211/ieee80211_i.h | 1 +
3 files changed, 59 insertions(+), 3 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index d5209130009c..765e9de4b575 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -642,6 +642,7 @@ struct ieee80211_fils_discovery {
* @fils_discovery: FILS discovery configuration
* @unsol_bcast_probe_resp_interval: Unsolicited broadcast probe response
* interval.
+ `* @multiple_bssid: the multiple bssid settings of the AP.
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -713,6 +714,7 @@ struct ieee80211_bss_conf {
bool nss_ap_isolate;
struct ieee80211_fils_discovery fils_discovery;
u32 unsol_bcast_probe_resp_interval;
+ struct ieee80211_multiple_bssid multiple_bssid;
};
/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 62b53ee9c77a..990787b90ba3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -987,12 +987,38 @@ static int ieee80211_set_ftm_responder_params(
return 0;
}
+static int ieee80211_get_multiple_bssid_beacon_len(struct cfg80211_multiple_bssid_data *data)
+{
+ int i, len = 0;
+
+ for (i = 0; i < data->cnt; i++)
+ len += data->len[i];
+
+ return len;
+}
+
+static u8 *ieee80211_copy_multiple_bssid_beacon(u8 *offset,
+ struct cfg80211_multiple_bssid_data *new,
+ struct cfg80211_multiple_bssid_data *old)
+{
+ int i;
+
+ *new = *old;
+ for (i = 0; i < new->cnt; i++) {
+ new->ies[i] = offset;
+ memcpy(new->ies[i], old->ies[i], new->len[i]);
+ offset += new->len[i];
+ }
+ return offset;
+}
+
static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
struct cfg80211_beacon_data *params,
const struct ieee80211_csa_settings *csa)
{
struct beacon_data *new, *old;
- int new_head_len, new_tail_len;
+ int new_head_len, new_tail_len, new_multiple_bssid_len;
+ u8 *new_multiple_bssid_offset;
int size, err;
u32 changed = BSS_CHANGED_BEACON;
@@ -1016,7 +1042,15 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
else
new_tail_len = old->tail_len;
- size = sizeof(*new) + new_head_len + new_tail_len;
+ /* new or old multiple_bssid? */
+ if (params->multiple_bssid.cnt || !old)
+ new_multiple_bssid_len =
+ ieee80211_get_multiple_bssid_beacon_len(&params->multiple_bssid);
+ else
+ new_multiple_bssid_len =
+ ieee80211_get_multiple_bssid_beacon_len(&old->multiple_bssid);
+
+ size = sizeof(*new) + new_head_len + new_tail_len + new_multiple_bssid_len;
new = kzalloc(size, GFP_KERNEL);
if (!new)
@@ -1033,6 +1067,18 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
new->head_len = new_head_len;
new->tail_len = new_tail_len;
+ new_multiple_bssid_offset = new->tail + new_tail_len;
+
+ /* copy in optional multiple_bssid_ies */
+ if (params->multiple_bssid.cnt)
+ ieee80211_copy_multiple_bssid_beacon(new_multiple_bssid_offset,
+ &new->multiple_bssid,
+ &params->multiple_bssid);
+ else if (old && old->multiple_bssid.cnt)
+ ieee80211_copy_multiple_bssid_beacon(new_multiple_bssid_offset,
+ &new->multiple_bssid,
+ &old->multiple_bssid);
+
if (csa) {
new->csa_current_counter = csa->count;
memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
@@ -1182,6 +1228,8 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
sizeof(struct ieee80211_he_obss_pd));
memcpy(&sdata->vif.bss_conf.he_bss_color, &params->he_bss_color,
sizeof(struct ieee80211_he_bss_color));
+ sdata->vif.bss_conf.multiple_bssid.count = params->multiple_bssid.count;
+ sdata->vif.bss_conf.multiple_bssid.index = params->multiple_bssid.index;
sdata->vif.bss_conf.ssid_len = params->ssid_len;
if (params->ssid_len)
@@ -3103,7 +3151,8 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
beacon->proberesp_ies_len + beacon->assocresp_ies_len +
- beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
+ beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len +
+ ieee80211_get_multiple_bssid_beacon_len(&beacon->multiple_bssid);
new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
if (!new_beacon)
@@ -3146,6 +3195,10 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
pos += beacon->probe_resp_len;
}
+ if (beacon->multiple_bssid.cnt)
+ pos = ieee80211_copy_multiple_bssid_beacon(pos,
+ &new_beacon->multiple_bssid,
+ &beacon->multiple_bssid);
/* might copy -1, meaning no changes requested */
new_beacon->ftm_responder = beacon->ftm_responder;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4ac2d24aaa75..5fa18a679114 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -262,6 +262,7 @@ struct beacon_data {
struct ieee80211_meshconf_ie *meshconf;
u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
u8 csa_current_counter;
+ struct cfg80211_multiple_bssid_data multiple_bssid;
struct rcu_head rcu_head;
};
--
2.25.0
From af57bc61b03173a359fae2a0cdc236008c626f0c Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 12 Aug 2020 14:58:08 +0200
Subject: [PATCH 4/9] mac80211: add multiple bssid/ema support to bcn
templating
Extend ieee80211_beacon_get_template() to allow generation of EMA beacons.
Drivers for hardware that does not support ema offloading can use this
function to update their becaons after they receive beacon completion
events from the hardware.
Signed-off-by: John Crispin <john@phrozen.org>
---
include/net/mac80211.h | 26 +++++++++++++++++++++
net/mac80211/ieee80211_i.h | 1 +
net/mac80211/tx.c | 48 ++++++++++++++++++++++++++++++++++----
3 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 765e9de4b575..5c8b73df2024 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4837,12 +4837,16 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
* @csa_counter_offs: array of IEEE80211_MAX_CSA_COUNTERS_NUM offsets
* to CSA counters. This array can contain zero values which
* should be ignored.
+ * @multiple_bssid_offset: position of the multiple bssid element
+ * @multiple_bssid_length: size of the multiple bssid element
*/
struct ieee80211_mutable_offsets {
u16 tim_offset;
u16 tim_length;
u16 csa_counter_offs[IEEE80211_MAX_CSA_COUNTERS_NUM];
+ u16 multiple_bssid_offset;
+ u16 multiple_bssid_length;
};
/**
@@ -4869,6 +4873,28 @@ ieee80211_beacon_get_template(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_mutable_offsets *offs);
+/**
+ * ieee80211_beacon_get_template - beacon template generation function
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will
+ * receive the offsets that may be updated by the driver.
+ *
+ * This function differs from ieee80211_beacon_get_template in the sense that
+ * it generates EMA VAP templates. When we use multiple_bssid, the beacons can
+ * get very large costing a lot of airtime. To work around this, we iterate
+ * over the multiple bssid elements and only send one inside the beacon for 1..n.
+ *
+ * This function needs to follow the same rules as ieee80211_beacon_get_template
+ *
+ * Return: The beacon template. %NULL on error.
+ */
+
+struct sk_buff *
+ieee80211_beacon_get_template_ema(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_mutable_offsets *offs);
+
/**
* ieee80211_beacon_get_tim - beacon generation function
* @hw: pointer obtained from ieee80211_alloc_hw().
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 5fa18a679114..db369c994d78 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -263,6 +263,7 @@ struct beacon_data {
u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM];
u8 csa_current_counter;
struct cfg80211_multiple_bssid_data multiple_bssid;
+ u16 ema_index;
struct rcu_head rcu_head;
};
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index dfcedf178884..abb9b052e53e 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4740,11 +4740,26 @@ static int ieee80211_beacon_protect(struct sk_buff *skb,
return 0;
}
+static void
+ieee80211_beacon_add_multiple_bssid_config(struct ieee80211_vif *vif, struct sk_buff *skb,
+ struct cfg80211_multiple_bssid_data *config)
+{
+ u8 *pos = skb_put(skb, 6);
+
+ *pos++ = WLAN_EID_EXTENSION;
+ *pos++ = 4;
+ *pos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
+ *pos++ = 2;
+ *pos++ = vif->bss_conf.multiple_bssid.count;
+ *pos++ = config->cnt;
+}
+
static struct sk_buff *
__ieee80211_beacon_get(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_mutable_offsets *offs,
- bool is_template)
+ bool is_template,
+ bool is_ema)
{
struct ieee80211_local *local = hw_to_local(hw);
struct beacon_data *beacon = NULL;
@@ -4772,6 +4787,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
beacon = rcu_dereference(ap->beacon);
if (beacon) {
+ int ema_len = 0;
if (beacon->csa_counter_offsets[0]) {
if (!is_template)
__ieee80211_csa_update_counter(beacon);
@@ -4779,6 +4795,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
ieee80211_set_csa(sdata, beacon);
}
+ if (is_ema && beacon->multiple_bssid.cnt)
+ ema_len = beacon->multiple_bssid.len[beacon->ema_index];
+
/*
* headroom, head length,
* tail length and maximum TIM length
@@ -4786,7 +4805,8 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
skb = dev_alloc_skb(local->tx_headroom +
beacon->head_len +
beacon->tail_len + 256 +
- local->hw.extra_beacon_tailroom);
+ local->hw.extra_beacon_tailroom +
+ ema_len);
if (!skb)
goto out;
@@ -4804,6 +4824,17 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
csa_off_base = skb->len;
}
+ if (ema_len) {
+ ieee80211_beacon_add_multiple_bssid_config(vif, skb,
+ &beacon->multiple_bssid);
+ skb_put_data(skb, beacon->multiple_bssid.ies[beacon->ema_index],
+ beacon->multiple_bssid.len[beacon->ema_index]);
+ if (offs)
+ offs->multiple_bssid_offset = skb->len - ema_len;
+ beacon->ema_index++;
+ beacon->ema_index %= beacon->multiple_bssid.cnt;
+ }
+
if (beacon->tail)
skb_put_data(skb, beacon->tail,
beacon->tail_len);
@@ -4932,16 +4963,25 @@ ieee80211_beacon_get_template(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_mutable_offsets *offs)
{
- return __ieee80211_beacon_get(hw, vif, offs, true);
+ return __ieee80211_beacon_get(hw, vif, offs, true, false);
}
EXPORT_SYMBOL(ieee80211_beacon_get_template);
+struct sk_buff *
+ieee80211_beacon_get_template_ema(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_mutable_offsets *offs)
+{
+ return __ieee80211_beacon_get(hw, vif, offs, true, true);
+}
+EXPORT_SYMBOL(ieee80211_beacon_get_template_ema);
+
struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
u16 *tim_offset, u16 *tim_length)
{
struct ieee80211_mutable_offsets offs = {};
- struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false);
+ struct sk_buff *bcn = __ieee80211_beacon_get(hw, vif, &offs, false, false);
struct sk_buff *copy;
struct ieee80211_supported_band *sband;
int shift;
--
2.25.0
From 5806a3b2d7a30ca99ad0240a9199fede6dc46ee9 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 12 Aug 2020 15:09:51 +0200
Subject: [PATCH 5/9] ath11k: add a struct to pass parameters into
ath11k_wmi_vdev_up
When setting up a multiple bssid we need to pass additional parameters to
the FW. Doing this as individual parameters would make the call signature
very long. Use an intermediate struct instead and adjust all callees to
make use of it.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/wireless/ath/ath11k/mac.c | 37 ++++++++++++++++++++++-----
drivers/net/wireless/ath/ath11k/wmi.c | 17 +++++++-----
drivers/net/wireless/ath/ath11k/wmi.h | 12 +++++++--
3 files changed, 52 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index fa7f5b1bf983..7c41c1f64093 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -783,6 +783,10 @@ static inline int ath11k_mac_vdev_setup_sync(struct ath11k *ar)
static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id)
{
+ struct vdev_up_params params = {
+ .vdev_id = vdev_id,
+ .bssid = ar->mac_addr,
+ };
struct cfg80211_chan_def *chandef = NULL;
struct ieee80211_channel *channel = NULL;
struct wmi_vdev_start_req_arg arg = {};
@@ -829,7 +833,7 @@ static int ath11k_mac_monitor_vdev_start(struct ath11k *ar, int vdev_id)
vdev_id, ret);
return ret;
}
- ret = ath11k_wmi_vdev_up(ar, vdev_id, 0, ar->mac_addr);
+ ret = ath11k_wmi_vdev_up(ar, &params);
if (ret) {
ath11k_warn(ar->ab, "failed to put up monitor vdev %i: %d\n",
vdev_id, ret);
@@ -1120,6 +1124,12 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
struct ieee80211_bss_conf *info)
{
struct ath11k *ar = arvif->ar;
+ struct vdev_up_params params = {
+ .vdev_id = arvif->vdev_id,
+ .bssid = arvif->bssid,
+ .profile_num = info->multiple_bssid.count,
+ .profile_idx = info->multiple_bssid.index,
+ };
int ret = 0;
lockdep_assert_held(&arvif->ar->conf_mutex);
@@ -1161,9 +1171,15 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
arvif->aid = 0;
ether_addr_copy(arvif->bssid, info->bssid);
+ if (arvif->vif->multiple_bssid.parent) {
+ struct ath11k_vif *pvif;
- ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
+ pvif = (struct ath11k_vif *)arvif->vif->multiple_bssid.parent->drv_priv;
+
+ params.trans_bssid = pvif->bssid;
+ }
+
+ ret = ath11k_wmi_vdev_up(arvif->ar, &params);
if (ret) {
ath11k_warn(ar->ab, "failed to bring up vdev %d: %i\n",
arvif->vdev_id, ret);
@@ -2304,6 +2320,11 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
struct ath11k *ar = hw->priv;
struct ath11k_vif *arvif = (void *)vif->drv_priv;
struct peer_assoc_params peer_arg;
+ struct vdev_up_params params = {
+ .vdev_id = arvif->vdev_id,
+ .bssid = bss_conf->bssid,
+ .aid = bss_conf->aid,
+ };
struct ieee80211_sta *ap_sta;
struct ieee80211_sta_he_cap he_cap;
int ret;
@@ -2361,7 +2382,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw,
arvif->aid = bss_conf->aid;
ether_addr_copy(arvif->bssid, bss_conf->bssid);
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, arvif->aid, arvif->bssid);
+ ret = ath11k_wmi_vdev_up(ar, &params);
if (ret) {
ath11k_warn(ar->ab, "failed to set vdev %d up: %d\n",
arvif->vdev_id, ret);
@@ -6070,6 +6091,8 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
/* TODO: Update ar->rx_channel */
for (i = 0; i < n_vifs; i++) {
+ struct vdev_up_params params;
+
arvif = (void *)vifs[i].vif->drv_priv;
if (WARN_ON(!arvif->is_started))
@@ -6090,8 +6113,10 @@ ath11k_mac_update_vif_chan(struct ath11k *ar,
continue;
}
- ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid,
- arvif->bssid);
+ params.vdev_id = arvif->vdev_id,
+ params.bssid = arvif->bssid,
+ params.aid = arvif->aid,
+ ret = ath11k_wmi_vdev_up(arvif->ar, &params);
if (ret) {
ath11k_warn(ab, "failed to bring vdev up %d: %d\n",
arvif->vdev_id, ret);
@@ -6279,7 +6340,12 @@ static int ath11k_start_vdev_delay(struc
}
if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) {
- ret = ath11k_wmi_vdev_up(ar, arvif->vdev_id, 0, ar->mac_addr);
+ struct vdev_up_params params;
+
+ params.vdev_id = arvif->vdev_id,
+ params.bssid = arvif->bssid,
+ params.aid = arvif->aid,
+ ret = ath11k_wmi_vdev_up(arvif->ar, &params);
if (ret) {
ath11k_warn(ab, "failed put monitor up: %d\n", ret);
return ret;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 2806efccd562..1035fa2a44f8 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -974,7 +974,7 @@ int ath11k_wmi_vdev_set_ratemask(struct ath11k *ar, u32 vdev_id, u32 *params)
return ret;
}
-int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
+int ath11k_wmi_vdev_up(struct ath11k *ar, struct vdev_up_params *params)
{
struct ath11k_pdev_wmi *wmi = ar->wmi;
struct wmi_vdev_up_cmd *cmd;
@@ -989,10 +989,14 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_VDEV_UP_CMD) |
FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
- cmd->vdev_id = vdev_id;
- cmd->vdev_assoc_id = aid;
+ cmd->vdev_id = params->vdev_id;
+ cmd->vdev_assoc_id = params->aid;
+ cmd->profile_idx = params->profile_idx;
+ cmd->profile_num = params->profile_num;
- ether_addr_copy(cmd->vdev_bssid.addr, bssid);
+ if (params->trans_bssid)
+ ether_addr_copy(cmd->trans_bssid.addr, params->trans_bssid);
+ ether_addr_copy(cmd->vdev_bssid.addr, params->bssid);
ret = ath11k_wmi_cmd_send(wmi, skb, WMI_VDEV_UP_CMDID);
if (ret) {
@@ -1001,8 +1005,9 @@ int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid)
}
ath11k_dbg(ar->ab, ATH11K_DBG_WMI,
- "WMI mgmt vdev up id 0x%x assoc id %d bssid %pM\n",
- vdev_id, aid, bssid);
+ "WMI mgmt vdev up id 0x%x assoc id %d idx %d num %d bssid %pM trans_bssid %pM\n",
+ params->vdev_id, params->aid, params->profile_idx, params->profile_num,
+ params->bssid, params->trans_bssid);
return ret;
}
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index fb7ece7466c0..5a55dd2af41d 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -2558,6 +2558,15 @@ struct wmi_vdev_config_ratemask_cmd {
u32 mask_l2;
} __packed;
+struct vdev_up_params {
+ u32 vdev_id;
+ u16 aid;
+ u32 profile_idx;
+ u32 profile_num;
+ const u8 *bssid;
+ u8 *trans_bssid;
+};
+
struct wmi_vdev_up_cmd {
u32 tlv_header;
u32 vdev_id;
@@ -5553,8 +5562,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
struct ieee80211_mutable_offsets *offs,
struct sk_buff *bcn);
int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id);
-int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid,
- const u8 *bssid);
+int ath11k_wmi_vdev_up(struct ath11k *ar, struct vdev_up_params *params);
int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id);
int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
bool restart);
--
2.25.0
From 7bc1e2a2485254b9ab8b938f949a345ff7d8f46e Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 26 Aug 2020 10:55:49 -0700
Subject: [PATCH 6/9] ath11k: add the multiple bssid WMI commands
Add the code to pass the BSS specific multiple bssid info to the FW.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/wireless/ath/ath11k/wmi.c | 3 +++
drivers/net/wireless/ath/ath11k/wmi.h | 10 ++++++++++
2 files changed, 13 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 1035fa2a44f8..856fe9d530e3 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -681,6 +681,8 @@ int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,
cmd->vdev_subtype = param->subtype;
cmd->num_cfg_txrx_streams = WMI_NUM_SUPPORTED_BAND_MAX;
cmd->pdev_id = param->pdev_id;
+ cmd->flags = param->flags;
+ cmd->vdevid_trans = param->vdevid_trans;
ether_addr_copy(cmd->vdev_macaddr.addr, macaddr);
ptr = skb->data + sizeof(*cmd);
@@ -1788,6 +1790,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
cmd->csa_switch_count_offset = offs->csa_counter_offs[0];
cmd->ext_csa_switch_count_offset = offs->csa_counter_offs[1];
cmd->buf_len = bcn->len;
+ cmd->mbssid_ie_offset = offs->multiple_bssid_offset;
ptr = skb->data + sizeof(*cmd);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 5a55dd2af41d..297282a60fbd 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -138,6 +138,12 @@ enum {
WMI_AUTORATE_3200NS_GI = (1 << 11),
};
+enum {
+ WMI_HOST_VDEV_FLAGS_NON_MBSSID_AP = 1,
+ WMI_HOST_VDEV_FLAGS_TRANSMIT_AP = 2,
+ WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP = 4,
+};
+
/*
* wmi command groups.
*/
@@ -2525,6 +2531,8 @@ struct vdev_create_params {
u8 rx;
} chains[NUM_NL80211_BANDS];
u32 pdev_id;
+ u32 flags;
+ u32 vdevid_trans;
};
struct wmi_vdev_create_cmd {
@@ -2535,6 +2543,8 @@ struct wmi_vdev_create_cmd {
struct wmi_mac_addr vdev_macaddr;
u32 num_cfg_txrx_streams;
u32 pdev_id;
+ u32 flags;
+ u32 vdevid_trans;
} __packed;
struct wmi_vdev_txrx_streams {
--
2.25.0
From 3af6fb803336d103f7b885ef768ec1369fbdfa08 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 26 Aug 2020 10:56:58 -0700
Subject: [PATCH 7/9] ath11k: add multiple bssid support to device creation
We need to pass info such as parent device, bssid count/index and
(non-)transmit mode information to the FW when we create a new vdev.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/wireless/ath/ath11k/mac.c | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 7c41c1f64093..d0bec170905d 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -5269,17 +5269,30 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw)
atomic_set(&ar->num_pending_mgmt_tx, 0);
}
-static void
+static int
ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
struct vdev_create_params *params)
{
struct ath11k *ar = arvif->ar;
+ struct ieee80211_vif *parent;
struct ath11k_pdev *pdev = ar->pdev;
params->if_id = arvif->vdev_id;
params->type = arvif->vdev_type;
params->subtype = arvif->vdev_subtype;
params->pdev_id = pdev->pdev_id;
+ params->vdevid_trans = 0;
+ if (arvif->vif->multiple_bssid.non_transmitted) {
+ params->flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
+ parent = arvif->vif->multiple_bssid.parent;
+ if (!parent)
+ return -ENOENT;
+ if (ar->hw->wiphy != ieee80211_vif_to_wdev(parent)->wiphy)
+ return -EINVAL;
+ params->vdevid_trans = ath11k_vif_to_arvif(parent)->vdev_id;
+ } else {
+ params->flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
+ }
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
@@ -5294,6 +5307,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
params->chains[NL80211_BAND_6GHZ].tx = ar->num_tx_chains;
params->chains[NL80211_BAND_6GHZ].rx = ar->num_rx_chains;
}
+ return 0;
}
static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
@@ -5386,7 +5400,11 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,
for (i = 0; i < ARRAY_SIZE(vif->hw_queue); i++)
vif->hw_queue[i] = i % (ATH11K_HW_MAX_QUEUES - 1);
- ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ ret = ath11k_mac_setup_vdev_create_params(arvif, &vdev_param);
+ if (ret) {
+ ath11k_warn(ab, "failed to prepare vdev %d\n", ret);
+ goto err;
+ }
ret = ath11k_wmi_vdev_create(ar, vif->addr, &vdev_param);
if (ret) {
--
2.25.0
From 80e2a22938840e0eca9306c5ce4ebbd44c85c79e Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 12 Aug 2020 15:33:33 +0200
Subject: [PATCH 8/9] ath11k: add EMA beacon support
We need to update the beacon in multiple bssid mode after each completion
event to get the next EMA beacon.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/wireless/ath/ath11k/mac.c | 20 +++++++++++++++++++-
drivers/net/wireless/ath/ath11k/mac.h | 1 +
drivers/net/wireless/ath/ath11k/wmi.c | 8 ++++++++
3 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index d0bec170905d..611286f41f3d 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1086,7 +1086,10 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
return 0;
- bcn = ieee80211_beacon_get_template(hw, vif, &offs);
+ if (arvif->vif->multiple_bssid.non_transmitted)
+ return 0;
+
+ bcn = ieee80211_beacon_get_template_ema(hw, vif, &offs);
if (!bcn) {
ath11k_warn(ab, "failed to get beacon template from mac80211\n");
return -EPERM;
@@ -1120,6 +1123,21 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
return ret;
}
+void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
+{
+ struct ieee80211_vif *vif = arvif->vif;
+ int multiple_bssid = 0;
+
+ if (!vif->multiple_bssid.non_transmitted &&
+ !list_empty(&vif->multiple_bssid.list))
+ multiple_bssid = 1;
+
+ if (!multiple_bssid)
+ return;
+
+ ath11k_mac_setup_bcn_tmpl(arvif);
+}
+
static void ath11k_control_beaconing(struct ath11k_vif *arvif,
struct ieee80211_bss_conf *info)
{
diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h
index 5aba197fc212..0e3451b0ec1d 100644
--- a/drivers/net/wireless/ath/ath11k/mac.h
+++ b/drivers/net/wireless/ath/ath11k/mac.h
@@ -154,4 +154,5 @@ int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx);
u8 ath11k_mac_bw_to_mac80211_bw(u8 bw);
enum ath11k_supported_bw ath11k_mac_mac80211_bw_to_ath11k_bw(enum rate_info_bw bw);
enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher);
+void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif);
#endif
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 856fe9d530e3..181ff2ae4422 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -7680,6 +7680,7 @@ exit:
static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *skb)
{
+ struct ath11k_vif *arvif;
u32 vdev_id, tx_status;
if (ath11k_pull_bcn_tx_status_ev(ab, skb->data, skb->len,
@@ -7687,6 +7688,13 @@ static void ath11k_bcn_tx_status_event(struct ath11k_base *ab, struct sk_buff *s
ath11k_warn(ab, "failed to extract bcn tx status");
return;
}
+
+ arvif = ath11k_mac_get_arvif_by_vdev_id(ab, vdev_id);
+ if (!arvif) {
+ ath11k_warn(ab, "invalid vdev id %d in bcn_tx_status", vdev_id);
+ return;
+ }
+ ath11k_mac_bcn_tx_event(arvif);
}
--
2.25.0
From 324b51335ca30729f8d627390e0e8d91037b0d61 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 26 Aug 2020 10:58:56 -0700
Subject: [PATCH 9/9] ath11k: set the multiple bssid hw flags and capabilities
This wraps up the support for multiple bssid and actually makes
the feature available.
Signed-off-by: John Crispin <john@phrozen.org>
---
drivers/net/wireless/ath/ath11k/mac.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 611286f41f3d..4ad9cc094d7b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -7481,19 +7481,23 @@ static void ath11k_mac_fetch_coex_info(struct ath11k *ar)
static const u8 ath11k_if_types_ext_capa[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
};
static const u8 ath11k_if_types_ext_capa_sta[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_REQUESTER_SUPPORT,
};
static const u8 ath11k_if_types_ext_capa_ap[] = {
[0] = WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING,
+ [2] = WLAN_EXT_CAPA3_MULTI_BSSID_SUPPORT,
[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF,
[9] = WLAN_EXT_CAPA10_TWT_RESPONDER_SUPPORT,
+ [11] = WLAN_EXT_CAPA11_EMA_SUPPORT,
};
static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
@@ -7609,6 +7613,8 @@ static int __ath11k_mac_register(struct ath11k *ar)
ieee80211_hw_set(ar->hw, QUEUE_CONTROL);
ieee80211_hw_set(ar->hw, SUPPORTS_TX_FRAG);
ieee80211_hw_set(ar->hw, REPORTS_LOW_ACK);
+ ieee80211_hw_set(ar->hw, SUPPORTS_MULTI_BSSID);
+ ieee80211_hw_set(ar->hw, SUPPORTS_MULTI_BSSID_AP);
if (ht_cap & WMI_HT_CAP_ENABLED) {
ieee80211_hw_set(ar->hw, AMPDU_AGGREGATION);
ieee80211_hw_set(ar->hw, TX_AMPDU_SETUP_IN_HW);
--
2.25.0