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

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

mac80211: add TDLS channel-switch Rx flow



When receiving a TDLS channel switch request or response, parse the frame
and call a new tdls_recv_channel_switch op in the low level driver with
the parsed data.

Signed-off-by: default avatarArik Nemtsov <arikx.nemtsov@intel.com>
Signed-off-by: default avatarArik Nemtsov <arik@wizery.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a7a6bdd0
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -1826,6 +1826,31 @@ struct ieee80211_scan_request {
	struct cfg80211_scan_request req;
};

/**
 * struct ieee80211_tdls_ch_sw_params - TDLS channel switch parameters
 *
 * @sta: peer this TDLS channel-switch request/response came from
 * @chandef: channel referenced in a TDLS channel-switch request
 * @action_code: see &enum ieee80211_tdls_actioncode
 * @status: channel-switch response status
 * @timestamp: time at which the frame was received
 * @switch_time: switch-timing parameter received in the frame
 * @switch_timeout: switch-timing parameter received in the frame
 * @tmpl_skb: TDLS switch-channel response template
 * @ch_sw_tm_ie: offset of the channel-switch timing IE inside @tmpl_skb
 */
struct ieee80211_tdls_ch_sw_params {
	struct ieee80211_sta *sta;
	struct cfg80211_chan_def *chandef;
	u8 action_code;
	u32 status;
	u32 timestamp;
	u16 switch_time;
	u16 switch_timeout;
	struct sk_buff *tmpl_skb;
	u32 ch_sw_tm_ie;
};

/**
 * wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy
 *
@@ -2925,6 +2950,13 @@ enum ieee80211_reconfig_type {
 *	optionally copy the skb for further re-use.
 * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
 *	peers must be on the base channel when the call completes.
 * @tdls_recv_channel_switch: a TDLS channel-switch related frame (request or
 *	response) has been received from a remote peer. The driver gets
 *	parameters parsed from the incoming frame and may use them to continue
 *	an ongoing channel-switch operation. In addition, a channel-switch
 *	response template is provided, together with the location of the
 *	switch-timing IE within the template. The skb can only be used within
 *	the function call.
 */
struct ieee80211_ops {
	void (*tx)(struct ieee80211_hw *hw,
@@ -3141,10 +3173,13 @@ struct ieee80211_ops {
				   struct ieee80211_vif *vif,
				   struct ieee80211_sta *sta, u8 oper_class,
				   struct cfg80211_chan_def *chandef,
				   struct sk_buff *skb, u32 ch_sw_tm_ie);
				   struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie);
	void (*tdls_cancel_channel_switch)(struct ieee80211_hw *hw,
					   struct ieee80211_vif *vif,
					   struct ieee80211_sta *sta);
	void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw,
					 struct ieee80211_vif *vif,
					 struct ieee80211_tdls_ch_sw_params *params);
};

/**
+12 −0
Original line number Diff line number Diff line
@@ -1337,4 +1337,16 @@ drv_tdls_cancel_channel_switch(struct ieee80211_local *local,
	trace_drv_return_void(local);
}

static inline void
drv_tdls_recv_channel_switch(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_tdls_ch_sw_params *params)
{
	trace_drv_tdls_recv_channel_switch(local, sdata, params);
	if (local->ops->tdls_recv_channel_switch)
		local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif,
						     params);
	trace_drv_return_void(local);
}

#endif /* __MAC80211_DRIVER_OPS */
+3 −0
Original line number Diff line number Diff line
@@ -993,6 +993,7 @@ enum sdata_queue_type {
	IEEE80211_SDATA_QUEUE_AGG_STOP		= 2,
	IEEE80211_SDATA_QUEUE_RX_AGG_START	= 3,
	IEEE80211_SDATA_QUEUE_RX_AGG_STOP	= 4,
	IEEE80211_SDATA_QUEUE_TDLS_CHSW		= 5,
};

enum {
@@ -2013,6 +2014,8 @@ int ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
void ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
					  struct net_device *dev,
					  const u8 *addr);
void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata,
					   struct sk_buff *skb);

extern const struct ethtool_ops ieee80211_ethtool_ops;

+2 −0
Original line number Diff line number Diff line
@@ -1202,6 +1202,8 @@ static void ieee80211_iface_work(struct work_struct *work)
							WLAN_BACK_RECIPIENT, 0,
							false);
			mutex_unlock(&local->sta_mtx);
		} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_TDLS_CHSW) {
			ieee80211_process_tdls_channel_switch(sdata, skb);
		} else if (ieee80211_is_action(mgmt->frame_control) &&
			   mgmt->u.action.category == WLAN_CATEGORY_BACK) {
			int len = skb->len;
+2 −1
Original line number Diff line number Diff line
@@ -766,7 +766,8 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)

	if ((hw->wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
	    (!local->ops->tdls_channel_switch ||
	     !local->ops->tdls_cancel_channel_switch))
	     !local->ops->tdls_cancel_channel_switch ||
	     !local->ops->tdls_recv_channel_switch))
		return -EOPNOTSUPP;

#ifdef CONFIG_PM
Loading