* [PATCH 1/8] mac80211: move managed mode station state modification
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 2/8] mac80211: simplify AP_VLAN handling Johannes Berg
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
Move the station state modification right before insert,
this just makes the current code more readable (you can
tell that it's before insertion looking at a single
screenful of code) right now, but some upcoming changes
will require this.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mlme.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
--- a/net/mac80211/mlme.c 2012-01-04 12:08:59.000000000 +0100
+++ b/net/mac80211/mlme.c 2012-01-04 12:12:23.000000000 +0100
@@ -1585,20 +1585,6 @@ static bool ieee80211_assoc_success(stru
return false;
}
- err = sta_info_move_state(sta, IEEE80211_STA_AUTH);
- if (!err)
- err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
- if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
- err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
- if (err) {
- printk(KERN_DEBUG
- "%s: failed to move station %pM to desired state\n",
- sdata->name, sta->sta.addr);
- WARN_ON(__sta_info_destroy(sta));
- mutex_unlock(&sdata->local->sta_mtx);
- return false;
- }
-
rates = 0;
basic_rates = 0;
sband = local->hw.wiphy->bands[wk->chan->band];
@@ -1646,6 +1632,20 @@ static bool ieee80211_assoc_success(stru
if (elems.wmm_param)
set_sta_flag(sta, WLAN_STA_WME);
+ err = sta_info_move_state(sta, IEEE80211_STA_AUTH);
+ if (!err)
+ err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
+ if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
+ err = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
+ if (err) {
+ printk(KERN_DEBUG
+ "%s: failed to move station %pM to desired state\n",
+ sdata->name, sta->sta.addr);
+ WARN_ON(__sta_info_destroy(sta));
+ mutex_unlock(&sdata->local->sta_mtx);
+ return false;
+ }
+
/* sta_info_reinsert will also unlock the mutex lock */
err = sta_info_reinsert(sta);
sta = NULL;
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 2/8] mac80211: simplify AP_VLAN handling
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
2012-01-05 15:30 ` [PATCH 1/8] mac80211: move managed mode station state modification Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 3/8] mac80211: dont program keys for stations not uploaded Johannes Berg
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
Setting keys and updating TKIP keys must use the
BSS sdata (not AP_VLAN), so we translate. Move
the translation into driver-ops wrappers instead
of having it inline in the code to simplify the
normal code flow.
The same can be done for sta_add/remove which
already does the translation in the wrapper.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/driver-ops.h | 2 ++
net/mac80211/key.c | 8 --------
net/mac80211/pm.c | 11 ++---------
net/mac80211/sta_info.c | 8 +-------
net/mac80211/util.c | 11 ++---------
5 files changed, 7 insertions(+), 33 deletions(-)
--- a/net/mac80211/driver-ops.h 2012-01-04 14:20:03.000000000 +0100
+++ b/net/mac80211/driver-ops.h 2012-01-04 14:20:09.000000000 +0100
@@ -253,6 +253,7 @@ static inline int drv_set_key(struct iee
might_sleep();
+ sdata = get_bss_sdata(sdata);
check_sdata_in_driver(sdata);
trace_drv_set_key(local, cmd, sdata, sta, key);
@@ -272,6 +273,7 @@ static inline void drv_update_tkip_key(s
if (sta)
ista = &sta->sta;
+ sdata = get_bss_sdata(sdata);
check_sdata_in_driver(sdata);
trace_drv_update_tkip_key(local, sdata, conf, ista, iv32);
--- a/net/mac80211/key.c 2012-01-04 14:20:03.000000000 +0100
+++ b/net/mac80211/key.c 2012-01-04 14:20:09.000000000 +0100
@@ -123,9 +123,6 @@ static int ieee80211_key_enable_hw_accel
*/
if (!(key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE))
goto out_unsupported;
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
}
ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
@@ -187,11 +184,6 @@ static void ieee80211_key_disable_hw_acc
(key->conf.flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE)))
increment_tailroom_need_count(sdata);
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
-
ret = drv_set_key(key->local, DISABLE_KEY, sdata,
sta, &key->conf);
--- a/net/mac80211/pm.c 2012-01-04 14:20:03.000000000 +0100
+++ b/net/mac80211/pm.c 2012-01-04 14:20:09.000000000 +0100
@@ -97,15 +97,8 @@ int __ieee80211_suspend(struct ieee80211
/* tear down aggregation sessions and remove STAs */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->uploaded) {
- sdata = sta->sdata;
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
-
- drv_sta_remove(local, sdata, &sta->sta);
- }
+ if (sta->uploaded)
+ drv_sta_remove(local, sta->sdata, &sta->sta);
mesh_plink_quiesce(sta);
}
--- a/net/mac80211/sta_info.c 2012-01-04 14:20:03.000000000 +0100
+++ b/net/mac80211/sta_info.c 2012-01-04 14:20:09.000000000 +0100
@@ -774,14 +774,8 @@ int __must_check __sta_info_destroy(stru
WARN_ON_ONCE(err != 0);
}
- if (sta->uploaded) {
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
+ if (sta->uploaded)
drv_sta_remove(local, sdata, &sta->sta);
- sdata = sta->sdata;
- }
/*
* At this point, after we wait for an RCU grace period,
--- a/net/mac80211/util.c 2012-01-04 14:20:03.000000000 +0100
+++ b/net/mac80211/util.c 2012-01-04 14:20:09.000000000 +0100
@@ -1185,15 +1185,8 @@ int ieee80211_reconfig(struct ieee80211_
/* add STAs back */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->uploaded) {
- sdata = sta->sdata;
- if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
- sdata = container_of(sdata->bss,
- struct ieee80211_sub_if_data,
- u.ap);
-
- WARN_ON(drv_sta_add(local, sdata, &sta->sta));
- }
+ if (sta->uploaded)
+ WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta));
}
mutex_unlock(&local->sta_mtx);
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 3/8] mac80211: dont program keys for stations not uploaded
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
2012-01-05 15:30 ` [PATCH 1/8] mac80211: move managed mode station state modification Johannes Berg
2012-01-05 15:30 ` [PATCH 2/8] mac80211: simplify AP_VLAN handling Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 4/8] mac80211: add NOTEXIST station state Johannes Berg
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
If a station couldn't be uploaded to the driver but
is still kept (only in IBSS mode) we still shouldn't
try to program the keys for it into hardware; fix
this bug by skipping the key upload in this case.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/key.c | 30 ++++++++++++++----------------
1 file changed, 14 insertions(+), 16 deletions(-)
--- a/net/mac80211/key.c 2012-01-05 09:16:58.000000000 +0100
+++ b/net/mac80211/key.c 2012-01-05 15:22:12.000000000 +0100
@@ -54,14 +54,6 @@ static void assert_key_lock(struct ieee8
lockdep_assert_held(&local->key_mtx);
}
-static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
-{
- if (key->sta)
- return &key->sta->sta;
-
- return NULL;
-}
-
static void increment_tailroom_need_count(struct ieee80211_sub_if_data *sdata)
{
/*
@@ -95,7 +87,7 @@ static void increment_tailroom_need_coun
static int ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_sta *sta;
+ struct sta_info *sta;
int ret;
might_sleep();
@@ -105,7 +97,7 @@ static int ieee80211_key_enable_hw_accel
assert_key_lock(key->local);
- sta = get_sta_for_key(key);
+ sta = key->sta;
/*
* If this is a per-STA GTK, check if it
@@ -115,6 +107,9 @@ static int ieee80211_key_enable_hw_accel
!(key->local->hw.flags & IEEE80211_HW_SUPPORTS_PER_STA_GTK))
goto out_unsupported;
+ if (sta && !sta->uploaded)
+ goto out_unsupported;
+
sdata = key->sdata;
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
/*
@@ -125,7 +120,8 @@ static int ieee80211_key_enable_hw_accel
goto out_unsupported;
}
- ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
+ ret = drv_set_key(key->local, SET_KEY, sdata,
+ sta ? &sta->sta : NULL, &key->conf);
if (!ret) {
key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
@@ -144,7 +140,8 @@ static int ieee80211_key_enable_hw_accel
if (ret != -ENOSPC && ret != -EOPNOTSUPP)
wiphy_err(key->local->hw.wiphy,
"failed to set key (%d, %pM) to hardware (%d)\n",
- key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+ key->conf.keyidx,
+ sta ? sta->sta.addr : bcast_addr, ret);
out_unsupported:
switch (key->conf.cipher) {
@@ -163,7 +160,7 @@ static int ieee80211_key_enable_hw_accel
static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
{
struct ieee80211_sub_if_data *sdata;
- struct ieee80211_sta *sta;
+ struct sta_info *sta;
int ret;
might_sleep();
@@ -176,7 +173,7 @@ static void ieee80211_key_disable_hw_acc
if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
return;
- sta = get_sta_for_key(key);
+ sta = key->sta;
sdata = key->sdata;
if (!((key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_MMIC) ||
@@ -185,12 +182,13 @@ static void ieee80211_key_disable_hw_acc
increment_tailroom_need_count(sdata);
ret = drv_set_key(key->local, DISABLE_KEY, sdata,
- sta, &key->conf);
+ sta ? &sta->sta : NULL, &key->conf);
if (ret)
wiphy_err(key->local->hw.wiphy,
"failed to remove key (%d, %pM) from hardware (%d)\n",
- key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
+ key->conf.keyidx,
+ sta ? sta->sta.addr : bcast_addr, ret);
key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
}
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 4/8] mac80211: add NOTEXIST station state
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
` (2 preceding siblings ...)
2012-01-05 15:30 ` [PATCH 3/8] mac80211: dont program keys for stations not uploaded Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 5/8] mac80211: add sta_state callback Johannes Berg
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
This will be used by drivers later if they
need to have stations inserted all the time,
in mac80211 has no purpose, is never used
and sta_state starts out in NONE.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/sta_info.c | 2 ++
net/mac80211/sta_info.h | 1 +
2 files changed, 3 insertions(+)
--- a/net/mac80211/sta_info.h 2012-01-04 14:13:16.000000000 +0100
+++ b/net/mac80211/sta_info.h 2012-01-04 14:19:42.000000000 +0100
@@ -77,6 +77,7 @@ enum ieee80211_sta_info_flags {
enum ieee80211_sta_state {
/* NOTE: These need to be ordered correctly! */
+ IEEE80211_STA_NOTEXIST,
IEEE80211_STA_NONE,
IEEE80211_STA_AUTH,
IEEE80211_STA_ASSOC,
--- a/net/mac80211/sta_info.c 2012-01-04 14:13:16.000000000 +0100
+++ b/net/mac80211/sta_info.c 2012-01-04 14:19:42.000000000 +0100
@@ -295,6 +295,8 @@ struct sta_info *sta_info_alloc(struct i
sta->sdata = sdata;
sta->last_rx = jiffies;
+ sta->sta_state = IEEE80211_STA_NONE;
+
do_posix_clock_monotonic_gettime(&uptime);
sta->last_connected = uptime.tv_sec;
ewma_init(&sta->avg_signal, 1024, 8);
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 5/8] mac80211: add sta_state callback
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
` (3 preceding siblings ...)
2012-01-05 15:30 ` [PATCH 4/8] mac80211: add NOTEXIST station state Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 6/8] mac80211: implement sta_add/sta_remove in sta_state Johannes Berg
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, Eliad Peller
From: Johannes Berg <johannes.berg@intel.com>
(based on Eliad's patch)
Add a callback to notify the low-level driver whenever
the state of a station changes. The driver is only
notified when the station is actually in the mac80211
hash table, not for pre-insert state transitions.
To allow the driver to replace sta_add/remove calls
with this, call extra transitions with the NOTEXIST
state.
This callback can fail, so we need to be careful in
handling it when a station is inserted, particularly
in the IBSS case where we still keep the station entry
around for mac80211 purposes.
Signed-off-by: Eliad Peller <eliad@wizery.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
v2: call drv_sta_state() within the sta addition process (thanks Johannes)
Johannes:
v3: - call drv_sta_state() in suspend
- introduce NOTEXIST state
- don't put old state into driver visible data but pass it to the
callback -- also fixes a reconfig bug
- make exclusive (forbid having sta_add/remove and sta_state)
- allow drv_sta_state() to fail and unwind initial
addition if it does
include/net/mac80211.h | 30 +++++++++++++++++++++
net/mac80211/driver-ops.h | 22 +++++++++++++++
net/mac80211/driver-trace.h | 32 +++++++++++++++++++++++
net/mac80211/main.c | 3 ++
net/mac80211/pm.c | 10 ++++++-
net/mac80211/sta_info.c | 61 ++++++++++++++++++++++++++++++++++++++++----
net/mac80211/sta_info.h | 9 ------
net/mac80211/util.c | 10 ++++++-
8 files changed, 161 insertions(+), 16 deletions(-)
--- a/include/net/mac80211.h 2012-01-05 15:24:59.000000000 +0100
+++ b/include/net/mac80211.h 2012-01-05 15:44:25.000000000 +0100
@@ -962,6 +962,25 @@ enum set_key_cmd {
};
/**
+ * enum ieee80211_sta_state - station state
+ *
+ * @IEEE80211_STA_NOTEXIST: station doesn't exist at all,
+ * this is a special state for add/remove transitions
+ * @IEEE80211_STA_NONE: station exists without special state
+ * @IEEE80211_STA_AUTH: station is authenticated
+ * @IEEE80211_STA_ASSOC: station is associated
+ * @IEEE80211_STA_AUTHORIZED: station is authorized (802.1X)
+ */
+enum ieee80211_sta_state {
+ /* NOTE: These need to be ordered correctly! */
+ IEEE80211_STA_NOTEXIST,
+ IEEE80211_STA_NONE,
+ IEEE80211_STA_AUTH,
+ IEEE80211_STA_ASSOC,
+ IEEE80211_STA_AUTHORIZED,
+};
+
+/**
* struct ieee80211_sta - station table entry
*
* A station table entry represents a station we are possibly
@@ -1963,6 +1982,13 @@ enum ieee80211_frame_release_type {
* in AP mode, this callback will not be called when the flag
* %IEEE80211_HW_AP_LINK_PS is set. Must be atomic.
*
+ * @sta_state: Notifies low level driver about state transition of a
+ * station (which can be the AP, a client, IBSS/WDS/mesh peer etc.)
+ * This callback is mutually exclusive with @sta_add/@sta_remove.
+ * It must not fail for down transitions but may fail for transitions
+ * up the list of states.
+ * The callback can sleep.
+ *
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
* bursting) for a hardware TX queue.
* Returns a negative error code on failure.
@@ -2182,6 +2208,10 @@ struct ieee80211_ops {
struct ieee80211_sta *sta);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta);
+ int (*sta_state)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state);
int (*conf_tx)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 queue,
const struct ieee80211_tx_queue_params *params);
--- a/net/mac80211/driver-ops.h 2012-01-05 15:25:00.000000000 +0100
+++ b/net/mac80211/driver-ops.h 2012-01-05 16:09:23.000000000 +0100
@@ -478,6 +478,28 @@ static inline void drv_sta_remove(struct
trace_drv_return_void(local);
}
+static inline __must_check
+int drv_sta_state(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
+{
+ int ret = 0;
+
+ might_sleep();
+
+ sdata = get_bss_sdata(sdata);
+ check_sdata_in_driver(sdata);
+
+ trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
+ if (local->ops->sta_state)
+ ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
+ old_state, new_state);
+ trace_drv_return_int(local, ret);
+ return ret;
+}
+
static inline int drv_conf_tx(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata, u16 queue,
const struct ieee80211_tx_queue_params *params)
--- a/net/mac80211/driver-trace.h 2012-01-05 15:24:59.000000000 +0100
+++ b/net/mac80211/driver-trace.h 2012-01-05 15:59:39.000000000 +0100
@@ -635,6 +635,38 @@ TRACE_EVENT(drv_sta_notify,
)
);
+TRACE_EVENT(drv_sta_state,
+ TP_PROTO(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state),
+
+ TP_ARGS(local, sdata, sta, old_state, new_state),
+
+ TP_STRUCT__entry(
+ LOCAL_ENTRY
+ VIF_ENTRY
+ STA_ENTRY
+ __field(u32, old_state)
+ __field(u32, new_state)
+ ),
+
+ TP_fast_assign(
+ LOCAL_ASSIGN;
+ VIF_ASSIGN;
+ STA_ASSIGN;
+ __entry->old_state = old_state;
+ __entry->new_state = new_state;
+ ),
+
+ TP_printk(
+ LOCAL_PR_FMT VIF_PR_FMT STA_PR_FMT " state: %d->%d",
+ LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG,
+ __entry->old_state, __entry->new_state
+ )
+);
+
TRACE_EVENT(drv_sta_add,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
--- a/net/mac80211/sta_info.c 2012-01-05 15:44:19.000000000 +0100
+++ b/net/mac80211/sta_info.c 2012-01-05 16:22:36.000000000 +0100
@@ -353,6 +353,38 @@ static int sta_info_insert_check(struct
return 0;
}
+static int sta_info_insert_drv_state(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ struct sta_info *sta)
+{
+ enum ieee80211_sta_state state;
+ int err = 0;
+
+ for (state = IEEE80211_STA_NOTEXIST; state < sta->sta_state; state++) {
+ err = drv_sta_state(local, sdata, sta, state, state + 1);
+ if (err)
+ break;
+ }
+
+ if (!err) {
+ sta->uploaded = true;
+ return 0;
+ }
+
+ if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
+ printk(KERN_DEBUG
+ "%s: failed to move IBSS STA %pM to state %d (%d) - keeping it anyway.\n",
+ sdata->name, sta->sta.addr, state + 1, err);
+ err = 0;
+ }
+
+ /* unwind on error */
+ for (; state > IEEE80211_STA_NOTEXIST; state--)
+ WARN_ON(drv_sta_state(local, sdata, sta, state, state - 1));
+
+ return err;
+}
+
/*
* should be called with sta_mtx locked
* this function replaces the mutex lock
@@ -394,8 +426,11 @@ static int sta_info_insert_finish(struct
printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
"driver (%d) - keeping it anyway.\n",
sdata->name, sta->sta.addr, err);
- } else
- sta->uploaded = true;
+ } else {
+ err = sta_info_insert_drv_state(local, sdata, sta);
+ if (err)
+ goto out_err;
+ }
}
if (!dummy_reinsert) {
@@ -772,12 +807,16 @@ int __must_check __sta_info_destroy(stru
RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
while (sta->sta_state > IEEE80211_STA_NONE) {
- int err = sta_info_move_state(sta, sta->sta_state - 1);
- WARN_ON_ONCE(err != 0);
+ ret = sta_info_move_state(sta, sta->sta_state - 1);
+ WARN_ON_ONCE(ret != 0);
}
- if (sta->uploaded)
+ if (sta->uploaded) {
drv_sta_remove(local, sdata, &sta->sta);
+ ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,
+ IEEE80211_STA_NOTEXIST);
+ WARN_ON_ONCE(ret != 0);
+ }
/*
* At this point, after we wait for an RCU grace period,
@@ -1455,6 +1494,18 @@ int sta_info_move_state(struct sta_info
printk(KERN_DEBUG "%s: moving STA %pM to state %d\n",
sta->sdata->name, sta->sta.addr, new_state);
+
+ /*
+ * notify the driver before the actual change, so it can
+ * fail the transition
+ */
+ if (test_sta_flag(sta, WLAN_STA_INSERTED)) {
+ int err = drv_sta_state(sta->local, sta->sdata, sta,
+ sta->sta_state, new_state);
+ if (err)
+ return err;
+ }
+
sta->sta_state = new_state;
return 0;
--- a/net/mac80211/util.c 2012-01-05 15:24:59.000000000 +0100
+++ b/net/mac80211/util.c 2012-01-05 16:09:23.000000000 +0100
@@ -1185,8 +1185,16 @@ int ieee80211_reconfig(struct ieee80211_
/* add STAs back */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->uploaded)
+ if (sta->uploaded) {
+ enum ieee80211_sta_state state;
+
WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta));
+
+ for (state = IEEE80211_STA_NOTEXIST;
+ state < sta->sta_state - 1; state++)
+ WARN_ON(drv_sta_state(local, sta->sdata, sta,
+ state, state + 1));
+ }
}
mutex_unlock(&local->sta_mtx);
--- a/net/mac80211/main.c 2012-01-05 15:24:59.000000000 +0100
+++ b/net/mac80211/main.c 2012-01-05 15:44:25.000000000 +0100
@@ -534,6 +534,9 @@ struct ieee80211_hw *ieee80211_alloc_hw(
int priv_size, i;
struct wiphy *wiphy;
+ if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove)))
+ return NULL;
+
/* Ensure 32-byte alignment of our private data and hw private data.
* We use the wiphy priv data for both our ieee80211_local and for
* the driver's private data
--- a/net/mac80211/sta_info.h 2012-01-05 15:44:19.000000000 +0100
+++ b/net/mac80211/sta_info.h 2012-01-05 16:04:35.000000000 +0100
@@ -75,15 +75,6 @@ enum ieee80211_sta_info_flags {
WLAN_STA_INSERTED,
};
-enum ieee80211_sta_state {
- /* NOTE: These need to be ordered correctly! */
- IEEE80211_STA_NOTEXIST,
- IEEE80211_STA_NONE,
- IEEE80211_STA_AUTH,
- IEEE80211_STA_ASSOC,
- IEEE80211_STA_AUTHORIZED,
-};
-
#define STA_TID_NUM 16
#define ADDBA_RESP_INTERVAL HZ
#define HT_AGG_MAX_RETRIES 15
--- a/net/mac80211/pm.c 2012-01-05 15:25:00.000000000 +0100
+++ b/net/mac80211/pm.c 2012-01-05 16:09:23.000000000 +0100
@@ -97,9 +97,17 @@ int __ieee80211_suspend(struct ieee80211
/* tear down aggregation sessions and remove STAs */
mutex_lock(&local->sta_mtx);
list_for_each_entry(sta, &local->sta_list, list) {
- if (sta->uploaded)
+ if (sta->uploaded) {
+ enum ieee80211_sta_state state;
+
drv_sta_remove(local, sta->sdata, &sta->sta);
+ state = sta->sta_state;
+ for (; state > IEEE80211_STA_NOTEXIST; state--)
+ WARN_ON(drv_sta_state(local, sdata, sta,
+ state, state - 1));
+ }
+
mesh_plink_quiesce(sta);
}
mutex_unlock(&local->sta_mtx);
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 6/8] mac80211: implement sta_add/sta_remove in sta_state
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
` (4 preceding siblings ...)
2012-01-05 15:30 ` [PATCH 5/8] mac80211: add sta_state callback Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 7/8] mac80211: call rate control only after init Johannes Berg
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
Instead of maintaining separate sta_add/sta_remove
callsites, implement it in sta_state when the driver
has no sta_state implementation.
The only behavioural change this should cause is in
secure mesh mode: with this the station entries will
only be created after the stations are set to AUTH.
Given which drivers support mesh, this seems to not
be a problem.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/driver-ops.h | 11 ++++++++++-
net/mac80211/pm.c | 2 --
net/mac80211/sta_info.c | 23 +++++++++--------------
net/mac80211/util.c | 2 --
4 files changed, 19 insertions(+), 19 deletions(-)
--- a/net/mac80211/sta_info.c 2012-01-05 16:22:36.000000000 +0100
+++ b/net/mac80211/sta_info.c 2012-01-05 16:29:46.000000000 +0100
@@ -367,7 +367,12 @@ static int sta_info_insert_drv_state(str
}
if (!err) {
- sta->uploaded = true;
+ /*
+ * Drivers using legacy sta_add/sta_remove callbacks only
+ * get uploaded set to true after sta_add is called.
+ */
+ if (!local->ops->sta_add)
+ sta->uploaded = true;
return 0;
}
@@ -419,18 +424,9 @@ static int sta_info_insert_finish(struct
if (!sta->dummy || dummy_reinsert) {
/* notify driver */
- err = drv_sta_add(local, sdata, &sta->sta);
- if (err) {
- if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
- goto out_err;
- printk(KERN_DEBUG "%s: failed to add IBSS STA %pM to "
- "driver (%d) - keeping it anyway.\n",
- sdata->name, sta->sta.addr, err);
- } else {
- err = sta_info_insert_drv_state(local, sdata, sta);
- if (err)
- goto out_err;
- }
+ err = sta_info_insert_drv_state(local, sdata, sta);
+ if (err)
+ goto out_err;
}
if (!dummy_reinsert) {
@@ -812,7 +808,6 @@ int __must_check __sta_info_destroy(stru
}
if (sta->uploaded) {
- drv_sta_remove(local, sdata, &sta->sta);
ret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,
IEEE80211_STA_NOTEXIST);
WARN_ON_ONCE(ret != 0);
--- a/net/mac80211/util.c 2012-01-05 16:09:23.000000000 +0100
+++ b/net/mac80211/util.c 2012-01-05 16:29:46.000000000 +0100
@@ -1188,8 +1188,6 @@ int ieee80211_reconfig(struct ieee80211_
if (sta->uploaded) {
enum ieee80211_sta_state state;
- WARN_ON(drv_sta_add(local, sta->sdata, &sta->sta));
-
for (state = IEEE80211_STA_NOTEXIST;
state < sta->sta_state - 1; state++)
WARN_ON(drv_sta_state(local, sta->sdata, sta,
--- a/net/mac80211/pm.c 2012-01-05 16:09:23.000000000 +0100
+++ b/net/mac80211/pm.c 2012-01-05 16:29:46.000000000 +0100
@@ -100,8 +100,6 @@ int __ieee80211_suspend(struct ieee80211
if (sta->uploaded) {
enum ieee80211_sta_state state;
- drv_sta_remove(local, sta->sdata, &sta->sta);
-
state = sta->sta_state;
for (; state > IEEE80211_STA_NOTEXIST; state--)
WARN_ON(drv_sta_state(local, sdata, sta,
--- a/net/mac80211/driver-ops.h 2012-01-05 16:09:23.000000000 +0100
+++ b/net/mac80211/driver-ops.h 2012-01-05 16:29:46.000000000 +0100
@@ -493,9 +493,18 @@ int drv_sta_state(struct ieee80211_local
check_sdata_in_driver(sdata);
trace_drv_sta_state(local, sdata, &sta->sta, old_state, new_state);
- if (local->ops->sta_state)
+ if (local->ops->sta_state) {
ret = local->ops->sta_state(&local->hw, &sdata->vif, &sta->sta,
old_state, new_state);
+ } else if (old_state == IEEE80211_STA_AUTH &&
+ new_state == IEEE80211_STA_ASSOC) {
+ ret = drv_sta_add(local, sdata, &sta->sta);
+ if (ret == 0)
+ sta->uploaded = true;
+ } else if (old_state == IEEE80211_STA_ASSOC &&
+ new_state == IEEE80211_STA_AUTH) {
+ drv_sta_remove(local, sdata, &sta->sta);
+ }
trace_drv_return_int(local, ret);
return ret;
}
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 7/8] mac80211: call rate control only after init
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
` (5 preceding siblings ...)
2012-01-05 15:30 ` [PATCH 6/8] mac80211: implement sta_add/sta_remove in sta_state Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-05 15:30 ` [PATCH 8/8] mac80211: remove dummy STA support Johannes Berg
2012-01-12 8:25 ` [PATCH 0/8] more station handling refactoring Johannes Berg
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
There are situations where we don't have the
necessary rate control information yet for
station entries, e.g. when associating. This
currently doesn't really happen due to the
dummy station handling; explicitly disabling
rate control when it's not initialised will
allow us to remove dummy stations.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/debugfs_sta.c | 4 ++--
net/mac80211/rate.c | 2 +-
net/mac80211/rate.h | 1 +
net/mac80211/sta_info.h | 2 ++
4 files changed, 6 insertions(+), 3 deletions(-)
--- a/net/mac80211/debugfs_sta.c 2012-01-05 09:16:57.000000000 +0100
+++ b/net/mac80211/debugfs_sta.c 2012-01-05 11:21:10.000000000 +0100
@@ -63,7 +63,7 @@ static ssize_t sta_flags_read(struct fil
test_sta_flag(sta, WLAN_STA_##flg) ? #flg "\n" : ""
int res = scnprintf(buf, sizeof(buf),
- "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
TEST(PS_DRIVER), TEST(AUTHORIZED),
TEST(SHORT_PREAMBLE),
@@ -71,7 +71,7 @@ static ssize_t sta_flags_read(struct fil
TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
- TEST(INSERTED));
+ TEST(INSERTED), TEST(RATE_CONTROL));
#undef TEST
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
--- a/net/mac80211/rate.c 2011-12-10 17:32:28.000000000 +0100
+++ b/net/mac80211/rate.c 2012-01-05 11:22:11.000000000 +0100
@@ -336,7 +336,7 @@ void rate_control_get_rate(struct ieee80
int i;
u32 mask;
- if (sta) {
+ if (sta && test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) {
ista = &sta->sta;
priv_sta = sta->rate_ctrl_priv;
}
--- a/net/mac80211/rate.h 2011-11-03 13:48:28.000000000 +0100
+++ b/net/mac80211/rate.h 2012-01-05 11:22:05.000000000 +0100
@@ -62,6 +62,7 @@ static inline void rate_control_rate_ini
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
ref->ops->rate_init(ref->priv, sband, ista, priv_sta);
+ set_sta_flag(sta, WLAN_STA_RATE_CONTROL);
}
static inline void rate_control_rate_update(struct ieee80211_local *local,
--- a/net/mac80211/sta_info.h 2012-01-05 11:20:04.000000000 +0100
+++ b/net/mac80211/sta_info.h 2012-01-05 11:20:53.000000000 +0100
@@ -53,6 +53,7 @@
* reply to other uAPSD trigger frames or PS-Poll.
* @WLAN_STA_4ADDR_EVENT: 4-addr event was already sent for this frame.
* @WLAN_STA_INSERTED: This station is inserted into the hash table.
+ * @WLAN_STA_RATE_CONTROL: rate control was initialized for this station.
*/
enum ieee80211_sta_info_flags {
WLAN_STA_AUTH,
@@ -73,6 +74,7 @@ enum ieee80211_sta_info_flags {
WLAN_STA_SP,
WLAN_STA_4ADDR_EVENT,
WLAN_STA_INSERTED,
+ WLAN_STA_RATE_CONTROL,
};
#define STA_TID_NUM 16
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH 8/8] mac80211: remove dummy STA support
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
` (6 preceding siblings ...)
2012-01-05 15:30 ` [PATCH 7/8] mac80211: call rate control only after init Johannes Berg
@ 2012-01-05 15:30 ` Johannes Berg
2012-01-12 8:25 ` [PATCH 0/8] more station handling refactoring Johannes Berg
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-05 15:30 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Johannes Berg <johannes.berg@intel.com>
The dummy STA support was added because I didn't
want to change the driver API at the time. Now
that we have state transitions triggering station
add/remove in the driver, we only call add once a
station reaches ASSOCIATED, so we can remove the
dummy station stuff again.
While at it, tighten the RX check and accept only
port control (EAP) frames from the AP station if
it's not associated yet -- in other cases there's
no race.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mlme.c | 15 +----
net/mac80211/rx.c | 13 +++-
net/mac80211/sta_info.c | 135 ++++++++----------------------------------------
net/mac80211/sta_info.h | 30 ----------
4 files changed, 38 insertions(+), 155 deletions(-)
--- a/net/mac80211/sta_info.h 2012-01-05 16:29:49.000000000 +0100
+++ b/net/mac80211/sta_info.h 2012-01-05 16:29:50.000000000 +0100
@@ -267,8 +267,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
@@ -366,9 +364,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;
};
@@ -470,15 +465,9 @@ rcu_dereference_protected_tid_tx(struct
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,
@@ -487,23 +476,7 @@ void for_each_sta_info_type_check(struct
{
}
-#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; \
@@ -542,7 +515,6 @@ void sta_info_free(struct ieee80211_loca
*/
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,
--- a/net/mac80211/sta_info.c 2012-01-05 16:29:46.000000000 +0100
+++ b/net/mac80211/sta_info.c 2012-01-05 16:29:50.000000000 +0100
@@ -100,25 +100,6 @@ struct sta_info *sta_info_get(struct iee
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
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,
@@ -399,66 +356,43 @@ static int sta_info_insert_finish(struct
{
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;
- }
+ /* check if STA exists already */
+ if (sta_info_get_bss(sdata, sta->sta.addr)) {
+ 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;
- }
-
- 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 */
@@ -510,25 +444,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)
{
/*
@@ -889,7 +804,7 @@ int sta_info_destroy_addr(struct ieee802
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);
@@ -903,7 +818,7 @@ int sta_info_destroy_addr_bss(struct iee
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);
--- a/net/mac80211/mlme.c 2012-01-05 16:04:34.000000000 +0100
+++ b/net/mac80211/mlme.c 2012-01-05 16:29:50.000000000 +0100
@@ -1579,7 +1579,7 @@ static bool ieee80211_assoc_success(stru
* 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;
@@ -1646,14 +1646,7 @@ static bool ieee80211_assoc_success(stru
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
@@ -2534,12 +2527,10 @@ static int ieee80211_pre_assoc(struct ie
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;
}
--- a/net/mac80211/rx.c 2012-01-05 16:04:34.000000000 +0100
+++ b/net/mac80211/rx.c 2012-01-05 16:29:50.000000000 +0100
@@ -859,7 +859,12 @@ ieee80211_rx_h_check(struct ieee80211_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;
@@ -2975,7 +2980,7 @@ static void __ieee80211_rx_handle_packet
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;
@@ -3019,7 +3024,7 @@ static void __ieee80211_rx_handle_packet
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);
@@ -3027,7 +3032,7 @@ static void __ieee80211_rx_handle_packet
}
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))
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH 0/8] more station handling refactoring
2012-01-05 15:30 [PATCH 0/8] more station handling refactoring Johannes Berg
` (7 preceding siblings ...)
2012-01-05 15:30 ` [PATCH 8/8] mac80211: remove dummy STA support Johannes Berg
@ 2012-01-12 8:25 ` Johannes Berg
8 siblings, 0 replies; 10+ messages in thread
From: Johannes Berg @ 2012-01-12 8:25 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
On Thu, 2012-01-05 at 16:30 +0100, Johannes Berg wrote:
> Here's another set of patches to refactor station
> handling, particularly station state handling (and
> fix a bug or two in the process).
>
> The major work here is getting rid of dummy stations
> again and notifying drivers about state transitions
> (but state transition and sta_add/sta_remove callbacks
> will be mutually exclusive).
Eliad identified a few issues here -- John, please drop this patchset,
I'll resend.
johannes
^ permalink raw reply [flat|nested] 10+ messages in thread