linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v8 0/4] Multiple BSSID support
@ 2021-03-09  3:54 Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 1/4] nl80211: add basic multiple bssid support Aloka Dixit
                   ` (3 more replies)
  0 siblings, 4 replies; 6+ messages in thread
From: Aloka Dixit @ 2021-03-09  3:54 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, Aloka Dixit

This patchset adds support for multiple BSSID and
enhanced multi-BSSID advertisements.

This version has changes only in patch 1/4 (nl80211) which add
new feature flags NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP and
NL80211_EXT_FEATURE_EMA_AP along with wiphy parameters
max_num_vaps and max_profile_periodicity to be used by drivers

John Crispin (4):
  nl80211: add basic multiple bssid support
  mac80211: add multiple bssid support to interface handling
  mac80211: add multiple bssid/EMA support to beacon handling
  mac80211: CSA on non-transmitting interfaces

 include/net/cfg80211.h       |  47 ++++++
 include/net/mac80211.h       | 116 ++++++++++++++-
 include/uapi/linux/nl80211.h |  84 +++++++++++
 net/mac80211/cfg.c           | 178 ++++++++++++++++++++--
 net/mac80211/debugfs.c       |   1 +
 net/mac80211/ieee80211_i.h   |   2 +
 net/mac80211/iface.c         |   6 +
 net/mac80211/tx.c            | 189 +++++++++++++++++++++---
 net/wireless/nl80211.c       | 277 ++++++++++++++++++++++++++++++-----
 9 files changed, 828 insertions(+), 72 deletions(-)


base-commit: 38b5133ad607ecdcc8d24906d1ac9cc8df41acd5
-- 
2.25.0


^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v8 1/4] nl80211: add basic multiple bssid support
  2021-03-09  3:54 [PATCH v8 0/4] Multiple BSSID support Aloka Dixit
@ 2021-03-09  3:54 ` Aloka Dixit
  2021-03-09  6:40   ` Dan Carpenter
  2021-03-09  3:54 ` [PATCH v8 2/4] mac80211: add multiple bssid support to interface handling Aloka Dixit
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 6+ messages in thread
From: Aloka Dixit @ 2021-03-09  3:54 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, John Crispin, Aloka Dixit

From: John Crispin <john@phrozen.org>

This patch adds support for passing the multiple bssid config to the
kernel when an AP gets started. If the BSS is non-transmitting we need
to pass

* the ifidx of the transmitting parent
* the BSS index in the set
* the BSS count of the set
* flag indicating if we want to do EMA
* the multiple bssid elements as an array inside the beacon data

This allows use to generate multiple bssid beacons as well as EMA ones.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
v8: Addition of NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP,
NL80211_EXT_FEATURE_EMA_AP, along with wiphy parameters
max_num_vaps and max_profile_periodicity to be used by drivers

 include/net/cfg80211.h       |  47 ++++++
 include/uapi/linux/nl80211.h |  84 +++++++++++
 net/wireless/nl80211.c       | 277 ++++++++++++++++++++++++++++++-----
 3 files changed, 369 insertions(+), 39 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 911fae42b0c0..565a1356095f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -485,6 +485,21 @@ struct ieee80211_supported_band {
 	const struct ieee80211_sband_iftype_data *iftype_data;
 };
 
