aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2014-05-04 04:48:12 -0400
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-07-07 14:41:20 -0400
commit7f0a7c671cdc0396f99b60b77bd02e2dee7c4838 (patch)
treed7271d4347e6f758cc4b98fe19d5c6babbc20881 /drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
parent664322fa43b7a52a9e8be9a3874c024412c24a50 (diff)
iwlwifi: mvm: Reflect GO channel switch in NoA
According to the spec, GO/AP should perform the channel switch just before "beacon 0". However, since the exact timing isn't defined, it may result in a sudden GO disappearance from the channel. Prevent potential packet loss when performing the CS by scheduling NoA time event and executing the channel switch flow when a notification from fw is received. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 19bd696bd6f8..a176d008dab1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -67,6 +67,7 @@
67#include "iwl-prph.h" 67#include "iwl-prph.h"
68#include "fw-api.h" 68#include "fw-api.h"
69#include "mvm.h" 69#include "mvm.h"
70#include "time-event.h"
70 71
71const u8 iwl_mvm_ac_to_tx_fifo[] = { 72const u8 iwl_mvm_ac_to_tx_fifo[] = {
72 IWL_MVM_TX_FIFO_VO, 73 IWL_MVM_TX_FIFO_VO,
@@ -1200,6 +1201,35 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1200 return 0; 1201 return 0;
1201} 1202}
1202 1203
1204static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
1205 struct ieee80211_vif *csa_vif, u32 gp2)
1206{
1207 struct iwl_mvm_vif *mvmvif =
1208 iwl_mvm_vif_from_mac80211(csa_vif);
1209
1210 if (!ieee80211_csa_is_complete(csa_vif)) {
1211 int c = ieee80211_csa_update_counter(csa_vif);
1212
1213 iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
1214 if (csa_vif->p2p &&
1215 !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) {
1216 u32 rel_time = (c + 1) *
1217 csa_vif->bss_conf.beacon_int -
1218 IWL_MVM_CHANNEL_SWITCH_TIME;
1219 u32 apply_time = gp2 + rel_time * 1024;
1220
1221 iwl_mvm_schedule_csa_noa(mvm, csa_vif,
1222 IWL_MVM_CHANNEL_SWITCH_TIME -
1223 IWL_MVM_CHANNEL_SWITCH_MARGIN,
1224 apply_time);
1225 }
1226 } else if (!iwl_mvm_te_scheduled(&mvmvif->time_event_data)) {
1227 /* we don't have CSA NoA scheduled yet, switch now */
1228 ieee80211_csa_finish(csa_vif);
1229 RCU_INIT_POINTER(mvm->csa_vif, NULL);
1230 }
1231}
1232
1203int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, 1233int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1204 struct iwl_rx_cmd_buffer *rxb, 1234 struct iwl_rx_cmd_buffer *rxb,
1205 struct iwl_device_cmd *cmd) 1235 struct iwl_device_cmd *cmd)
@@ -1234,15 +1264,8 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1234 1264
1235 csa_vif = rcu_dereference_protected(mvm->csa_vif, 1265 csa_vif = rcu_dereference_protected(mvm->csa_vif,
1236 lockdep_is_held(&mvm->mutex)); 1266 lockdep_is_held(&mvm->mutex));
1237 if (unlikely(csa_vif && csa_vif->csa_active)) { 1267 if (unlikely(csa_vif && csa_vif->csa_active))
1238 if (!ieee80211_csa_is_complete(csa_vif)) { 1268 iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2);
1239 ieee80211_csa_update_counter(csa_vif);
1240 iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
1241 } else {
1242 ieee80211_csa_finish(csa_vif);
1243 RCU_INIT_POINTER(mvm->csa_vif, NULL);
1244 }
1245 }
1246 1269
1247 return 0; 1270 return 0;
1248} 1271}