aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNaftali Goldstein <naftali.goldstein@intel.com>2017-08-28 04:51:05 -0400
committerLuca Coelho <luciano.coelho@intel.com>2017-09-08 04:43:38 -0400
commitbd800e41a3de5c7e56b2fd27088bdaf5e228d227 (patch)
tree724b6e0a84bf13aab82f5aa42fcb41af909a09a5
parent0fe8bed6e37c259b85d123ef9667f972305c9d6b (diff)
iwlwifi: mvm: change state when queueing agg start work
Add a new state to enum iwl_mvm_agg_state, which is used between queueing the work that starts tx aggregations and actually starting that work (changing to state IWL_AGG_STARTING). This solves a race where ieee80211_start_tx_ba_session is called a second time, before the work queued by the first run has a chance to change the agg_state. In this case the second call to ieee80211_start_tx_ba_session returns an error, and the fallback is to abort the ba session start. Fixes: 482e48440a0e ("iwlwifi: mvm: change open and close criteria of a BA session") Signed-off-by: Naftali Goldstein <naftali.goldstein@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/rs.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/sta.h2
3 files changed, 8 insertions, 3 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
index ba7bd049d3d4..0fe723ca844e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c
@@ -661,7 +661,8 @@ static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
661 (lq_sta->tx_agg_tid_en & BIT(tid)) && 661 (lq_sta->tx_agg_tid_en & BIT(tid)) &&
662 (tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD)) { 662 (tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD)) {
663 IWL_DEBUG_RATE(mvm, "try to aggregate tid %d\n", tid); 663 IWL_DEBUG_RATE(mvm, "try to aggregate tid %d\n", tid);
664 rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta); 664 if (rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta) == 0)
665 tid_data->state = IWL_AGG_QUEUED;
665 } 666 }
666} 667}
667 668
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
index 411a2055dc45..2dafe9bb4d8b 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c
@@ -2385,8 +2385,10 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
2385 if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) 2385 if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT))
2386 return -EINVAL; 2386 return -EINVAL;
2387 2387
2388 if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) { 2388 if (mvmsta->tid_data[tid].state != IWL_AGG_QUEUED &&
2389 IWL_ERR(mvm, "Start AGG when state is not IWL_AGG_OFF %d!\n", 2389 mvmsta->tid_data[tid].state != IWL_AGG_OFF) {
2390 IWL_ERR(mvm,
2391 "Start AGG when state is not IWL_AGG_QUEUED or IWL_AGG_OFF %d!\n",
2390 mvmsta->tid_data[tid].state); 2392 mvmsta->tid_data[tid].state);
2391 return -ENXIO; 2393 return -ENXIO;
2392 } 2394 }
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
index d13893806513..aedabe101cf0 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h
@@ -281,6 +281,7 @@ struct iwl_mvm_vif;
281 * These states relate to a specific RA / TID. 281 * These states relate to a specific RA / TID.
282 * 282 *
283 * @IWL_AGG_OFF: aggregation is not used 283 * @IWL_AGG_OFF: aggregation is not used
284 * @IWL_AGG_QUEUED: aggregation start work has been queued
284 * @IWL_AGG_STARTING: aggregation are starting (between start and oper) 285 * @IWL_AGG_STARTING: aggregation are starting (between start and oper)
285 * @IWL_AGG_ON: aggregation session is up 286 * @IWL_AGG_ON: aggregation session is up
286 * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the 287 * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
@@ -290,6 +291,7 @@ struct iwl_mvm_vif;
290 */ 291 */
291enum iwl_mvm_agg_state { 292enum iwl_mvm_agg_state {
292 IWL_AGG_OFF = 0, 293 IWL_AGG_OFF = 0,
294 IWL_AGG_QUEUED,
293 IWL_AGG_STARTING, 295 IWL_AGG_STARTING,
294 IWL_AGG_ON, 296 IWL_AGG_ON,
295 IWL_EMPTYING_HW_QUEUE_ADDBA, 297 IWL_EMPTYING_HW_QUEUE_ADDBA,