mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 19:03:39 +00:00
1153 lines
39 KiB
Diff
1153 lines
39 KiB
Diff
From 65b31d0f691ddcc06ecaf7e86bb13772efd016c8 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Tue, 20 Oct 2020 13:50:59 -0700
|
|
Subject: [PATCH 1/5] nl80211: add basic multiple bssid support
|
|
|
|
This patch adds support for passing the multiple bssid config to the
|
|
kernel when adding an AP gets started. If the BSS is non-transmitting we
|
|
need to pass the ifidx of the transmitting parent. The multiple bssid
|
|
elements are passed as an array inside the beacon data. This allows use
|
|
to generate multiple bssid beacons aswell as EMA ones.
|
|
|
|
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
include/net/cfg80211.h | 6 +++---
|
|
include/uapi/linux/nl80211.h | 7 +++----
|
|
net/wireless/nl80211.c | 22 ++++++++--------------
|
|
3 files changed, 14 insertions(+), 21 deletions(-)
|
|
|
|
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
|
|
index 31ab73b..a032810 100644
|
|
--- a/include/net/cfg80211.h
|
|
+++ b/include/net/cfg80211.h
|
|
@@ -492,14 +492,14 @@ struct ieee80211_supported_band {
|
|
*
|
|
* @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
|
|
+ * @parent: non-transmitted BSSs transmitted parents index
|
|
+ * @ema: Shall the beacons be sent out in EMA mode.
|
|
*/
|
|
struct ieee80211_multiple_bssid {
|
|
u8 index;
|
|
u8 count;
|
|
u32 parent;
|
|
- bool non_transmitted;
|
|
+ bool ema;
|
|
};
|
|
|
|
/**
|
|
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
|
|
index 4b191f8..59d08ac 100644
|
|
--- a/include/uapi/linux/nl80211.h
|
|
+++ b/include/uapi/linux/nl80211.h
|
|
@@ -2599,9 +2599,6 @@ enum nl80211_commands {
|
|
* @NL80211_ATTR_HE_MUEDCA_PARAMS: MU-EDCA AC parameters for the
|
|
* %NL80211_CMD_UPDATE_HE_MUEDCA_PARAMS command.
|
|
*
|
|
- * @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.
|
|
*
|
|
@@ -2613,6 +2610,8 @@ enum nl80211_commands {
|
|
* @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.
|
|
*
|
|
+ * @NL80211_ATTR_MULTIPLE_BSSID_EMA: Shall the multiple BSS beacons be sent out in EMA mode.
|
|
+ *
|
|
* @NL80211_ATTR_OBSS_COLOR_BITMAP: bitmap of the u64 BSS colors for the
|
|
* %NL80211_CMD_OBSS_COLOR_COLLISION event.
|
|
*
|
|
@@ -3126,11 +3125,11 @@ enum nl80211_attrs {
|
|
|
|
NL80211_ATTR_HE_MUEDCA_PARAMS,
|
|
|
|
- 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,
|
|
+ NL80211_ATTR_MULTIPLE_BSSID_EMA,
|
|
|
|
NL80211_ATTR_OBSS_COLOR_BITMAP,
|
|
|
|
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
|
|
index f198daf..9c9148e 100644
|
|
--- a/net/wireless/nl80211.c
|
|
+++ b/net/wireless/nl80211.c
|
|
@@ -777,11 +777,11 @@ 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_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_COUNT] = NLA_POLICY_RANGE(NLA_U8, 1, 16),
|
|
[NL80211_ATTR_MULTIPLE_BSSID_IES] = { .type = NLA_NESTED },
|
|
+ [NL80211_ATTR_MULTIPLE_BSSID_EMA] = { .type = NLA_FLAG },
|
|
[NL80211_ATTR_OBSS_COLOR_BITMAP] = { .type = NLA_U64 },
|
|
[NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COUNT] = { .type = NLA_U8 },
|
|
[NL80211_ATTR_COLOR_CHANGE_ANNOUNCEMENT_COLOR] = { .type = NLA_U8 },
|
|
@@ -3999,14 +3999,6 @@ 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;
|
|
|
|
@@ -5560,6 +5552,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|
goto out;
|
|
}
|
|
|
|
+ if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT])
|
|
+ params.multiple_bssid.parent =
|
|
+ nla_get_u32(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT]);
|
|
+
|
|
if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_INDEX])
|
|
params.multiple_bssid.index = nla_get_u8(
|
|
info->attrs[NL80211_ATTR_MULTIPLE_BSSID_INDEX]);
|
|
@@ -5567,10 +5563,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
|
|
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;
|
|
+ params.multiple_bssid.ema =
|
|
+ nla_get_flag(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_EMA]);
|
|
|
|
nl80211_calculate_ap_params(¶ms);
|
|
|
|
--
|
|
2.7.4
|
|
|
|
From c8998ca44327b2f9dbdb0f47522417858220fdc2 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Tue, 20 Oct 2020 14:23:02 -0700
|
|
Subject: [PATCH 2/5] mac80211: add multiple bssid support to interface
|
|
handling
|
|
|
|
When bringing up multi bssid APs we need to track the parent-child
|
|
relation aswell as figuring out if the BSS is (non-)transmitting.
|
|
The new helper function ieee80211_set_multiple_bssid_options() takes
|
|
care of storing the config as well as figuring out the runtime flags of the
|
|
virtual interface.
|
|
|
|
The patch also makes sure that when a parent is closed, its children are
|
|
also closed.
|
|
|
|
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
include/net/mac80211.h | 21 ++++++++++---
|
|
net/mac80211/cfg.c | 80 ++++++++++++++++++++++++++------------------------
|
|
net/mac80211/iface.c | 10 +++----
|
|
3 files changed, 62 insertions(+), 49 deletions(-)
|
|
|
|
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
|
index af627fd..437dc26 100644
|
|
--- a/include/net/mac80211.h
|
|
+++ b/include/net/mac80211.h
|
|
@@ -1687,6 +1687,20 @@ enum ieee80211_offload_flags {
|
|
};
|
|
|
|
/**
|
|
+ * 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
|
|
*
|
|
* Data in this structure is continually present for driver
|
|
@@ -1733,8 +1747,8 @@ enum ieee80211_offload_flags {
|
|
* @offload_flags: 802.3 -> 802.11 enapsulation offload flags, see
|
|
* &enum ieee80211_offload_flags.
|
|
* @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
|
|
+ * @multiple_bssid.flags: multiple bssid flags, see
|
|
+ * &enum ieee80211_vif_multiple_bssid_flags
|
|
* @color_change_active: marks whether a color change is going on. Internally it is
|
|
* write-protected by sdata_lock and local->mtx so holding either is fine
|
|
* for read access.
|
|
@@ -1768,8 +1782,7 @@ struct ieee80211_vif {
|
|
bool txqs_stopped[IEEE80211_NUM_ACS];
|
|
struct {
|
|
struct ieee80211_vif *parent;
|
|
- struct list_head list;
|
|
- bool non_transmitted;
|
|
+ u32 flags;
|
|
} multiple_bssid;
|
|
|
|
bool color_change_active;
|
|
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
|
index 1f62028..f457ca3 100644
|
|
--- a/net/mac80211/cfg.c
|
|
+++ b/net/mac80211/cfg.c
|
|
@@ -111,8 +111,8 @@ 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)
|
|
+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;
|
|
@@ -120,22 +120,28 @@ static int ieee80211_set_multiple_bssid_options(struct ieee80211_sub_if_data *sd
|
|
struct ieee80211_sub_if_data *psdata;
|
|
|
|
if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP))
|
|
- return 0;
|
|
+ return;
|
|
|
|
- if (params->multiple_bssid.non_transmitted) {
|
|
+ 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 -EINVAL;
|
|
+ return;
|
|
psdata = IEEE80211_WDEV_TO_SUB_IF(parent->ieee80211_ptr);
|
|
- if (psdata->vif.multiple_bssid.non_transmitted)
|
|
- return -EINVAL;
|
|
+ if (psdata->vif.multiple_bssid.parent)
|
|
+ return;
|
|
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;
|
|
+ sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_NON_TRANSMITTING;
|
|
+ } else {
|
|
+ sdata->vif.multiple_bssid.flags |= IEEE80211_VIF_MBSS_TRANSMITTING;
|
|
}
|
|
- return 0;
|
|
+
|
|
+ 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,
|
|
@@ -163,32 +169,25 @@ 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);
|
|
+ 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 {
|
|
- list_del(&sdata->vif.multiple_bssid.list);
|
|
+ sdata->vif.multiple_bssid.parent = NULL;
|
|
}
|
|
}
|
|
|
|
@@ -1216,6 +1215,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
|
|
sizeof(*params->he_cap));
|
|
}
|
|
|
|
+ if (sdata->vif.type == NL80211_IFTYPE_AP)
|
|
+ ieee80211_set_multiple_bssid_options(sdata, params);
|
|
+
|
|
mutex_lock(&local->mtx);
|
|
err = ieee80211_vif_use_channel(sdata, ¶ms->chandef,
|
|
IEEE80211_CHANCTX_SHARED);
|
|
@@ -4316,19 +4318,19 @@ static void ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_dat
|
|
ieee80211_bss_info_change_notify(sdata, changed);
|
|
|
|
if (ieee80211_hw_check(&sdata->local->hw, SUPPORTS_MULTI_BSSID_AP) &&
|
|
- !sdata->vif.multiple_bssid.non_transmitted) {
|
|
- struct ieee80211_vif *child;
|
|
-
|
|
- list_for_each_entry(child, &sdata->vif.multiple_bssid.list,
|
|
- multiple_bssid.list) {
|
|
- struct ieee80211_sub_if_data *child_sdata = vif_to_sdata(child);
|
|
-
|
|
- sdata_lock(child_sdata);
|
|
- child->bss_conf.he_bss_color.color = color;
|
|
- child->bss_conf.he_bss_color.enabled = enable;
|
|
- ieee80211_bss_info_change_notify(child_sdata, BSS_CHANGED_HE_BSS_COLOR);
|
|
- sdata_unlock(child_sdata);
|
|
+ !(sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_NON_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) {
|
|
+ child->vif.bss_conf.he_bss_color.color = color;
|
|
+ child->vif.bss_conf.he_bss_color.enabled = enable;
|
|
+ ieee80211_bss_info_change_notify(child, BSS_CHANGED_HE_BSS_COLOR);
|
|
+
|
|
+ }
|
|
}
|
|
+ rcu_read_unlock();
|
|
}
|
|
}
|
|
|
|
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
|
|
index 741b55a..6aea11f 100644
|
|
--- a/net/mac80211/iface.c
|
|
+++ b/net/mac80211/iface.c
|
|
@@ -380,12 +380,11 @@ 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.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);
|
|
+ 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);
|
|
|
|
@@ -2065,7 +2064,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
|
|
skb_queue_head_init(&sdata->fragments[i].skb_list);
|
|
|
|
INIT_LIST_HEAD(&sdata->key_list);
|
|
- INIT_LIST_HEAD(&sdata->vif.multiple_bssid.list);
|
|
|
|
INIT_DELAYED_WORK(&sdata->dfs_cac_timer_work,
|
|
ieee80211_dfs_cac_timer_work);
|
|
--
|
|
2.7.4
|
|
|
|
From acc7bd542b47cdefb373eee145509a265fe504ce Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Tue, 20 Oct 2020 14:37:21 -0700
|
|
Subject: [PATCH 3/5] mac80211: add multiple bssid/EMA 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.
|
|
|
|
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: Aloka Dixit <alokad@codeaurora.org>
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
include/net/mac80211.h | 86 ++++++++++++++++++++++++++++
|
|
net/mac80211/tx.c | 148 ++++++++++++++++++++++++++++++++++++++-----------
|
|
2 files changed, 201 insertions(+), 33 deletions(-)
|
|
|
|
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
|
|
index bb43484..81d4c11 100644
|
|
--- a/include/net/mac80211.h
|
|
+++ b/include/net/mac80211.h
|
|
@@ -4960,6 +4960,7 @@ struct ieee80211_mutable_offsets {
|
|
u16 tim_length;
|
|
|
|
u16 cntdwn_counter_offs[IEEE80211_MAX_CNTDWN_COUNTERS_NUM];
|
|
+
|
|
u16 multiple_bssid_offset;
|
|
u16 multiple_bssid_length;
|
|
};
|
|
@@ -4989,6 +4990,91 @@ ieee80211_beacon_get_template(struct ieee80211_hw *hw,
|
|
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_template - beacon template generation function
|
|
* @hw: pointer obtained from ieee80211_alloc_hw().
|
|
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
|
|
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
|
|
index b955f02..81e634e 100644
|
|
--- a/net/mac80211/tx.c
|
|
+++ b/net/mac80211/tx.c
|
|
@@ -4802,7 +4802,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_mutable_offsets *offs,
|
|
bool is_template,
|
|
- bool is_ema)
|
|
+ int ema_index)
|
|
{
|
|
struct ieee80211_local *local = hw_to_local(hw);
|
|
struct beacon_data *beacon = NULL;
|
|
@@ -4814,13 +4814,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));
|
|
@@ -4830,7 +4828,8 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
|
|
beacon = rcu_dereference(ap->beacon);
|
|
if (beacon) {
|
|
- int ema_len = 0;
|
|
+ int multiple_bssid_len = 0;
|
|
+
|
|
if (beacon->cntdwn_counter_offsets[0]) {
|
|
if (!is_template)
|
|
ieee80211_beacon_update_cntdwn(vif);
|
|
@@ -4838,8 +4837,26 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
ieee80211_set_beacon_cntdwn(sdata, beacon);
|
|
}
|
|
|
|
- if (is_ema && beacon->multiple_bssid.cnt)
|
|
- ema_len = beacon->multiple_bssid.len[beacon->ema_index];
|
|
+ if (ema_index == IEEE80211_BCN_EMA_NEXT) {
|
|
+ ema_index = beacon->ema_index;
|
|
+ beacon->ema_index++;
|
|
+ beacon->ema_index %= beacon->multiple_bssid.cnt;
|
|
+ }
|
|
+
|
|
+ if (ema_index != IEEE80211_BCN_EMA_NONE &&
|
|
+ ema_index >= beacon->multiple_bssid.cnt)
|
|
+ return NULL;
|
|
+
|
|
+ if (beacon->multiple_bssid.cnt) {
|
|
+ if (ema_index >= IEEE80211_BCN_EMA_INDEX) {
|
|
+ multiple_bssid_len = beacon->multiple_bssid.len[ema_index];
|
|
+ } else {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < beacon->multiple_bssid.cnt; i++)
|
|
+ multiple_bssid_len = beacon->multiple_bssid.len[i];
|
|
+ }
|
|
+ }
|
|
|
|
/*
|
|
* headroom, head length,
|
|
@@ -4849,9 +4866,9 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
beacon->head_len +
|
|
beacon->tail_len + 256 +
|
|
local->hw.extra_beacon_tailroom +
|
|
- ema_len);
|
|
+ multiple_bssid_len);
|
|
if (!skb)
|
|
- goto out;
|
|
+ return NULL;
|
|
|
|
skb_reserve(skb, local->tx_headroom);
|
|
skb_put_data(skb, beacon->head, beacon->head_len);
|
|
@@ -4868,16 +4885,22 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
csa_off_base = skb->len;
|
|
}
|
|
|
|
- if (ema_len) {
|
|
- ieee80211_beacon_add_multiple_bssid_config(vif, skb,
|
|
+ if (multiple_bssid_len) {
|
|
+ if (ema_index >= IEEE80211_BCN_EMA_INDEX) {
|
|
+ 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]);
|
|
+ skb_put_data(skb,
|
|
+ beacon->multiple_bssid.ies[beacon->ema_index],
|
|
+ beacon->multiple_bssid.len[beacon->ema_index]);
|
|
+ } else {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < beacon->multiple_bssid.cnt; i++)
|
|
+ skb_put_data(skb, beacon->multiple_bssid.ies[i],
|
|
+ beacon->multiple_bssid.len[i]);
|
|
+ }
|
|
if (offs)
|
|
- offs->multiple_bssid_offset = skb->len - ema_len;
|
|
-
|
|
- beacon->ema_index++;
|
|
- beacon->ema_index %= beacon->multiple_bssid.cnt;
|
|
+ offs->multiple_bssid_offset = skb->len - multiple_bssid_len;
|
|
}
|
|
|
|
if (beacon->tail)
|
|
@@ -4885,16 +4908,16 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw,
|
|
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)
|
|
@@ -4906,7 +4929,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);
|
|
|
|
@@ -4918,7 +4941,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)
|
|
@@ -4941,7 +4964,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);
|
|
@@ -4954,7 +4977,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 */
|
|
@@ -4997,8 +5020,6 @@ __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;
|
|
|
|
}
|
|
@@ -5008,25 +5029,86 @@ 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, false);
|
|
+ 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(struct ieee80211_hw *hw,
|
|
- struct ieee80211_vif *vif,
|
|
- struct ieee80211_mutable_offsets *offs)
|
|
+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)
|
|
{
|
|
- return __ieee80211_beacon_get(hw, vif, offs, true, true);
|
|
+ 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);
|
|
+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, 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.7.4
|
|
|
|
From 1d79e56f5a89230ae150ed5d840cecb8ef5696a8 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Thu, 15 Oct 2020 18:11:33 -0700
|
|
Subject: [PATCH 4/5] mac80211: don't allow CSA on non-transmitting interfaces
|
|
|
|
As a non-transmitting interface does not broadcast a beacon, we do not
|
|
want to allow channel switch announcements. They need to be triggered
|
|
on the transmitting interface.
|
|
|
|
Signed-off-by: Aloka Dixit <alokad@codeaurora.org>
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
net/mac80211/cfg.c | 3 +++
|
|
1 file changed, 3 insertions(+)
|
|
|
|
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
|
|
index f457ca3..3470991 100644
|
|
--- a/net/mac80211/cfg.c
|
|
+++ b/net/mac80211/cfg.c
|
|
@@ -3547,6 +3547,9 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
|
|
if (sdata->vif.csa_active)
|
|
return -EBUSY;
|
|
|
|
+ if (sdata->vif.multiple_bssid.flags & IEEE80211_VIF_MBSS_NON_TRANSMITTING)
|
|
+ return -EINVAL;
|
|
+
|
|
mutex_lock(&local->chanctx_mtx);
|
|
conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
|
|
lockdep_is_held(&local->chanctx_mtx));
|
|
--
|
|
2.7.4
|
|
|
|
From 3307ad5a2e005ad800e02a6154e95b6cd4450a95 Mon Sep 17 00:00:00 2001
|
|
From: John Crispin <john@phrozen.org>
|
|
Date: Tue, 20 Oct 2020 14:58:39 -0700
|
|
Subject: [PATCH 5/5] ath11k: add EMA support
|
|
|
|
This patch adds EMA support to mac80211/EMA. Currently the patch will
|
|
crash the FW.
|
|
The RFT is aimed at the QCA team to help debug the FW crash.
|
|
|
|
Signed-off-by: John Crispin <john@phrozen.org>
|
|
---
|
|
drivers/net/wireless/ath/ath11k/mac.c | 145 +++++++++++++++++++++++-----------
|
|
drivers/net/wireless/ath/ath11k/wmi.c | 8 +-
|
|
drivers/net/wireless/ath/ath11k/wmi.h | 21 ++++-
|
|
3 files changed, 126 insertions(+), 48 deletions(-)
|
|
|
|
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
|
|
index 282dc82..b158c7f 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/mac.c
|
|
@@ -1062,32 +1062,19 @@ err_mon_del:
|
|
return 0;
|
|
}
|
|
|
|
-static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
|
+static int __ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif, struct sk_buff *bcn,
|
|
+ struct ieee80211_mutable_offsets offs,
|
|
+ int ema_idx, int ema_cnt)
|
|
{
|
|
struct ath11k *ar = arvif->ar;
|
|
struct ath11k_base *ab = ar->ab;
|
|
- struct ieee80211_hw *hw = ar->hw;
|
|
- struct ieee80211_vif *vif = arvif->vif;
|
|
- struct ieee80211_mutable_offsets offs = {};
|
|
- struct sk_buff *bcn;
|
|
struct ieee80211_mgmt *mgmt;
|
|
struct ieee80211_vht_cap *vht_cap;
|
|
+ u32 ema_param = 0;
|
|
u8 *ies;
|
|
int ret;
|
|
const u8 *vht_cap_ie;
|
|
|
|
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
|
- return 0;
|
|
-
|
|
- 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;
|
|
- }
|
|
-
|
|
ies = bcn->data + ieee80211_get_hdrlen_from_skb(bcn);
|
|
ies += sizeof(mgmt->u.beacon);
|
|
|
|
@@ -1105,9 +1092,17 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
|
ies, (skb_tail_pointer(bcn) - ies)))
|
|
arvif->wpaie_present = true;
|
|
|
|
- ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn);
|
|
+ if (ema_cnt) {
|
|
+ ema_param = ema_cnt << WMI_BEACON_EMA_PARAM_PERIODICITY_SHIFT;
|
|
+ ema_param |= ema_idx << WMI_BEACON_EMA_PARAM_TMPL_IDX_SHIFT;
|
|
+ ema_param |= (!ema_idx ? 1 : 0) <<
|
|
+ WMI_BEACON_EMA_PARAM_FIRST_TMPL_SHIFT;
|
|
+ ema_param |= (ema_idx + 1 == ema_cnt ? 1 : 0) <<
|
|
+ WMI_BEACON_EMA_PARAM_LAST_TMPL_SHIFT;
|
|
+ printk("%s:%s[%d]%x\n", __FILE__, __func__, __LINE__, ema_param);
|
|
+ }
|
|
|
|
- kfree_skb(bcn);
|
|
+ ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, ema_param);
|
|
|
|
if (ret)
|
|
ath11k_warn(ab, "failed to submit beacon template command: %d\n",
|
|
@@ -1116,38 +1111,90 @@ static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
|
return ret;
|
|
}
|
|
|
|
-void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
|
|
+static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
|
|
{
|
|
- struct ieee80211_vif *vif = arvif->vif, *child, *tmp;
|
|
- int multiple_bssid = 0;
|
|
+ struct ath11k *ar = arvif->ar;
|
|
+ struct ieee80211_vif *vif = arvif->vif;
|
|
+ struct ieee80211_ema_bcn_list *bcn;
|
|
+ struct ieee80211_hw *hw = ar->hw;
|
|
+ struct list_head bcns;
|
|
+ int cnt, idx = 0, ret = 0;
|
|
|
|
- if (!vif->multiple_bssid.non_transmitted &&
|
|
- !list_empty(&vif->multiple_bssid.list))
|
|
- multiple_bssid = 1;
|
|
+ INIT_LIST_HEAD(&bcns);
|
|
+ cnt = ieee80211_beacon_get_template_ema_list(hw, vif, &bcns);
|
|
+ if (!cnt){
|
|
+ ath11k_warn(ar->ab, "failed to get ema beacon template from mac80211\n");
|
|
+ return -EPERM;
|
|
+ }
|
|
|
|
- if (!multiple_bssid && !vif->color_change_active && !arvif->bcca_zero_sent)
|
|
- return;
|
|
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
|
|
+ list_for_each_entry(bcn, &bcns, list) {
|
|
+ printk("%s:%s[%d]%d / %d\n", __FILE__, __func__, __LINE__, idx, cnt);
|
|
+ ret = __ath11k_mac_setup_bcn_tmpl(arvif, bcn->skb, bcn->offs, idx++, cnt);
|
|
+ if (ret)
|
|
+ break;
|
|
+ }
|
|
+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
|
|
|
|
- if (vif->csa_active && ieee80211_beacon_cntdwn_is_complete(vif)) {
|
|
- ieee80211_csa_finish(vif);
|
|
- list_for_each_entry_safe(child, tmp,
|
|
- &vif->multiple_bssid.list,
|
|
- multiple_bssid.list)
|
|
- ieee80211_csa_finish(child);
|
|
- return;
|
|
- }
|
|
+ ieee80211_beacon_free_ema_list(&bcns);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int ath11k_mac_setup_bcn_tmpl_legacy(struct ath11k_vif *arvif)
|
|
+{
|
|
+ struct ath11k *ar = arvif->ar;
|
|
+ struct ieee80211_mutable_offsets offs = {};
|
|
+ struct ieee80211_vif *vif = arvif->vif;
|
|
+ struct ieee80211_hw *hw = ar->hw;
|
|
+ struct sk_buff *bcn;
|
|
+ int ret;
|
|
+
|
|
+ bcn = ieee80211_beacon_get_template(hw, vif, &offs);
|
|
+ if (!bcn) {
|
|
+ ath11k_warn(ar->ab, "failed to get beacon template from mac80211\n");
|
|
+ return -EPERM;
|
|
+ }
|
|
+
|
|
+ ret = __ath11k_mac_setup_bcn_tmpl(arvif, bcn, offs, 0, 0);
|
|
+
|
|
+ kfree_skb(bcn);
|
|
|
|
- if (vif->color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) {
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int ath11k_mac_setup_bcn_tmpl(struct ath11k_vif *arvif)
|
|
+{
|
|
+ if (arvif->vdev_type != WMI_VDEV_TYPE_AP)
|
|
+ return 0;
|
|
+
|
|
+ if (arvif->vif->multiple_bssid.parent)
|
|
+ return 0;
|
|
+
|
|
+ if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_EMA_BEACON)
|
|
+ return ath11k_mac_setup_bcn_tmpl_ema(arvif);
|
|
+
|
|
+ return ath11k_mac_setup_bcn_tmpl_legacy(arvif);
|
|
+}
|
|
+
|
|
+void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif)
|
|
+{
|
|
+ struct ieee80211_vif *vif = arvif->vif;
|
|
+
|
|
+ if (!vif->color_change_active && !arvif->bcca_zero_sent)
|
|
+ return;
|
|
+
|
|
+ if (vif->color_change_active && ieee80211_beacon_cntdwn_is_complete(vif)) {
|
|
arvif->bcca_zero_sent = true;
|
|
- ieee80211_color_change_finish(vif);
|
|
- return;
|
|
- }
|
|
+ ieee80211_color_change_finish(vif);
|
|
+ return;
|
|
+ }
|
|
|
|
if (arvif->bcca_zero_sent)
|
|
arvif->bcca_zero_sent = false;
|
|
|
|
- if (vif->color_change_active || vif->csa_active)
|
|
- ieee80211_beacon_update_cntdwn(vif);
|
|
+ if (vif->color_change_active)
|
|
+ ieee80211_beacon_update_cntdwn(vif);
|
|
|
|
ath11k_mac_setup_bcn_tmpl(arvif);
|
|
}
|
|
@@ -3153,7 +3200,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,
|
|
ret = ath11k_wmi_send_obss_color_collision_cfg_cmd(
|
|
ar, arvif->vdev_id, info->he_bss_color.color,
|
|
ATH11K_BSS_COLOR_COLLISION_DETECTION_AP_PERIOD_MS,
|
|
- !arvif->vif->multiple_bssid.non_transmitted ?
|
|
+ !(arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_NON_TRANSMITTING) ?
|
|
(info->he_bss_color.enabled & color_collision_enable) : 0);
|
|
|
|
if (ret)
|
|
@@ -5754,7 +5801,7 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
|
params->subtype = arvif->vdev_subtype;
|
|
params->pdev_id = pdev->pdev_id;
|
|
params->vdevid_trans = 0;
|
|
- if (arvif->vif->multiple_bssid.non_transmitted) {
|
|
+ if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_NON_TRANSMITTING) {
|
|
params->flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
|
|
parent = arvif->vif->multiple_bssid.parent;
|
|
if (!parent)
|
|
@@ -5762,10 +5809,13 @@ ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,
|
|
if (ar->hw->wiphy != ieee80211_vif_to_wdev(parent)->wiphy)
|
|
return -EINVAL;
|
|
params->vdevid_trans = ath11k_vif_to_arvif(parent)->vdev_id;
|
|
- } else {
|
|
+ } else if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) {
|
|
params->flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
|
|
}
|
|
|
|
+ if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_EMA_BEACON)
|
|
+ params->flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
|
|
+
|
|
if (pdev->cap.supported_bands & WMI_HOST_WLAN_2G_CAP) {
|
|
params->chains[NL80211_BAND_2GHZ].tx = ar->num_tx_chains;
|
|
params->chains[NL80211_BAND_2GHZ].rx = ar->num_rx_chains;
|
|
@@ -6407,7 +6457,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
|
|
|
arg.channel.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
|
|
|
|
- if (arvif->vif->multiple_bssid.non_transmitted) {
|
|
+ if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_NON_TRANSMITTING) {
|
|
arg.mbss_capability_flags = WMI_HOST_VDEV_FLAGS_NON_TRANSMIT_AP;
|
|
parent = arvif->vif->multiple_bssid.parent;
|
|
if (!parent)
|
|
@@ -6415,10 +6465,13 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
|
|
if (ar->hw->wiphy != ieee80211_vif_to_wdev(parent)->wiphy)
|
|
return -EINVAL;
|
|
arg.vdevid_trans = ath11k_vif_to_arvif(parent)->vdev_id;
|
|
- } else {
|
|
+ } else if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_TRANSMITTING) {
|
|
arg.mbss_capability_flags = WMI_HOST_VDEV_FLAGS_TRANSMIT_AP;
|
|
}
|
|
|
|
+ if (arvif->vif->multiple_bssid.flags & IEEE80211_VIF_MBSS_EMA_BEACON) {
|
|
+ arg.mbss_capability_flags |= WMI_HOST_VDEV_FLAGS_EMA_MODE;
|
|
+ }
|
|
ath11k_dbg(ab, ATH11K_DBG_MAC,
|
|
"mac vdev %d start center_freq %d phymode %s\n",
|
|
arg.vdev_id, arg.channel.freq,
|
|
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
index 7bf688c..a3bde5c 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.c
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
|
|
@@ -1897,7 +1897,7 @@ int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,
|
|
|
|
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
|
struct ieee80211_mutable_offsets *offs,
|
|
- struct sk_buff *bcn)
|
|
+ struct sk_buff *bcn, u32 ema_params)
|
|
{
|
|
struct ath11k_vif *arvif = ath11k_mac_get_arvif(ar, vdev_id);
|
|
struct ieee80211_vif *vif = arvif->vif;
|
|
@@ -1929,6 +1929,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
|
|
|
cmd->buf_len = bcn->len;
|
|
cmd->mbssid_ie_offset = offs->multiple_bssid_offset;
|
|
+ cmd->ema_params = ema_params;
|
|
|
|
ptr = skb->data + sizeof(*cmd);
|
|
|
|
@@ -4172,6 +4173,8 @@ ath11k_wmi_copy_resource_config(struct wmi_resource_config *wmi_cfg,
|
|
wmi_cfg->sched_params = tg_cfg->sched_params;
|
|
wmi_cfg->twt_ap_pdev_count = tg_cfg->twt_ap_pdev_count;
|
|
wmi_cfg->twt_ap_sta_count = tg_cfg->twt_ap_sta_count;
|
|
+ wmi_cfg->ema_max_vap_cnt = tg_cfg->ema_max_vap_cnt;
|
|
+ wmi_cfg->ema_max_profile_period = tg_cfg->ema_max_profile_period;
|
|
}
|
|
|
|
static int ath11k_init_cmd_send(struct ath11k_pdev_wmi *wmi,
|
|
@@ -4388,6 +4391,9 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
|
|
memset(&init_param, 0, sizeof(init_param));
|
|
memset(&config, 0, sizeof(config));
|
|
|
|
+ config.ema_max_vap_cnt = 16;
|
|
+ config.ema_max_profile_period = 8;
|
|
+
|
|
ab->hw_params.hw_ops->wmi_init_config(ab, &config);
|
|
|
|
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
|
|
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
index bd0aa88..d0322ef 100644
|
|
--- a/drivers/net/wireless/ath/ath11k/wmi.h
|
|
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
|
|
@@ -2426,6 +2426,18 @@ struct wmi_resource_config {
|
|
u32 sched_params;
|
|
u32 twt_ap_pdev_count;
|
|
u32 twt_ap_sta_count;
|
|
+ u32 max_nlo_ssids;
|
|
+ u32 num_pkt_filters;
|
|
+ u32 num_max_sta_vdevs;
|
|
+ u32 max_bssid_indicator;
|
|
+ u32 ul_resp_config;
|
|
+ u32 msdu_flow_override_config0;
|
|
+ u32 msdu_flow_override_config1;
|
|
+ u32 flags2;
|
|
+ u32 host_service_flags;
|
|
+ u32 max_rnr_neighbours;
|
|
+ u32 ema_max_vap_cnt;
|
|
+ u32 ema_max_profile_period;
|
|
} __packed;
|
|
|
|
struct wmi_service_ready_event {
|
|
@@ -3674,6 +3686,11 @@ struct wmi_ftm_event_msg {
|
|
|
|
#define WMI_BEACON_TX_BUFFER_SIZE 512
|
|
|
|
+#define WMI_BEACON_EMA_PARAM_PERIODICITY_SHIFT 0
|
|
+#define WMI_BEACON_EMA_PARAM_TMPL_IDX_SHIFT 8
|
|
+#define WMI_BEACON_EMA_PARAM_FIRST_TMPL_SHIFT 16
|
|
+#define WMI_BEACON_EMA_PARAM_LAST_TMPL_SHIFT 24
|
|
+
|
|
struct wmi_bcn_tmpl_cmd {
|
|
u32 tlv_header;
|
|
u32 vdev_id;
|
|
@@ -5585,6 +5602,8 @@ struct target_resource_config {
|
|
u32 sched_params;
|
|
u32 twt_ap_pdev_count;
|
|
u32 twt_ap_sta_count;
|
|
+ u32 ema_max_vap_cnt;
|
|
+ u32 ema_max_profile_period;
|
|
};
|
|
|
|
enum wmi_tpc_pream_bw {
|
|
@@ -5975,7 +5994,7 @@ int ath11k_wmi_qos_null_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,
|
|
struct sk_buff *frame);
|
|
int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
|
|
struct ieee80211_mutable_offsets *offs,
|
|
- struct sk_buff *bcn);
|
|
+ struct sk_buff *bcn, u32 ema_param);
|
|
int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id);
|
|
int ath11k_wmi_vdev_up(struct ath11k *ar, struct vdev_up_params *params);
|
|
int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id);
|
|
--
|
|
2.7.4
|
|
|