diff options
-rw-r--r-- | net/mac80211/mlme.c | 15 | ||||
-rw-r--r-- | net/mac80211/rx.c | 13 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 135 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 30 |
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, |