forked from Minki/linux
mac80211: optimise roaming time again
The last fixes re-added the RCU synchronize penalty on roaming to fix the races. Split up sta_info_flush() now to get rid of that again, and let managed mode (and only it) delay the actual destruction. Tested-by: Ben Greear <greearb@candelatech.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
09f4114e02
commit
051007d9e2
@ -775,8 +775,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||
* This is relevant only in WDS mode, in all other modes we've
|
||||
* already removed all stations when disconnecting or similar,
|
||||
* so warn otherwise.
|
||||
*
|
||||
* We call sta_info_flush_cleanup() later, to combine RCU waits.
|
||||
*/
|
||||
flushed = sta_info_flush(sdata);
|
||||
flushed = sta_info_flush_defer(sdata);
|
||||
WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
|
||||
(sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
|
||||
|
||||
@ -861,11 +863,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
|
||||
cancel_work_sync(&sdata->work);
|
||||
/*
|
||||
* When we get here, the interface is marked down.
|
||||
* Call synchronize_rcu() to wait for the RX path
|
||||
* should it be using the interface and enqueuing
|
||||
* frames at this very time on another CPU.
|
||||
* sta_info_flush_cleanup() calls rcu_barrier to
|
||||
* wait for the station call_rcu() calls to complete,
|
||||
* here we require it to wait for the RX path in case
|
||||
* it is using the interface and enqueuing frames at
|
||||
* this very time on another CPU.
|
||||
*/
|
||||
synchronize_rcu();
|
||||
sta_info_flush_cleanup(sdata);
|
||||
|
||||
skb_queue_purge(&sdata->skb_queue);
|
||||
|
||||
/*
|
||||
|
@ -1521,7 +1521,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
memset(ifmgd->bssid, 0, ETH_ALEN);
|
||||
|
||||
/* remove AP and TDLS peers */
|
||||
sta_info_flush(sdata);
|
||||
sta_info_flush_defer(sdata);
|
||||
|
||||
/* finally reset all BSS / config parameters */
|
||||
changed |= ieee80211_reset_erp_info(sdata);
|
||||
|
@ -104,6 +104,16 @@ static void cleanup_single_sta(struct sta_info *sta)
|
||||
* neither mac80211 nor the driver can reference this
|
||||
* sta struct any more except by still existing timers
|
||||
* associated with this station that we clean up below.
|
||||
*
|
||||
* Note though that this still uses the sdata and even
|
||||
* calls the driver in AP and mesh mode, so interfaces
|
||||
* of those types mush use call sta_info_flush_cleanup()
|
||||
* (typically via sta_info_flush()) before deconfiguring
|
||||
* the driver.
|
||||
*
|
||||
* In station mode, nothing happens here so it doesn't
|
||||
* have to (and doesn't) do that, this is intentional to
|
||||
* speed up roaming.
|
||||
*/
|
||||
|
||||
if (test_sta_flag(sta, WLAN_STA_PS_STA)) {
|
||||
@ -887,14 +897,8 @@ void sta_info_stop(struct ieee80211_local *local)
|
||||
del_timer_sync(&local->sta_cleanup);
|
||||
}
|
||||
|
||||
/**
|
||||
* sta_info_flush - flush matching STA entries from the STA table
|
||||
*
|
||||
* Returns the number of removed STA entries.
|
||||
*
|
||||
* @sdata: sdata to remove all stations from
|
||||
*/
|
||||
int sta_info_flush(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta, *tmp;
|
||||
@ -911,12 +915,15 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata)
|
||||
}
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
rcu_barrier();
|
||||
|
||||
ieee80211_cleanup_sdata_stas(sdata);
|
||||
cancel_work_sync(&sdata->cleanup_stations_wk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
|
||||
|
@ -548,7 +548,25 @@ void sta_info_recalc_tim(struct sta_info *sta);
|
||||
|
||||
void sta_info_init(struct ieee80211_local *local);
|
||||
void sta_info_stop(struct ieee80211_local *local);
|
||||
int sta_info_flush(struct ieee80211_sub_if_data *sdata);
|
||||
int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata);
|
||||
void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata);
|
||||
|
||||
/**
|
||||
* sta_info_flush - flush matching STA entries from the STA table
|
||||
*
|
||||
* Returns the number of removed STA entries.
|
||||
*
|
||||
* @sdata: sdata to remove all stations from
|
||||
*/
|
||||
static inline int sta_info_flush(struct ieee80211_sub_if_data *sdata)
|
||||
{
|
||||
int ret = sta_info_flush_defer(sdata);
|
||||
|
||||
sta_info_flush_cleanup(sdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void sta_set_rate_info_tx(struct sta_info *sta,
|
||||
const struct ieee80211_tx_rate *rate,
|
||||
struct rate_info *rinfo);
|
||||
|
Loading…
Reference in New Issue
Block a user