Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b98fb44f authored by Arik Nemtsov's avatar Arik Nemtsov Committed by Johannes Berg
Browse files

mac80211: define TDLS wider BW support bits



Allow a device to specify support for the TDLS wider-bandwidth feature.
Indicate this support during TDLS setup in the ext-capab IE and set an
appropriate station flag when our TDLS peer supports it.
This feature gives TDLS peers the ability to use a wider channel than
the base width of the BSS. For instance VHT capable TDLS peers connected
on a 20MHz channel can extend the channel to 80MHz, if regulatory
considerations allow it.

Do not cap the bandwidth of such stations by the current BSS channel width
in mac80211.

Signed-off-by: default avatarArik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 7584f88f
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -1887,6 +1887,9 @@ struct ieee80211_txq {
 * @IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands
 *	in one command, mac80211 doesn't have to run separate scans per band.
 *
 * @IEEE80211_HW_TDLS_WIDER_BW: The device/driver supports wider bandwidth
 *	than then BSS bandwidth for a TDLS link on the base channel.
 *
 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
 */
enum ieee80211_hw_flags {
@@ -1919,6 +1922,7 @@ enum ieee80211_hw_flags {
	IEEE80211_HW_CHANCTX_STA_CSA,
	IEEE80211_HW_SUPPORTS_CLONED_SKBS,
	IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS,
	IEEE80211_HW_TDLS_WIDER_BW,

	/* keep last, obviously */
	NUM_IEEE80211_HW_FLAGS
+6 −0
Original line number Diff line number Diff line
@@ -1155,6 +1155,12 @@ static int sta_apply_parameters(struct ieee80211_local *local,
	    params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)
		set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH);

	if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
	    ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
	    params->ext_capab_len >= 8 &&
	    params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED)
		set_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW);

	if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
		sta->sta.uapsd_queues = params->uapsd_queues;
		sta->sta.max_sp = params->max_sp;
+1 −0
Original line number Diff line number Diff line
@@ -122,6 +122,7 @@ static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = {
	FLAG(CHANCTX_STA_CSA),
	FLAG(SUPPORTS_CLONED_SKBS),
	FLAG(SINGLE_SCAN_ON_ALL_BANDS),
	FLAG(TDLS_WIDER_BW),

	/* keep last for the build bug below */
	(void *)0x1
+3 −0
Original line number Diff line number Diff line
@@ -53,6 +53,8 @@
 * @WLAN_STA_TDLS_CHAN_SWITCH: This TDLS peer supports TDLS channel-switching
 * @WLAN_STA_TDLS_OFF_CHANNEL: The local STA is currently off-channel with this
 *	TDLS peer
 * @WLAN_STA_TDLS_WIDER_BW: This TDLS peer supports working on a wider bw on
 *	the BSS base channel.
 * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
 *	keeping station in power-save mode, reply when the driver
 *	unblocks the station.
@@ -84,6 +86,7 @@ enum ieee80211_sta_info_flags {
	WLAN_STA_TDLS_INITIATOR,
	WLAN_STA_TDLS_CHAN_SWITCH,
	WLAN_STA_TDLS_OFF_CHANNEL,
	WLAN_STA_TDLS_WIDER_BW,
	WLAN_STA_UAPSD,
	WLAN_STA_SP,
	WLAN_STA_4ADDR_EVENT,
+13 −5
Original line number Diff line number Diff line
@@ -35,20 +35,28 @@ void ieee80211_tdls_peer_del_work(struct work_struct *wk)
	mutex_unlock(&local->mtx);
}

static void ieee80211_tdls_add_ext_capab(struct ieee80211_local *local,
static void ieee80211_tdls_add_ext_capab(struct ieee80211_sub_if_data *sdata,
					 struct sk_buff *skb)
{
	u8 *pos = (void *)skb_put(skb, 7);
	struct ieee80211_local *local = sdata->local;
	bool chan_switch = local->hw.wiphy->features &
			   NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
	bool wider_band = ieee80211_hw_check(&local->hw, TDLS_WIDER_BW);
	enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
	struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
	bool vht = sband && sband->vht_cap.vht_supported;
	u8 *pos = (void *)skb_put(skb, 10);

	*pos++ = WLAN_EID_EXT_CAPABILITY;
	*pos++ = 5; /* len */
	*pos++ = 8; /* len */
	*pos++ = 0x0;
	*pos++ = 0x0;
	*pos++ = 0x0;
	*pos++ = chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0;
	*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
	*pos++ = 0;
	*pos++ = 0;
	*pos++ = (vht && wider_band) ? WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED : 0;
}

static u8
@@ -320,7 +328,7 @@ ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata,
		offset = noffset;
	}

	ieee80211_tdls_add_ext_capab(local, skb);
	ieee80211_tdls_add_ext_capab(sdata, skb);

	/* add the QoS element if we support it */
	if (local->hw.queues >= IEEE80211_NUM_ACS &&
@@ -784,7 +792,7 @@ ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
			       max(sizeof(struct ieee80211_mgmt),
				   sizeof(struct ieee80211_tdls_data)) +
			       50 + /* supported rates */
			       7 + /* ext capab */
			       10 + /* ext capab */
			       26 + /* max(WMM-info, WMM-param) */
			       2 + max(sizeof(struct ieee80211_ht_cap),
				       sizeof(struct ieee80211_ht_operation)) +
Loading