+/**
+ * struct cfg80211_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: non-transmitted BSSs transmitted parents index
+ * @ema: Shall the beacons be sent out in EMA mode.
+ */
+struct cfg80211_multiple_bssid {
+	u8 index;
+	u8 count;
+	u32 parent;
+	bool ema;
+};
+
 /**
  * ieee80211_get_sband_iftype_data - return sband data for a given iftype
  * @sband: the sband to search for the STA on
@@ -1032,6 +1047,23 @@ struct cfg80211_crypto_settings {
 	enum nl80211_sae_pwe_mechanism sae_pwe;
 };
 
+/**
+ * struct cfg80211_multiple_bssid_data - Multiple BSSID elements
+ *
+ * @cnt: Number of elements in array %elems.
+ *
+ * @elems: Array of multiple BSSID element(s) to be added into Beacon frames.
+ * @elems.data: Data for multiple BSSID elements.
+ * @elems.len: Length of data.
+ */
+struct cfg80211_multiple_bssid_data {
+	u8 cnt;
+	struct {
+		u8 *data;
+		size_t len;
+	} elems[];
+};
+
 /**
  * struct cfg80211_beacon_data - beacon data
  * @head: head portion of beacon (before TIM IE)
@@ -1058,6 +1090,7 @@ struct cfg80211_crypto_settings {
  *	Token (measurement type 11)
  * @lci_len: LCI data length
  * @civicloc_len: Civic location data length
+ * @multiple_bssid: multiple_bssid elements
  */
 struct cfg80211_beacon_data {
 	const u8 *head, *tail;
@@ -1076,6 +1109,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 {
@@ -1181,6 +1216,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 parameters
+ * @multiple_bssid: AP settings for multiple bssid.
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -1213,6 +1249,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 cfg80211_multiple_bssid multiple_bssid;
 };
 
 /**
@@ -4941,6 +4978,11 @@ struct wiphy_iftype_akm_suites {
  *	configuration through the %NL80211_TID_CONFIG_ATTR_RETRY_SHORT and
  *	%NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes
  * @sar_capa: SAR control capabilities
+ *
+ * @multiple_bssid: Describes device's multiple BSSID config support
+ * @multiple_bssid.max_num_vaps: Maximum number of VAPS supported by the driver
+ * @multiple_bssid.max_num_elems: Maximum number of multiple BSSID elements
+ *	supported by the driver
  */
 struct wiphy {
 	struct mutex mtx;
@@ -5083,6 +5125,11 @@ struct wiphy {
 
 	const struct cfg80211_sar_capa *sar_capa;
 
+	struct {
+		u8 max_num_vaps;
+		u8 max_profile_periodicity;
+	} multiple_bssid;
+
 	char priv[] __aligned(NETDEV_ALIGN);
 };
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index ac78da99fccd..c40e6789d142 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2557,6 +2557,19 @@ enum nl80211_commands {
  *	disassoc events to indicate that an immediate reconnect to the AP
  *	is desired.
  *
+ * @NL80211_ATTR_MULTIPLE_BSSID_CONFIG: Optional parameter to configure
+ *	multiple BSSID and enhanced multi-BSSID advertisements.
+ *	This attribute is also used to advertise the maximum number of VAPs
+ *	supported by the driver to the application. It is a nested attribute,
+ *	see &enum nl80211_multiple_bssid_config_attributes.
+ *
+ * @NL80211_ATTR_MULTIPLE_BSSID_ELEMS: Optional parameter for multiple BSSID
+ *	elements data. This attribute is also used to advertise the maximum
+ *	profile periodicity supported by the driver to the application, if
+ *	enhanced multi-BSS advertisements (EMA) feature is enabled.
+ *	It is a nested attribute, see
+ *	&enum nl80211_multiple_bssid_elems_attributes.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3054,6 +3067,9 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_DISABLE_HE,
 
+	NL80211_ATTR_MULTIPLE_BSSID_CONFIG,
+	NL80211_ATTR_MULTIPLE_BSSID_ELEMS,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -5937,6 +5953,11 @@ enum nl80211_feature_flags {
  * @NL80211_EXT_FEATURE_BEACON_RATE_HE: Driver supports beacon rate
  *	configuration (AP/mesh) with HE rates.
  *
+ * @NL80211_EXT_FEATURE_MULTIPLE_BSSID: Driver/device supports multiple BSSID
+ *	advertisements.
+ * @NL80211_EXT_FEATURE_EMA_AP: Driver/device supports enhanced multiple BSSID
+ *	advertisements (EMA).
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5998,6 +6019,8 @@ enum nl80211_ext_feature_index {
 	NL80211_EXT_FEATURE_FILS_DISCOVERY,
 	NL80211_EXT_FEATURE_UNSOL_BCAST_PROBE_RESP,
 	NL80211_EXT_FEATURE_BEACON_RATE_HE,
+	NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP,
+	NL80211_EXT_FEATURE_EMA_AP,
 
 	/* add new features before the definition below */
 	NUM_NL80211_EXT_FEATURES,
@@ -7277,4 +7300,65 @@ enum nl80211_sar_specs_attrs {
 	NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
 };
 
+/**
+ * enum nl80211_multiple_bssid_config_attributes - Attributes to configure
+ *	multiple BSSID and enhanced multi-BSSID advertisements.
+ *
+ * @__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INVALID: Invalid
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT: For a non-transmitted BSSID, this
+ *	attribute provides the interface index (u32) of the transmitted profile
+ *	in the multiple BSSID set.
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX: The index of this BSS (u8) inside
+ *	multiple BSSID set.
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT: Total number of BSSs (u8) in the
+ *	multiple BSSID set.
+ *
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA: Flag to indicate if enhanced multi-BSSID
+ *	advertisements (EMA) feature is enabled.
+ *	If set to 1, elements provided through attribute
+ *	%NL80211_ATTR_MULTIPLE_BSSID_ELEMS are split into multiple beacons.
+ *	Otherwise, all elements will be included in every beacon.
+ *
+ * @__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_LAST: Internal
+ * @NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX: highest attribute
+ */
+enum nl80211_multiple_bssid_config_attributes {
+	__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INVALID,
+
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA,
+
+	/* keep last */
+	__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_LAST,
+	NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX =
+		__NL80211_MULTIPLE_BSSID_CONFIG_ATTR_LAST - 1,
+};
+
+/**
+ * enum nl80211_multiple_bssid_elems_attributes - Attributes used to pass
+ *	multiple BSSID elements data.
+ *
+ * @__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_INVALID: Invalid
+ *
+ * @NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT: Number of multiple BSSID
+ *	elements (u8).
+ *
+ * @NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA: Array of multiple BSSID elements.
+ */
+enum nl80211_multiple_bssid_elems_attributes {
+	__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_INVALID,
+
+	NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT,
+	NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA,
+
+	__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_LAST,
+	NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX =
+		__NL80211_MULTIPLE_BSSID_ELEMS_ATTR_LAST - 1,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 521d36bb0803..06f7e314b161 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -431,6 +431,20 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = {
 	[NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy),
 };
 
+static const struct nla_policy
+nl80211_multiple_bssid_elems_policy[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX + 1] = {
+	[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT] = { .type = NLA_U8 },
+	[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA] = { .type = NLA_NESTED },
+};
+
+static const struct nla_policy
+nl80211_multiple_bssid_policy[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX + 1] = {
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT] = { .type = NLA_U32 },
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 },
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT] = { .type = NLA_U8 },
+	[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA] = { .type = NLA_FLAG },
+};
+
 static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[0] = { .strict_start_type = NL80211_ATTR_HE_OBSS_PD },
 	[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
@@ -753,6 +767,10 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
 	[NL80211_ATTR_RECONNECT_REQUESTED] = { .type = NLA_REJECT },
 	[NL80211_ATTR_SAR_SPEC] = NLA_POLICY_NESTED(sar_policy),
 	[NL80211_ATTR_DISABLE_HE] = { .type = NLA_FLAG },
+	[NL80211_ATTR_MULTIPLE_BSSID_CONFIG] =
+			NLA_POLICY_NESTED(nl80211_multiple_bssid_policy),
+	[NL80211_ATTR_MULTIPLE_BSSID_ELEMS] =
+			NLA_POLICY_NESTED(nl80211_multiple_bssid_elems_policy),
 };
 
 /* policy for the key attributes */
@@ -2192,6 +2210,49 @@ nl80211_put_sar_specs(struct cfg80211_registered_device *rdev,
 	return -ENOBUFS;
 }
 
+static int
+nl80211_put_multiple_bssid_support(struct wiphy *wiphy, struct sk_buff *msg)
+{
+	struct nlattr *config = NULL, *elems = NULL;
+
+	if (!wiphy_ext_feature_isset(wiphy,
+				     NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP))
+		return 0;
+
+	if (wiphy->multiple_bssid.max_num_vaps) {
+		config = nla_nest_start(msg,
+					NL80211_ATTR_MULTIPLE_BSSID_CONFIG);
+		if (!config)
+			return -ENOSPC;
+
+		if (nla_put_u8(msg, NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT,
+			       wiphy->multiple_bssid.max_num_vaps))
+			goto fail_config;
+
+		nla_nest_end(msg, config);
+	}
+
+	if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_EMA_AP) &&
+	    wiphy->multiple_bssid.max_profile_periodicity) {
+		elems = nla_nest_start(msg, NL80211_ATTR_MULTIPLE_BSSID_ELEMS);
+		if (!elems)
+			goto fail_config;
+
+		if (nla_put_u8(msg, NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT,
+			       wiphy->multiple_bssid.max_profile_periodicity))
+			goto fail_elems;
+
+		nla_nest_end(msg, elems);
+	}
+	return 0;
+
+fail_elems:
+	nla_nest_cancel(msg, elems);
+fail_config:
+	nla_nest_cancel(msg, config);
+	return -ENOBUFS;
+}
+
 struct nl80211_dump_wiphy_state {
 	s64 filter_wiphy;
 	long start;
@@ -2774,6 +2835,9 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
 		if (nl80211_put_sar_specs(rdev, msg))
 			goto nla_put_failure;
 
+		if (nl80211_put_multiple_bssid_support(&rdev->wiphy, msg))
+			goto nla_put_failure;
+
 		/* done */
 		state->split_start = 0;
 		break;
@@ -4952,6 +5016,90 @@ static int validate_beacon_tx_rate(struct cfg80211_registered_device *rdev,
 	return 0;
 }
 
+static int
+nl80211_parse_multiple_bssid_config(struct wiphy *wiphy,
+				    struct nlattr *attrs,
+				    struct cfg80211_ap_settings *params)
+{
+	struct nlattr *tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX + 1];
+	int ret;
+	struct cfg80211_multiple_bssid *config = &params->multiple_bssid;
+
+	if (!wiphy_ext_feature_isset(wiphy,
+				     NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP))
+		return -EINVAL;
+
+	ret = nla_parse_nested(tb, NL80211_MULTIPLE_BSSID_CONFIG_ATTR_MAX, attrs, NULL,
+			       NULL);
+	if (ret)
+		return ret;
+
+	config->ema = nla_get_flag(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_EMA]);
+	if (config->ema &&
+	    (!wiphy_ext_feature_isset(wiphy,
+				      NL80211_EXT_FEATURE_EMA_AP) ||
+	     (wiphy->multiple_bssid.max_profile_periodicity &&
+	      params->beacon.multiple_bssid->cnt >
+	      wiphy->multiple_bssid.max_profile_periodicity)))
+		return -EINVAL;
+
+	if (!tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT])
+		return -EINVAL;
+
+	config->count = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_COUNT]);
+	if (config->count < 1 ||
+	    (wiphy->multiple_bssid.max_num_vaps &&
+	     config->count > wiphy->multiple_bssid.max_num_vaps))
+		return -EINVAL;
+
+	if (tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT])
+		config->parent = nla_get_u32(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_PARENT]);
+
+	if (tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX])
+		config->index = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_CONFIG_ATTR_INDEX]);
+
+	return 0;
+}
+
+static struct cfg80211_multiple_bssid_data *
+nl80211_parse_multiple_bssid_elems(struct wiphy *wiphy, struct nlattr *attrs)
+{
+	struct cfg80211_multiple_bssid_data *multiple_bssid;
+	struct nlattr *nl_ie;
+	struct nlattr *tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX + 1];
+	int rem_ie;
+	u8 i = 0, err, num_elems;
+
+	if (!wiphy_ext_feature_isset(wiphy,
+				     NL80211_EXT_FEATURE_MULTIPLE_BSSID_AP))
+		return NULL;
+
+	err = nla_parse_nested(tb, NL80211_MULTIPLE_BSSID_ELEMS_ATTR_MAX,
+			       attrs, NULL, NULL);
+	if (err)
+		return NULL;
+
+	if (!tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT] ||
+	    !tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA])
+		return NULL;
+
+	num_elems = nla_get_u8(tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_COUNT]);
+	multiple_bssid = kzalloc(struct_size(multiple_bssid, elems, num_elems),
+				 GFP_KERNEL);
+	if (!multiple_bssid)
+		return NULL;
+
+	multiple_bssid->cnt = num_elems;
+	nla_for_each_nested(nl_ie, tb[NL80211_MULTIPLE_BSSID_ELEMS_ATTR_DATA],
+			    rem_ie) {
+		multiple_bssid->elems[i].data = nla_data(nl_ie);
+		multiple_bssid->elems[i].len = nla_len(nl_ie);
+		i++;
+	}
+
+	return multiple_bssid;
+}
+
 static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
 				struct nlattr *attrs[],
 				struct cfg80211_beacon_data *bcn)
@@ -5032,6 +5180,14 @@ static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev,
 		bcn->ftm_responder = -1;
 	}
 
+	if (attrs[NL80211_ATTR_MULTIPLE_BSSID_ELEMS]) {
+		bcn->multiple_bssid = nl80211_parse_multiple_bssid_elems(
+				&rdev->wiphy,
+				attrs[NL80211_ATTR_MULTIPLE_BSSID_ELEMS]);
+		if (!bcn->multiple_bssid)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -5317,7 +5473,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 
 	err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
 	if (err)
-		return err;
+		goto out;
 
 	params.beacon_interval =
 		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
@@ -5327,7 +5483,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
 					   params.beacon_interval);
 	if (err)
