You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
committed by
John W. Linville
parent
f679f65d41
commit
af6b63741c
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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);
|
||||
|
||||
+148
-810
File diff suppressed because it is too large
Load Diff
@@ -1945,6 +1945,7 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = rx->sdata;
|
||||
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
|
||||
ieee80211_rx_result rxs;
|
||||
|
||||
if (!(rx->flags & IEEE80211_RX_RA_MATCH))
|
||||
return RX_DROP_MONITOR;
|
||||
@@ -1952,6 +1953,10 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
|
||||
if (ieee80211_drop_unencrypted(rx, mgmt->frame_control))
|
||||
return RX_DROP_MONITOR;
|
||||
|
||||
rxs = ieee80211_work_rx_mgmt(rx->sdata, rx->skb);
|
||||
if (rxs != RX_CONTINUE)
|
||||
return rxs;
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif))
|
||||
return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
|
||||
|
||||
|
||||
+2
-6
@@ -434,7 +434,6 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
struct cfg80211_scan_request *req)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
int rc;
|
||||
|
||||
if (local->scan_req)
|
||||
@@ -464,11 +463,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
|
||||
local->scan_req = req;
|
||||
local->scan_sdata = sdata;
|
||||
|
||||
if (req != local->int_scan_req &&
|
||||
sdata->vif.type == NL80211_IFTYPE_STATION &&
|
||||
!list_empty(&ifmgd->work_list)) {
|
||||
/* actually wait for the work it's doing to finish/time out */
|
||||
set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request);
|
||||
if (!list_empty(&local->work_list)) {
|
||||
/* wait for the work to finish/time out */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user