summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c345
1 files changed, 122 insertions, 223 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index a8c2130c8ba..f44f4caa69e 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -91,41 +91,6 @@ MODULE_PARM_DESC(probe_wait_ms,
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
/*
- * All cfg80211 functions have to be called outside a locked
- * section so that they can acquire a lock themselves... This
- * is much simpler than queuing up things in cfg80211, but we
- * do need some indirection for that here.
- */
-enum rx_mgmt_action {
- /* no action required */
- RX_MGMT_NONE,
-
- /* caller must call cfg80211_send_deauth() */
- RX_MGMT_CFG80211_DEAUTH,
-
- /* caller must call cfg80211_send_disassoc() */
- RX_MGMT_CFG80211_DISASSOC,
-
- /* caller must call cfg80211_send_rx_auth() */
- RX_MGMT_CFG80211_RX_AUTH,
-
- /* caller must call cfg80211_send_rx_assoc() */
- RX_MGMT_CFG80211_RX_ASSOC,
-
- /* caller must call cfg80211_send_assoc_timeout() */
- RX_MGMT_CFG80211_ASSOC_TIMEOUT,
-
- /* used when a processed beacon causes a deauth */
- RX_MGMT_CFG80211_TX_DEAUTH,
-};
-
-/* utils */
-static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
-{
- lockdep_assert_held(&ifmgd->mtx);
-}
-
-/*
* We can have multiple work items (and connection probing)
* scheduling this timer, but we need to take care to only
* reschedule it when it should fire _earlier_ than it was
@@ -135,13 +100,14 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
* has happened -- the work that runs from this timer will
* do that.
*/
-static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)
+static void run_again(struct ieee80211_sub_if_data *sdata,
+ unsigned long timeout)
{
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
- if (!timer_pending(&ifmgd->timer) ||
- time_before(timeout, ifmgd->timer.expires))
- mod_timer(&ifmgd->timer, timeout);
+ if (!timer_pending(&sdata->u.mgd.timer) ||
+ time_before(timeout, sdata->u.mgd.timer.expires))
+ mod_timer(&sdata->u.mgd.timer, timeout);
}
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
@@ -652,7 +618,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_channel *chan;
u32 rates = 0;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
@@ -962,7 +928,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if (!ieee80211_sdata_running(sdata))
return;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated)
goto out;
@@ -985,7 +951,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
IEEE80211_QUEUE_STOP_REASON_CSA);
out:
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1036,7 +1002,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_ht_operation *ht_oper;
int secondary_channel_offset = -1;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (!cbss)
return;
@@ -1390,6 +1356,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
IEEE80211_STA_CONNECTION_POLL))
return false;
+ if (!sdata->vif.bss_conf.dtim_period)
+ return false;
+
rcu_read_lock();
sta = sta_info_get(sdata, mgd->bssid);
if (sta)
@@ -1842,7 +1811,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
u32 changed = 0;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (WARN_ON_ONCE(tx && !frame_buf))
return;
@@ -2051,7 +2020,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
}
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
- run_again(ifmgd, ifmgd->probe_timeout);
+ run_again(sdata, ifmgd->probe_timeout);
if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
ieee80211_flush_queues(sdata->local, sdata);
}
@@ -2065,7 +2034,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
if (!ieee80211_sdata_running(sdata))
return;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated)
goto out;
@@ -2119,7 +2088,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
ifmgd->probe_send_count = 0;
ieee80211_mgd_probe_ap_send(sdata);
out:
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
@@ -2135,7 +2104,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
return NULL;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (ifmgd->associated)
cbss = ifmgd->associated;
@@ -2168,9 +2137,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
@@ -2181,13 +2150,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
ieee80211_wake_queues_by_reason(&sdata->local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- mutex_unlock(&ifmgd->mtx);
- /*
- * must be outside lock due to cfg80211,
- * but that's not a problem.
- */
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
+ sdata_unlock(sdata);
}
static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -2254,7 +2219,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if (!assoc) {
sta_info_destroy_addr(sdata, auth_data->bss->bssid);
@@ -2295,27 +2260,26 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
auth_data->key_idx, tx_flags);
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 bssid[ETH_ALEN];
u16 auth_alg, auth_transaction, status_code;
struct sta_info *sta;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 6)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->auth_data || ifmgd->auth_data->done)
- return RX_MGMT_NONE;
+ return;
memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
if (!ether_addr_equal(bssid, mgmt->bssid))
- return RX_MGMT_NONE;
+ return;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
@@ -2327,14 +2291,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
auth_transaction,
ifmgd->auth_data->expected_transaction);
- return RX_MGMT_NONE;
+ return;
}
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied authentication (status %d)\n",
mgmt->sa, status_code);
ieee80211_destroy_auth_data(sdata, false);
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
}
switch (ifmgd->auth_data->algorithm) {
@@ -2347,20 +2312,20 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
if (ifmgd->auth_data->expected_transaction != 4) {
ieee80211_auth_challenge(sdata, mgmt, len);
/* need another frame */
- return RX_MGMT_NONE;
+ return;
}
break;
default:
WARN_ONCE(1, "invalid auth alg %d",
ifmgd->auth_data->algorithm);
- return RX_MGMT_NONE;
+ return;
}
sdata_info(sdata, "authenticated\n");
ifmgd->auth_data->done = true;
ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
ifmgd->auth_data->expected_transaction != 2) {
@@ -2368,7 +2333,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
* Report auth frame to user space for processing since another
* round of Authentication frames is still needed.
*/
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
}
/* move station state to auth */
@@ -2384,30 +2350,29 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
}
mutex_unlock(&sdata->local->sta_mtx);
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
out_err:
mutex_unlock(&sdata->local->sta_mtx);
/* ignore frame -- wait for timeout */
- return RX_MGMT_NONE;
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
const u8 *bssid = NULL;
u16 reason_code;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 2)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
bssid = ifmgd->associated->bssid;
@@ -2418,25 +2383,24 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- return RX_MGMT_CFG80211_DEAUTH;
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len);
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u16 reason_code;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 2)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -2445,7 +2409,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- return RX_MGMT_CFG80211_DISASSOC;
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len);
}
static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
@@ -2495,7 +2459,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if (!assoc) {
sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
@@ -2676,10 +2640,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
return true;
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len,
- struct cfg80211_bss **bss)
+static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt,
+ size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
@@ -2687,13 +2650,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems elems;
u8 *pos;
bool reassoc;
+ struct cfg80211_bss *bss;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (!assoc_data)
- return RX_MGMT_NONE;
+ return;
if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))
- return RX_MGMT_NONE;
+ return;
/*
* AssocResp and ReassocResp have identical structure, so process both
@@ -2701,7 +2665,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
*/
if (len < 24 + 6)
- return RX_MGMT_NONE;
+ return;
reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
@@ -2728,22 +2692,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
assoc_data->timeout_started = true;
if (ms > IEEE80211_ASSOC_TIMEOUT)
- run_again(ifmgd, assoc_data->timeout);
- return RX_MGMT_NONE;
+ run_again(sdata, assoc_data->timeout);
+ return;
}
- *bss = assoc_data->bss;
+ bss = assoc_data->bss;
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied association (code=%d)\n",
mgmt->sa, status_code);
ieee80211_destroy_assoc_data(sdata, false);
} else {
- if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
+ if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
/* oops -- internal error -- send timeout for now */
ieee80211_destroy_assoc_data(sdata, false);
- cfg80211_put_bss(sdata->local->hw.wiphy, *bss);
- return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
+ cfg80211_put_bss(sdata->local->hw.wiphy, bss);
+ cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
+ return;
}
sdata_info(sdata, "associated\n");
@@ -2755,7 +2720,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_destroy_assoc_data(sdata, true);
}
- return RX_MGMT_CFG80211_RX_ASSOC;
+ cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len);
}
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2769,7 +2734,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel;
bool need_ps = false;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if ((sdata->u.mgd.associated &&
ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
@@ -2828,7 +2793,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd = &sdata->u.mgd;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
return; /* ignore ProbeResp to foreign address */
@@ -2853,7 +2818,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data->tries = 0;
ifmgd->auth_data->timeout = jiffies;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
}
}
@@ -2878,10 +2843,9 @@ static const u64 care_about_ies =
(1ULL << WLAN_EID_HT_CAPABILITY) |
(1ULL << WLAN_EID_HT_OPERATION);
-static enum rx_mgmt_action
-ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len,
- u8 *deauth_buf, struct ieee80211_rx_status *rx_status)
+static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ struct ieee80211_rx_status *rx_status)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
@@ -2896,24 +2860,25 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
u8 erp_value = 0;
u32 ncrc;
u8 *bssid;
+ u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
/* Process beacon from the current BSS */
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
if (baselen > len)
- return RX_MGMT_NONE;
+ return;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
- return RX_MGMT_NONE;
+ return;
}
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
rcu_read_unlock();
- return RX_MGMT_NONE;
+ return;
}
chan = chanctx_conf->def.chan;
rcu_read_unlock();
@@ -2940,13 +2905,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
/* continue assoc process */
ifmgd->assoc_data->timeout = jiffies;
ifmgd->assoc_data->timeout_started = true;
- run_again(ifmgd, ifmgd->assoc_data->timeout);
- return RX_MGMT_NONE;
+ run_again(sdata, ifmgd->assoc_data->timeout);
+ return;
}
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
bssid = ifmgd->associated->bssid;
/* Track average RSSI from the Beacon frames of the current AP */
@@ -3092,7 +3057,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
- return RX_MGMT_NONE;
+ return;
ifmgd->beacon_crc = ncrc;
ifmgd->beacon_crc_valid = true;
@@ -3126,6 +3091,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
changed |= BSS_CHANGED_DTIM_PERIOD;
+ ieee80211_recalc_ps_vif(sdata);
}
if (elems.erp_info) {
@@ -3147,7 +3113,9 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DEAUTH_LEAVING,
true, deauth_buf);
- return RX_MGMT_CFG80211_TX_DEAUTH;
+ cfg80211_send_deauth(sdata->dev, deauth_buf,
+ sizeof(deauth_buf));
+ return;
}
if (sta && elems.opmode_notif)
@@ -3164,19 +3132,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
elems.pwr_constr_elem);
ieee80211_bss_info_change_notify(sdata, changed);
-
- return RX_MGMT_NONE;
}
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
- struct cfg80211_bss *bss = NULL;
- enum rx_mgmt_action rma = RX_MGMT_NONE;
- u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
u16 fc;
struct ieee802_11_elems elems;
int ies_len;
@@ -3185,28 +3147,27 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BEACON:
- rma = ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
- deauth_buf, rx_status);
+ ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
break;
case IEEE80211_STYPE_PROBE_RESP:
ieee80211_rx_mgmt_probe_resp(sdata, skb);
break;
case IEEE80211_STYPE_AUTH:
- rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_DEAUTH:
- rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_DISASSOC:
- rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
- rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
+ ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ACTION:
if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
@@ -3252,34 +3213,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}
break;
}
- mutex_unlock(&ifmgd->mtx);
-
- switch (rma) {
- case RX_MGMT_NONE:
- /* no action */
- break;
- case RX_MGMT_CFG80211_DEAUTH:
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_DISASSOC:
- cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_RX_AUTH:
- cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_RX_ASSOC:
- cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_ASSOC_TIMEOUT:
- cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
- break;
- case RX_MGMT_CFG80211_TX_DEAUTH:
- cfg80211_send_deauth(sdata->dev, deauth_buf,
- sizeof(deauth_buf));
- break;
- default:
- WARN(1, "unexpected: %d", rma);
- }
+ sdata_unlock(sdata);
}
static void ieee80211_sta_timer(unsigned long data)
@@ -3293,20 +3227,12 @@ static void ieee80211_sta_timer(unsigned long data)
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 reason, bool tx)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
tx, frame_buf);
- mutex_unlock(&ifmgd->mtx);
- /*
- * must be outside lock due to cfg80211,
- * but that's not a problem.
- */
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
-
- mutex_lock(&ifmgd->mtx);
}
static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3316,7 +3242,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
u32 tx_flags = 0;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (WARN_ON_ONCE(!auth_data))
return -EINVAL;
@@ -3389,7 +3315,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
if (tx_flags == 0) {
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, auth_data->timeout);
+ run_again(sdata, auth_data->timeout);
} else {
auth_data->timeout_started = false;
}
@@ -3402,7 +3328,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
struct ieee80211_local *local = sdata->local;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
assoc_data->tries++;
if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
@@ -3426,7 +3352,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
assoc_data->timeout_started = true;
- run_again(&sdata->u.mgd, assoc_data->timeout);
+ run_again(sdata, assoc_data->timeout);
} else {
assoc_data->timeout_started = false;
}
@@ -3451,7 +3377,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (ifmgd->status_received) {
__le16 fc = ifmgd->status_fc;
@@ -3463,7 +3389,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (status_acked) {
ifmgd->auth_data->timeout =
jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
} else {
ifmgd->auth_data->timeout = jiffies - 1;
}
@@ -3474,7 +3400,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (status_acked) {
ifmgd->assoc_data->timeout =
jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;
- run_again(ifmgd, ifmgd->assoc_data->timeout);
+ run_again(sdata, ifmgd->assoc_data->timeout);
} else {
ifmgd->assoc_data->timeout = jiffies - 1;
}
@@ -3497,12 +3423,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
cfg80211_send_auth_timeout(sdata->dev, bssid);
- mutex_lock(&ifmgd->mtx);
}
} else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
time_after(jiffies, ifmgd->assoc_data->timeout)) {
@@ -3515,12 +3439,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_destroy_assoc_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
cfg80211_send_assoc_timeout(sdata->dev, bssid);
- mutex_lock(&ifmgd->mtx);
}
} else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
- run_again(ifmgd, ifmgd->assoc_data->timeout);
+ run_again(sdata, ifmgd->assoc_data->timeout);
if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL) &&
@@ -3554,7 +3476,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
false);
}
} else if (time_is_after_jiffies(ifmgd->probe_timeout))
- run_again(ifmgd, ifmgd->probe_timeout);
+ run_again(sdata, ifmgd->probe_timeout);
else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
mlme_dbg(sdata,
"Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
@@ -3583,7 +3505,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
}
}
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -3644,9 +3566,9 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
@@ -3657,10 +3579,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
ifmgd->associated->bssid,
WLAN_REASON_UNSPECIFIED,
true);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
#endif
@@ -3692,8 +3614,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
ifmgd->p2p_noa_index = -1;
- mutex_init(&ifmgd->mtx);
-
if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
else
@@ -4049,8 +3969,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* try to authenticate/probe */
- mutex_lock(&ifmgd->mtx);
-
if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
ifmgd->assoc_data) {
err = -EBUSY;
@@ -4070,8 +3988,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
WLAN_REASON_UNSPECIFIED,
false, frame_buf);
- __cfg80211_send_deauth(sdata->dev, frame_buf,
- sizeof(frame_buf));
+ cfg80211_send_deauth(sdata->dev, frame_buf,
+ sizeof(frame_buf));
}
sdata_info(sdata, "authenticate with %pM\n", req->bss->bssid);
@@ -4088,8 +4006,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* hold our own reference */
cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
- err = 0;
- goto out_unlock;
+ return 0;
err_clear:
memset(ifmgd->bssid, 0, ETH_ALEN);
@@ -4097,9 +4014,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data = NULL;
err_free:
kfree(auth_data);
- out_unlock:
- mutex_unlock(&ifmgd->mtx);
-
return err;
}
@@ -4130,8 +4044,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
assoc_data->ssid_len = ssidie[1];
rcu_read_unlock();
- mutex_lock(&ifmgd->mtx);
-
if (ifmgd->associated) {
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
@@ -4139,8 +4051,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
WLAN_REASON_UNSPECIFIED,
false, frame_buf);
- __cfg80211_send_deauth(sdata->dev, frame_buf,
- sizeof(frame_buf));
+ cfg80211_send_deauth(sdata->dev, frame_buf,
+ sizeof(frame_buf));
}
if (ifmgd->auth_data && !ifmgd->auth_data->done) {
@@ -4334,7 +4246,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
rcu_read_unlock();
- run_again(ifmgd, assoc_data->timeout);
+ run_again(sdata, assoc_data->timeout);
if (bss->corrupt_data) {
char *corrupt_type = "data";
@@ -4350,17 +4262,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
corrupt_type);
}
- err = 0;
- goto out;
+ return 0;
err_clear:
memset(ifmgd->bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
ifmgd->assoc_data = NULL;
err_free:
kfree(assoc_data);
- out:
- mutex_unlock(&ifmgd->mtx);
-
return err;
}
@@ -4372,8 +4280,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
bool tx = !req->local_state_change;
bool report_frame = false;
- mutex_lock(&ifmgd->mtx);
-
sdata_info(sdata,
"deauthenticating from %pM by local choice (reason=%d)\n",
req->bssid, req->reason_code);
@@ -4385,7 +4291,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
req->reason_code, tx,
frame_buf);
ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
report_frame = true;
goto out;
@@ -4397,12 +4302,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
req->reason_code, tx, frame_buf);
report_frame = true;
}
- mutex_unlock(&ifmgd->mtx);
out:
if (report_frame)
- __cfg80211_send_deauth(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
+ cfg80211_send_deauth(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
return 0;
}
@@ -4414,18 +4318,14 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
u8 bssid[ETH_ALEN];
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- mutex_lock(&ifmgd->mtx);
-
/*
* cfg80211 should catch this ... but it's racy since
* we can receive a disassoc frame, process it, hand it
* to cfg80211 while that's in a locked section already
* trying to tell us that the user wants to disconnect.
*/
- if (ifmgd->associated != req->bss) {
- mutex_unlock(&ifmgd->mtx);
+ if (ifmgd->associated != req->bss)
return -ENOLINK;
- }
sdata_info(sdata,
"disassociating from %pM by local choice (reason=%d)\n",
@@ -4435,10 +4335,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
req->reason_code, !req->local_state_change,
frame_buf);
- mutex_unlock(&ifmgd->mtx);
- __cfg80211_send_disassoc(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
+ cfg80211_send_disassoc(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
return 0;
}
@@ -4458,13 +4357,13 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->csa_connection_drop_work);
cancel_work_sync(&ifmgd->chswitch_work);
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false);
if (ifmgd->auth_data)
ieee80211_destroy_auth_data(sdata, false);
del_timer_sync(&ifmgd->timer);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,