-		return err;
+		goto out;
 
 	/*
 	 * In theory, some of these attributes should be required here
@@ -5340,8 +5496,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
 		params.ssid_len =
 			nla_len(info->attrs[NL80211_ATTR_SSID]);
-		if (params.ssid_len == 0)
-			return -EINVAL;
+		if (params.ssid_len == 0) {
+			err = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
@@ -5354,57 +5512,74 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 		params.auth_type = nla_get_u32(
 			info->attrs[NL80211_ATTR_AUTH_TYPE]);
 		if (!nl80211_valid_auth_type(rdev, params.auth_type,
-					     NL80211_CMD_START_AP))
-			return -EINVAL;
+					     NL80211_CMD_START_AP)) {
+			err = -EINVAL;
+			goto out;
+		}
 	} else
 		params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
 
 	err = nl80211_crypto_settings(rdev, info, &params.crypto,
 				      NL80211_MAX_NR_CIPHER_SUITES);
 	if (err)
-		return err;
+		goto out;
 
 	if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
-		if (!(rdev->wiphy.features & NL80211_FEATURE_INACTIVITY_TIMER))
-			return -EOPNOTSUPP;
+		if (!(rdev->wiphy.features &
+		      NL80211_FEATURE_INACTIVITY_TIMER)) {
+			err = -EOPNOTSUPP;
+			goto out;
+		}
 		params.inactivity_timeout = nla_get_u16(
 			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
 	}
 
 	if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
-		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
-			return -EINVAL;
+		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+			err = -EINVAL;
+			goto out;
+		}
 		params.p2p_ctwindow =
 			nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
 		if (params.p2p_ctwindow != 0 &&
-		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN))
-			return -EINVAL;
+		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
+			err = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
 		u8 tmp;
 
-		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
-			return -EINVAL;
+		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
+			err = -EINVAL;
+			goto out;
+		}
 		tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
 		params.p2p_opp_ps = tmp;
 		if (params.p2p_opp_ps != 0 &&
-		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS))
-			return -EINVAL;
+		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
+			err = -EINVAL;
+			goto out;
+		}
 	}
 
 	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
 		err = nl80211_parse_chandef(rdev, info, &params.chandef);
 		if (err)
-			return err;
+			goto out;
 	} else if (wdev->preset_chandef.chan) {
 		params.chandef = wdev->preset_chandef;
-	} else if (!nl80211_get_ap_channel(rdev, &params))
-		return -EINVAL;
+	} else if (!nl80211_get_ap_channel(rdev, &params)) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
-					   wdev->iftype))
-		return -EINVAL;
+					   wdev->iftype)) {
+		err = -EINVAL;
+		goto out;
+	}
 
 	if (info->attrs[NL80211_ATTR_TX_RATES]) {
 		err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
@@ -5412,12 +5587,12 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 						    &params.beacon_rate,
 						    dev, false);
 		if (err)
-			return err;
+			goto out;
 
 		err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
 					      &params.beacon_rate);
 		if (err)
-			return err;
+			goto out;
 	}
 
 	if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
@@ -5428,29 +5603,38 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 			break;
 		case NL80211_SMPS_STATIC:
 			if (!(rdev->wiphy.features &
-			      NL80211_FEATURE_STATIC_SMPS))
-				return -EINVAL;
+			      NL80211_FEATURE_STATIC_SMPS)) {
+				err = -EINVAL;
+				goto out;
+			}
 			break;
 		case NL80211_SMPS_DYNAMIC:
 			if (!(rdev->wiphy.features &
-			      NL80211_FEATURE_DYNAMIC_SMPS))
-				return -EINVAL;
+			      NL80211_FEATURE_DYNAMIC_SMPS)) {
+				err = -EINVAL;
+				goto out;
+			}
 			break;
 		default:
-			return -EINVAL;
+			err = -EINVAL;
+			goto out;
 		}
 	} else {
 		params.smps_mode = NL80211_SMPS_OFF;
 	}
 
 	params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
-	if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ])
-		return -EOPNOTSUPP;
+	if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
 
 	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
 		params.acl = parse_acl_data(&rdev->wiphy, info);
-		if (IS_ERR(params.acl))
-			return PTR_ERR(params.acl);
+		if (IS_ERR(params.acl)) {
+			err = PTR_ERR(params.acl);
+			goto out;
+		}
 	}
 
 	params.twt_responder =
@@ -5485,7 +5669,16 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 			rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
 			&params);
 		if (err)
-			return err;
+			goto out;
+	}
+
+	if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG]) {
+		err = nl80211_parse_multiple_bssid_config(
+			&rdev->wiphy,
+			info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG],
+			&params);
+		if (err)
+			goto out;
 	}
 
 	nl80211_calculate_ap_params(&params);
@@ -5509,7 +5702,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
 
 out:
 	kfree(params.acl);
-
+	kfree(params.beacon.multiple_bssid);
 	return err;
 }
 
@@ -5533,12 +5726,14 @@ static int nl80211_set_beacon(struct sk_buff *skb, struct genl_info *info)
 
 	err = nl80211_parse_beacon(rdev, info->attrs, &params);
 	if (err)
-		return err;
+		goto out;
 
 	wdev_lock(wdev);
 	err = rdev_change_beacon(rdev, dev, &params);
 	wdev_unlock(wdev);
 
+out:
+	kfree(params.multiple_bssid);
 	return err;
 }
 
@@ -9218,12 +9413,14 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
 
 	err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon_after);
 	if (err)
-		return err;
+		goto free;
 
 	csa_attrs = kcalloc(NL80211_ATTR_MAX + 1, sizeof(*csa_attrs),
 			    GFP_KERNEL);
-	if (!csa_attrs)
-		return -ENOMEM;
+	if (!csa_attrs) {
+		err = -ENOMEM;
+		goto free;
+	}
 
 	err = nla_parse_nested_deprecated(csa_attrs, NL80211_ATTR_MAX,
 					  info->attrs[NL80211_ATTR_CSA_IES],
@@ -9341,6 +9538,8 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
 	wdev_unlock(wdev);
 
 free:
+	kfree(params.beacon_after.multiple_bssid);
+	kfree(params.beacon_csa.multiple_bssid);
 	kfree(csa_attrs);
 	return err;
 }
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v8 2/4] mac80211: add multiple bssid support to interface handling
  2021-03-09  3:54 [PATCH v8 0/4] Multiple BSSID support Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 1/4] nl80211: add basic multiple bssid support Aloka Dixit
@ 2021-03-09  3:54 ` Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 3/4] mac80211: add multiple bssid/EMA support to beacon handling Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 4/4] mac80211: CSA on non-transmitting interfaces Aloka Dixit
  3 siblings, 0 replies; 6+ messages in thread
From: Aloka Dixit @ 2021-03-09  3:54 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, John Crispin, Aloka Dixit

From: John Crispin <john@phrozen.org>

Add a new helper ieee80211_set_multiple_bssid_options() takes propagating
the cfg80211 data down the stack.

The patch also makes sure that all members of the bss set will get closed
when either of them is shutdown.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
v8: No changes from v7

 include/net/mac80211.h | 30 +++++++++++++++++++++++-
 net/mac80211/cfg.c     | 53 ++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/debugfs.c |  1 +
 net/mac80211/iface.c   |  6 +++++
 4 files changed, 89 insertions(+), 1 deletion(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2d1d629e5d14..b9f51515c2e8 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -631,6 +631,7 @@ struct ieee80211_fils_discovery {
  * @s1g: BSS is S1G BSS (affects Association Request format).
  * @beacon_tx_rate: The configured beacon transmit rate that needs to be passed
  *	to driver when rate control is offloaded to firmware.
+ * @multiple_bssid: the multiple bssid settings of the AP.
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -700,6 +701,7 @@ struct ieee80211_bss_conf {
 	u32 unsol_bcast_probe_resp_interval;
 	bool s1g;
 	struct cfg80211_bitrate_mask beacon_tx_rate;
+	struct cfg80211_multiple_bssid multiple_bssid;
 };
 
 /**
@@ -1663,6 +1665,19 @@ enum ieee80211_offload_flags {
 	IEEE80211_OFFLOAD_DECAP_ENABLED		= BIT(2),
 };
 
+/**
+ * enum ieee80211_vif_multiple_bssid_flags - virtual interface multiple bssid flags
+ *
+ * @IEEE80211_VIF_MBSS_TRANSMITTING: this BSS is transmitting beacons
+ * @IEEE80211_VIF_MBSS_NON_TRANSMITTING: this BSS is not transmitting beacons
+ * @IEEE80211_VIF_MBSS_EMA_BEACON: beacons should be send out in EMA mode
+ */
+enum ieee80211_vif_multiple_bssid_flags {
+	IEEE80211_VIF_MBSS_TRANSMITTING         = BIT(1),
+	IEEE80211_VIF_MBSS_NON_TRANSMITTING     = BIT(2),
+	IEEE80211_VIF_MBSS_EMA_BEACON           = BIT(3),
+};
+
 /**
  * struct ieee80211_vif - per-interface data
  *
@@ -1709,6 +1724,11 @@ enum ieee80211_offload_flags {
  *	protected by fq->lock.
  * @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
  *	&enum ieee80211_offload_flags.
+ *
+ * @multiple_bssid: Multiple BSSID configurations.
+ * @multiple_bssid.parent: Interface index of the transmitted BSS.
+ * @multiple_bssid.flags: multiple bssid flags, see
+ *	enum ieee80211_vif_multiple_bssid_flags.
  */
 struct ieee80211_vif {
 	enum nl80211_iftype type;
@@ -1737,6 +1757,11 @@ struct ieee80211_vif {
 
 	bool txqs_stopped[IEEE80211_NUM_ACS];
 
+	struct {
+		struct ieee80211_vif *parent;
+		u32 flags;
+	} multiple_bssid;
+
 	/* must be last */
 	u8 drv_priv[] __aligned(sizeof(void *));
 };
@@ -2384,7 +2409,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.
@@ -2399,6 +2424,8 @@ struct ieee80211_txq {
  * @IEEE80211_HW_SUPPORTS_RX_DECAP_OFFLOAD: Hardware supports rx decapsulation
  *	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 {
@@ -2453,6 +2480,7 @@ enum ieee80211_hw_flags {
 	IEEE80211_HW_AMPDU_KEYBORDER_SUPPORT,
 	IEEE80211_HW_SUPPORTS_TX_ENCAP_OFFLOAD,
 	IEEE80211_HW_SUPPORTS_RX_DECAP_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 c4c70e30ad7f..91e659a43f67 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -111,6 +111,39 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
 	return 0;
 }
 
+static void ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sdata,
+						 struct cfg80211_ap_settings *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;
+
+	if (!params->multiple_bssid.count)
+		return;
+
+	if (params->multiple_bssid.parent) {
+		parent = __dev_get_by_index(wiphy_net(wiphy),
+					    params->multiple_bssid.parent);
+		if (!parent || !parent->ieee80211_ptr)
+			return;
+		psdata = IEEE80211_WDEV_TO_SUB_IF(parent->ieee80211_ptr);
+		if (psdata->vif.multiple_bssid.parent)
+			return;
+		sdata->vif.multiple_bssid.parent = &psdata->vif;
+		sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_NON_TRANSMITTING;
+	} else {
+		sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_TRANSMITTING;
+	}
+
+	if (params->multiple_bssid.ema)
+		sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_EMA_BEACON;
+	sdata->vif.bss_conf.multiple_bssid = params->multiple_bssid;
+}
+
 static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
 						const char *name,
 						unsigned char name_assign_type,
@@ -141,6 +174,23 @@ static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
 
 static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+	if (sdata && sdata->vif.type == NL80211_IFTYPE_AP) {
+		if (sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) {
+			struct ieee80211_sub_if_data *child;
+
+			rcu_read_lock();
+			list_for_each_entry_rcu(child, &sdata->local->interfaces, list)
+				if (child->vif.multiple_bssid.parent == &sdata->vif)
+					dev_close(child->wdev.netdev);
+			rcu_read_unlock();
+		} else {
+			sdata->vif.multiple_bssid.parent = NULL;
+		}
+	}
+
 	ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));
 
 	return 0;
