Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 290338
b: refs/heads/master
c: 7852e36
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed Feb 6, 2012
1 parent 71e96d3 commit 0242ac6
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 156 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: a4ec45a421b80bc36fd37578accf081f32527a7f
refs/heads/master: 7852e36186d2a1983c215836d7e3d7b8927c930d
15 changes: 3 additions & 12 deletions trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down
13 changes: 9 additions & 4 deletions trunk/net/mac80211/rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2993,15 +2998,15 @@ 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);

prev = sdata;
}

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))
Expand Down
135 changes: 25 additions & 110 deletions trunk/net/mac80211/sta_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,6 @@ struct sta_info *sta_info_get(struct ieee80211_sub_if_data *sdata,
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->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) {
Expand All @@ -138,30 +119,6 @@ struct sta_info *sta_info_get_bss(struct ieee80211_sub_if_data *sdata,
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)) &&
!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) {
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
{
/*
Expand Down Expand Up @@ -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);

Expand All @@ -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);

Expand Down
30 changes: 1 addition & 29 deletions trunk/net/mac80211/sta_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
};
Expand Down Expand Up @@ -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,
Expand All @@ -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; \
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 0242ac6

Please sign in to comment.