diff options
author | Andrei Otcheretianski <andrei.otcheretianski@intel.com> | 2014-05-04 04:48:12 -0400 |
---|---|---|
committer | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2014-07-07 14:41:20 -0400 |
commit | 7f0a7c671cdc0396f99b60b77bd02e2dee7c4838 (patch) | |
tree | d7271d4347e6f758cc4b98fe19d5c6babbc20881 /drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |
parent | 664322fa43b7a52a9e8be9a3874c024412c24a50 (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.c | 41 |
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 | ||
71 | const u8 iwl_mvm_ac_to_tx_fifo[] = { | 72 | const 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 | ||
1204 | static 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 | |||
1203 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | 1233 | int 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 | } |