@@ -1078,6 +1128,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 			changed |= BSS_CHANGED_HE_BSS_COLOR;
 	}
 
+	if (sdata->vif.type == NL80211_IFTYPE_AP)
+		ieee80211_set_multiple_bssid_options(sdata, params);
+
 	mutex_lock(&local->mtx);
 	err = ieee80211_vif_use_channel(sdata, &params->chandef,
 					IEEE80211_CHANCTX_SHARED);
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 5296898875ff..249b8f4e6a54 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -456,6 +456,7 @@ static const char *hw_flag_names[] = {
 	FLAG(AMPDU_KEYBORDER_SUPPORT),
 	FLAG(SUPPORTS_TX_ENCAP_OFFLOAD),
 	FLAG(SUPPORTS_RX_DECAP_OFFLOAD),
+	FLAG(SUPPORTS_MULTI_BSSID_AP),
 #undef FLAG
 };
 
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index b80c9b016b2b..6bb48bf87aca 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -376,6 +376,12 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_do
 	bool cancel_scan;
 	struct cfg80211_nan_func *func;
 
+	/* make sure the parent is already down */
+	if (sdata->vif.type == NL80211_IFTYPE_AP &&
+	    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


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v8 3/4] mac80211: add multiple bssid/EMA support to beacon handling
  2021-03-09  3:54 [PATCH v8 0/4] Multiple BSSID support Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 1/4] nl80211: add basic multiple bssid support Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 2/4] mac80211: add multiple bssid support to interface handling Aloka Dixit
@ 2021-03-09  3:54 ` Aloka Dixit
  2021-03-09  3:54 ` [PATCH v8 4/4] mac80211: CSA on non-transmitting interfaces Aloka Dixit
  3 siblings, 0 replies; 6+ messages in thread
From: Aloka Dixit @ 2021-03-09  3:54 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, John Crispin, Aloka Dixit

From: John Crispin <john@phrozen.org>

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.

Extend ieee80211_beacon_get_template() to allow generation of multiple
bssid/EMA beacons. The API provides support for HW that can offload the
EMA beaconing aswell as HW that will require periodic updates of the
beacon template upon completion events.

In case the HW can do full EMA offload, functions are provided that allow
the driver to get a list of the periodicity number of beacons and their
matching mutable offsets.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
v8: No changes from v7

 include/net/mac80211.h     |  86 +++++++++++++++++
 net/mac80211/cfg.c         | 114 +++++++++++++++++++---
 net/mac80211/ieee80211_i.h |   2 +
 net/mac80211/tx.c          | 189 ++++++++++++++++++++++++++++++++-----
 4 files changed, 359 insertions(+), 32 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index b9f51515c2e8..fc456262b335 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4889,12 +4889,17 @@ void ieee80211_report_low_ack(struct ieee80211_sta *sta, u32 num_packets);
  * @cntdwn_counter_offs: array of IEEE80211_MAX_CNTDWN_COUNTERS_NUM offsets
  *	to countdown 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 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
+
+	u16 multiple_bssid_offset;
+	u16 multiple_bssid_length;
 };
 
 /**
@@ -4921,6 +4926,87 @@ ieee80211_beacon_get_template(struct ieee80211_hw *hw,
 			      struct ieee80211_vif *vif,
 			      struct ieee80211_mutable_offsets *offs);
 
+/**
+ * enum ieee80211_bcn_tmpl_ema - EMA beacon generation type
+ * @IEEE80211_BCN_EMA_NONE: don't generate an EMA beacon.
+ * @IEEE80211_BCN_EMA_NEXT: generate the next periodicity beacon.
+ * @IEEE80211_BCN_EMA_INDEX: generate beacon by periodicity index
+ *	if the value is >= this enum value.
+ */
+enum ieee80211_bcn_tmpl_ema {
+	IEEE80211_BCN_EMA_NONE	= -2,
+	IEEE80211_BCN_EMA_NEXT	= -1,
+	IEEE80211_BCN_EMA_INDEX	= 0,
+};
+
+/**
+ * ieee80211_beacon_get_template_ema_next - EMA beacon template generation
+ *	function for drivers using the sw offload path.
+ * @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. Calling this function will auto-increment the periodicity counter.
+ *
+ * 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_next(struct ieee80211_hw *hw,
+						       struct ieee80211_vif *vif,
+						       struct ieee80211_mutable_offsets *offs);
+
+/**
+ * struct ieee80211_ema_bcn_list - list entry of an EMA beacon
+ * @list: the list pointer.
+ * @skb: the skb containing this specific beacon
+ * @offs: &struct ieee80211_mutable_offsets pointer to struct that will
+ *	receive the offsets that may be updated by the driver.
+ */
+struct ieee80211_ema_bcn_list {
+	struct list_head list;
+	struct sk_buff *skb;
+	struct ieee80211_mutable_offsets offs;
+};
+
+/**
+ * ieee80211_beacon_get_template_ema_list - EMA beacon template generation
+ *	function for drivers using the hw offload.
+ * @hw: pointer obtained from ieee80211_alloc_hw().
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ * @head: linked list head that will get populated with
+ *	&struct ieee80211_ema_bcn_list pointers.
+ *
+ * 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 will populate a linked list that the driver can pass
+ * to the HW.
+ *
+ * This function needs to follow the same rules as ieee80211_beacon_get_template
+ *
+ * Return: The nuber of entries in the list or 0 on error.
+ */
+
+int ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
+					   struct ieee80211_vif *vif,
+					   struct list_head *head);
+
+/**
+ * ieee80211_beacon_free_ema_list - free an EMA beacon template list
+ * @head: linked list head containing &struct ieee80211_ema_bcn_list pointers.
+ *
+ * This function will free a list previously acquired by calling
+ * ieee80211_beacon_get_template_ema_list()
+ */
+void ieee80211_beacon_free_ema_list(struct list_head *head);
+
 /**
  * ieee80211_beacon_get_tim - beacon generation function
  * @hw: pointer obtained from ieee80211_alloc_hw().
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 91e659a43f67..e72c0a4a26c3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -984,14 +984,49 @@ 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;
+
+	if (!data)
+		return 0;
+
+	for (i = 0; i < data->cnt; i++)
+		len += data->elems[i].len;
+
+	return len;
+}
+
+static u8 *ieee80211_copy_multiple_bssid_beacon(u8 *offset,
+						struct cfg80211_multiple_bssid_data *dest,
+						struct cfg80211_multiple_bssid_data *src)
+{
+	int i;
+
+	if (!dest || !src)
+		return offset;
+
+	dest->cnt = src->cnt;
+	for (i = 0; i < dest->cnt; i++) {
+		dest->elems[i].len = src->elems[i].len;
+		dest->elems[i].data = offset;
+		memcpy(dest->elems[i].data, src->elems[i].data,
+		       dest->elems[i].len);
+		offset += dest->elems[i].len;
+	}
+
+	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 = 0;
 	int size, err;
 	u32 changed = BSS_CHANGED_BEACON;
+	u8 *new_multiple_bssid_offset;
 
 	old = sdata_dereference(sdata->u.ap.beacon, sdata);
 
@@ -1013,12 +1048,30 @@ 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)
+		new_multiple_bssid_len =
+			ieee80211_get_multiple_bssid_beacon_len(params->multiple_bssid);
+	else if (old && old->multiple_bssid)
+		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)
 		return -ENOMEM;
 
+	if (new_multiple_bssid_len) {
+		new->multiple_bssid = kzalloc(sizeof(*params->multiple_bssid),
+					      GFP_KERNEL);
+		if (!new->multiple_bssid) {
+			kfree(new);
+			return -ENOMEM;
+		}
+	}
+
 	/* start filling the new info now */
 
 	/*
@@ -1030,6 +1083,17 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	new->head_len = new_head_len;
 	new->tail_len = new_tail_len;
 
+	/* copy in optional multiple_bssid_ies */
+	new_multiple_bssid_offset = new->tail + new_tail_len;
+	if (params->multiple_bssid)
+		ieee80211_copy_multiple_bssid_beacon(new_multiple_bssid_offset,
+						     new->multiple_bssid,
+						     params->multiple_bssid);
+	else if (old && old->multiple_bssid)
+		ieee80211_copy_multiple_bssid_beacon(new_multiple_bssid_offset,
+						     new->multiple_bssid,
+						     old->multiple_bssid);
+
 	if (csa) {
 		new->cntdwn_current_counter = csa->count;
 		memcpy(new->cntdwn_counter_offsets, csa->counter_offsets_beacon,
@@ -1053,6 +1117,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 	err = ieee80211_set_probe_resp(sdata, params->probe_resp,
 				       params->probe_resp_len, csa);
 	if (err < 0) {
+		kfree(new->multiple_bssid);
 		kfree(new);
 		return err;
 	}
@@ -1068,6 +1133,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 							 params->civicloc_len);
 
 		if (err < 0) {
+			kfree(new->multiple_bssid);
 			kfree(new);
 			return err;
 		}
@@ -1077,9 +1143,10 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
 
 	rcu_assign_pointer(sdata->u.ap.beacon, new);
 
-	if (old)
+	if (old) {
+		kfree(old->multiple_bssid);
 		kfree_rcu(old, rcu_head);
-
+	}
 	return changed;
 }
 
