[RFT/PATCH] atk11: add EMA support
John Crispin
john at phrozen.org
Tue Oct 13 03:05:50 EDT 2020
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 at phrozen.org>
---
drivers/net/wireless/ath/ath11k/mac.c | 112 ++++++++++++++------
drivers/net/wireless/ath/ath11k/wmi.c | 5 +-
drivers/net/wireless/ath/ath11k/wmi.h | 27 ++++-
include/net/cfg80211.h | 2 +
include/net/mac80211.h | 79 ++++++++++++--
include/uapi/linux/nl80211.h | 3 +
net/mac80211/cfg.c | 67 ++++++------
net/mac80211/iface.c | 9 +-
net/mac80211/tx.c | 143 ++++++++++++++++++++------
net/wireless/nl80211.c | 5 +-
10 files changed, 338 insertions(+), 114 deletions(-)
Index: backports-20200628-4.4.60-9a94b73e75/drivers/net/wireless/ath/ath11k/mac.c
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/drivers/net/wireless/ath/ath11k/mac.c
+++ backports-20200628-4.4.60-9a94b73e75/drivers/net/wireless/ath/ath11k/mac.c
@@ -1069,32 +1069,19 @@ err_mon_del:
return ret;
}
-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);
@@ -1112,9 +1099,17 @@ static int ath11k_mac_setup_bcn_tmpl(str
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",
@@ -1123,12 +1118,80 @@ static int ath11k_mac_setup_bcn_tmpl(str
return ret;
}
+static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif)
+{
+ 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;
+
+ 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;
+ }
+
+ 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__);
+
+ 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);
+
+ 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, *child, *tmp;
int multiple_bssid = 0;
- if (!vif->multiple_bssid.non_transmitted &&
+ return;
+
+/* if (!vif->multiple_bssid_parent &&
!list_empty(&vif->multiple_bssid.list)) {
if (vif->csa_active) {
if (ieee80211_csa_is_complete(vif)) {
@@ -1146,7 +1209,7 @@ void ath11k_mac_bcn_tx_event(struct ath1
multiple_bssid = 1;
}
-
+*/
if (!multiple_bssid)
return;
@@ -5449,7 +5512,7 @@ ath11k_mac_setup_vdev_create_params(stru
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)
@@ -5457,10 +5520,13 @@ ath11k_mac_setup_vdev_create_params(stru
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;
@@ -6095,7 +6161,7 @@ ath11k_mac_vdev_start_restart(struct ath
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)
@@ -6103,10 +6169,13 @@ ath11k_mac_vdev_start_restart(struct ath
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,
Index: backports-20200628-4.4.60-9a94b73e75/drivers/net/wireless/ath/ath11k/wmi.c
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/drivers/net/wireless/ath/ath11k/wmi.c
+++ backports-20200628-4.4.60-9a94b73e75/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1788,7 +1788,7 @@ int ath11k_wmi_send_bcn_offload_control_
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_pdev_wmi *wmi = ar->wmi;
struct wmi_bcn_tmpl_cmd *cmd;
@@ -1814,6 +1814,7 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *a
cmd->ext_csa_switch_count_offset = offs->csa_counter_offs[1];
cmd->buf_len = bcn->len;
cmd->mbssid_ie_offset = offs->multiple_bssid_offset;
+ cmd->ema_params = ema_params;
ptr = skb->data + sizeof(*cmd);
@@ -3727,6 +3728,8 @@ ath11k_wmi_copy_resource_config(struct w
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,
@@ -3959,6 +3962,8 @@ int ath11k_wmi_cmd_init(struct ath11k_ba
config.peer_map_unmap_v2_support = 1;
config.twt_ap_pdev_count = ab->num_radios;
config.twt_ap_sta_count = 1000;
+ config.ema_max_vap_cnt = 16;
+ config.ema_max_profile_period = 8;
memcpy(&wmi_sc->wlan_resource_config, &config, sizeof(config));
Index: backports-20200628-4.4.60-9a94b73e75/drivers/net/wireless/ath/ath11k/wmi.h
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/drivers/net/wireless/ath/ath11k/wmi.h
+++ backports-20200628-4.4.60-9a94b73e75/drivers/net/wireless/ath/ath11k/wmi.h
@@ -2407,6 +2407,9 @@ struct wmi_resource_config {
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 {
@@ -3620,6 +3623,11 @@ struct wmi_get_pdev_temperature_cmd {
#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;
@@ -5433,6 +5441,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 {
@@ -5647,7 +5657,7 @@ int ath11k_wmi_mgmt_send(struct ath11k *
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);
Index: backports-20200628-4.4.60-9a94b73e75/include/net/cfg80211.h
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/include/net/cfg80211.h
+++ backports-20200628-4.4.60-9a94b73e75/include/net/cfg80211.h
@@ -460,14 +460,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;
};
/**
@@ -614,7 +614,6 @@ static inline void wiphy_read_of_freq_li
* belonging to that MU-MIMO groupID; %NULL if not changed
* @vht_mumimo_follow_addr: MU-MIMO follow address, used for monitoring
* MU-MIMO packets going to the specified station; %NULL if not changed
- * @multiple_bssid: AP settings for multiple bssid
*/
struct vif_params {
u32 flags;
@@ -622,7 +621,6 @@ struct vif_params {
u8 macaddr[ETH_ALEN];
const u8 *vht_mumimo_groups;
const u8 *vht_mumimo_follow_addr;
- struct ieee80211_multiple_bssid multiple_bssid;
};
/**
Index: backports-20200628-4.4.60-9a94b73e75/include/net/mac80211.h
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/include/net/mac80211.h
+++ backports-20200628-4.4.60-9a94b73e75/include/net/mac80211.h
@@ -642,7 +642,7 @@ struct ieee80211_fils_discovery {
* @fils_discovery: FILS discovery configuration
* @unsol_bcast_probe_resp_interval: Unsolicited broadcast probe response
* interval.
- `* @multiple_bssid: the multiple bssid settings of the AP.
+ * @multiple_bssid: the multiple bssid settings of the AP.
*/
struct ieee80211_bss_conf {
const u8 *bssid;
@@ -1644,6 +1644,12 @@ enum ieee80211_vif_flags {
IEEE80211_VIF_GET_NOA_UPDATE = BIT(3),
};
+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
*
@@ -1685,8 +1691,6 @@ enum ieee80211_vif_flags {
* @txqs_stopped: per AC flag to indicate that intermediate TXQs are stopped,
* protected by fq->lock.
* @multiple_bssid.parent: a non-transmitted bssid has a transmitted parent.
- * @multiple_bssid.list: linked list for tracking parent - child relations.
- * @multiple_bssid.non_transmitted: Is this a non-transmitted bssi
*/
struct ieee80211_vif {
enum nl80211_iftype type;
@@ -1716,8 +1720,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;
/* must be last */
@@ -4874,7 +4877,21 @@ ieee80211_beacon_get_template(struct iee
struct ieee80211_mutable_offsets *offs);
/**
- * ieee80211_beacon_get_template - beacon template generation function
+ * 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
@@ -4883,7 +4900,8 @@ ieee80211_beacon_get_template(struct iee
* 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.
+ * 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
*
@@ -4891,9 +4909,57 @@ ieee80211_beacon_get_template(struct iee
*/
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 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
Index: backports-20200628-4.4.60-9a94b73e75/include/uapi/linux/nl80211.h
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/include/uapi/linux/nl80211.h
+++ backports-20200628-4.4.60-9a94b73e75/include/uapi/linux/nl80211.h
@@ -2522,9 +2522,6 @@ enum nl80211_commands {
* unsolicited broadcast probe response. It is a nested attribute, see
* &enum nl80211_unsol_bcast_probe_resp_attributes.
*
- * @NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING: Set the Non-Transmitted flag for this
- * BSSIDs beacon.
- *
* @NL80211_ATTR_MULTIPLE_BSSID_PARENT: If this is a Non-Transmitted BSSID, define
* the parent (transmitting) interface.
*
@@ -2536,6 +2533,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.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -3024,11 +3023,11 @@ enum nl80211_attrs {
NL80211_ATTR_UNSOL_BCAST_PROBE_RESP,
- NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING,
NL80211_ATTR_MULTIPLE_BSSID_PARENT,
NL80211_ATTR_MULTIPLE_BSSID_INDEX,
NL80211_ATTR_MULTIPLE_BSSID_COUNT,
NL80211_ATTR_MULTIPLE_BSSID_IES,
+ NL80211_ATTR_MULTIPLE_BSSID_EMA,
/* add attributes here, update the policy in nl80211.c */
Index: backports-20200628-4.4.60-9a94b73e75/net/mac80211/cfg.c
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/net/mac80211/cfg.c
+++ backports-20200628-4.4.60-9a94b73e75/net/mac80211/cfg.c
@@ -111,8 +111,8 @@ static int ieee80211_set_mon_options(str
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,25 +120,28 @@ static int ieee80211_set_multiple_bssid_
struct ieee80211_sub_if_data *psdata;
if (!ieee80211_hw_check(&local->hw, SUPPORTS_MULTI_BSSID_AP))
- return 0;
+ return;
+
+ if (!params->multiple_bssid.count)
+ return;
- if (params->multiple_bssid.non_transmitted) {
+ 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 {
- INIT_LIST_HEAD(&sdata->vif.multiple_bssid.list);
+ 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,
@@ -166,32 +169,25 @@ static struct wireless_dev *ieee80211_ad
}
}
- 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->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;
}
}
@@ -1180,6 +1176,9 @@ static int ieee80211_start_ap(struct wip
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);
@@ -1228,8 +1227,6 @@ static int ieee80211_start_ap(struct wip
sizeof(struct ieee80211_he_obss_pd));
memcpy(&sdata->vif.bss_conf.he_bss_color, ¶ms->he_bss_color,
sizeof(struct ieee80211_he_bss_color));
- sdata->vif.bss_conf.multiple_bssid.count = params->multiple_bssid.count;
- sdata->vif.bss_conf.multiple_bssid.index = params->multiple_bssid.index;
sdata->vif.bss_conf.ssid_len = params->ssid_len;
if (params->ssid_len)
Index: backports-20200628-4.4.60-9a94b73e75/net/mac80211/iface.c
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/net/mac80211/iface.c
+++ backports-20200628-4.4.60-9a94b73e75/net/mac80211/iface.c
@@ -851,12 +851,11 @@ static void ieee80211_do_stop(struct iee
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);
Index: backports-20200628-4.4.60-9a94b73e75/net/mac80211/tx.c
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/net/mac80211/tx.c
+++ backports-20200628-4.4.60-9a94b73e75/net/mac80211/tx.c
@@ -4802,7 +4802,7 @@ __ieee80211_beacon_get(struct ieee80211_
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_
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_
beacon = rcu_dereference(ap->beacon);
if (beacon) {
- int ema_len = 0;
+ int multiple_bssid_len = 0;
+
if (beacon->csa_counter_offsets[0]) {
if (!is_template)
__ieee80211_csa_update_counter(beacon);
@@ -4838,8 +4837,26 @@ __ieee80211_beacon_get(struct ieee80211_
ieee80211_set_csa(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_
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);
@@ -4867,16 +4884,22 @@ __ieee80211_beacon_get(struct ieee80211_
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]);
- if (offs)
- offs->multiple_bssid_offset = skb->len - ema_len;
+ skb_put_data(skb, beacon->multiple_bssid.ies[ema_index],
+ beacon->multiple_bssid.len[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]);
+ }
- beacon->ema_index++;
- beacon->ema_index %= beacon->multiple_bssid.cnt;
+ if (offs)
+ offs->multiple_bssid_offset = skb->len - multiple_bssid_len;
}
if (beacon->tail)
@@ -4884,16 +4907,16 @@ __ieee80211_beacon_get(struct ieee80211_
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->csa_counter_offsets[0]) {
if (!is_template)
@@ -4905,7 +4928,7 @@ __ieee80211_beacon_get(struct ieee80211_
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);
@@ -4917,7 +4940,7 @@ __ieee80211_beacon_get(struct ieee80211_
beacon = rcu_dereference(ifmsh->beacon);
if (!beacon)
- goto out;
+ return NULL;
if (beacon->csa_counter_offsets[0]) {
if (!is_template)
@@ -4940,7 +4963,7 @@ __ieee80211_beacon_get(struct ieee80211_
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);
@@ -4953,7 +4976,7 @@ __ieee80211_beacon_get(struct ieee80211_
skb_put_data(skb, beacon->tail, beacon->tail_len);
} else {
WARN_ON(1);
- goto out;
+ return NULL;
}
/* CSA offsets */
@@ -4996,8 +5019,6 @@ __ieee80211_beacon_get(struct ieee80211_
info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT |
IEEE80211_TX_CTL_ASSIGN_SEQ |
IEEE80211_TX_CTL_FIRST_FRAGMENT;
- out:
- rcu_read_unlock();
return skb;
}
@@ -5007,25 +5028,86 @@ ieee80211_beacon_get_template(struct iee
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)
{
- return __ieee80211_beacon_get(hw, vif, offs, true, true);
+ 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);
+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;
Index: backports-20200628-4.4.60-9a94b73e75/net/wireless/nl80211.c
===================================================================
--- backports-20200628-4.4.60-9a94b73e75.orig/net/wireless/nl80211.c
+++ backports-20200628-4.4.60-9a94b73e75/net/wireless/nl80211.c
@@ -758,10 +758,10 @@ static const struct nla_policy nl80211_p
NLA_POLICY_NESTED(fils_discovery_policy),
[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP] =
NLA_POLICY_NESTED(unsol_bcast_probe_resp_policy),
- [NL80211_ATTR_MULTIPLE_BSSID_NON_TRANSMITTING] = { .type = NLA_FLAG },
[NL80211_ATTR_MULTIPLE_BSSID_PARENT] = { .type = NLA_U32 },
[NL80211_ATTR_MULTIPLE_BSSID_INDEX] = { .type = NLA_U8 },
[NL80211_ATTR_MULTIPLE_BSSID_COUNT] = { .type = NLA_U8 },
+ [NL80211_ATTR_MULTIPLE_BSSID_EMA] = { .type = NLA_FLAG },
[NL80211_ATTR_MULTIPLE_BSSID_IES] = { .type = NLA_NESTED },
};
@@ -3862,14 +3862,6 @@ static int nl80211_new_interface(struct
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;
@@ -5265,6 +5257,10 @@ static int nl80211_start_ap(struct sk_bu
return err;
}
+ 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]);
@@ -5272,10 +5268,10 @@ static int nl80211_start_ap(struct sk_bu
if (info->attrs[NL80211_ATTR_MULTIPLE_BSSID_COUNT])
params.multiple_bssid.count = nla_get_u8(
info->attrs[NL80211_ATTR_MULTIPLE_BSSID_COUNT]);
+ params.multiple_bssid.ema =
+ nla_get_flag(info->attrs[NL80211_ATTR_MULTIPLE_BSSID_EMA]);
- if (params.multiple_bssid.non_transmitted &&
- !info->attrs[NL80211_ATTR_MULTIPLE_BSSID_PARENT])
- return -EOPNOTSUPP;
+ printk("%s:%s[%d]%p %d %d %d\n", __FILE__, __func__, __LINE__, params.multiple_bssid.parent, params.multiple_bssid.index, params.multiple_bssid.count, params.multiple_bssid.ema);
nl80211_calculate_ap_params(¶ms);
More information about the ath11k
mailing list