aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi
diff options
context:
space:
mode:
authorAndrei Otcheretianski <andrei.otcheretianski@intel.com>2014-11-10 04:10:11 -0500
committerEmmanuel Grumbach <emmanuel.grumbach@intel.com>2014-11-24 01:30:29 -0500
commit7ef0aab66b317ff4d818966b2104c900c7126ec8 (patch)
tree14e643acbf19c1a9146c56e9a4f76417374ccb17 /drivers/net/wireless/iwlwifi
parent6fd1fb63abeb78fd7fe30f08f478732ad601702c (diff)
iwlwifi: mvm: Handle failed beacon transmissions during CSA
The spec requires to decrement the CSA counters based on TBTT, regardless if the beacon was actually transmitted. Previously, the fw would send beacon notifications only for successfully transmitted beacons. This behavior resulted in inaccurate CSA countdown. In order to address this issue, the fw was changed to send beacon notifications also for not transmitted beacons. Such notifications have TX_STATUS_INTERNAL_ABORT (0x92). Don't start the CSA countdown before first successfully transmitted beacon, in order to guarantee that the CSA is announced for a required period. Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi')
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c21
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c11
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h3
3 files changed, 29 insertions, 6 deletions
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index a1dc9b86c2d1..0cb79bc06781 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -1263,17 +1263,25 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
1263} 1263}
1264 1264
1265static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm, 1265static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
1266 struct ieee80211_vif *csa_vif, u32 gp2) 1266 struct ieee80211_vif *csa_vif, u32 gp2,
1267 bool tx_success)
1267{ 1268{
1268 struct iwl_mvm_vif *mvmvif = 1269 struct iwl_mvm_vif *mvmvif =
1269 iwl_mvm_vif_from_mac80211(csa_vif); 1270 iwl_mvm_vif_from_mac80211(csa_vif);
1270 1271
1272 /* Don't start to countdown from a failed beacon */
1273 if (!tx_success && !mvmvif->csa_countdown)
1274 return;
1275
1276 mvmvif->csa_countdown = true;
1277
1271 if (!ieee80211_csa_is_complete(csa_vif)) { 1278 if (!ieee80211_csa_is_complete(csa_vif)) {
1272 int c = ieee80211_csa_update_counter(csa_vif); 1279 int c = ieee80211_csa_update_counter(csa_vif);
1273 1280
1274 iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif); 1281 iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
1275 if (csa_vif->p2p && 1282 if (csa_vif->p2p &&
1276 !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) { 1283 !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
1284 tx_success) {
1277 u32 rel_time = (c + 1) * 1285 u32 rel_time = (c + 1) *
1278 csa_vif->bss_conf.beacon_int - 1286 csa_vif->bss_conf.beacon_int -
1279 IWL_MVM_CHANNEL_SWITCH_TIME_GO; 1287 IWL_MVM_CHANNEL_SWITCH_TIME_GO;
@@ -1300,6 +1308,7 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1300 struct ieee80211_vif *csa_vif; 1308 struct ieee80211_vif *csa_vif;
1301 struct ieee80211_vif *tx_blocked_vif; 1309 struct ieee80211_vif *tx_blocked_vif;
1302 u64 tsf; 1310 u64 tsf;
1311 u16 status;
1303 1312
1304 lockdep_assert_held(&mvm->mutex); 1313 lockdep_assert_held(&mvm->mutex);
1305 1314
@@ -1316,18 +1325,18 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
1316 tsf = le64_to_cpu(beacon->tsf); 1325 tsf = le64_to_cpu(beacon->tsf);
1317 } 1326 }
1318 1327
1328 status = le16_to_cpu(beacon_notify_hdr->status.status) & TX_STATUS_MSK;
1319 IWL_DEBUG_RX(mvm, 1329 IWL_DEBUG_RX(mvm,
1320 "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n", 1330 "beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
1321 le16_to_cpu(beacon_notify_hdr->status.status) & 1331 status, beacon_notify_hdr->failure_frame, tsf,
1322 TX_STATUS_MSK,
1323 beacon_notify_hdr->failure_frame, tsf,
1324 mvm->ap_last_beacon_gp2, 1332 mvm->ap_last_beacon_gp2,
1325 le32_to_cpu(beacon_notify_hdr->initial_rate)); 1333 le32_to_cpu(beacon_notify_hdr->initial_rate));
1326 1334
1327 csa_vif = rcu_dereference_protected(mvm->csa_vif, 1335 csa_vif = rcu_dereference_protected(mvm->csa_vif,
1328 lockdep_is_held(&mvm->mutex)); 1336 lockdep_is_held(&mvm->mutex));
1329 if (unlikely(csa_vif && csa_vif->csa_active)) 1337 if (unlikely(csa_vif && csa_vif->csa_active))
1330 iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2); 1338 iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2,
1339 (status == TX_STATUS_SUCCESS));
1331 1340
1332 tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif, 1341 tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
1333 lockdep_is_held(&mvm->mutex)); 1342 lockdep_is_held(&mvm->mutex));
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 1d556173fcb6..6098eafcf13a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -2909,6 +2909,8 @@ static void __iwl_mvm_unassign_vif_chanctx(struct iwl_mvm *mvm,
2909 if (!vif->csa_active || !mvmvif->ap_ibss_active) 2909 if (!vif->csa_active || !mvmvif->ap_ibss_active)
2910 goto out; 2910 goto out;
2911 2911
2912 mvmvif->csa_countdown = false;
2913
2912 /* Set CS bit on all the stations */ 2914 /* Set CS bit on all the stations */
2913 iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true); 2915 iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
2914 2916
@@ -3164,6 +3166,7 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
3164{ 3166{
3165 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); 3167 struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
3166 struct ieee80211_vif *csa_vif; 3168 struct ieee80211_vif *csa_vif;
3169 struct iwl_mvm_vif *mvmvif;
3167 int ret; 3170 int ret;
3168 3171
3169 mutex_lock(&mvm->mutex); 3172 mutex_lock(&mvm->mutex);
@@ -3183,6 +3186,14 @@ static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
3183 } 3186 }
3184 3187
3185 rcu_assign_pointer(mvm->csa_vif, vif); 3188 rcu_assign_pointer(mvm->csa_vif, vif);
3189
3190 mvmvif = iwl_mvm_vif_from_mac80211(vif);
3191 if (WARN_ONCE(mvmvif->csa_countdown,
3192 "Previous CSA countdown didn't complete")) {
3193 ret = -EBUSY;
3194 goto out_unlock;
3195 }
3196
3186 break; 3197 break;
3187 default: 3198 default:
3188 break; 3199 break;
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 44625adae1c5..2c54c522b8c6 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -399,6 +399,9 @@ struct iwl_mvm_vif {
399 399
400 /* FW identified misbehaving AP */ 400 /* FW identified misbehaving AP */
401 u8 uapsd_misbehaving_bssid[ETH_ALEN]; 401 u8 uapsd_misbehaving_bssid[ETH_ALEN];
402
403 /* Indicates that CSA countdown may be started */
404 bool csa_countdown;
402}; 405};
403 406
404static inline struct iwl_mvm_vif * 407static inline struct iwl_mvm_vif *