mac80211: backport MBSSID/EMA support patches
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -0,0 +1,262 @@ | |||||||
|  | From: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Date: Tue, 5 Oct 2021 21:09:36 -0700 | ||||||
|  | Subject: [PATCH] mac80211: split beacon retrieval functions | ||||||
|  |  | ||||||
|  | Split __ieee80211_beacon_get() into a separate function for AP mode | ||||||
|  | ieee80211_beacon_get_ap(). | ||||||
|  | Also, move the code common to all modes (AP, adhoc and mesh) to | ||||||
|  | a separate function ieee80211_beacon_get_finish(). | ||||||
|  |  | ||||||
|  | Signed-off-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Link: https://lore.kernel.org/r/20211006040938.9531-2-alokad@codeaurora.org | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/tx.c | ||||||
|  | +++ b/net/mac80211/tx.c | ||||||
|  | @@ -4987,6 +4987,115 @@ static int ieee80211_beacon_protect(stru | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static void | ||||||
|  | +ieee80211_beacon_get_finish(struct ieee80211_hw *hw, | ||||||
|  | +			    struct ieee80211_vif *vif, | ||||||
|  | +			    struct ieee80211_mutable_offsets *offs, | ||||||
|  | +			    struct beacon_data *beacon, | ||||||
|  | +			    struct sk_buff *skb, | ||||||
|  | +			    struct ieee80211_chanctx_conf *chanctx_conf, | ||||||
|  | +			    u16 csa_off_base) | ||||||
|  | +{ | ||||||
|  | +	struct ieee80211_local *local = hw_to_local(hw); | ||||||
|  | +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||||||
|  | +	struct ieee80211_tx_info *info; | ||||||
|  | +	enum nl80211_band band; | ||||||
|  | +	struct ieee80211_tx_rate_control txrc; | ||||||
|  | + | ||||||
|  | +	/* CSA offsets */ | ||||||
|  | +	if (offs && beacon) { | ||||||
|  | +		u16 i; | ||||||
|  | + | ||||||
|  | +		for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { | ||||||
|  | +			u16 csa_off = beacon->cntdwn_counter_offsets[i]; | ||||||
|  | + | ||||||
|  | +			if (!csa_off) | ||||||
|  | +				continue; | ||||||
|  | + | ||||||
|  | +			offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; | ||||||
|  | +		} | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	band = chanctx_conf->def.chan->band; | ||||||
|  | +	info = IEEE80211_SKB_CB(skb); | ||||||
|  | +	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||||||
|  | +	info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||||||
|  | +	info->band = band; | ||||||
|  | + | ||||||
|  | +	memset(&txrc, 0, sizeof(txrc)); | ||||||
|  | +	txrc.hw = hw; | ||||||
|  | +	txrc.sband = local->hw.wiphy->bands[band]; | ||||||
|  | +	txrc.bss_conf = &sdata->vif.bss_conf; | ||||||
|  | +	txrc.skb = skb; | ||||||
|  | +	txrc.reported_rate.idx = -1; | ||||||
|  | +	if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) | ||||||
|  | +		txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; | ||||||
|  | +	else | ||||||
|  | +		txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; | ||||||
|  | +	txrc.bss = true; | ||||||
|  | +	rate_control_get_rate(sdata, NULL, &txrc); | ||||||
|  | + | ||||||
|  | +	info->control.vif = vif; | ||||||
|  | +	info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | | ||||||
|  | +		       IEEE80211_TX_CTL_ASSIGN_SEQ | | ||||||
|  | +		       IEEE80211_TX_CTL_FIRST_FRAGMENT; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct sk_buff * | ||||||
|  | +ieee80211_beacon_get_ap(struct ieee80211_hw *hw, | ||||||
|  | +			struct ieee80211_vif *vif, | ||||||
|  | +			struct ieee80211_mutable_offsets *offs, | ||||||
|  | +			bool is_template, | ||||||
|  | +			struct beacon_data *beacon, | ||||||
|  | +			struct ieee80211_chanctx_conf *chanctx_conf) | ||||||
|  | +{ | ||||||
|  | +	struct ieee80211_local *local = hw_to_local(hw); | ||||||
|  | +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||||||
|  | +	struct ieee80211_if_ap *ap = &sdata->u.ap; | ||||||
|  | +	struct sk_buff *skb = NULL; | ||||||
|  | +	u16 csa_off_base = 0; | ||||||
|  | + | ||||||
|  | +	if (beacon->cntdwn_counter_offsets[0]) { | ||||||
|  | +		if (!is_template) | ||||||
|  | +			ieee80211_beacon_update_cntdwn(vif); | ||||||
|  | + | ||||||
|  | +		ieee80211_set_beacon_cntdwn(sdata, beacon); | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	/* headroom, head length, | ||||||
|  | +	 * tail length and maximum TIM length | ||||||
|  | +	 */ | ||||||
|  | +	skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + | ||||||
|  | +			    beacon->tail_len + 256 + | ||||||
|  | +			    local->hw.extra_beacon_tailroom); | ||||||
|  | +	if (!skb) | ||||||
|  | +		return NULL; | ||||||
|  | + | ||||||
|  | +	skb_reserve(skb, local->tx_headroom); | ||||||
|  | +	skb_put_data(skb, beacon->head, beacon->head_len); | ||||||
|  | + | ||||||
|  | +	ieee80211_beacon_add_tim(sdata, &ap->ps, skb, is_template); | ||||||
|  | + | ||||||
|  | +	if (offs) { | ||||||
|  | +		offs->tim_offset = beacon->head_len; | ||||||
|  | +		offs->tim_length = skb->len - beacon->head_len; | ||||||
|  | +		offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; | ||||||
|  | + | ||||||
|  | +		/* for AP the csa offsets are from tail */ | ||||||
|  | +		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) | ||||||
|  | +		return NULL; | ||||||
|  | + | ||||||
|  | +	ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, chanctx_conf, | ||||||
|  | +				    csa_off_base); | ||||||
|  | +	return skb; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static struct sk_buff * | ||||||
|  |  __ieee80211_beacon_get(struct ieee80211_hw *hw, | ||||||
|  |  		       struct ieee80211_vif *vif, | ||||||
|  | @@ -4996,12 +5105,8 @@ __ieee80211_beacon_get(struct ieee80211_ | ||||||
|  |  	struct ieee80211_local *local = hw_to_local(hw); | ||||||
|  |  	struct beacon_data *beacon = NULL; | ||||||
|  |  	struct sk_buff *skb = NULL; | ||||||
|  | -	struct ieee80211_tx_info *info; | ||||||
|  |  	struct ieee80211_sub_if_data *sdata = NULL; | ||||||
|  | -	enum nl80211_band band; | ||||||
|  | -	struct ieee80211_tx_rate_control txrc; | ||||||
|  |  	struct ieee80211_chanctx_conf *chanctx_conf; | ||||||
|  | -	int csa_off_base = 0; | ||||||
|  |   | ||||||
|  |  	rcu_read_lock(); | ||||||
|  |   | ||||||
|  | @@ -5018,48 +5123,11 @@ __ieee80211_beacon_get(struct ieee80211_ | ||||||
|  |  		struct ieee80211_if_ap *ap = &sdata->u.ap; | ||||||
|  |   | ||||||
|  |  		beacon = rcu_dereference(ap->beacon); | ||||||
|  | -		if (beacon) { | ||||||
|  | -			if (beacon->cntdwn_counter_offsets[0]) { | ||||||
|  | -				if (!is_template) | ||||||
|  | -					ieee80211_beacon_update_cntdwn(vif); | ||||||
|  | - | ||||||
|  | -				ieee80211_set_beacon_cntdwn(sdata, beacon); | ||||||
|  | -			} | ||||||
|  | - | ||||||
|  | -			/* | ||||||
|  | -			 * headroom, head length, | ||||||
|  | -			 * tail length and maximum TIM length | ||||||
|  | -			 */ | ||||||
|  | -			skb = dev_alloc_skb(local->tx_headroom + | ||||||
|  | -					    beacon->head_len + | ||||||
|  | -					    beacon->tail_len + 256 + | ||||||
|  | -					    local->hw.extra_beacon_tailroom); | ||||||
|  | -			if (!skb) | ||||||
|  | -				goto out; | ||||||
|  | - | ||||||
|  | -			skb_reserve(skb, local->tx_headroom); | ||||||
|  | -			skb_put_data(skb, beacon->head, beacon->head_len); | ||||||
|  | - | ||||||
|  | -			ieee80211_beacon_add_tim(sdata, &ap->ps, skb, | ||||||
|  | -						 is_template); | ||||||
|  | - | ||||||
|  | -			if (offs) { | ||||||
|  | -				offs->tim_offset = beacon->head_len; | ||||||
|  | -				offs->tim_length = skb->len - beacon->head_len; | ||||||
|  | -				offs->cntdwn_counter_offs[0] = beacon->cntdwn_counter_offsets[0]; | ||||||
|  | - | ||||||
|  | -				/* for AP the csa offsets are from tail */ | ||||||
|  | -				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; | ||||||
|  | -		} else | ||||||
|  | +		if (!beacon) | ||||||
|  |  			goto out; | ||||||
|  | + | ||||||
|  | +		skb = ieee80211_beacon_get_ap(hw, vif, offs, is_template, | ||||||
|  | +					      beacon, chanctx_conf); | ||||||
|  |  	} else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | ||||||
|  |  		struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | ||||||
|  |  		struct ieee80211_hdr *hdr; | ||||||
|  | @@ -5085,6 +5153,9 @@ __ieee80211_beacon_get(struct ieee80211_ | ||||||
|  |  		hdr = (struct ieee80211_hdr *) skb->data; | ||||||
|  |  		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||||||
|  |  						 IEEE80211_STYPE_BEACON); | ||||||
|  | + | ||||||
|  | +		ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, | ||||||
|  | +					    chanctx_conf, 0); | ||||||
|  |  	} else if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||||||
|  |  		struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||||||
|  |   | ||||||
|  | @@ -5124,51 +5195,13 @@ __ieee80211_beacon_get(struct ieee80211_ | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  |  		skb_put_data(skb, beacon->tail, beacon->tail_len); | ||||||
|  | +		ieee80211_beacon_get_finish(hw, vif, offs, beacon, skb, | ||||||
|  | +					    chanctx_conf, 0); | ||||||
|  |  	} else { | ||||||
|  |  		WARN_ON(1); | ||||||
|  |  		goto out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | -	/* CSA offsets */ | ||||||
|  | -	if (offs && beacon) { | ||||||
|  | -		int i; | ||||||
|  | - | ||||||
|  | -		for (i = 0; i < IEEE80211_MAX_CNTDWN_COUNTERS_NUM; i++) { | ||||||
|  | -			u16 csa_off = beacon->cntdwn_counter_offsets[i]; | ||||||
|  | - | ||||||
|  | -			if (!csa_off) | ||||||
|  | -				continue; | ||||||
|  | - | ||||||
|  | -			offs->cntdwn_counter_offs[i] = csa_off_base + csa_off; | ||||||
|  | -		} | ||||||
|  | -	} | ||||||
|  | - | ||||||
|  | -	band = chanctx_conf->def.chan->band; | ||||||
|  | - | ||||||
|  | -	info = IEEE80211_SKB_CB(skb); | ||||||
|  | - | ||||||
|  | -	info->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | ||||||
|  | -	info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||||||
|  | -	info->band = band; | ||||||
|  | - | ||||||
|  | -	memset(&txrc, 0, sizeof(txrc)); | ||||||
|  | -	txrc.hw = hw; | ||||||
|  | -	txrc.sband = local->hw.wiphy->bands[band]; | ||||||
|  | -	txrc.bss_conf = &sdata->vif.bss_conf; | ||||||
|  | -	txrc.skb = skb; | ||||||
|  | -	txrc.reported_rate.idx = -1; | ||||||
|  | -	if (sdata->beacon_rate_set && sdata->beacon_rateidx_mask[band]) | ||||||
|  | -		txrc.rate_idx_mask = sdata->beacon_rateidx_mask[band]; | ||||||
|  | -	else | ||||||
|  | -		txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; | ||||||
|  | -	txrc.bss = true; | ||||||
|  | -	rate_control_get_rate(sdata, NULL, &txrc); | ||||||
|  | - | ||||||
|  | -	info->control.vif = vif; | ||||||
|  | - | ||||||
|  | -	info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT | | ||||||
|  | -			IEEE80211_TX_CTL_ASSIGN_SEQ | | ||||||
|  | -			IEEE80211_TX_CTL_FIRST_FRAGMENT; | ||||||
|  |   out: | ||||||
|  |  	rcu_read_unlock(); | ||||||
|  |  	return skb; | ||||||
| @@ -0,0 +1,493 @@ | |||||||
|  | From: John Crispin <john@phrozen.org> | ||||||
|  | Date: Wed, 15 Sep 2021 19:54:34 -0700 | ||||||
|  | Subject: [PATCH] nl80211: MBSSID and EMA support in AP mode | ||||||
|  |  | ||||||
|  | Add new attributes to configure support for multiple BSSID | ||||||
|  | and advanced multi-BSSID advertisements (EMA) in AP mode. | ||||||
|  |  | ||||||
|  | - NL80211_ATTR_MBSSID_CONFIG used for per interface configuration. | ||||||
|  | - NL80211_ATTR_MBSSID_ELEMS used to MBSSID elements for beacons. | ||||||
|  |  | ||||||
|  | Memory for the elements is allocated dynamically. This change frees | ||||||
|  | the memory in existing functions which call nl80211_parse_beacon(), | ||||||
|  | a comment is added to indicate the new references to do the same. | ||||||
|  |  | ||||||
|  | Signed-off-by: John Crispin <john@phrozen.org> | ||||||
|  | Co-developed-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Signed-off-by: Aloka Dixit <alokad@codeaurora.org> | ||||||
|  | Link: https://lore.kernel.org/r/20210916025437.29138-2-alokad@codeaurora.org | ||||||
|  | [don't leave ERR_PTR hanging around] | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/include/net/cfg80211.h | ||||||
|  | +++ b/include/net/cfg80211.h | ||||||
|  | @@ -1046,6 +1046,36 @@ struct cfg80211_crypto_settings { | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | + * struct cfg80211_mbssid_config - AP settings for multi bssid | ||||||
|  | + * | ||||||
|  | + * @tx_wdev: pointer to the transmitted interface in the MBSSID set | ||||||
|  | + * @index: index of this AP in the multi bssid group. | ||||||
|  | + * @ema: set to true if the beacons should be sent out in EMA mode. | ||||||
|  | + */ | ||||||
|  | +struct cfg80211_mbssid_config { | ||||||
|  | +	struct wireless_dev *tx_wdev; | ||||||
|  | +	u8 index; | ||||||
|  | +	bool ema; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  | + * struct cfg80211_mbssid_elems - Multiple BSSID elements | ||||||
|  | + * | ||||||
|  | + * @cnt: Number of elements in array %elems. | ||||||
|  | + * | ||||||
|  | + * @elem: Array of multiple BSSID element(s) to be added into Beacon frames. | ||||||
|  | + * @elem.data: Data for multiple BSSID elements. | ||||||
|  | + * @elem.len: Length of data. | ||||||
|  | + */ | ||||||
|  | +struct cfg80211_mbssid_elems { | ||||||
|  | +	u8 cnt; | ||||||
|  | +	struct { | ||||||
|  | +		const u8 *data; | ||||||
|  | +		size_t len; | ||||||
|  | +	} elem[]; | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  | +/** | ||||||
|  |   * struct cfg80211_beacon_data - beacon data | ||||||
|  |   * @head: head portion of beacon (before TIM IE) | ||||||
|  |   *	or %NULL if not changed | ||||||
|  | @@ -1063,6 +1093,7 @@ struct cfg80211_crypto_settings { | ||||||
|  |   * @assocresp_ies_len: length of assocresp_ies in octets | ||||||
|  |   * @probe_resp_len: length of probe response template (@probe_resp) | ||||||
|  |   * @probe_resp: probe response template (AP mode only) | ||||||
|  | + * @mbssid_ies: multiple BSSID elements | ||||||
|  |   * @ftm_responder: enable FTM responder functionality; -1 for no change | ||||||
|  |   *	(which also implies no change in LCI/civic location data) | ||||||
|  |   * @lci: Measurement Report element content, starting with Measurement Token | ||||||
|  | @@ -1080,6 +1111,7 @@ struct cfg80211_beacon_data { | ||||||
|  |  	const u8 *probe_resp; | ||||||
|  |  	const u8 *lci; | ||||||
|  |  	const u8 *civicloc; | ||||||
|  | +	struct cfg80211_mbssid_elems *mbssid_ies; | ||||||
|  |  	s8 ftm_responder; | ||||||
|  |   | ||||||
|  |  	size_t head_len, tail_len; | ||||||
|  | @@ -1194,6 +1226,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 | ||||||
|  | + * @mbssid_config: AP settings for multiple bssid | ||||||
|  |   */ | ||||||
|  |  struct cfg80211_ap_settings { | ||||||
|  |  	struct cfg80211_chan_def chandef; | ||||||
|  | @@ -1226,6 +1259,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_mbssid_config mbssid_config; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /** | ||||||
|  | @@ -4986,6 +5020,13 @@ struct wiphy_iftype_akm_suites { | ||||||
|  |   *	%NL80211_TID_CONFIG_ATTR_RETRY_LONG attributes | ||||||
|  |   * @sar_capa: SAR control capabilities | ||||||
|  |   * @rfkill: a pointer to the rfkill structure | ||||||
|  | + * | ||||||
|  | + * @mbssid_max_interfaces: maximum number of interfaces supported by the driver | ||||||
|  | + *	in a multiple BSSID set. This field must be set to a non-zero value | ||||||
|  | + *	by the driver to advertise MBSSID support. | ||||||
|  | + * @mbssid_max_ema_profile_periodicity: maximum profile periodicity supported by | ||||||
|  | + *	the driver. Setting this field to a non-zero value indicates that the | ||||||
|  | + *	driver supports enhanced multi-BSSID advertisements (EMA AP). | ||||||
|  |   */ | ||||||
|  |  struct wiphy { | ||||||
|  |  	struct mutex mtx; | ||||||
|  | @@ -5133,6 +5174,9 @@ struct wiphy { | ||||||
|  |   | ||||||
|  |  	struct rfkill *rfkill; | ||||||
|  |   | ||||||
|  | +	u8 mbssid_max_interfaces; | ||||||
|  | +	u8 ema_max_profile_periodicity; | ||||||
|  | + | ||||||
|  |  	char priv[] __aligned(NETDEV_ALIGN); | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | --- a/include/uapi/linux/nl80211.h | ||||||
|  | +++ b/include/uapi/linux/nl80211.h | ||||||
|  | @@ -337,7 +337,10 @@ | ||||||
|  |   * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes | ||||||
|  |   *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from | ||||||
|  |   *	userspace to request deletion of a virtual interface, then requires | ||||||
|  | - *	attribute %NL80211_ATTR_IFINDEX. | ||||||
|  | + *	attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are | ||||||
|  | + *	enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS, | ||||||
|  | + *	and if this command is used for the transmitting interface, then all | ||||||
|  | + *	the non-transmitting interfaces are deleted as well. | ||||||
|  |   * | ||||||
|  |   * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified | ||||||
|  |   *	by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. | ||||||
|  | @@ -2593,6 +2596,18 @@ enum nl80211_commands { | ||||||
|  |   * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE | ||||||
|  |   *	information for the time while performing a color switch. | ||||||
|  |   * | ||||||
|  | + * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID | ||||||
|  | + *	advertisements (MBSSID) parameters in AP mode. | ||||||
|  | + *	Kernel uses this attribute to indicate the driver's support for MBSSID | ||||||
|  | + *	and enhanced multi-BSSID advertisements (EMA AP) to the userspace. | ||||||
|  | + *	Userspace should use this attribute to configure per interface MBSSID | ||||||
|  | + *	parameters. | ||||||
|  | + *	See &enum nl80211_mbssid_config_attributes for details. | ||||||
|  | + * | ||||||
|  | + * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements. | ||||||
|  | + *	Mandatory parameter for the transmitting interface to enable MBSSID. | ||||||
|  | + *	Optional for the non-transmitting interfaces. | ||||||
|  | + * | ||||||
|  |   * @NUM_NL80211_ATTR: total number of nl80211_attrs available | ||||||
|  |   * @NL80211_ATTR_MAX: highest attribute number currently defined | ||||||
|  |   * @__NL80211_ATTR_AFTER_LAST: internal use | ||||||
|  | @@ -3096,6 +3111,9 @@ enum nl80211_attrs { | ||||||
|  |  	NL80211_ATTR_COLOR_CHANGE_COLOR, | ||||||
|  |  	NL80211_ATTR_COLOR_CHANGE_ELEMS, | ||||||
|  |   | ||||||
|  | +	NL80211_ATTR_MBSSID_CONFIG, | ||||||
|  | +	NL80211_ATTR_MBSSID_ELEMS, | ||||||
|  | + | ||||||
|  |  	/* add attributes here, update the policy in nl80211.c */ | ||||||
|  |   | ||||||
|  |  	__NL80211_ATTR_AFTER_LAST, | ||||||
|  | @@ -7349,4 +7367,60 @@ enum nl80211_sar_specs_attrs { | ||||||
|  |  	NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +/** | ||||||
|  | + * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced | ||||||
|  | + * multi-BSSID advertisements (EMA) in AP mode. | ||||||
|  | + * Kernel uses some of these attributes to advertise driver's support for | ||||||
|  | + * MBSSID and EMA. | ||||||
|  | + * Remaining attributes should be used by the userspace to configure the | ||||||
|  | + * features. | ||||||
|  | + * | ||||||
|  | + * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid | ||||||
|  | + * | ||||||
|  | + * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise | ||||||
|  | + *	the maximum number of MBSSID interfaces supported by the driver. | ||||||
|  | + *	Driver should indicate MBSSID support by setting | ||||||
|  | + *	wiphy->mbssid_max_interfaces to a value more than or equal to 2. | ||||||
|  | + * | ||||||
|  | + * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel | ||||||
|  | + *	to advertise the maximum profile periodicity supported by the driver | ||||||
|  | + *	if EMA is enabled. Driver should indicate EMA support to the userspace | ||||||
|  | + *	by setting wiphy->mbssid_max_ema_profile_periodicity to | ||||||
|  | + *	a non-zero value. | ||||||
|  | + * | ||||||
|  | + * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of | ||||||
|  | + *	this BSS (u8) in the multiple BSSID set. | ||||||
|  | + *	Value must be set to 0 for the transmitting interface and non-zero for | ||||||
|  | + *	all non-transmitting interfaces. The userspace will be responsible | ||||||
|  | + *	for using unique indices for the interfaces. | ||||||
|  | + *	Range: 0 to wiphy->mbssid_max_interfaces-1. | ||||||
|  | + * | ||||||
|  | + * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for | ||||||
|  | + *	a non-transmitted profile which provides the interface index (u32) of | ||||||
|  | + *	the transmitted profile. The value must match one of the interface | ||||||
|  | + *	indices advertised by the kernel. Optional if the interface being set up | ||||||
|  | + *	is the transmitting one, however, if provided then the value must match | ||||||
|  | + *	the interface index of the same. | ||||||
|  | + * | ||||||
|  | + * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. | ||||||
|  | + *	Setting this flag is permitted only if the driver advertises EMA support | ||||||
|  | + *	by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero. | ||||||
|  | + * | ||||||
|  | + * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal | ||||||
|  | + * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute | ||||||
|  | + */ | ||||||
|  | +enum nl80211_mbssid_config_attributes { | ||||||
|  | +	__NL80211_MBSSID_CONFIG_ATTR_INVALID, | ||||||
|  | + | ||||||
|  | +	NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, | ||||||
|  | +	NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, | ||||||
|  | +	NL80211_MBSSID_CONFIG_ATTR_INDEX, | ||||||
|  | +	NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, | ||||||
|  | +	NL80211_MBSSID_CONFIG_ATTR_EMA, | ||||||
|  | + | ||||||
|  | +	/* keep last */ | ||||||
|  | +	__NL80211_MBSSID_CONFIG_ATTR_LAST, | ||||||
|  | +	NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1, | ||||||
|  | +}; | ||||||
|  | + | ||||||
|  |  #endif /* __LINUX_NL80211_H */ | ||||||
|  | --- a/net/wireless/nl80211.c | ||||||
|  | +++ b/net/wireless/nl80211.c | ||||||
|  | @@ -439,6 +439,16 @@ sar_policy[NL80211_SAR_ATTR_MAX + 1] = { | ||||||
|  |  	[NL80211_SAR_ATTR_SPECS] = NLA_POLICY_NESTED_ARRAY(sar_specs_policy), | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static const struct nla_policy | ||||||
|  | +nl80211_mbssid_config_policy[NL80211_MBSSID_CONFIG_ATTR_MAX + 1] = { | ||||||
|  | +	[NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES] = NLA_POLICY_MIN(NLA_U8, 2), | ||||||
|  | +	[NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY] = | ||||||
|  | +						NLA_POLICY_MIN(NLA_U8, 1), | ||||||
|  | +	[NL80211_MBSSID_CONFIG_ATTR_INDEX] = { .type = NLA_U8 }, | ||||||
|  | +	[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX] = { .type = NLA_U32 }, | ||||||
|  | +	[NL80211_MBSSID_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 }, | ||||||
|  | @@ -780,6 +790,9 @@ static const struct nla_policy nl80211_p | ||||||
|  |  	[NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 }, | ||||||
|  |  	[NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 }, | ||||||
|  |  	[NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy), | ||||||
|  | +	[NL80211_ATTR_MBSSID_CONFIG] = | ||||||
|  | +			NLA_POLICY_NESTED(nl80211_mbssid_config_policy), | ||||||
|  | +	[NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  /* policy for the key attributes */ | ||||||
|  | @@ -2228,6 +2241,35 @@ fail: | ||||||
|  |  	return -ENOBUFS; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int nl80211_put_mbssid_support(struct wiphy *wiphy, struct sk_buff *msg) | ||||||
|  | +{ | ||||||
|  | +	struct nlattr *config; | ||||||
|  | + | ||||||
|  | +	if (!wiphy->mbssid_max_interfaces) | ||||||
|  | +		return 0; | ||||||
|  | + | ||||||
|  | +	config = nla_nest_start(msg, NL80211_ATTR_MBSSID_CONFIG); | ||||||
|  | +	if (!config) | ||||||
|  | +		return -ENOBUFS; | ||||||
|  | + | ||||||
|  | +	if (nla_put_u8(msg, NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, | ||||||
|  | +		       wiphy->mbssid_max_interfaces)) | ||||||
|  | +		goto fail; | ||||||
|  | + | ||||||
|  | +	if (wiphy->ema_max_profile_periodicity && | ||||||
|  | +	    nla_put_u8(msg, | ||||||
|  | +		       NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, | ||||||
|  | +		       wiphy->ema_max_profile_periodicity)) | ||||||
|  | +		goto fail; | ||||||
|  | + | ||||||
|  | +	nla_nest_end(msg, config); | ||||||
|  | +	return 0; | ||||||
|  | + | ||||||
|  | +fail: | ||||||
|  | +	nla_nest_cancel(msg, config); | ||||||
|  | +	return -ENOBUFS; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  struct nl80211_dump_wiphy_state { | ||||||
|  |  	s64 filter_wiphy; | ||||||
|  |  	long start; | ||||||
|  | @@ -2813,6 +2855,9 @@ static int nl80211_send_wiphy(struct cfg | ||||||
|  |  		if (nl80211_put_sar_specs(rdev, msg)) | ||||||
|  |  			goto nla_put_failure; | ||||||
|  |   | ||||||
|  | +		if (nl80211_put_mbssid_support(&rdev->wiphy, msg)) | ||||||
|  | +			goto nla_put_failure; | ||||||
|  | + | ||||||
|  |  		/* done */ | ||||||
|  |  		state->split_start = 0; | ||||||
|  |  		break; | ||||||
|  | @@ -5002,6 +5047,96 @@ static int validate_beacon_tx_rate(struc | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | +static int nl80211_parse_mbssid_config(struct wiphy *wiphy, | ||||||
|  | +				       struct net_device *dev, | ||||||
|  | +				       struct nlattr *attrs, | ||||||
|  | +				       struct cfg80211_mbssid_config *config, | ||||||
|  | +				       u8 num_elems) | ||||||
|  | +{ | ||||||
|  | +	struct nlattr *tb[NL80211_MBSSID_CONFIG_ATTR_MAX + 1]; | ||||||
|  | + | ||||||
|  | +	if (!wiphy->mbssid_max_interfaces) | ||||||
|  | +		return -EOPNOTSUPP; | ||||||
|  | + | ||||||
|  | +	if (nla_parse_nested(tb, NL80211_MBSSID_CONFIG_ATTR_MAX, attrs, NULL, | ||||||
|  | +			     NULL) || | ||||||
|  | +	    !tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	config->ema = nla_get_flag(tb[NL80211_MBSSID_CONFIG_ATTR_EMA]); | ||||||
|  | +	if (config->ema) { | ||||||
|  | +		if (!wiphy->ema_max_profile_periodicity) | ||||||
|  | +			return -EOPNOTSUPP; | ||||||
|  | + | ||||||
|  | +		if (num_elems > wiphy->ema_max_profile_periodicity) | ||||||
|  | +			return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	config->index = nla_get_u8(tb[NL80211_MBSSID_CONFIG_ATTR_INDEX]); | ||||||
|  | +	if (config->index >= wiphy->mbssid_max_interfaces || | ||||||
|  | +	    (!config->index && !num_elems)) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  | +	if (tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]) { | ||||||
|  | +		u32 tx_ifindex = | ||||||
|  | +			nla_get_u32(tb[NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX]); | ||||||
|  | + | ||||||
|  | +		if ((!config->index && tx_ifindex != dev->ifindex) || | ||||||
|  | +		    (config->index && tx_ifindex == dev->ifindex)) | ||||||
|  | +			return -EINVAL; | ||||||
|  | + | ||||||
|  | +		if (tx_ifindex != dev->ifindex) { | ||||||
|  | +			struct net_device *tx_netdev = | ||||||
|  | +				dev_get_by_index(wiphy_net(wiphy), tx_ifindex); | ||||||
|  | + | ||||||
|  | +			if (!tx_netdev || !tx_netdev->ieee80211_ptr || | ||||||
|  | +			    tx_netdev->ieee80211_ptr->wiphy != wiphy || | ||||||
|  | +			    tx_netdev->ieee80211_ptr->iftype != | ||||||
|  | +							NL80211_IFTYPE_AP) { | ||||||
|  | +				dev_put(tx_netdev); | ||||||
|  | +				return -EINVAL; | ||||||
|  | +			} | ||||||
|  | + | ||||||
|  | +			config->tx_wdev = tx_netdev->ieee80211_ptr; | ||||||
|  | +		} else { | ||||||
|  | +			config->tx_wdev = dev->ieee80211_ptr; | ||||||
|  | +		} | ||||||
|  | +	} else if (!config->index) { | ||||||
|  | +		config->tx_wdev = dev->ieee80211_ptr; | ||||||
|  | +	} else { | ||||||
|  | +		return -EINVAL; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  | +	return 0; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  | +static struct cfg80211_mbssid_elems * | ||||||
|  | +nl80211_parse_mbssid_elems(struct wiphy *wiphy, struct nlattr *attrs) | ||||||
|  | +{ | ||||||
|  | +	struct nlattr *nl_elems; | ||||||
|  | +	struct cfg80211_mbssid_elems *elems; | ||||||
|  | +	int rem_elems; | ||||||
|  | +	u8 i = 0, num_elems = 0; | ||||||
|  | + | ||||||
|  | +	if (!wiphy->mbssid_max_interfaces) | ||||||
|  | +		return ERR_PTR(-EINVAL); | ||||||
|  | + | ||||||
|  | +	nla_for_each_nested(nl_elems, attrs, rem_elems) | ||||||
|  | +		num_elems++; | ||||||
|  | + | ||||||
|  | +	elems = kzalloc(struct_size(elems, elem, num_elems), GFP_KERNEL); | ||||||
|  | +	if (!elems) | ||||||
|  | +		return ERR_PTR(-ENOMEM); | ||||||
|  | + | ||||||
|  | +	nla_for_each_nested(nl_elems, attrs, rem_elems) { | ||||||
|  | +		elems->elem[i].data = nla_data(nl_elems); | ||||||
|  | +		elems->elem[i].len = nla_len(nl_elems); | ||||||
|  | +		i++; | ||||||
|  | +	} | ||||||
|  | +	elems->cnt = num_elems; | ||||||
|  | +	return elems; | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static int nl80211_parse_beacon(struct cfg80211_registered_device *rdev, | ||||||
|  |  				struct nlattr *attrs[], | ||||||
|  |  				struct cfg80211_beacon_data *bcn) | ||||||
|  | @@ -5082,6 +5217,17 @@ static int nl80211_parse_beacon(struct c | ||||||
|  |  		bcn->ftm_responder = -1; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (attrs[NL80211_ATTR_MBSSID_ELEMS]) { | ||||||
|  | +		struct cfg80211_mbssid_elems *mbssid = | ||||||
|  | +			nl80211_parse_mbssid_elems(&rdev->wiphy, | ||||||
|  | +						   attrs[NL80211_ATTR_MBSSID_ELEMS]); | ||||||
|  | + | ||||||
|  | +		if (IS_ERR(mbssid)) | ||||||
|  | +			return PTR_ERR(mbssid); | ||||||
|  | + | ||||||
|  | +		bcn->mbssid_ies = mbssid; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	return 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -5538,6 +5684,17 @@ static int nl80211_start_ap(struct sk_bu | ||||||
|  |  			goto out; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  | +	if (info->attrs[NL80211_ATTR_MBSSID_CONFIG]) { | ||||||
|  | +		err = nl80211_parse_mbssid_config(&rdev->wiphy, dev, | ||||||
|  | +						  info->attrs[NL80211_ATTR_MBSSID_CONFIG], | ||||||
|  | +						  ¶ms.mbssid_config, | ||||||
|  | +						  params.beacon.mbssid_ies ? | ||||||
|  | +							params.beacon.mbssid_ies->cnt : | ||||||
|  | +							0); | ||||||
|  | +		if (err) | ||||||
|  | +			goto out; | ||||||
|  | +	} | ||||||
|  | + | ||||||
|  |  	nl80211_calculate_ap_params(¶ms); | ||||||
|  |   | ||||||
|  |  	if (info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT]) | ||||||
|  | @@ -5559,6 +5716,11 @@ static int nl80211_start_ap(struct sk_bu | ||||||
|  |   | ||||||
|  |  out: | ||||||
|  |  	kfree(params.acl); | ||||||
|  | +	kfree(params.beacon.mbssid_ies); | ||||||
|  | +	if (params.mbssid_config.tx_wdev && | ||||||
|  | +	    params.mbssid_config.tx_wdev->netdev && | ||||||
|  | +	    params.mbssid_config.tx_wdev->netdev != dev) | ||||||
|  | +		dev_put(params.mbssid_config.tx_wdev->netdev); | ||||||
|  |   | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  | @@ -5583,12 +5745,14 @@ static int nl80211_set_beacon(struct sk_ | ||||||
|  |   | ||||||
|  |  	err = nl80211_parse_beacon(rdev, info->attrs, ¶ms); | ||||||
|  |  	if (err) | ||||||
|  | -		return err; | ||||||
|  | +		goto out; | ||||||
|  |   | ||||||
|  |  	wdev_lock(wdev); | ||||||
|  |  	err = rdev_change_beacon(rdev, dev, ¶ms); | ||||||
|  |  	wdev_unlock(wdev); | ||||||
|  |   | ||||||
|  | +out: | ||||||
|  | +	kfree(params.mbssid_ies); | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | @@ -9265,12 +9429,14 @@ static int nl80211_channel_switch(struct | ||||||
|  |   | ||||||
|  |  	err = nl80211_parse_beacon(rdev, info->attrs, ¶ms.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], | ||||||
|  | @@ -9389,6 +9555,8 @@ skip_beacons: | ||||||
|  |  	wdev_unlock(wdev); | ||||||
|  |   | ||||||
|  |  free: | ||||||
|  | +	kfree(params.beacon_after.mbssid_ies); | ||||||
|  | +	kfree(params.beacon_csa.mbssid_ies); | ||||||
|  |  	kfree(csa_attrs); | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
|  | @@ -14924,6 +15092,8 @@ static int nl80211_color_change(struct s | ||||||
|  |  	wdev_unlock(wdev); | ||||||
|  |   | ||||||
|  |  out: | ||||||
|  | +	kfree(params.beacon_next.mbssid_ies); | ||||||
|  | +	kfree(params.beacon_color_change.mbssid_ies); | ||||||
|  |  	kfree(tb); | ||||||
|  |  	return err; | ||||||
|  |  } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| --- a/include/net/cfg80211.h | --- a/include/net/cfg80211.h | ||||||
| +++ b/include/net/cfg80211.h | +++ b/include/net/cfg80211.h | ||||||
| @@ -3835,6 +3835,7 @@ struct mgmt_frame_regs { | @@ -3869,6 +3869,7 @@ struct mgmt_frame_regs { | ||||||
|   *	(as advertised by the nl80211 feature flag.) |   *	(as advertised by the nl80211 feature flag.) | ||||||
|   * @get_tx_power: store the current TX power into the dbm variable; |   * @get_tx_power: store the current TX power into the dbm variable; | ||||||
|   *	return 0 if successful |   *	return 0 if successful | ||||||
| @@ -8,7 +8,7 @@ | |||||||
|   * |   * | ||||||
|   * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting |   * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting | ||||||
|   *	functions to adjust rfkill hw state |   *	functions to adjust rfkill hw state | ||||||
| @@ -4159,6 +4160,7 @@ struct cfg80211_ops { | @@ -4193,6 +4194,7 @@ struct cfg80211_ops { | ||||||
|  				enum nl80211_tx_power_setting type, int mbm); |  				enum nl80211_tx_power_setting type, int mbm); | ||||||
|  	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, |  	int	(*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev, | ||||||
|  				int *dbm); |  				int *dbm); | ||||||
| @@ -36,9 +36,9 @@ | |||||||
|  	u8 ps_dtim_period; |  	u8 ps_dtim_period; | ||||||
| --- a/include/uapi/linux/nl80211.h | --- a/include/uapi/linux/nl80211.h | ||||||
| +++ b/include/uapi/linux/nl80211.h | +++ b/include/uapi/linux/nl80211.h | ||||||
| @@ -2593,6 +2593,9 @@ enum nl80211_commands { | @@ -2608,6 +2608,9 @@ enum nl80211_commands { | ||||||
|   * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE |   *	Mandatory parameter for the transmitting interface to enable MBSSID. | ||||||
|   *	information for the time while performing a color switch. |   *	Optional for the non-transmitting interfaces. | ||||||
|   * |   * | ||||||
| + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce | + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce | ||||||
| + *	transmit power to stay within regulatory limits. u32, dBi. | + *	transmit power to stay within regulatory limits. u32, dBi. | ||||||
| @@ -46,9 +46,9 @@ | |||||||
|   * @NUM_NL80211_ATTR: total number of nl80211_attrs available |   * @NUM_NL80211_ATTR: total number of nl80211_attrs available | ||||||
|   * @NL80211_ATTR_MAX: highest attribute number currently defined |   * @NL80211_ATTR_MAX: highest attribute number currently defined | ||||||
|   * @__NL80211_ATTR_AFTER_LAST: internal use |   * @__NL80211_ATTR_AFTER_LAST: internal use | ||||||
| @@ -3096,6 +3099,8 @@ enum nl80211_attrs { | @@ -3114,6 +3117,8 @@ enum nl80211_attrs { | ||||||
|  	NL80211_ATTR_COLOR_CHANGE_COLOR, |  	NL80211_ATTR_MBSSID_CONFIG, | ||||||
|  	NL80211_ATTR_COLOR_CHANGE_ELEMS, |  	NL80211_ATTR_MBSSID_ELEMS, | ||||||
|   |   | ||||||
| +	NL80211_ATTR_WIPHY_ANTENNA_GAIN, | +	NL80211_ATTR_WIPHY_ANTENNA_GAIN, | ||||||
| + | + | ||||||
| @@ -129,19 +129,18 @@ | |||||||
|  	local->hw.max_mtu = IEEE80211_MAX_DATA_LEN; |  	local->hw.max_mtu = IEEE80211_MAX_DATA_LEN; | ||||||
| --- a/net/wireless/nl80211.c | --- a/net/wireless/nl80211.c | ||||||
| +++ b/net/wireless/nl80211.c | +++ b/net/wireless/nl80211.c | ||||||
| @@ -780,6 +780,7 @@ static const struct nla_policy nl80211_p | @@ -793,6 +793,7 @@ static const struct nla_policy nl80211_p | ||||||
|  	[NL80211_ATTR_COLOR_CHANGE_COUNT] = { .type = NLA_U8 }, |  	[NL80211_ATTR_MBSSID_CONFIG] = | ||||||
|  	[NL80211_ATTR_COLOR_CHANGE_COLOR] = { .type = NLA_U8 }, |  			NLA_POLICY_NESTED(nl80211_mbssid_config_policy), | ||||||
|  	[NL80211_ATTR_COLOR_CHANGE_ELEMS] = NLA_POLICY_NESTED(nl80211_policy), |  	[NL80211_ATTR_MBSSID_ELEMS] = { .type = NLA_NESTED }, | ||||||
| +	[NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, | +	[NL80211_ATTR_WIPHY_ANTENNA_GAIN] = { .type = NLA_U32 }, | ||||||
|  }; |  }; | ||||||
|   |   | ||||||
|  /* policy for the key attributes */ |  /* policy for the key attributes */ | ||||||
| @@ -3328,6 +3329,22 @@ static int nl80211_set_wiphy(struct sk_b | @@ -3374,6 +3375,22 @@ static int nl80211_set_wiphy(struct sk_b | ||||||
|  		if (result) |  | ||||||
|  			goto out; |  			goto out; | ||||||
|  	} |  	} | ||||||
| + |   | ||||||
| +	if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { | +	if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_GAIN]) { | ||||||
| +		int idx, dbi = 0; | +		int idx, dbi = 0; | ||||||
| + | + | ||||||
| @@ -157,6 +156,7 @@ | |||||||
| +		if (result) | +		if (result) | ||||||
| +			goto out; | +			goto out; | ||||||
| +	} | +	} | ||||||
|   | + | ||||||
|  	if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { |  	if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) { | ||||||
|  		struct wireless_dev *txp_wdev = wdev; |  		struct wireless_dev *txp_wdev = wdev; | ||||||
|  |  		enum nl80211_tx_power_setting type; | ||||||
|   | |||||||
| @@ -30,19 +30,7 @@ | |||||||
|   * enum nl80211_commands - supported nl80211 commands |   * enum nl80211_commands - supported nl80211 commands | ||||||
|   * |   * | ||||||
|   * @NL80211_CMD_UNSPEC: unspecified command to catch errors |   * @NL80211_CMD_UNSPEC: unspecified command to catch errors | ||||||
| @@ -360,10 +337,7 @@ | @@ -1226,12 +1203,6 @@ | ||||||
|   * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes |  | ||||||
|   *	%NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from |  | ||||||
|   *	userspace to request deletion of a virtual interface, then requires |  | ||||||
| - *	attribute %NL80211_ATTR_IFINDEX. If multiple BSSID advertisements are |  | ||||||
| - *	enabled using %NL80211_ATTR_MBSSID_CONFIG, %NL80211_ATTR_MBSSID_ELEMS, |  | ||||||
| - *	and if this command is used for the transmitting interface, then all |  | ||||||
| - *	the non-transmitting interfaces are deleted as well. |  | ||||||
| + *	attribute %NL80211_ATTR_IFINDEX. |  | ||||||
|   * |  | ||||||
|   * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified |  | ||||||
|   *	by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. |  | ||||||
| @@ -1226,12 +1200,6 @@ |  | ||||||
|   * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change |   * @NL80211_CMD_COLOR_CHANGE_COMPLETED: Notify userland that the color change | ||||||
|   *	has completed |   *	has completed | ||||||
|   * |   * | ||||||
| @@ -55,7 +43,7 @@ | |||||||
|   * @NL80211_CMD_MAX: highest used command number |   * @NL80211_CMD_MAX: highest used command number | ||||||
|   * @__NL80211_CMD_AFTER_LAST: internal use |   * @__NL80211_CMD_AFTER_LAST: internal use | ||||||
|   */ |   */ | ||||||
| @@ -1472,8 +1440,6 @@ enum nl80211_commands { | @@ -1472,8 +1443,6 @@ enum nl80211_commands { | ||||||
|  	NL80211_CMD_COLOR_CHANGE_ABORTED, |  	NL80211_CMD_COLOR_CHANGE_ABORTED, | ||||||
|  	NL80211_CMD_COLOR_CHANGE_COMPLETED, |  	NL80211_CMD_COLOR_CHANGE_COMPLETED, | ||||||
|   |   | ||||||
| @@ -64,37 +52,26 @@ | |||||||
|  	/* add new commands above here */ |  	/* add new commands above here */ | ||||||
|   |   | ||||||
|  	/* used to define NL80211_CMD_MAX below */ |  	/* used to define NL80211_CMD_MAX below */ | ||||||
| @@ -2627,17 +2593,8 @@ enum nl80211_commands { | @@ -2639,6 +2608,9 @@ enum nl80211_commands { | ||||||
|   * @NL80211_ATTR_COLOR_CHANGE_ELEMS: Nested set of attributes containing the IE |   *	Mandatory parameter for the transmitting interface to enable MBSSID. | ||||||
|   *	information for the time while performing a color switch. |   *	Optional for the non-transmitting interfaces. | ||||||
|   * |   * | ||||||
| - * @NL80211_ATTR_MBSSID_CONFIG: Nested attribute for multiple BSSID |  | ||||||
| - *	advertisements (MBSSID) parameters in AP mode. |  | ||||||
| - *	Kernel uses this attribute to indicate the driver's support for MBSSID |  | ||||||
| - *	and enhanced multi-BSSID advertisements (EMA AP) to the userspace. |  | ||||||
| - *	Userspace should use this attribute to configure per interface MBSSID |  | ||||||
| - *	parameters. |  | ||||||
| - *	See &enum nl80211_mbssid_config_attributes for details. |  | ||||||
| - * |  | ||||||
| - * @NL80211_ATTR_MBSSID_ELEMS: Nested parameter to pass multiple BSSID elements. |  | ||||||
| - *	Mandatory parameter for the transmitting interface to enable MBSSID. |  | ||||||
| - *	Optional for the non-transmitting interfaces. |  | ||||||
| + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce | + * @NL80211_ATTR_WIPHY_ANTENNA_GAIN: Configured antenna gain. Used to reduce | ||||||
| + *	transmit power to stay within regulatory limits. u32, dBi. | + *	transmit power to stay within regulatory limits. u32, dBi. | ||||||
|   * | + * | ||||||
|   * @NUM_NL80211_ATTR: total number of nl80211_attrs available |   * @NUM_NL80211_ATTR: total number of nl80211_attrs available | ||||||
|   * @NL80211_ATTR_MAX: highest attribute number currently defined |   * @NL80211_ATTR_MAX: highest attribute number currently defined | ||||||
| @@ -3142,8 +3099,7 @@ enum nl80211_attrs { |   * @__NL80211_ATTR_AFTER_LAST: internal use | ||||||
|  	NL80211_ATTR_COLOR_CHANGE_COLOR, | @@ -3145,6 +3117,8 @@ enum nl80211_attrs { | ||||||
|  	NL80211_ATTR_COLOR_CHANGE_ELEMS, |  	NL80211_ATTR_MBSSID_CONFIG, | ||||||
|  |  	NL80211_ATTR_MBSSID_ELEMS, | ||||||
|   |   | ||||||
| -	NL80211_ATTR_MBSSID_CONFIG, |  | ||||||
| -	NL80211_ATTR_MBSSID_ELEMS, |  | ||||||
| +	NL80211_ATTR_WIPHY_ANTENNA_GAIN, | +	NL80211_ATTR_WIPHY_ANTENNA_GAIN, | ||||||
|   | + | ||||||
|  	/* add attributes here, update the policy in nl80211.c */ |  	/* add attributes here, update the policy in nl80211.c */ | ||||||
|   |   | ||||||
| @@ -4978,7 +4934,6 @@ enum nl80211_txrate_gi { |  	__NL80211_ATTR_AFTER_LAST, | ||||||
|  | @@ -4978,7 +4952,6 @@ enum nl80211_txrate_gi { | ||||||
|   * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) |   * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 69.12 GHz) | ||||||
|   * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) |   * @NL80211_BAND_6GHZ: around 6 GHz band (5.9 - 7.2 GHz) | ||||||
|   * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs |   * @NL80211_BAND_S1GHZ: around 900MHz, supported by S1G PHYs | ||||||
| @@ -102,7 +79,7 @@ | |||||||
|   * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace |   * @NUM_NL80211_BANDS: number of bands, avoid using this in userspace | ||||||
|   *	since newer kernel versions may support more bands |   *	since newer kernel versions may support more bands | ||||||
|   */ |   */ | ||||||
| @@ -4988,7 +4943,6 @@ enum nl80211_band { | @@ -4988,7 +4961,6 @@ enum nl80211_band { | ||||||
|  	NL80211_BAND_60GHZ, |  	NL80211_BAND_60GHZ, | ||||||
|  	NL80211_BAND_6GHZ, |  	NL80211_BAND_6GHZ, | ||||||
|  	NL80211_BAND_S1GHZ, |  	NL80211_BAND_S1GHZ, | ||||||
| @@ -110,7 +87,7 @@ | |||||||
|   |   | ||||||
|  	NUM_NL80211_BANDS, |  	NUM_NL80211_BANDS, | ||||||
|  }; |  }; | ||||||
| @@ -6046,11 +6000,6 @@ enum nl80211_feature_flags { | @@ -6046,11 +6018,6 @@ enum nl80211_feature_flags { | ||||||
|   * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision |   * @NL80211_EXT_FEATURE_BSS_COLOR: The driver supports BSS color collision | ||||||
|   *	detection and change announcemnts. |   *	detection and change announcemnts. | ||||||
|   * |   * | ||||||
| @@ -122,7 +99,7 @@ | |||||||
|   * @NUM_NL80211_EXT_FEATURES: number of extended features. |   * @NUM_NL80211_EXT_FEATURES: number of extended features. | ||||||
|   * @MAX_NL80211_EXT_FEATURES: highest extended feature index. |   * @MAX_NL80211_EXT_FEATURES: highest extended feature index. | ||||||
|   */ |   */ | ||||||
| @@ -6116,7 +6065,6 @@ enum nl80211_ext_feature_index { | @@ -6116,7 +6083,6 @@ enum nl80211_ext_feature_index { | ||||||
|  	NL80211_EXT_FEATURE_SECURE_RTT, |  	NL80211_EXT_FEATURE_SECURE_RTT, | ||||||
|  	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, |  	NL80211_EXT_FEATURE_PROT_RANGE_NEGO_AND_MEASURE, | ||||||
|  	NL80211_EXT_FEATURE_BSS_COLOR, |  	NL80211_EXT_FEATURE_BSS_COLOR, | ||||||
| @@ -130,67 +107,24 @@ | |||||||
|   |   | ||||||
|  	/* add new features before the definition below */ |  	/* add new features before the definition below */ | ||||||
|  	NUM_NL80211_EXT_FEATURES, |  	NUM_NL80211_EXT_FEATURES, | ||||||
| @@ -7406,60 +7354,4 @@ enum nl80211_sar_specs_attrs { | @@ -7424,7 +7390,7 @@ enum nl80211_sar_specs_attrs { | ||||||
|  	NL80211_SAR_ATTR_SPECS_MAX = __NL80211_SAR_ATTR_SPECS_LAST - 1, |   * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel | ||||||
|  }; |   *	to advertise the maximum profile periodicity supported by the driver | ||||||
|   |   *	if EMA is enabled. Driver should indicate EMA support to the userspace | ||||||
| -/** |  | ||||||
| - * enum nl80211_mbssid_config_attributes - multiple BSSID (MBSSID) and enhanced |  | ||||||
| - * multi-BSSID advertisements (EMA) in AP mode. |  | ||||||
| - * Kernel uses some of these attributes to advertise driver's support for |  | ||||||
| - * MBSSID and EMA. |  | ||||||
| - * Remaining attributes should be used by the userspace to configure the |  | ||||||
| - * features. |  | ||||||
| - * |  | ||||||
| - * @__NL80211_MBSSID_CONFIG_ATTR_INVALID: Invalid |  | ||||||
| - * |  | ||||||
| - * @NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES: Used by the kernel to advertise |  | ||||||
| - *	the maximum number of MBSSID interfaces supported by the driver. |  | ||||||
| - *	Driver should indicate MBSSID support by setting |  | ||||||
| - *	wiphy->mbssid_max_interfaces to a value more than or equal to 2. |  | ||||||
| - * |  | ||||||
| - * @NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY: Used by the kernel |  | ||||||
| - *	to advertise the maximum profile periodicity supported by the driver |  | ||||||
| - *	if EMA is enabled. Driver should indicate EMA support to the userspace |  | ||||||
| - *	by setting wiphy->ema_max_profile_periodicity to | - *	by setting wiphy->ema_max_profile_periodicity to | ||||||
| - *	a non-zero value. | + *	by setting wiphy->mbssid_max_ema_profile_periodicity to | ||||||
| - * |   *	a non-zero value. | ||||||
| - * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of |   * | ||||||
| - *	this BSS (u8) in the multiple BSSID set. |   * @NL80211_MBSSID_CONFIG_ATTR_INDEX: Mandatory parameter to pass the index of | ||||||
| - *	Value must be set to 0 for the transmitting interface and non-zero for | @@ -7443,7 +7409,7 @@ enum nl80211_sar_specs_attrs { | ||||||
| - *	all non-transmitting interfaces. The userspace will be responsible |   * | ||||||
| - *	for using unique indices for the interfaces. |   * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. | ||||||
| - *	Range: 0 to wiphy->mbssid_max_interfaces-1. |   *	Setting this flag is permitted only if the driver advertises EMA support | ||||||
| - * |  | ||||||
| - * @NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX: Mandatory parameter for |  | ||||||
| - *	a non-transmitted profile which provides the interface index (u32) of |  | ||||||
| - *	the transmitted profile. The value must match one of the interface |  | ||||||
| - *	indices advertised by the kernel. Optional if the interface being set up |  | ||||||
| - *	is the transmitting one, however, if provided then the value must match |  | ||||||
| - *	the interface index of the same. |  | ||||||
| - * |  | ||||||
| - * @NL80211_MBSSID_CONFIG_ATTR_EMA: Flag used to enable EMA AP feature. |  | ||||||
| - *	Setting this flag is permitted only if the driver advertises EMA support |  | ||||||
| - *	by setting wiphy->ema_max_profile_periodicity to non-zero. | - *	by setting wiphy->ema_max_profile_periodicity to non-zero. | ||||||
| - * | + *	by setting wiphy->mbssid_max_ema_profile_periodicity to non-zero. | ||||||
| - * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal |   * | ||||||
| - * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute |   * @__NL80211_MBSSID_CONFIG_ATTR_LAST: Internal | ||||||
| - */ |   * @NL80211_MBSSID_CONFIG_ATTR_MAX: highest attribute | ||||||
| -enum nl80211_mbssid_config_attributes { |  | ||||||
| -	__NL80211_MBSSID_CONFIG_ATTR_INVALID, |  | ||||||
| - |  | ||||||
| -	NL80211_MBSSID_CONFIG_ATTR_MAX_INTERFACES, |  | ||||||
| -	NL80211_MBSSID_CONFIG_ATTR_MAX_EMA_PROFILE_PERIODICITY, |  | ||||||
| -	NL80211_MBSSID_CONFIG_ATTR_INDEX, |  | ||||||
| -	NL80211_MBSSID_CONFIG_ATTR_TX_IFINDEX, |  | ||||||
| -	NL80211_MBSSID_CONFIG_ATTR_EMA, |  | ||||||
| - |  | ||||||
| -	/* keep last */ |  | ||||||
| -	__NL80211_MBSSID_CONFIG_ATTR_LAST, |  | ||||||
| -	NL80211_MBSSID_CONFIG_ATTR_MAX = __NL80211_MBSSID_CONFIG_ATTR_LAST - 1, |  | ||||||
| -}; |  | ||||||
| - |  | ||||||
|  #endif /* __LINUX_NL80211_H */ |  | ||||||
| --- a/info.c | --- a/info.c | ||||||
| +++ b/info.c | +++ b/info.c | ||||||
| @@ -701,7 +701,6 @@ broken_combination: | @@ -701,7 +701,6 @@ broken_combination: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau