From f8e7ec408c357d6438abd980f700353a7efcac7e Mon Sep 17 00:00:00 2001
From: Maharaja Kennadyrajan <mkenna@codeaurora.org>
Date: Tue, 12 Jan 2021 18:11:33 +0530
Subject: [PATCH] mac80211: Add support for beacon tx mode

User can configure the beacon tx mode while bring-up the
AP via hostapd configuration.

Use the below configuration in the hostapd to configure
the beacon tx mode.

"beacon_tx_mode=N", where N = 0 for STAGGERED beacon mode
and N = 1 for BURST beacon mode.

Signed-off-by: Maharaja Kennadyrajan <mkenna@codeaurora.org>
---
 include/net/cfg80211.h       | 2 +-
 include/net/mac80211.h       | 1 +
 include/uapi/linux/nl80211.h | 2 ++
 net/mac80211/cfg.c           | 1 +
 net/wireless/nl80211.c       | 7 ++++++-
 5 files changed, 11 insertions(+), 2 deletions(-)

--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1233,6 +1233,7 @@ enum cfg80211_ap_settings_flags {
  * @he_bss_color: BSS Color settings
  * @he_oper: HE operation IE (or %NULL if HE isn't enabled)
  * @multiple_bssid: AP settings for multiple bssid
+ * @beacon_tx_mode: Beacon Tx Mode setting
  */
 struct cfg80211_ap_settings {
 	struct cfg80211_chan_def chandef;
@@ -1264,6 +1265,7 @@ struct cfg80211_ap_settings {
 	struct ieee80211_he_obss_pd he_obss_pd;
 	struct cfg80211_he_bss_color he_bss_color;
 	struct ieee80211_multiple_bssid multiple_bssid;
+	enum nl80211_beacon_tx_mode beacon_tx_mode;
 };
 
 /**
@@ -2132,6 +2134,7 @@ struct mesh_config {
  *	to operate on DFS channels.
  * @control_port_over_nl80211: TRUE if userspace expects to exchange control
  *	port frames over NL80211 instead of the network interface.
+ * @beacon_tx_mode: Beacon Tx Mode setting.
  *
  * These parameters are fixed when the mesh is created.
  */
@@ -2155,6 +2158,7 @@ struct mesh_setup {
 	struct cfg80211_bitrate_mask beacon_rate;
 	bool userspace_handles_dfs;
 	bool control_port_over_nl80211;
+	enum nl80211_beacon_tx_mode beacon_tx_mode;
 };
 
 /**
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -647,6 +647,7 @@ struct ieee80211_fils_discovery {
  *	to driver when rate control is offloaded to firmware.
  * @nss_ap_isolate: Used for notifying the NSS host about AP isolate feature
  * @multiple_bssid: the multiple bssid settings of the AP.
+ * @beacon_tx_mode: Beacon Tx Mode setting.
  */
 struct ieee80211_bss_conf {
 	const u8 *bssid;
@@ -719,6 +720,7 @@ struct ieee80211_bss_conf {
 	struct cfg80211_bitrate_mask beacon_tx_rate;
 	bool nss_ap_isolate;
 	struct ieee80211_multiple_bssid multiple_bssid;
+	enum nl80211_beacon_tx_mode beacon_tx_mode;
 };
 
 /**
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -2636,7 +2636,9 @@ enum nl80211_commands {
  *	The last additional RNR group, if present, points to information
  *	for co-located APs and neighbor APs in ESS to be added in all
  *	EMA beacons.
- *
+ * @NL80211_ATTR_BEACON_TX_MODE: used to configure the beacon tx mode as
+ *	staggered mode = 1 or burst mode = 2 in %NL80211_CMD_START_AP or
+ *	%NL80211_CMD_JOIN_MESH from user-space.
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3150,6 +3152,8 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_RNR_OFFSETS,
 
+	NL80211_ATTR_BEACON_TX_MODE,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -7412,4 +7416,12 @@ enum nl80211_sar_specs_attrs {
 	NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1,
 };
 
+/**
+ * enum nl80211_beacon_tx_mode - Beacon Tx Mode enum.
+ * 	Used to configure beacon staggered mode or beacon burst mode.
+ */
+enum nl80211_beacon_tx_mode {
+	NL80211_BEACON_STAGGERED_MODE = 1,
+	NL80211_BEACON_BURST_MODE = 2,
+};
 #endif /* __LINUX_NL80211_H */
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1228,6 +1228,7 @@ static int ieee80211_start_ap(struct wip
 
 	prev_beacon_int = sdata->vif.bss_conf.beacon_int;
 	sdata->vif.bss_conf.beacon_int = params->beacon_interval;
+	sdata->vif.bss_conf.beacon_tx_mode = params->beacon_tx_mode;
 
 	if (params->he_cap && params->he_oper) {
 		sdata->vif.bss_conf.he_support = true;
@@ -2256,6 +2257,7 @@ static int copy_mesh_setup(struct ieee80
 
 	sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
 	sdata->vif.bss_conf.dtim_period = setup->dtim_period;
+	sdata->vif.bss_conf.beacon_tx_mode = setup->beacon_tx_mode;
 
 	sdata->beacon_rate_set = false;
 	if (wiphy_ext_feature_isset(sdata->local->hw.wiphy,
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -794,6 +794,8 @@ static const struct nla_policy nl80211_p
 	[NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COLOR] = { .type = NLA_U8 },
 	[NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_IES] = NLA_POLICY_NESTED(nl80211_policy),
 	[NL80211_ATTR_RNR_OFFSETS] = NLA_POLICY_NESTED(nl80211_rnr_ies_policy),
+	[NL80211_ATTR_BEACON_TX_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2),
+
 };
 
 /* policy for the key attributes */
@@ -5437,6 +5439,9 @@ static int nl80211_start_ap(struct sk_bu
 		nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
 	params.dtim_period =
 		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
+	if (info->attrs[NL80211_ATTR_BEACON_TX_MODE])
+		params.beacon_tx_mode =
+			nla_get_u32(info->attrs[NL80211_ATTR_BEACON_TX_MODE]);
 
 	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
 					   params.beacon_interval);
@@ -12024,6 +12029,10 @@ static int nl80211_join_mesh(struct sk_b
 			return -EINVAL;
 	}
 
+	if (info->attrs[NL80211_ATTR_BEACON_TX_MODE])
+		setup.beacon_tx_mode =
+			nla_get_u32(info->attrs[NL80211_ATTR_BEACON_TX_MODE]);
+
 	if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
 		/* parse additional setup parameters if given */
 		err = nl80211_parse_mesh_setup(info, &setup);