@@ -1234,8 +1301,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 	if (err) {
 		old = sdata_dereference(sdata->u.ap.beacon, sdata);
 
-		if (old)
+		if (old) {
+			kfree(old->multiple_bssid);
 			kfree_rcu(old, rcu_head);
+		}
 		RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
 		goto error;
 	}
@@ -1315,8 +1384,11 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 
 	mutex_unlock(&local->mtx);
 
-	kfree(sdata->u.ap.next_beacon);
-	sdata->u.ap.next_beacon = NULL;
+	if (sdata->u.ap.next_beacon) {
+		kfree(sdata->u.ap.next_beacon->multiple_bssid);
+		kfree(sdata->u.ap.next_beacon);
+		sdata->u.ap.next_beacon = NULL;
+	}
 
 	/* turn off carrier for this interface and dependent VLANs */
 	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
@@ -1328,6 +1400,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 	RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
 	RCU_INIT_POINTER(sdata->u.ap.fils_discovery, NULL);
 	RCU_INIT_POINTER(sdata->u.ap.unsol_bcast_probe_resp, NULL);
+	kfree(old_beacon->multiple_bssid);
 	kfree_rcu(old_beacon, rcu_head);
 	if (old_probe_resp)
 		kfree_rcu(old_probe_resp, rcu_head);
@@ -3084,13 +3157,24 @@ 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)
 		return NULL;
 
+	if (beacon->multiple_bssid) {
+		new_beacon->multiple_bssid = kzalloc(sizeof(*beacon->multiple_bssid),
+						     GFP_KERNEL);
+		if (!new_beacon->multiple_bssid) {
+			kfree(new_beacon);
+			return NULL;
+		}
+	}
+
 	pos = (u8 *)(new_beacon + 1);
+
 	if (beacon->head_len) {
 		new_beacon->head_len = beacon->head_len;
 		new_beacon->head = pos;
@@ -3127,6 +3211,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 && 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;
@@ -3164,8 +3252,11 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
 	case NL80211_IFTYPE_AP:
 		err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
 					      NULL);
-		kfree(sdata->u.ap.next_beacon);
-		sdata->u.ap.next_beacon = NULL;
+		if (sdata->u.ap.next_beacon) {
+			kfree(sdata->u.ap.next_beacon->multiple_bssid);
+			kfree(sdata->u.ap.next_beacon);
+			sdata->u.ap.next_beacon = NULL;
+		}
 
 		if (err < 0)
 			return err;
@@ -3330,7 +3421,8 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
 		csa.count = params->count;
 
 		err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa);
-		if (err < 0) {
+		if (err < 0 && sdata->u.ap.next_beacon) {
+			kfree(sdata->u.ap.next_beacon->multiple_bssid);
 			kfree(sdata->u.ap.next_beacon);
 			return err;
 		}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index ecda126a7026..d30d53cfec1a 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -261,6 +261,8 @@ struct beacon_data {
 	struct ieee80211_meshconf_ie *meshconf;
 	u16 cntdwn_counter_offsets[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
 	u8 cntdwn_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 5d06de61047a..5cdf977e7289 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -4724,11 +4724,71 @@ static int ieee80211_beacon_protect(struct sk_buff *skb,
 	return 0;
 }
 
+static int ieee80211_beacon_multiple_bssid_len(struct beacon_data *beacon,
+					       int index)
+{
+	int len = 0, i;
+
+	if (index == IEEE80211_BCN_EMA_NEXT) {
+		index = beacon->ema_index;
+		beacon->ema_index++;
+		beacon->ema_index %= beacon->multiple_bssid->cnt;
+	}
+
+	if (index != IEEE80211_BCN_EMA_NONE &&
+	    index >= beacon->multiple_bssid->cnt)
+		return -1;
+
+	if (beacon->multiple_bssid->cnt) {
+		if (index >= IEEE80211_BCN_EMA_INDEX) {
+			len = beacon->multiple_bssid->elems[index].len;
+		} else {
+			for (i = 0; i < beacon->multiple_bssid->cnt; i++)
+				len += beacon->multiple_bssid->elems[i].len;
+		}
+	}
+	return len;
+}
+
+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, 5);
+
+	*pos++ = WLAN_EID_EXTENSION;
+	*pos++ = 3;
+	*pos++ = WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION;
+	*pos++ = vif->bss_conf.multiple_bssid.count;
+	*pos++ = config->cnt;
+}
+
+static void
+ieee80211_beacon_add_multiple_bssid(struct ieee80211_vif *vif,
+				    struct sk_buff *skb,
+				    struct cfg80211_multiple_bssid_data *config,
+				    int index)
+{
+	if (index >= IEEE80211_BCN_EMA_INDEX) {
+		ieee80211_beacon_add_multiple_bssid_config(vif, skb, config);
+		skb_put_data(skb, config->elems[index].data,
+			     config->elems[index].len);
+	} else {
+		int i;
+
+		for (i = 0; i < config->cnt; i++)
+			skb_put_data(skb, config->elems[i].data,
+				     config->elems[i].len);
+	}
+}
+
 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,
+		       int ema_index)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
 	struct beacon_data *beacon = NULL;
@@ -4740,13 +4800,11 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 	struct ieee80211_chanctx_conf *chanctx_conf;
 	int csa_off_base = 0;
 
-	rcu_read_lock();
-
 	sdata = vif_to_sdata(vif);
 	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
 
 	if (!ieee80211_sdata_running(sdata) || !chanctx_conf)
-		goto out;
+		return NULL;
 
 	if (offs)
 		memset(offs, 0, sizeof(*offs));
@@ -4756,6 +4814,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 
 		beacon = rcu_dereference(ap->beacon);
 		if (beacon) {
+			int multiple_bssid_elems_len = 0;
+			int multiple_bssid_config_len = 5;
+
 			if (beacon->cntdwn_counter_offsets[0]) {
 				if (!is_template)
 					ieee80211_beacon_update_cntdwn(vif);
@@ -4763,6 +4824,14 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 				ieee80211_set_beacon_cntdwn(sdata, beacon);
 			}
 
+			if (beacon->multiple_bssid) {
+				multiple_bssid_elems_len =
+					ieee80211_beacon_multiple_bssid_len(beacon,
+									    ema_index);
+				if (multiple_bssid_elems_len == -1)
+					return NULL;
+			}
+
 			/*
 			 * headroom, head length,
 			 * tail length and maximum TIM length
@@ -4770,9 +4839,11 @@ __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 +
+					    multiple_bssid_config_len +
+					    multiple_bssid_elems_len);
 			if (!skb)
-				goto out;
+				return NULL;
 
 			skb_reserve(skb, local->tx_headroom);
 			skb_put_data(skb, beacon->head, beacon->head_len);
@@ -4788,21 +4859,32 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 				csa_off_base = skb->len;
 			}
 
+			if (multiple_bssid_elems_len) {
+				ieee80211_beacon_add_multiple_bssid(vif, skb,
+								    beacon->multiple_bssid,
+								    ema_index);
+				if (offs) {
+					offs->multiple_bssid_offset = skb->len -
+								      multiple_bssid_elems_len;
+					csa_off_base = skb->len;
+				}
+			}
+
 			if (beacon->tail)
 				skb_put_data(skb, beacon->tail,
 					     beacon->tail_len);
 
 			if (ieee80211_beacon_protect(skb, local, sdata) < 0)
-				goto out;
+				return NULL;
 		} else
-			goto out;
+			return NULL;
 	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 		struct ieee80211_hdr *hdr;
 
 		beacon = rcu_dereference(ifibss->presp);
 		if (!beacon)
-			goto out;
+			return NULL;
 
 		if (beacon->cntdwn_counter_offsets[0]) {
 			if (!is_template)
@@ -4814,7 +4896,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 		skb = dev_alloc_skb(local->tx_headroom + beacon->head_len +
 				    local->hw.extra_beacon_tailroom);
 		if (!skb)
-			goto out;
+			return NULL;
 		skb_reserve(skb, local->tx_headroom);
 		skb_put_data(skb, beacon->head, beacon->head_len);
 
@@ -4826,7 +4908,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 
 		beacon = rcu_dereference(ifmsh->beacon);
 		if (!beacon)
-			goto out;
+			return NULL;
 
 		if (beacon->cntdwn_counter_offsets[0]) {
 			if (!is_template)
@@ -4849,7 +4931,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 				    beacon->tail_len +
 				    local->hw.extra_beacon_tailroom);
 		if (!skb)
-			goto out;
+			return NULL;
 		skb_reserve(skb, local->tx_headroom);
 		skb_put_data(skb, beacon->head, beacon->head_len);
 		ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template);
@@ -4862,7 +4944,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 		skb_put_data(skb, beacon->tail, beacon->tail_len);
 	} else {
 		WARN_ON(1);
-		goto out;
+		return NULL;
 	}
 
 	/* CSA offsets */
@@ -4905,27 +4987,92 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
 	info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
 			IEEE80211_TX_CTL_ASSIGN_SEQ |
 			IEEE80211_TX_CTL_FIRST_FRAGMENT;
- out:
-	rcu_read_unlock();
 	return skb;
 
 }
 
