Commit 682e5f64 authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Wey-Yi Guy

iwlwifi: split between AGG_ON and AGG_STARTING

This allows not to notify the transport about aggregation stopped
while aggregation haven't been started.
Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
parent c27cf685
...@@ -522,6 +522,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -522,6 +522,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
{ {
struct iwl_tid_data *tid_data; struct iwl_tid_data *tid_data;
int sta_id, txq_id; int sta_id, txq_id;
enum iwl_agg_state agg_state;
sta_id = iwl_sta_id(sta); sta_id = iwl_sta_id(sta);
...@@ -545,6 +546,13 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -545,6 +546,13 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
*/ */
IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
goto turn_off; goto turn_off;
case IWL_AGG_STARTING:
/*
* This can happen when the session is stopped before
* we receive ADDBA response
*/
IWL_DEBUG_HT(priv, "AGG stop before AGG became operational\n");
goto turn_off;
case IWL_AGG_ON: case IWL_AGG_ON:
break; break;
default: default:
...@@ -576,12 +584,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -576,12 +584,17 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
tid_data->agg.ssn); tid_data->agg.ssn);
turn_off: turn_off:
agg_state = priv->tid_data[sta_id][tid].agg.state;
priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF; priv->tid_data[sta_id][tid].agg.state = IWL_AGG_OFF;
spin_unlock_bh(&priv->sta_lock); spin_unlock_bh(&priv->sta_lock);
if (test_bit(txq_id, priv->agg_q_alloc)) { if (test_bit(txq_id, priv->agg_q_alloc)) {
iwl_trans_tx_agg_disable(priv->trans, txq_id); /* If the transport didn't know that we wanted to start
* agreggation, don't tell it that we want to stop them
*/
if (agg_state != IWL_AGG_STARTING)
iwl_trans_tx_agg_disable(priv->trans, txq_id);
iwlagn_dealloc_agg_txq(priv, txq_id); iwlagn_dealloc_agg_txq(priv, txq_id);
} }
...@@ -634,7 +647,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -634,7 +647,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
if (*ssn == tid_data->next_reclaimed) { if (*ssn == tid_data->next_reclaimed) {
IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n", IWL_DEBUG_TX_QUEUES(priv, "Can proceed: ssn = next_recl = %d\n",
tid_data->agg.ssn); tid_data->agg.ssn);
tid_data->agg.state = IWL_AGG_ON; tid_data->agg.state = IWL_AGG_STARTING;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
} else { } else {
IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, " IWL_DEBUG_TX_QUEUES(priv, "Can't proceed: ssn %d, "
...@@ -661,6 +674,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, ...@@ -661,6 +674,7 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif,
spin_lock_bh(&priv->sta_lock); spin_lock_bh(&priv->sta_lock);
ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn; ssn = priv->tid_data[sta_priv->sta_id][tid].agg.ssn;
q = priv->tid_data[sta_priv->sta_id][tid].agg.txq_id; q = priv->tid_data[sta_priv->sta_id][tid].agg.txq_id;
priv->tid_data[sta_priv->sta_id][tid].agg.state = IWL_AGG_ON;
spin_unlock_bh(&priv->sta_lock); spin_unlock_bh(&priv->sta_lock);
fifo = ctx->ac_to_fifo[tid_to_ac[tid]]; fifo = ctx->ac_to_fifo[tid_to_ac[tid]];
...@@ -745,7 +759,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) ...@@ -745,7 +759,7 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
IWL_DEBUG_TX_QUEUES(priv, IWL_DEBUG_TX_QUEUES(priv,
"Can continue ADDBA flow ssn = next_recl =" "Can continue ADDBA flow ssn = next_recl ="
" %d", tid_data->next_reclaimed); " %d", tid_data->next_reclaimed);
tid_data->agg.state = IWL_AGG_ON; tid_data->agg.state = IWL_AGG_STARTING;
ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
} }
break; break;
......
...@@ -194,6 +194,7 @@ struct iwl_qos_info { ...@@ -194,6 +194,7 @@ struct iwl_qos_info {
* These states relate to a specific RA / TID. * These states relate to a specific RA / TID.
* *
* @IWL_AGG_OFF: aggregation is not used * @IWL_AGG_OFF: aggregation is not used
* @IWL_AGG_STARTING: aggregation are starting (between start and oper)
* @IWL_AGG_ON: aggregation session is up * @IWL_AGG_ON: aggregation session is up
* @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the
* HW queue to be empty from packets for this RA /TID. * HW queue to be empty from packets for this RA /TID.
...@@ -202,6 +203,7 @@ struct iwl_qos_info { ...@@ -202,6 +203,7 @@ struct iwl_qos_info {
*/ */
enum iwl_agg_state { enum iwl_agg_state {
IWL_AGG_OFF = 0, IWL_AGG_OFF = 0,
IWL_AGG_STARTING,
IWL_AGG_ON, IWL_AGG_ON,
IWL_EMPTYING_HW_QUEUE_ADDBA, IWL_EMPTYING_HW_QUEUE_ADDBA,
IWL_EMPTYING_HW_QUEUE_DELBA, IWL_EMPTYING_HW_QUEUE_DELBA,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment