diff options
author | Emmanuel Grumbach <emmanuel.grumbach@intel.com> | 2012-02-01 07:01:32 -0800 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-02-01 15:26:00 -0500 |
commit | 3d29dd9b5b160ba4542a9b8f869a220559e633a0 (patch) | |
tree | 300ef96f8681c3b853686b11b04062f3045860f2 /drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |
parent | a6c84622b7fa3ea5417a9d1d0ce0bc3e7fbe3be1 (diff) |
iwlwifi: don't mess up QoS counters with non-QoS frames
In my AMPDU rework, I rely on the sequence numbers of frames. But
I didn't check that the frame has a valid tid before updating the
tracking counters. As a result, the Tx queues were stalled. People
who hit this bug saw that we simply didn't let any data out.
This bug was introduced in 3.3.
This patch fixes that and checks that the frame is a QoS frame before
looking at its tid and changing the counters.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 339e8d96b654..63bbc60be28e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -91,6 +91,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, tx_cmd->tid_tspec = qc[0] & 0xf; tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; } else { + tx_cmd->tid_tspec = IWL_TID_NON_QOS; if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; else @@ -808,6 +809,8 @@ static void iwl_rx_reply_tx_agg(struct iwl_priv *priv, u32 status = le16_to_cpu(tx_resp->status.status); int i; + WARN_ON(tid == IWL_TID_NON_QOS); + if (agg->wait_for_ba) IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); @@ -1035,10 +1038,13 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, } __skb_queue_head_init(&skbs); - priv->tid_data[sta_id][tid].next_reclaimed = next_reclaimed; - IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", - next_reclaimed); + if (tid != IWL_TID_NON_QOS) { + priv->tid_data[sta_id][tid].next_reclaimed = + next_reclaimed; + IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d", + next_reclaimed); + } /*we can free until ssn % q.n_bd not inclusive */ WARN_ON(iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, |