mac80211: stop only the queues assigned to the vif during channel switch

Instead of stopping all the hardware queues during channel switch,
which is especially bad when we have large CSA counts, stop only the
queues that are assigned to the vif that is performing the channel
switch.

Additionally, check for (sdata->csa_block_tx) instead of calling
ieee80211_csa_needs_block_tx(), which can now be removed.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Luciano Coelho 2014-06-13 16:30:07 +03:00 коммит произвёл Johannes Berg
Родитель 26da23b695
Коммит a46992b441
4 изменённых файлов: 35 добавлений и 64 удалений

Просмотреть файл

@ -790,31 +790,6 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
return 0; return 0;
} }
bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
lockdep_assert_held(&local->mtx);
rcu_read_lock();
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
if (!sdata->vif.csa_active)
continue;
if (!sdata->csa_block_tx)
continue;
rcu_read_unlock();
return true;
}
rcu_read_unlock();
return false;
}
static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
{ {
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@ -834,11 +809,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
/* abort any running channel switch */ /* abort any running channel switch */
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
sdata->vif.csa_active = false; sdata->vif.csa_active = false;
if (!ieee80211_csa_needs_block_tx(local)) if (sdata->csa_block_tx) {
ieee80211_wake_queues_by_reason(&local->hw, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA, sdata->csa_block_tx = false;
false); }
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
kfree(sdata->u.ap.next_beacon); kfree(sdata->u.ap.next_beacon);
@ -2826,11 +2802,11 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
if (!ieee80211_csa_needs_block_tx(local)) if (sdata->csa_block_tx) {
ieee80211_wake_queues_by_reason(&local->hw, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA, sdata->csa_block_tx = false;
false); }
return 0; return 0;
} }
@ -3060,10 +3036,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
sdata->vif.csa_active = true; sdata->vif.csa_active = true;
if (sdata->csa_block_tx) if (sdata->csa_block_tx)
ieee80211_stop_queues_by_reason(&local->hw, ieee80211_stop_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA,
false);
if (changed) { if (changed) {
ieee80211_bss_info_change_notify(sdata, changed); ieee80211_bss_info_change_notify(sdata, changed);

Просмотреть файл

@ -1489,7 +1489,6 @@ void ieee80211_sw_roc_work(struct work_struct *work);
void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
/* channel switch handling */ /* channel switch handling */
bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local);
void ieee80211_csa_finalize_work(struct work_struct *work); void ieee80211_csa_finalize_work(struct work_struct *work);
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_csa_settings *params); struct cfg80211_csa_settings *params);

Просмотреть файл

@ -841,11 +841,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
sdata_lock(sdata); sdata_lock(sdata);
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
sdata->vif.csa_active = false; sdata->vif.csa_active = false;
if (!ieee80211_csa_needs_block_tx(local)) if (sdata->csa_block_tx) {
ieee80211_wake_queues_by_reason(&local->hw, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA, sdata->csa_block_tx = false;
false); }
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
sdata_unlock(sdata); sdata_unlock(sdata);

Просмотреть файл

@ -980,11 +980,11 @@ static void ieee80211_chswitch_work(struct work_struct *work)
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
sdata->vif.csa_active = false; sdata->vif.csa_active = false;
/* XXX: wait for a beacon first? */ /* XXX: wait for a beacon first? */
if (!ieee80211_csa_needs_block_tx(local)) if (sdata->csa_block_tx) {
ieee80211_wake_queues_by_reason(&local->hw, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA, sdata->csa_block_tx = false;
false); }
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
@ -1114,10 +1114,8 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
sdata->csa_block_tx = csa_ie.mode; sdata->csa_block_tx = csa_ie.mode;
if (sdata->csa_block_tx) if (sdata->csa_block_tx)
ieee80211_stop_queues_by_reason(&local->hw, ieee80211_stop_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA,
false);
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
if (local->ops->channel_switch) { if (local->ops->channel_switch) {
@ -1833,11 +1831,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_vif_release_channel(sdata); ieee80211_vif_release_channel(sdata);
sdata->vif.csa_active = false; sdata->vif.csa_active = false;
if (!ieee80211_csa_needs_block_tx(local)) if (sdata->csa_block_tx) {
ieee80211_wake_queues_by_reason(&local->hw, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA, sdata->csa_block_tx = false;
false); }
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
@ -2083,11 +2081,11 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
mutex_lock(&local->mtx); mutex_lock(&local->mtx);
sdata->vif.csa_active = false; sdata->vif.csa_active = false;
if (!ieee80211_csa_needs_block_tx(local)) if (sdata->csa_block_tx) {
ieee80211_wake_queues_by_reason(&local->hw, ieee80211_wake_vif_queues(local, sdata,
IEEE80211_MAX_QUEUE_MAP, IEEE80211_QUEUE_STOP_REASON_CSA);
IEEE80211_QUEUE_STOP_REASON_CSA, sdata->csa_block_tx = false;
false); }
mutex_unlock(&local->mtx); mutex_unlock(&local->mtx);
cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,