-struct sk_buff *
-ieee80211_beacon_get_template(struct ieee80211_hw *hw,
-			      struct ieee80211_vif *vif,
-			      struct ieee80211_mutable_offsets *offs)
+struct sk_buff *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);
+	struct sk_buff *bcn;
+
+	rcu_read_lock();
+	bcn = __ieee80211_beacon_get(hw, vif, offs, true,
+				     IEEE80211_BCN_EMA_NONE);
+	rcu_read_unlock();
+
+	return bcn;
 }
 EXPORT_SYMBOL(ieee80211_beacon_get_template);
 
+struct sk_buff *ieee80211_beacon_get_template_ema_next(struct ieee80211_hw *hw,
+						       struct ieee80211_vif *vif,
+						       struct ieee80211_mutable_offsets *offs)
+{
+	struct sk_buff *bcn;
+
+	rcu_read_lock();
+	bcn = __ieee80211_beacon_get(hw, vif, offs, true,
+				     IEEE80211_BCN_EMA_NEXT);
+	rcu_read_unlock();
+
+	return bcn;
+}
+EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_next);
+
+void ieee80211_beacon_free_ema_list(struct list_head *head)
+{
+	struct ieee80211_ema_bcn_list *ema, *tmp;
+
+	list_for_each_entry_safe(ema, tmp, head, list) {
+		kfree_skb(ema->skb);
+		kfree(ema);
+	}
+}
+EXPORT_SYMBOL(ieee80211_beacon_free_ema_list);
+
+int
+ieee80211_beacon_get_template_ema_list(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct list_head *head)
+{
+	int cnt = 0;
+
+	rcu_read_lock();
+	while (true) {
+		struct ieee80211_ema_bcn_list *ema;
+
+		ema = kmalloc(sizeof(*ema), GFP_KERNEL);
+		if (!ema) {
+			ieee80211_beacon_free_ema_list(head);
+			cnt = 0;
+			goto out;
+		}
+
+		ema->skb = __ieee80211_beacon_get(hw, vif, &ema->offs, true,
+						  cnt);
+		if (!ema->skb) {
+			kfree(ema);
+			break;
+		}
+		list_add_tail(&ema->list, head);
+		cnt++;
+	}
+out:
+	rcu_read_unlock();
+
+	return cnt;
+}
+EXPORT_SYMBOL(ieee80211_beacon_get_template_ema_list);
+
 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,
+						     IEEE80211_BCN_EMA_NONE);
 	struct sk_buff *copy;
 	struct ieee80211_supported_band *sband;
 	int shift;
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH v8 4/4] mac80211: CSA on non-transmitting interfaces
  2021-03-09  3:54 [PATCH v8 0/4] Multiple BSSID support Aloka Dixit
                   ` (2 preceding siblings ...)
  2021-03-09  3:54 ` [PATCH v8 3/4] mac80211: add multiple bssid/EMA support to beacon handling Aloka Dixit
@ 2021-03-09  3:54 ` Aloka Dixit
  3 siblings, 0 replies; 6+ messages in thread
From: Aloka Dixit @ 2021-03-09  3:54 UTC (permalink / raw)
  To: johannes; +Cc: linux-wireless, John Crispin, Aloka Dixit

From: John Crispin <john@phrozen.org>

Trigger ieee80211_csa_finish() on the non-transmitting interfaces when
CSA concludes on the tranmitting interface.

Modify offset in beacon generation to reflect multiple BSSID element
length.

Signed-off-by: John Crispin <john@phrozen.org>
Co-developed-by: Aloka Dixit <alokad@codeaurora.org>
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
---
v8: No changes from v7

 net/mac80211/cfg.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index e72c0a4a26c3..ccafa39f7ad6 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3238,6 +3238,17 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif)
 {
 	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
 
+	if (sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) {
+		struct ieee80211_sub_if_data *child;
+
+		rcu_read_lock();
+		list_for_each_entry_rcu(child, &sdata->local->interfaces, list)
+			if (child->vif.multiple_bssid.parent == &sdata->vif)
+				ieee80211_queue_work(&child->local->hw,
+						     &child->csa_finalize_work);
+		rcu_read_unlock();
+	}
+
 	ieee80211_queue_work(&sdata->local->hw,
 			     &sdata->csa_finalize_work);
 }
-- 
2.25.0


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v8 1/4] nl80211: add basic multiple bssid support
  2021-03-09  3:54 ` [PATCH v8 1/4] nl80211: add basic multiple bssid support Aloka Dixit
