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

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

mac80211: generalise work handling



In order to use auth/assoc for different purposes
other than MLME, it needs to be split up. For other
purposes, a generic work handling (potentially on
another channel) will be useful.

To achieve that, this patch moves much of the MLME
work handling out of mlme into a new work API. The
API can currently handle probing a specific AP,
authentication and association. The MLME previously
handled probe/authentication as one step and will
continue to do so, but they are separate in the new
work handling.

Work items are RCU-managed to be able to check for
existence of an item for a specific frame in the RX
path, but they can be re-used which the MLME right
now will do for its combined probe/auth step.

Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f679f65d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -9,7 +9,7 @@ mac80211-y := \
	scan.o \
	ht.o agg-tx.o agg-rx.o \
	ibss.o \
	mlme.o \
	mlme.o work.o \
	iface.o \
	rate.o \
	michael.o \
+0 −2
Original line number Diff line number Diff line
@@ -133,7 +133,6 @@ IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
/* STA attributes */
IEEE80211_IF_FILE(bssid, u.mgd.bssid, MAC);
IEEE80211_IF_FILE(aid, u.mgd.aid, DEC);
IEEE80211_IF_FILE(capab, u.mgd.capab, HEX);

static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
			      enum ieee80211_smps_mode smps_mode)
@@ -270,7 +269,6 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)

	DEBUGFS_ADD(bssid, sta);
	DEBUGFS_ADD(aid, sta);
	DEBUGFS_ADD(capab, sta);
	DEBUGFS_ADD_MODE(smps, 0600);
}

+44 −15
Original line number Diff line number Diff line
@@ -228,41 +228,63 @@ struct mesh_preq_queue {
};

enum ieee80211_work_type {
	IEEE80211_WORK_AUTH_PROBE,
	IEEE80211_WORK_DIRECT_PROBE,
	IEEE80211_WORK_AUTH,
	IEEE80211_WORK_ASSOC,
};

/**
 * enum work_done_result - indicates what to do after work was done
 *
 * @WORK_DONE_DESTROY: This work item is no longer needed, destroy.
 * @WORK_DONE_REQUEUE: This work item was reset to be reused, and
 *	should be requeued.
 */
enum work_done_result {
	WORK_DONE_DESTROY,
	WORK_DONE_REQUEUE,
};

struct ieee80211_work {
	struct list_head list;

	struct rcu_head rcu_head;

	struct ieee80211_sub_if_data *sdata;

	enum work_done_result (*done)(struct ieee80211_work *wk,
				      struct sk_buff *skb);

	struct ieee80211_channel *chan;
	/* XXX: chan type? -- right now not really needed */

	unsigned long timeout;
	enum ieee80211_work_type type;

	u8 filter_ta[ETH_ALEN];

	union {
		struct {
			int tries;
			u16 algorithm, transaction;
			u8 ssid[IEEE80211_MAX_SSID_LEN];
			u8 ssid_len;
			u8 bssid[ETH_ALEN];
			u8 key[WLAN_KEY_LEN_WEP104];
			u8 key_len, key_idx;
			bool privacy;
		} auth;
		} probe_auth;
		struct {
			struct ieee80211_bss *bss;
			const u8 *supp_rates;
			const u8 *ht_information_ie;
			enum ieee80211_smps_mode smps;
			int tries;
			u16 capability;
			u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
			u8 prev_bssid[ETH_ALEN];
			u8 ssid[IEEE80211_MAX_SSID_LEN];
			u8 ssid_len;
			u8 supp_rates_len;
			bool wmm_used;
			bool wmm_used, use_11n;
		} assoc;
	};

@@ -276,17 +298,11 @@ enum ieee80211_sta_flags {
	IEEE80211_STA_BEACON_POLL	= BIT(0),
	IEEE80211_STA_CONNECTION_POLL	= BIT(1),
	IEEE80211_STA_CONTROL_PORT	= BIT(2),
	IEEE80211_STA_WMM_ENABLED	= BIT(3),
	IEEE80211_STA_DISABLE_11N	= BIT(4),
	IEEE80211_STA_CSA_RECEIVED	= BIT(5),
	IEEE80211_STA_MFP_ENABLED	= BIT(6),
};

/* flags for MLME request */
enum ieee80211_sta_request {
	IEEE80211_STA_REQ_SCAN,
};

struct ieee80211_if_managed {
	struct timer_list timer;
	struct timer_list conn_mon_timer;
@@ -302,12 +318,10 @@ struct ieee80211_if_managed {

	struct mutex mtx;
	struct ieee80211_bss *associated;
	struct list_head work_list;

	u8 bssid[ETH_ALEN];

	u16 aid;
	u16 capab;

	struct sk_buff_head skb_queue;

@@ -316,8 +330,6 @@ struct ieee80211_if_managed {
	enum ieee80211_smps_mode req_smps, /* requested smps mode */
				 ap_smps; /* smps mode AP thinks we're in */

	unsigned long request;

	unsigned int flags;

	u32 beacon_crc;
@@ -583,6 +595,15 @@ struct ieee80211_local {

	const struct ieee80211_ops *ops;

	/*
	 * work stuff, potentially off-channel (in the future)
	 */
	struct mutex work_mtx;
	struct list_head work_list;
	struct timer_list work_timer;
	struct work_struct work_work;
	struct sk_buff_head work_skb_queue;

	/*
	 * private workqueue to mac80211. mac80211 makes this accessible
	 * via ieee80211_queue_work()
@@ -1127,6 +1148,14 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
void ieee80211_recalc_smps(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *forsdata);

/* internal work items */
void ieee80211_work_init(struct ieee80211_local *local);
void ieee80211_add_work(struct ieee80211_work *wk);
void free_work(struct ieee80211_work *wk);
void ieee80211_work_purge(struct ieee80211_sub_if_data *sdata);
ieee80211_rx_result ieee80211_work_rx_mgmt(struct ieee80211_sub_if_data *sdata,
					   struct sk_buff *skb);

#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
#else
+9 −2
Original line number Diff line number Diff line
@@ -361,6 +361,11 @@ static int ieee80211_stop(struct net_device *dev)
	 */
	netif_stop_queue(dev);

	/*
	 * Purge work for this interface.
	 */
	ieee80211_work_purge(sdata);

	/*
	 * Now delete all active aggregation sessions.
	 */
@@ -928,6 +933,9 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
	struct ieee80211_sub_if_data *sdata;
	int count = 0;

	if (!list_empty(&local->work_list))
		return ieee80211_idle_off(local, "working");

	if (local->scanning)
		return ieee80211_idle_off(local, "scanning");

@@ -936,8 +944,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
			continue;
		/* do not count disabled managed interfaces */
		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
		    !sdata->u.mgd.associated &&
		    list_empty(&sdata->u.mgd.work_list))
		    !sdata->u.mgd.associated)
			continue;
		/* do not count unused IBSS interfaces */
		if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
+2 −0
Original line number Diff line number Diff line
@@ -395,6 +395,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,

	INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work);

	ieee80211_work_init(local);

	INIT_WORK(&local->restart_work, ieee80211_restart_work);

	INIT_WORK(&local->reconfig_filter, ieee80211_reconfig_filter);
Loading