summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLuciano Coelho <luciano.coelho@intel.com>2014-11-10 11:10:21 +0200
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-11-24 08:30:35 +0200
commit686e7fe1c4389984c5f623ebe1bb636d41841f37 (patch)
tree4931a3fce5fed177c785eef8e2d8c72954f7663e
parent0c6505c6ed180ee342c98a6ec2c91e4ee80c1a10 (diff)
downloadop-kernel-dev-686e7fe1c4389984c5f623ebe1bb636d41841f37.zip
op-kernel-dev-686e7fe1c4389984c5f623ebe1bb636d41841f37.tar.gz
iwlwifi: mvm: protect session during CSA
When another vif is also running during a channel switch, we need to use a session protection when we move to the new channel, so that we don't miss the beacons. Without this, sometimes the other vif repeatedly gets time exactly when we should be hearing the beacons, preventing channel switch from completing. Adding a session protection that lasts from the moment the channel changes until 2 TBTTs later, ensures that we will hear the beacons on the destination channel. Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h1
2 files changed, 22 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index a62014e..6214133 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -2847,6 +2847,25 @@ static int __iwl_mvm_assign_vif_chanctx(struct iwl_mvm *mvm,
}
if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
+ u32 duration = 2 * vif->bss_conf.beacon_int;
+
+ /* iwl_mvm_protect_session() reads directly from the
+ * device (the system time), so make sure it is
+ * available.
+ */
+ ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
+ if (ret)
+ goto out_remove_binding;
+
+ /* Protect the session to make sure we hear the first
+ * beacon on the new channel.
+ */
+ iwl_mvm_protect_session(mvm, vif, duration, duration,
+ vif->bss_conf.beacon_int / 2,
+ true);
+
+ iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
+
iwl_mvm_update_quotas(mvm, NULL);
}
@@ -3256,6 +3275,8 @@ static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
if (ret)
goto out_unlock;
+
+ iwl_mvm_stop_session_protection(mvm, vif);
}
mvmvif->ps_disabled = false;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 99a2590..7c62f80 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -275,6 +275,7 @@ enum iwl_mvm_ref_type {
IWL_MVM_REF_NMI,
IWL_MVM_REF_TM_CMD,
IWL_MVM_REF_EXIT_WORK,
+ IWL_MVM_REF_PROTECT_CSA,
/* update debugfs.c when changing this */
OpenPOWER on IntegriCloud