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
|
* This is relevant only in WDS mode, in all other modes we've
|
||||||
* already removed all stations when disconnecting or similar,
|
* already removed all stations when disconnecting or similar,
|
||||||
* so warn otherwise.
|
* 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) ||
|
WARN_ON_ONCE((sdata->vif.type != NL80211_IFTYPE_WDS && flushed > 0) ||
|
||||||
(sdata->vif.type == NL80211_IFTYPE_WDS && flushed != 1));
|
(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);
|
cancel_work_sync(&sdata->work);
|
||||||
/*
|
/*
|
||||||
* When we get here, the interface is marked down.
|
* When we get here, the interface is marked down.
|
||||||
* Call synchronize_rcu() to wait for the RX path
|
* sta_info_flush_cleanup() calls rcu_barrier to
|
||||||
* should it be using the interface and enqueuing
|
* wait for the station call_rcu() calls to complete,
|
||||||
* frames at this very time on another CPU.
|
* 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);
|
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);
|
memset(ifmgd->bssid, 0, ETH_ALEN);
|
||||||
|
|
||||||
/* remove AP and TDLS peers */
|
/* remove AP and TDLS peers */
|
||||||
sta_info_flush(sdata);
|
sta_info_flush_defer(sdata);
|
||||||
|
|
||||||
/* finally reset all BSS / config parameters */
|
/* finally reset all BSS / config parameters */
|
||||||
changed |= ieee80211_reset_erp_info(sdata);
|
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
|
* neither mac80211 nor the driver can reference this
|
||||||
* sta struct any more except by still existing timers
|
* sta struct any more except by still existing timers
|
||||||
* associated with this station that we clean up below.
|
* 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)) {
|
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);
|
del_timer_sync(&local->sta_cleanup);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* sta_info_flush - flush matching STA entries from the STA table
|
int sta_info_flush_defer(struct ieee80211_sub_if_data *sdata)
|
||||||
*
|
|
||||||
* Returns the number of removed STA entries.
|
|
||||||
*
|
|
||||||
* @sdata: sdata to remove all stations from
|
|
||||||
*/
|
|
||||||
int sta_info_flush(struct ieee80211_sub_if_data *sdata)
|
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct sta_info *sta, *tmp;
|
struct sta_info *sta, *tmp;
|
||||||
|
@ -911,12 +915,15 @@ int sta_info_flush(struct ieee80211_sub_if_data *sdata)
|
||||||
}
|
}
|
||||||
mutex_unlock(&local->sta_mtx);
|
mutex_unlock(&local->sta_mtx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sta_info_flush_cleanup(struct ieee80211_sub_if_data *sdata)
|
||||||
|
{
|
||||||
rcu_barrier();
|
rcu_barrier();
|
||||||
|
|
||||||
ieee80211_cleanup_sdata_stas(sdata);
|
ieee80211_cleanup_sdata_stas(sdata);
|
||||||
cancel_work_sync(&sdata->cleanup_stations_wk);
|
cancel_work_sync(&sdata->cleanup_stations_wk);
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata,
|
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_init(struct ieee80211_local *local);
|
||||||
void sta_info_stop(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,
|
void sta_set_rate_info_tx(struct sta_info *sta,
|
||||||
const struct ieee80211_tx_rate *rate,
|
const struct ieee80211_tx_rate *rate,
|
||||||
struct rate_info *rinfo);
|
struct rate_info *rinfo);
|
||||||
|
|
Loading…
Reference in New Issue