@ 2021-03-09  6:40   ` Dan Carpenter
  0 siblings, 0 replies; 6+ messages in thread
From: Dan Carpenter @ 2021-03-09  6:40 UTC (permalink / raw)
  To: kbuild, Aloka Dixit, johannes
  Cc: lkp, kbuild-all, linux-wireless, John Crispin, Aloka Dixit

[-- Attachment #1: Type: text/plain, Size: 22930 bytes --]

Hi Aloka,

url:    https://github.com/0day-ci/linux/commits/Aloka-Dixit/Multiple-BSSID-support/20210309-115621
base:   38b5133ad607ecdcc8d24906d1ac9cc8df41acd5
config: x86_64-randconfig-m001-20210309 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>

New smatch warnings:
net/wireless/nl80211.c:5704 nl80211_start_ap() error: 'params.acl' dereferencing possible ERR_PTR()

vim +5704 net/wireless/nl80211.c

8860020e0be1f0 Johannes Berg             2012-02-13  5448  static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
8860020e0be1f0 Johannes Berg             2012-02-13  5449  {
8860020e0be1f0 Johannes Berg             2012-02-13  5450  	struct cfg80211_registered_device *rdev = info->user_ptr[0];
8860020e0be1f0 Johannes Berg             2012-02-13  5451  	struct net_device *dev = info->user_ptr[1];
8860020e0be1f0 Johannes Berg             2012-02-13  5452  	struct wireless_dev *wdev = dev->ieee80211_ptr;
8860020e0be1f0 Johannes Berg             2012-02-13  5453  	struct cfg80211_ap_settings params;
8860020e0be1f0 Johannes Berg             2012-02-13  5454  	int err;
8860020e0be1f0 Johannes Berg             2012-02-13  5455  
074ac8df9f93f2 Johannes Berg             2010-09-16  5456  	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
4c476991062a0a Johannes Berg             2010-10-04  5457  	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
4c476991062a0a Johannes Berg             2010-10-04  5458  		return -EOPNOTSUPP;
eec60b037a8755 Jouni Malinen             2009-03-20  5459  
8860020e0be1f0 Johannes Berg             2012-02-13  5460  	if (!rdev->ops->start_ap)
8860020e0be1f0 Johannes Berg             2012-02-13  5461  		return -EOPNOTSUPP;
8860020e0be1f0 Johannes Berg             2012-02-13  5462  
8860020e0be1f0 Johannes Berg             2012-02-13  5463  	if (wdev->beacon_interval)
8860020e0be1f0 Johannes Berg             2012-02-13  5464  		return -EALREADY;
8860020e0be1f0 Johannes Berg             2012-02-13  5465  
56d1893d94bc06 Johannes Berg             2011-05-09  5466  	memset(&params, 0, sizeof(params));
56d1893d94bc06 Johannes Berg             2011-05-09  5467  
8860020e0be1f0 Johannes Berg             2012-02-13  5468  	/* these are required for START_AP */
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5469  	if (!info->attrs[NL80211_ATTR_BEACON_INTERVAL] ||
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5470  	    !info->attrs[NL80211_ATTR_DTIM_PERIOD] ||
4c476991062a0a Johannes Berg             2010-10-04  5471  	    !info->attrs[NL80211_ATTR_BEACON_HEAD])
4c476991062a0a Johannes Berg             2010-10-04  5472  		return -EINVAL;
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5473  
81e54d08d9d845 Pradeep Kumar Chitrapu    2018-09-20  5474  	err = nl80211_parse_beacon(rdev, info->attrs, &params.beacon);
8860020e0be1f0 Johannes Berg             2012-02-13  5475  	if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5476  		goto out;
8860020e0be1f0 Johannes Berg             2012-02-13  5477  
8860020e0be1f0 Johannes Berg             2012-02-13  5478  	params.beacon_interval =
56d1893d94bc06 Johannes Berg             2011-05-09  5479  		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
56d1893d94bc06 Johannes Berg             2011-05-09  5480  	params.dtim_period =
56d1893d94bc06 Johannes Berg             2011-05-09  5481  		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
56d1893d94bc06 Johannes Berg             2011-05-09  5482  
0c317a02ca982c Purushottam Kushwaha      2016-10-12  5483  	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
0c317a02ca982c Purushottam Kushwaha      2016-10-12  5484  					   params.beacon_interval);
56d1893d94bc06 Johannes Berg             2011-05-09  5485  	if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5486  		goto out;
56d1893d94bc06 Johannes Berg             2011-05-09  5487  
32e9de846be885 Jouni Malinen             2011-08-10  5488  	/*
8860020e0be1f0 Johannes Berg             2012-02-13  5489  	 * In theory, some of these attributes should be required here
8860020e0be1f0 Johannes Berg             2012-02-13  5490  	 * but since they were not used when the command was originally
8860020e0be1f0 Johannes Berg             2012-02-13  5491  	 * added, keep them optional for old user space programs to let
8860020e0be1f0 Johannes Berg             2012-02-13  5492  	 * them continue to work with drivers that do not need the
8860020e0be1f0 Johannes Berg             2012-02-13  5493  	 * additional information -- drivers must check!
32e9de846be885 Jouni Malinen             2011-08-10  5494  	 */
32e9de846be885 Jouni Malinen             2011-08-10  5495  	if (info->attrs[NL80211_ATTR_SSID]) {
32e9de846be885 Jouni Malinen             2011-08-10  5496  		params.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]);
32e9de846be885 Jouni Malinen             2011-08-10  5497  		params.ssid_len =
32e9de846be885 Jouni Malinen             2011-08-10  5498  			nla_len(info->attrs[NL80211_ATTR_SSID]);
1a41c96851bfa3 John Crispin              2021-03-08  5499  		if (params.ssid_len == 0) {
1a41c96851bfa3 John Crispin              2021-03-08  5500  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5501  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5502  		}
32e9de846be885 Jouni Malinen             2011-08-10  5503  	}
32e9de846be885 Jouni Malinen             2011-08-10  5504  
ab0d76f6823cc3 Johannes Berg             2018-10-02  5505  	if (info->attrs[NL80211_ATTR_HIDDEN_SSID])
32e9de846be885 Jouni Malinen             2011-08-10  5506  		params.hidden_ssid = nla_get_u32(
32e9de846be885 Jouni Malinen             2011-08-10  5507  			info->attrs[NL80211_ATTR_HIDDEN_SSID]);
32e9de846be885 Jouni Malinen             2011-08-10  5508  
5fb628e9105eef Jouni Malinen             2011-08-10  5509  	params.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
5fb628e9105eef Jouni Malinen             2011-08-10  5510  
5fb628e9105eef Jouni Malinen             2011-08-10  5511  	if (info->attrs[NL80211_ATTR_AUTH_TYPE]) {
5fb628e9105eef Jouni Malinen             2011-08-10  5512  		params.auth_type = nla_get_u32(
5fb628e9105eef Jouni Malinen             2011-08-10  5513  			info->attrs[NL80211_ATTR_AUTH_TYPE]);
e39e5b5e720676 Jouni Malinen             2012-09-30  5514  		if (!nl80211_valid_auth_type(rdev, params.auth_type,
1a41c96851bfa3 John Crispin              2021-03-08  5515  					     NL80211_CMD_START_AP)) {
1a41c96851bfa3 John Crispin              2021-03-08  5516  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5517  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5518  		}
5fb628e9105eef Jouni Malinen             2011-08-10  5519  	} else
5fb628e9105eef Jouni Malinen             2011-08-10  5520  		params.auth_type = NL80211_AUTHTYPE_AUTOMATIC;
5fb628e9105eef Jouni Malinen             2011-08-10  5521  
5fb628e9105eef Jouni Malinen             2011-08-10  5522  	err = nl80211_crypto_settings(rdev, info, &params.crypto,
5fb628e9105eef Jouni Malinen             2011-08-10  5523  				      NL80211_MAX_NR_CIPHER_SUITES);
5fb628e9105eef Jouni Malinen             2011-08-10  5524  	if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5525  		goto out;
5fb628e9105eef Jouni Malinen             2011-08-10  5526  
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5527  	if (info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]) {
1a41c96851bfa3 John Crispin              2021-03-08  5528  		if (!(rdev->wiphy.features &
1a41c96851bfa3 John Crispin              2021-03-08  5529  		      NL80211_FEATURE_INACTIVITY_TIMER)) {
1a41c96851bfa3 John Crispin              2021-03-08  5530  			err = -EOPNOTSUPP;
1a41c96851bfa3 John Crispin              2021-03-08  5531  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5532  		}
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5533  		params.inactivity_timeout = nla_get_u16(
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5534  			info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]);
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5535  	}
1b658f118b11de Vasanthakumar Thiagarajan 2012-03-02  5536  
53cabad70ecf0c Johannes Berg             2012-11-14  5537  	if (info->attrs[NL80211_ATTR_P2P_CTWINDOW]) {
1a41c96851bfa3 John Crispin              2021-03-08  5538  		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
1a41c96851bfa3 John Crispin              2021-03-08  5539  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5540  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5541  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5542  		params.p2p_ctwindow =
53cabad70ecf0c Johannes Berg             2012-11-14  5543  			nla_get_u8(info->attrs[NL80211_ATTR_P2P_CTWINDOW]);
53cabad70ecf0c Johannes Berg             2012-11-14  5544  		if (params.p2p_ctwindow != 0 &&
1a41c96851bfa3 John Crispin              2021-03-08  5545  		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_CTWIN)) {
1a41c96851bfa3 John Crispin              2021-03-08  5546  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5547  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5548  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5549  	}
53cabad70ecf0c Johannes Berg             2012-11-14  5550  
53cabad70ecf0c Johannes Berg             2012-11-14  5551  	if (info->attrs[NL80211_ATTR_P2P_OPPPS]) {
53cabad70ecf0c Johannes Berg             2012-11-14  5552  		u8 tmp;
53cabad70ecf0c Johannes Berg             2012-11-14  5553  
1a41c96851bfa3 John Crispin              2021-03-08  5554  		if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
1a41c96851bfa3 John Crispin              2021-03-08  5555  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5556  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5557  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5558  		tmp = nla_get_u8(info->attrs[NL80211_ATTR_P2P_OPPPS]);
53cabad70ecf0c Johannes Berg             2012-11-14  5559  		params.p2p_opp_ps = tmp;
53cabad70ecf0c Johannes Berg             2012-11-14  5560  		if (params.p2p_opp_ps != 0 &&
1a41c96851bfa3 John Crispin              2021-03-08  5561  		    !(rdev->wiphy.features & NL80211_FEATURE_P2P_GO_OPPPS)) {
1a41c96851bfa3 John Crispin              2021-03-08  5562  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5563  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5564  		}
53cabad70ecf0c Johannes Berg             2012-11-14  5565  	}
53cabad70ecf0c Johannes Berg             2012-11-14  5566  
aa430da41019c1 Johannes Berg             2012-05-16  5567  	if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) {
683b6d3b31a519 Johannes Berg             2012-11-08  5568  		err = nl80211_parse_chandef(rdev, info, &params.chandef);
683b6d3b31a519 Johannes Berg             2012-11-08  5569  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5570  			goto out;
683b6d3b31a519 Johannes Berg             2012-11-08  5571  	} else if (wdev->preset_chandef.chan) {
683b6d3b31a519 Johannes Berg             2012-11-08  5572  		params.chandef = wdev->preset_chandef;
1a41c96851bfa3 John Crispin              2021-03-08  5573  	} else if (!nl80211_get_ap_channel(rdev, &params)) {
1a41c96851bfa3 John Crispin              2021-03-08  5574  		err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5575  		goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5576  	}
aa430da41019c1 Johannes Berg             2012-05-16  5577  
923b352f19d9ea Arik Nemtsov              2015-07-08  5578  	if (!cfg80211_reg_can_beacon_relax(&rdev->wiphy, &params.chandef,
1a41c96851bfa3 John Crispin              2021-03-08  5579  					   wdev->iftype)) {
1a41c96851bfa3 John Crispin              2021-03-08  5580  		err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5581  		goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5582  	}
aa430da41019c1 Johannes Berg             2012-05-16  5583  
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5584  	if (info->attrs[NL80211_ATTR_TX_RATES]) {
9a5f6488623730 Tamizh Chelvam            2020-05-13  5585  		err = nl80211_parse_tx_bitrate_mask(info, info->attrs,
9a5f6488623730 Tamizh Chelvam            2020-05-13  5586  						    NL80211_ATTR_TX_RATES,
eb89a6a6b7a1af Miles Hu                  2020-08-04  5587  						    &params.beacon_rate,
857b34c4fb104c Rajkumar Manoharan        2020-10-16  5588  						    dev, false);
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5589  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5590  			goto out;
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5591  
8564e38206de2f Johannes Berg             2016-09-19  5592  		err = validate_beacon_tx_rate(rdev, params.chandef.chan->band,
8564e38206de2f Johannes Berg             2016-09-19  5593  					      &params.beacon_rate);
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5594  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5595  			goto out;
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5596  	}
a7c7fbff6a408d Purushottam Kushwaha      2016-09-14  5597  
18998c381b19bf Eliad Peller              2014-09-10  5598  	if (info->attrs[NL80211_ATTR_SMPS_MODE]) {
18998c381b19bf Eliad Peller              2014-09-10  5599  		params.smps_mode =
18998c381b19bf Eliad Peller              2014-09-10  5600  			nla_get_u8(info->attrs[NL80211_ATTR_SMPS_MODE]);
18998c381b19bf Eliad Peller              2014-09-10  5601  		switch (params.smps_mode) {
18998c381b19bf Eliad Peller              2014-09-10  5602  		case NL80211_SMPS_OFF:
18998c381b19bf Eliad Peller              2014-09-10  5603  			break;
18998c381b19bf Eliad Peller              2014-09-10  5604  		case NL80211_SMPS_STATIC:
18998c381b19bf Eliad Peller              2014-09-10  5605  			if (!(rdev->wiphy.features &
1a41c96851bfa3 John Crispin              2021-03-08  5606  			      NL80211_FEATURE_STATIC_SMPS)) {
1a41c96851bfa3 John Crispin              2021-03-08  5607  				err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5608  				goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5609  			}
18998c381b19bf Eliad Peller              2014-09-10  5610  			break;
18998c381b19bf Eliad Peller              2014-09-10  5611  		case NL80211_SMPS_DYNAMIC:
18998c381b19bf Eliad Peller              2014-09-10  5612  			if (!(rdev->wiphy.features &
1a41c96851bfa3 John Crispin              2021-03-08  5613  			      NL80211_FEATURE_DYNAMIC_SMPS)) {
1a41c96851bfa3 John Crispin              2021-03-08  5614  				err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5615  				goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5616  			}
18998c381b19bf Eliad Peller              2014-09-10  5617  			break;
18998c381b19bf Eliad Peller              2014-09-10  5618  		default:
1a41c96851bfa3 John Crispin              2021-03-08  5619  			err = -EINVAL;
1a41c96851bfa3 John Crispin              2021-03-08  5620  			goto out;
18998c381b19bf Eliad Peller              2014-09-10  5621  		}
18998c381b19bf Eliad Peller              2014-09-10  5622  	} else {
18998c381b19bf Eliad Peller              2014-09-10  5623  		params.smps_mode = NL80211_SMPS_OFF;
18998c381b19bf Eliad Peller              2014-09-10  5624  	}
18998c381b19bf Eliad Peller              2014-09-10  5625  
6e8ef842223b90 Purushottam Kushwaha      2016-07-05  5626  	params.pbss = nla_get_flag(info->attrs[NL80211_ATTR_PBSS]);
1a41c96851bfa3 John Crispin              2021-03-08  5627  	if (params.pbss && !rdev->wiphy.bands[NL80211_BAND_60GHZ]) {
1a41c96851bfa3 John Crispin              2021-03-08  5628  		err = -EOPNOTSUPP;
1a41c96851bfa3 John Crispin              2021-03-08  5629  		goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5630  	}
6e8ef842223b90 Purushottam Kushwaha      2016-07-05  5631  
4baf6bea37247e Ola Olsson                2015-10-29  5632  	if (info->attrs[NL80211_ATTR_ACL_POLICY]) {
4baf6bea37247e Ola Olsson                2015-10-29  5633  		params.acl = parse_acl_data(&rdev->wiphy, info);
1a41c96851bfa3 John Crispin              2021-03-08  5634  		if (IS_ERR(params.acl)) {
1a41c96851bfa3 John Crispin              2021-03-08  5635  			err = PTR_ERR(params.acl);

params.acl is an error pointer.

1a41c96851bfa3 John Crispin              2021-03-08  5636  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5637  		}
4baf6bea37247e Ola Olsson                2015-10-29  5638  	}
4baf6bea37247e Ola Olsson                2015-10-29  5639  
a0de1ca383c77a John Crispin              2019-05-28  5640  	params.twt_responder =
a0de1ca383c77a John Crispin              2019-05-28  5641  		    nla_get_flag(info->attrs[NL80211_ATTR_TWT_RESPONDER]);
a0de1ca383c77a John Crispin              2019-05-28  5642  
796e90f42b7e52 John Crispin              2019-07-30  5643  	if (info->attrs[NL80211_ATTR_HE_OBSS_PD]) {
796e90f42b7e52 John Crispin              2019-07-30  5644  		err = nl80211_parse_he_obss_pd(
796e90f42b7e52 John Crispin              2019-07-30  5645  					info->attrs[NL80211_ATTR_HE_OBSS_PD],
796e90f42b7e52 John Crispin              2019-07-30  5646  					&params.he_obss_pd);
bc7a39b4272b96 Luca Coelho               2020-06-26  5647  		if (err)
9951ebfcdf2b97 Johannes Berg             2020-02-21  5648  			goto out;
796e90f42b7e52 John Crispin              2019-07-30  5649  	}
796e90f42b7e52 John Crispin              2019-07-30  5650  
5c5e52d1bb9625 John Crispin              2019-12-17  5651  	if (info->attrs[NL80211_ATTR_HE_BSS_COLOR]) {
5c5e52d1bb9625 John Crispin              2019-12-17  5652  		err = nl80211_parse_he_bss_color(
5c5e52d1bb9625 John Crispin              2019-12-17  5653  					info->attrs[NL80211_ATTR_HE_BSS_COLOR],
5c5e52d1bb9625 John Crispin              2019-12-17  5654  					&params.he_bss_color);
5c5e52d1bb9625 John Crispin              2019-12-17  5655  		if (err)
60a0121f8fa64b Luca Coelho               2020-06-26  5656  			goto out;
5c5e52d1bb9625 John Crispin              2019-12-17  5657  	}
5c5e52d1bb9625 John Crispin              2019-12-17  5658  
291c49ded2fda1 Aloka Dixit               2020-09-11  5659  	if (info->attrs[NL80211_ATTR_FILS_DISCOVERY]) {
291c49ded2fda1 Aloka Dixit               2020-09-11  5660  		err = nl80211_parse_fils_discovery(rdev,
291c49ded2fda1 Aloka Dixit               2020-09-11  5661  						   info->attrs[NL80211_ATTR_FILS_DISCOVERY],
291c49ded2fda1 Aloka Dixit               2020-09-11  5662  						   &params);
291c49ded2fda1 Aloka Dixit               2020-09-11  5663  		if (err)
291c49ded2fda1 Aloka Dixit               2020-09-11  5664  			goto out;
291c49ded2fda1 Aloka Dixit               2020-09-11  5665  	}
291c49ded2fda1 Aloka Dixit               2020-09-11  5666  
7443dcd1f1718a Aloka Dixit               2020-09-11  5667  	if (info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP]) {
7443dcd1f1718a Aloka Dixit               2020-09-11  5668  		err = nl80211_parse_unsol_bcast_probe_resp(
7443dcd1f1718a Aloka Dixit               2020-09-11  5669  			rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP],
7443dcd1f1718a Aloka Dixit               2020-09-11  5670  			&params);
7443dcd1f1718a Aloka Dixit               2020-09-11  5671  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5672  			goto out;
1a41c96851bfa3 John Crispin              2021-03-08  5673  	}
1a41c96851bfa3 John Crispin              2021-03-08  5674  
1a41c96851bfa3 John Crispin              2021-03-08  5675  	if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG]) {
1a41c96851bfa3 John Crispin              2021-03-08  5676  		err = nl80211_parse_multiple_bssid_config(
1a41c96851bfa3 John Crispin              2021-03-08  5677  			&rdev->wiphy,
1a41c96851bfa3 John Crispin              2021-03-08  5678  			info->attrs[NL80211_ATTR_MULTIPLE_BSSID_CONFIG],
1a41c96851bfa3 John Crispin              2021-03-08  5679  			&params);
1a41c96851bfa3 John Crispin              2021-03-08  5680  		if (err)
1a41c96851bfa3 John Crispin              2021-03-08  5681  			goto out;
7443dcd1f1718a Aloka Dixit               2020-09-11  5682  	}
7443dcd1f1718a Aloka Dixit               2020-09-11  5683  
66cd794e3c30b8 Johannes Berg             2017-02-07  5684  	nl80211_calculate_ap_params(&params);
66cd794e3c30b8 Johannes Berg             2017-02-07  5685  
fe4943702c850f Srinivas Dasari           2019-01-23  5686  	if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])
fe4943702c850f Srinivas Dasari           2019-01-23  5687  		params.flags |= AP_SETTINGS_EXTERNAL_AUTH_SUPPORT;
fe4943702c850f Srinivas Dasari           2019-01-23  5688  
c56589ed1d25ae Simon Wunderlich          2013-11-21  5689  	wdev_lock(wdev);
e35e4d28b687d4 Hila Gonen                2012-06-27  5690  	err = rdev_start_ap(rdev, dev, &params);
46c1dd0c7fac54 Felix Fietkau             2012-06-19  5691  	if (!err) {
683b6d3b31a519 Johannes Berg             2012-11-08  5692  		wdev->preset_chandef = params.chandef;
8860020e0be1f0 Johannes Berg             2012-02-13  5693  		wdev->beacon_interval = params.beacon_interval;
9e0e29615a2077 Michal Kazior             2014-01-29  5694  		wdev->chandef = params.chandef;
06e191e22eb99c Antonio Quartulli         2012-11-07  5695  		wdev->ssid_len = params.ssid_len;
06e191e22eb99c Antonio Quartulli         2012-11-07  5696  		memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
466a306142c002 Denis Kenzior             2018-03-26  5697  
466a306142c002 Denis Kenzior             2018-03-26  5698  		if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
466a306142c002 Denis Kenzior             2018-03-26  5699  			wdev->conn_owner_nlportid = info->snd_portid;
46c1dd0c7fac54 Felix Fietkau             2012-06-19  5700  	}
c56589ed1d25ae Simon Wunderlich          2013-11-21  5701  	wdev_unlock(wdev);
77765eaf5cfb6b Vasanthakumar Thiagarajan 2013-01-18  5702  
9951ebfcdf2b97 Johannes Berg             2020-02-21  5703  out:
77765eaf5cfb6b Vasanthakumar Thiagarajan 2013-01-18 @5704  	kfree(params.acl);
                                                                      ^^^^^^^^^^
Dereferencing potential error pointer.  Freeing resources that weren't
allocated is one of the classic bugs with "out:" labels that free
everything.

1a41c96851bfa3 John Crispin              2021-03-08  5705  	kfree(params.beacon.multiple_bssid);
8860020e0be1f0 Johannes Berg             2012-02-13  5706  	return err;
ed1b6cc7f80f83 Johannes Berg             2007-12-19  5707  }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 41135 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-03-09  6:41 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-03-09  3:54 [PATCH v8 0/4] Multiple BSSID support Aloka Dixit
2021-03-09  3:54 ` [PATCH v8 1/4] nl80211: add basic multiple bssid support Aloka Dixit
2021-03-09  6:40   ` Dan Carpenter
2021-03-09  3:54 ` [PATCH v8 2/4] mac80211: add multiple bssid support to interface handling Aloka Dixit
2021-03-09  3:54 ` [PATCH v8 3/4] mac80211: add multiple bssid/EMA support to beacon handling Aloka Dixit
2021-03-09  3:54 ` [PATCH v8 4/4] mac80211: CSA on non-transmitting interfaces Aloka Dixit

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).