|
@@ -90,41 +90,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
|
|
@@ -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)
|
|
@@ -1015,7 +981,8 @@ static void ieee80211_chswitch_timer(unsigned long data)
|
|
|
|
|
|
static void
|
|
|
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
- u64 timestamp, struct ieee802_11_elems *elems)
|
|
|
+ u64 timestamp, struct ieee802_11_elems *elems,
|
|
|
+ bool beacon)
|
|
|
{
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
@@ -1032,9 +999,10 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
struct cfg80211_chan_def new_vht_chandef = {};
|
|
|
const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
|
|
|
const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie;
|
|
|
+ const struct ieee80211_ht_operation *ht_oper;
|
|
|
int secondary_channel_offset = -1;
|
|
|
|
|
|
- ASSERT_MGD_MTX(ifmgd);
|
|
|
+ sdata_assert_lock(sdata);
|
|
|
|
|
|
if (!cbss)
|
|
|
return;
|
|
@@ -1048,11 +1016,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
sec_chan_offs = elems->sec_chan_offs;
|
|
|
wide_bw_chansw_ie = elems->wide_bw_chansw_ie;
|
|
|
+ ht_oper = elems->ht_operation;
|
|
|
|
|
|
if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT |
|
|
|
IEEE80211_STA_DISABLE_40MHZ)) {
|
|
|
sec_chan_offs = NULL;
|
|
|
wide_bw_chansw_ie = NULL;
|
|
|
+ /* only used for bandwidth here */
|
|
|
+ ht_oper = NULL;
|
|
|
}
|
|
|
|
|
|
if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT)
|
|
@@ -1094,10 +1065,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- if (sec_chan_offs) {
|
|
|
+ if (!beacon && sec_chan_offs) {
|
|
|
secondary_channel_offset = sec_chan_offs->sec_chan_offs;
|
|
|
+ } else if (beacon && ht_oper) {
|
|
|
+ secondary_channel_offset =
|
|
|
+ ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
|
|
|
} else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) {
|
|
|
- /* if HT is enabled and the IE not present, it's still HT */
|
|
|
+ /*
|
|
|
+ * If it's not a beacon, HT is enabled and the IE not present,
|
|
|
+ * it's 20 MHz, 802.11-2012 8.5.2.6:
|
|
|
+ * This element [the Secondary Channel Offset Element] is
|
|
|
+ * present when switching to a 40 MHz channel. It may be
|
|
|
+ * present when switching to a 20 MHz channel (in which
|
|
|
+ * case the secondary channel offset is set to SCN).
|
|
|
+ */
|
|
|
secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
|
|
|
}
|
|
|
|
|
@@ -1375,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)
|
|
@@ -1827,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;
|
|
@@ -2036,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);
|
|
|
}
|
|
@@ -2050,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;
|
|
@@ -2104,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,
|
|
@@ -2120,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;
|
|
@@ -2153,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;
|
|
|
}
|
|
|
|
|
@@ -2166,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)
|
|
@@ -2239,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);
|
|
@@ -2280,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);
|
|
@@ -2312,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) {
|
|
@@ -2332,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) {
|
|
@@ -2353,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 */
|
|
@@ -2369,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;
|
|
|
|
|
@@ -2403,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);
|
|
|
|
|
@@ -2430,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,
|
|
@@ -2480,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);
|
|
@@ -2661,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;
|
|
@@ -2672,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
|
|
@@ -2686,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);
|
|
@@ -2713,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");
|
|
|
|
|
@@ -2740,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,
|
|
@@ -2754,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)) ||
|
|
@@ -2796,7 +2776,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
|
|
|
mutex_unlock(&local->iflist_mtx);
|
|
|
}
|
|
|
|
|
|
- ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems);
|
|
|
+ ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
|
|
|
+ elems, true);
|
|
|
|
|
|
}
|
|
|
|
|
@@ -2812,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 */
|
|
@@ -2837,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);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2862,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;
|
|
@@ -2880,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();
|
|
@@ -2924,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 */
|
|
@@ -3076,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;
|
|
|
|
|
@@ -3110,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) {
|
|
@@ -3131,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)
|
|
@@ -3148,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;
|
|
@@ -3169,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) {
|
|
@@ -3210,7 +3187,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
ieee80211_sta_process_chanswitch(sdata,
|
|
|
rx_status->mactime,
|
|
|
- &elems);
|
|
|
+ &elems, false);
|
|
|
} else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
|
|
|
ies_len = skb->len -
|
|
|
offsetof(struct ieee80211_mgmt,
|
|
@@ -3232,38 +3209,11 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
|
|
|
|
|
|
ieee80211_sta_process_chanswitch(sdata,
|
|
|
rx_status->mactime,
|
|
|
- &elems);
|
|
|
+ &elems, false);
|
|
|
}
|
|
|
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)
|
|
@@ -3277,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)
|
|
@@ -3300,15 +3242,11 @@ 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;
|
|
|
|
|
|
- if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
|
|
- tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
|
|
- IEEE80211_TX_INTFL_MLME_CONN_TX;
|
|
|
-
|
|
|
auth_data->tries++;
|
|
|
|
|
|
if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) {
|
|
@@ -3342,6 +3280,10 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
|
|
|
auth_data->expected_transaction = trans;
|
|
|
}
|
|
|
|
|
|
+ if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
|
|
|
+ tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
|
|
|
+ IEEE80211_TX_INTFL_MLME_CONN_TX;
|
|
|
+
|
|
|
ieee80211_send_auth(sdata, trans, auth_data->algorithm, status,
|
|
|
auth_data->data, auth_data->data_len,
|
|
|
auth_data->bss->bssid,
|
|
@@ -3365,15 +3307,15 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
|
|
|
* will not answer to direct packet in unassociated state.
|
|
|
*/
|
|
|
ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
|
|
|
- NULL, 0, (u32) -1, true, tx_flags,
|
|
|
+ NULL, 0, (u32) -1, true, 0,
|
|
|
auth_data->bss->channel, false);
|
|
|
rcu_read_unlock();
|
|
|
}
|
|
|
|
|
|
- if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
|
|
|
+ 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;
|
|
|
}
|
|
@@ -3386,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) {
|
|
@@ -3410,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;
|
|
|
}
|
|
@@ -3435,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;
|
|
@@ -3447,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;
|
|
|
}
|
|
@@ -3458,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;
|
|
|
}
|
|
@@ -3481,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)) {
|
|
@@ -3499,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) &&
|
|
@@ -3538,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",
|
|
@@ -3567,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)
|
|
@@ -3623,6 +3561,31 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_PM
|
|
|
+void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
|
|
|
+{
|
|
|
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
+
|
|
|
+ sdata_lock(sdata);
|
|
|
+ if (!ifmgd->associated) {
|
|
|
+ sdata_unlock(sdata);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) {
|
|
|
+ sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME;
|
|
|
+ mlme_dbg(sdata, "driver requested disconnect after resume\n");
|
|
|
+ ieee80211_sta_connection_lost(sdata,
|
|
|
+ ifmgd->associated->bssid,
|
|
|
+ WLAN_REASON_UNSPECIFIED,
|
|
|
+ true);
|
|
|
+ sdata_unlock(sdata);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ sdata_unlock(sdata);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/* interface setup */
|
|
|
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
|
|
|
{
|
|
@@ -3651,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
|
|
@@ -4008,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;
|
|
@@ -4029,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);
|
|
@@ -4047,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);
|
|
@@ -4056,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;
|
|
|
}
|
|
|
|
|
@@ -4089,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];
|
|
|
|
|
@@ -4098,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) {
|
|
@@ -4293,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";
|
|
@@ -4309,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;
|
|
|
}
|
|
|
|
|
@@ -4329,9 +4278,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
|
|
|
bool tx = !req->local_state_change;
|
|
|
- bool sent_frame = false;
|
|
|
-
|
|
|
- mutex_lock(&ifmgd->mtx);
|
|
|
+ bool report_frame = false;
|
|
|
|
|
|
sdata_info(sdata,
|
|
|
"deauthenticating from %pM by local choice (reason=%d)\n",
|
|
@@ -4344,9 +4291,8 @@ 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);
|
|
|
|
|
|
- sent_frame = tx;
|
|
|
+ report_frame = true;
|
|
|
goto out;
|
|
|
}
|
|
|
|
|
@@ -4354,14 +4300,13 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
|
|
ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
|
|
|
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
|
|
|
req->reason_code, tx, frame_buf);
|
|
|
- sent_frame = tx;
|
|
|
+ report_frame = true;
|
|
|
}
|
|
|
- mutex_unlock(&ifmgd->mtx);
|
|
|
|
|
|
out:
|
|
|
- if (sent_frame)
|
|
|
- __cfg80211_send_deauth(sdata->dev, frame_buf,
|
|
|
- IEEE80211_DEAUTH_FRAME_LEN);
|
|
|
+ if (report_frame)
|
|
|
+ cfg80211_send_deauth(sdata->dev, frame_buf,
|
|
|
+ IEEE80211_DEAUTH_FRAME_LEN);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -4373,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",
|
|
@@ -4394,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;
|
|
|
}
|
|
@@ -4417,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,
|