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

Commit b8bc4b0a authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville
Browse files

mac80211: support remain-on-channel command



This implements the new remain-on-channel cfg80211
command in mac80211, extending the work interface.

Also change the work purge code to be able to clean
up events properly (pretending they timed out.)

Signed-off-by: default avatarJouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9588bbd5
Loading
Loading
Loading
Loading
+24 −0
Original line number Original line Diff line number Diff line
@@ -1441,6 +1441,28 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
	return -EINVAL;
	return -EINVAL;
}
}


static int ieee80211_remain_on_channel(struct wiphy *wiphy,
				       struct net_device *dev,
				       struct ieee80211_channel *chan,
				       enum nl80211_channel_type channel_type,
				       unsigned int duration,
				       u64 *cookie)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	return ieee80211_wk_remain_on_channel(sdata, chan, channel_type,
					      duration, cookie);
}

static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy,
					      struct net_device *dev,
					      u64 cookie)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);

	return ieee80211_wk_cancel_remain_on_channel(sdata, cookie);
}

struct cfg80211_ops mac80211_config_ops = {
struct cfg80211_ops mac80211_config_ops = {
	.add_virtual_intf = ieee80211_add_iface,
	.add_virtual_intf = ieee80211_add_iface,
	.del_virtual_intf = ieee80211_del_iface,
	.del_virtual_intf = ieee80211_del_iface,
@@ -1487,4 +1509,6 @@ struct cfg80211_ops mac80211_config_ops = {
	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
	CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
	.set_power_mgmt = ieee80211_set_power_mgmt,
	.set_power_mgmt = ieee80211_set_power_mgmt,
	.set_bitrate_mask = ieee80211_set_bitrate_mask,
	.set_bitrate_mask = ieee80211_set_bitrate_mask,
	.remain_on_channel = ieee80211_remain_on_channel,
	.cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
};
};
+15 −0
Original line number Original line Diff line number Diff line
@@ -225,9 +225,11 @@ struct mesh_preq_queue {
};
};


enum ieee80211_work_type {
enum ieee80211_work_type {
	IEEE80211_WORK_ABORT,
	IEEE80211_WORK_DIRECT_PROBE,
	IEEE80211_WORK_DIRECT_PROBE,
	IEEE80211_WORK_AUTH,
	IEEE80211_WORK_AUTH,
	IEEE80211_WORK_ASSOC,
	IEEE80211_WORK_ASSOC,
	IEEE80211_WORK_REMAIN_ON_CHANNEL,
};
};


/**
/**
@@ -283,6 +285,9 @@ struct ieee80211_work {
			u8 supp_rates_len;
			u8 supp_rates_len;
			bool wmm_used, use_11n;
			bool wmm_used, use_11n;
		} assoc;
		} assoc;
		struct {
			unsigned long timeout;
		} remain;
	};
	};


	int ie_len;
	int ie_len;
@@ -729,6 +734,10 @@ struct ieee80211_local {
	enum nl80211_channel_type oper_channel_type;
	enum nl80211_channel_type oper_channel_type;
	struct ieee80211_channel *oper_channel, *csa_channel;
	struct ieee80211_channel *oper_channel, *csa_channel;


	/* Temporary remain-on-channel for off-channel operations */
	struct ieee80211_channel *tmp_channel;
	enum nl80211_channel_type tmp_channel_type;

	/* SNMP counters */
	/* SNMP counters */
	/* dot11CountersTable */
	/* dot11CountersTable */
	u32 dot11TransmittedFragmentCount;
	u32 dot11TransmittedFragmentCount;
@@ -1162,6 +1171,12 @@ void free_work(struct ieee80211_work *wk);
void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
					   struct sk_buff *skb);
					   struct sk_buff *skb);
int ieee80211_wk_remain_on_channel(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_channel *chan,
				   enum nl80211_channel_type channel_type,
				   unsigned int duration, u64 *cookie);
int ieee80211_wk_cancel_remain_on_channel(
	struct ieee80211_sub_if_data *sdata, u64 cookie);


#ifdef CONFIG_MAC80211_NOINLINE
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
#define debug_noinline noinline
+3 −0
Original line number Original line Diff line number Diff line
@@ -107,6 +107,9 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
	if (scan_chan) {
	if (scan_chan) {
		chan = scan_chan;
		chan = scan_chan;
		channel_type = NL80211_CHAN_NO_HT;
		channel_type = NL80211_CHAN_NO_HT;
	} else if (local->tmp_channel) {
		chan = scan_chan = local->tmp_channel;
		channel_type = local->tmp_channel_type;
	} else {
	} else {
		chan = local->oper_channel;
		chan = local->oper_channel;
		channel_type = local->oper_channel_type;
		channel_type = local->oper_channel_type;
+3 −0
Original line number Original line Diff line number Diff line
@@ -857,6 +857,9 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
	if (sdata->local->scanning)
	if (sdata->local->scanning)
		return;
		return;


	if (sdata->local->tmp_channel)
		return;

	mutex_lock(&ifmgd->mtx);
	mutex_lock(&ifmgd->mtx);


	if (!ifmgd->associated)
	if (!ifmgd->associated)
+6 −2
Original line number Original line Diff line number Diff line
@@ -106,9 +106,13 @@ void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
		/*
		/*
		 * only handle non-STA interfaces here, STA interfaces
		 * only handle non-STA interfaces here, STA interfaces
		 * are handled in ieee80211_offchannel_stop_station(),
		 * are handled in ieee80211_offchannel_stop_station(),
		 * e.g., from the background scan state machine
		 * e.g., from the background scan state machine.
		 *
		 * In addition, do not stop monitor interface to allow it to be
		 * used from user space controlled off-channel operations.
		 */
		 */
		if (sdata->vif.type != NL80211_IFTYPE_STATION)
		if (sdata->vif.type != NL80211_IFTYPE_STATION &&
		    sdata->vif.type != NL80211_IFTYPE_MONITOR)
			netif_stop_queue(sdata->dev);
			netif_stop_queue(sdata->dev);
	}
	}
	mutex_unlock(&local->iflist_mtx);
	mutex_unlock(&local->iflist_mtx);
Loading