summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/mac80211/rx.c13
-rw-r--r--net/mac80211/sta_info.c135
-rw-r--r--net/mac80211/sta_info.h30
4 files changed, 38 insertions, 155 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 40b929d57a97..d04811a29cdf 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1581,7 +1581,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
* station info was already allocated and inserted before
* the association and should be available to us
*/
- sta = sta_info_get_rx(sdata, cbss->bssid);
+ sta = sta_info_get(sdata, cbss->bssid);
if (WARN_ON(!sta)) {
mutex_unlock(&sdata->local->sta_mtx);
return false;
@@ -1648,14 +1648,7 @@ static bool ieee80211_assoc_success(struct ieee80211_work *wk,
return false;
}
- /* sta_info_reinsert will also unlock the mutex lock */
- err = sta_info_reinsert(sta);
- sta = NULL;
- if (err) {
- printk(KERN_DEBUG "%s: failed to insert STA entry for"
- " the AP (error %d)\n", sdata->name, err);
- return false;
- }
+ mutex_unlock(&sdata->local->sta_mtx);
/*
* Always handle WMM once after association regardless
@@ -2536,12 +2529,10 @@ static int ieee80211_pre_assoc(struct ieee80211_sub_if_data *sdata,
if (!sta)
return -ENOMEM;
- sta->dummy = true;
-
err = sta_info_insert(sta);
sta = NULL;
if (err) {
- printk(KERN_DEBUG "%s: failed to insert Dummy STA entry for"
+ printk(KERN_DEBUG "%s: failed to insert STA entry for"
" the AP (error %d)\n", sdata->name, err);
return err;
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index ab29253fb4f2..8d6fa674f53e 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
- if (rx->sta && rx->sta->dummy &&
+ /*
+ * accept port control frames from the AP even when it's not
+ * yet marked ASSOC to prevent a race where we don't set the
+ * assoc bit quickly enough before it sends the first frame
+ */
+ if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&
ieee80211_is_data_present(hdr->frame_control)) {
u16 ethertype;
u8 *payload;
@@ -2949,7 +2954,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (ieee80211_is_data(fc)) {
prev_sta = NULL;
- for_each_sta_info_rx(local, hdr->addr2, sta, tmp) {
+ for_each_sta_info(local, hdr->addr2, sta, tmp) {
if (!prev_sta) {
prev_sta = sta;
continue;
@@ -2993,7 +2998,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
continue;
}
- rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
ieee80211_prepare_and_rx_handle(&rx, skb, false);
@@ -3001,7 +3006,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
}
if (prev) {
- rx.sta = sta_info_get_bss_rx(prev, hdr->addr2);
+ rx.sta = sta_info_get_bss(prev, hdr->addr2);
rx.sdata = prev;
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 5e577bd0e6aa..31cd6d92531c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
lockdep_is_held(&local->sta_mtx));
while (sta) {
- if (sta->sdata == sdata && !sta->dummy &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
- break;
- sta = rcu_dereference_check(sta->hnext,
- lockdep_is_held(&local->sta_mtx));
- }
- return sta;
-}
-
-/* get a station info entry even if it is a dummy station*/
-struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
- lockdep_is_held(&local->sta_mtx));
- while (sta) {
if (sta->sdata == sdata &&
memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
@@ -143,30 +124,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
while (sta) {
if ((sta->sdata == sdata ||
(sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
- !sta->dummy &&
- memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
- break;
- sta = rcu_dereference_check(sta->hnext,
- lockdep_is_held(&local->sta_mtx));
- }
- return sta;
-}
-
-/*
- * Get sta info either from the specified interface
- * or from one of its vlans (including dummy stations)
- */
-struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr)
-{
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- sta = rcu_dereference_check(local->sta_hash[STA_HASH(addr)],
- lockdep_is_held(&local->sta_mtx));
- while (sta) {
- if ((sta->sdata == sdata ||
- (sta->sdata->bss && sta->sdata->bss == sdata->bss)) &&
memcmp(sta->sta.addr, addr, ETH_ALEN) == 0)
break;
sta = rcu_dereference_check(sta->hnext,
@@ -397,66 +354,43 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
{
struct ieee80211_local *local = sta->local;
struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct sta_info *exist_sta;
- bool dummy_reinsert = false;
+ struct station_info sinfo;
int err = 0;
lockdep_assert_held(&local->sta_mtx);
- /*
- * check if STA exists already.
- * only accept a scenario of a second call to sta_info_insert_finish
- * with a dummy station entry that was inserted earlier
- * in that case - assume that the dummy station flag should
- * be removed.
- */
- exist_sta = sta_info_get_bss_rx(sdata, sta->sta.addr);
- if (exist_sta) {
- if (exist_sta == sta && sta->dummy) {
- dummy_reinsert = true;
- } else {
- err = -EEXIST;
- goto out_err;
- }
- }
-
- if (!sta->dummy || dummy_reinsert) {
- /* notify driver */
- err = sta_info_insert_drv_state(local, sdata, sta);
- if (err)
- goto out_err;
+ /* check if STA exists already */
+ if (sta_info_get_bss(sdata, sta->sta.addr)) {
+ err = -EEXIST;
+ goto out_err;
}
- if (!dummy_reinsert) {
- local->num_sta++;
- local->sta_generation++;
- smp_mb();
+ /* notify driver */
+ err = sta_info_insert_drv_state(local, sdata, sta);
+ if (err)
+ goto out_err;
- /* make the station visible */
- sta_info_hash_add(local, sta);
+ local->num_sta++;
+ local->sta_generation++;
+ smp_mb();
- list_add(&sta->list, &local->sta_list);
+ /* make the station visible */
+ sta_info_hash_add(local, sta);
- set_sta_flag(sta, WLAN_STA_INSERTED);
- } else {
- sta->dummy = false;
- }
+ list_add(&sta->list, &local->sta_list);
- if (!sta->dummy) {
- struct station_info sinfo;
+ set_sta_flag(sta, WLAN_STA_INSERTED);
- ieee80211_sta_debugfs_add(sta);
- rate_control_add_sta_debugfs(sta);
+ ieee80211_sta_debugfs_add(sta);
+ rate_control_add_sta_debugfs(sta);
- memset(&sinfo, 0, sizeof(sinfo));
- sinfo.filled = 0;
- sinfo.generation = local->sta_generation;
- cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
- }
+ memset(&sinfo, 0, sizeof(sinfo));
+ sinfo.filled = 0;
+ sinfo.generation = local->sta_generation;
+ cfg80211_new_sta(sdata->dev, sta->sta.addr, &sinfo, GFP_KERNEL);
#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
- wiphy_debug(local->hw.wiphy, "Inserted %sSTA %pM\n",
- sta->dummy ? "dummy " : "", sta->sta.addr);
+ wiphy_debug(local->hw.wiphy, "Inserted STA %pM\n", sta->sta.addr);
#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
/* move reference to rcu-protected */
@@ -508,25 +442,6 @@ int sta_info_insert(struct sta_info *sta)
return err;
}
-/* Caller must hold sta->local->sta_mtx */
-int sta_info_reinsert(struct sta_info *sta)
-{
- struct ieee80211_local *local = sta->local;
- int err = 0;
-
- err = sta_info_insert_check(sta);
- if (err) {
- mutex_unlock(&local->sta_mtx);
- return err;
- }
-
- might_sleep();
-
- err = sta_info_insert_finish(sta);
- rcu_read_unlock();
- return err;
-}
-
static inline void __bss_tim_set(struct ieee80211_if_ap *bss, u16 aid)
{
/*
@@ -873,7 +788,7 @@ int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata, const u8 *addr)
int ret;
mutex_lock(&sdata->local->sta_mtx);
- sta = sta_info_get_rx(sdata, addr);
+ sta = sta_info_get(sdata, addr);
ret = __sta_info_destroy(sta);
mutex_unlock(&sdata->local->sta_mtx);
@@ -887,7 +802,7 @@ int sta_info_destroy_addr_bss(struct ieee80211_sub_if_data *sdata,
int ret;
mutex_lock(&sdata->local->sta_mtx);
- sta = sta_info_get_bss_rx(sdata, addr);
+ sta = sta_info_get_bss(sdata, addr);
ret = __sta_info_destroy(sta);
mutex_unlock(&sdata->local->sta_mtx);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 2ee808860007..03f249bc2766 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -265,8 +265,6 @@ struct sta_ampdu_mlme {
* @dead: set to true when sta is unlinked
* @uploaded: set to true when sta is uploaded to the driver
* @lost_packets: number of consecutive lost packets
- * @dummy: indicate a dummy station created for receiving
- * EAP frames before association
* @sta: station information we share with the driver
* @sta_state: duplicates information about station state (for debug)
* @beacon_loss_count: number of times beacon loss has triggered
@@ -364,9 +362,6 @@ struct sta_info {
unsigned int lost_packets;
unsigned int beacon_loss_count;
- /* should be right in front of sta to be in the same cache line */
- bool dummy;
-
/* keep last! */
struct ieee80211_sta sta;
};
@@ -468,15 +463,9 @@ rcu_dereference_protected_tid_tx(struct sta_info *sta, int tid)
struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
-struct sta_info *sta_info_get_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-
struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
const u8 *addr);
-struct sta_info *sta_info_get_bss_rx(struct ieee80211_sub_if_data *sdata,
- const u8 *addr);
-
static inline
void for_each_sta_info_type_check(struct ieee80211_local *local,
const u8 *addr,
@@ -485,23 +474,7 @@ void for_each_sta_info_type_check(struct ieee80211_local *local,
{
}
-#define for_each_sta_info(local, _addr, _sta, nxt) \
- for ( /* initialise loop */ \
- _sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
- nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
- /* typecheck */ \
- for_each_sta_info_type_check(local, (_addr), _sta, nxt),\
- /* continue condition */ \
- _sta; \
- /* advance loop */ \
- _sta = nxt, \
- nxt = _sta ? rcu_dereference(_sta->hnext) : NULL \
- ) \
- /* run code only if address matches and it's not a dummy sta */ \
- if (memcmp(_sta->sta.addr, (_addr), ETH_ALEN) == 0 && \
- !_sta->dummy)
-
-#define for_each_sta_info_rx(local, _addr, _sta, nxt) \
+#define for_each_sta_info(local, _addr, _sta, nxt) \
for ( /* initialise loop */ \
_sta = rcu_dereference(local->sta_hash[STA_HASH(_addr)]),\
nxt = _sta ? rcu_dereference(_sta->hnext) : NULL; \
@@ -540,7 +513,6 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta);
*/
int sta_info_insert(struct sta_info *sta);
int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU);
-int sta_info_reinsert(struct sta_info *sta);
int __must_check __sta_info_destroy(struct sta_info *sta);
int sta_info_destroy_addr(struct ieee80211_sub_if_data *sdata,