Commit d0eb6334 authored by Daniel Halperin's avatar Daniel Halperin Committed by Wey-Yi Guy

iwlwifi: cleanup and bugfix tx aggregation code

Since the driver split, there's no need for no_agg_framecnt_info since
all devices have this set to false. Secondly, the compressed block ack
handling code was broken. Fix this.

(1) A shift less than zero simply implies that the buffer wrapped, this
is expected. Remove the incorrect comment.

(2) The (agg->frame_count > (64-sh)) condition can happen if the last
frame is dropped. E.g., if I send 7 frames and the 6th is received but
the 7th is lost, the other side may only shift the window 6, not 7
frames since the last bit is a 0. This is perfectly fine behavior and
doesn't invalidate the feedback.

(3) Store the feedback from a Compressed BA in the first newly received
frame, rather than the start of the window. This way it will get
processed by the rate selection code. Feedback stored in a non-received
frame is likely to get overwritten by the retransmission.
    This is based on the approach taken by minstrel_ht.
Signed-off-by: default avatarDaniel Halperin <dhalperi@cs.washington.edu>
Signed-off-by: default avatarWey-Yi Guy <wey-yi.w.guy@intel.com>
parent 374920cb
...@@ -1263,11 +1263,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, ...@@ -1263,11 +1263,11 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
struct iwl_compressed_ba_resp *ba_resp) struct iwl_compressed_ba_resp *ba_resp)
{ {
int i, sh, ack; int sh;
u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
int successes = 0;
struct ieee80211_tx_info *info; struct ieee80211_tx_info *info;
u64 bitmap, sent_bitmap;
if (unlikely(!agg->wait_for_ba)) { if (unlikely(!agg->wait_for_ba)) {
if (unlikely(ba_resp->bitmap)) if (unlikely(ba_resp->bitmap))
...@@ -1281,70 +1281,42 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv, ...@@ -1281,70 +1281,42 @@ static int iwlagn_tx_status_reply_compressed_ba(struct iwl_priv *priv,
/* Calculate shift to align block-ack bits with our Tx window bits */ /* Calculate shift to align block-ack bits with our Tx window bits */
sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
if (sh < 0) /* tbw something is wrong with indices */ if (sh < 0)
sh += 0x100; sh += 0x100;
if (agg->frame_count > (64 - sh)) { /*
IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); * Check for success or failure according to the
return -1; * transmitted bitmap and block-ack bitmap
} */
if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
sent_bitmap = bitmap & agg->bitmap;
/* Sanity check values reported by uCode */
if (ba_resp->txed_2_done > ba_resp->txed) {
IWL_DEBUG_TX_REPLY(priv,
"bogus sent(%d) and ack(%d) count\n",
ba_resp->txed, ba_resp->txed_2_done);
/* /*
* sent and ack information provided by uCode * set txed_2_done = txed,
* use it instead of figure out ourself * so it won't impact rate scale
*/ */
if (ba_resp->txed_2_done > ba_resp->txed) { ba_resp->txed = ba_resp->txed_2_done;
IWL_DEBUG_TX_REPLY(priv, }
"bogus sent(%d) and ack(%d) count\n", IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
ba_resp->txed, ba_resp->txed_2_done); ba_resp->txed, ba_resp->txed_2_done);
/*
* set txed_2_done = txed,
* so it won't impact rate scale
*/
ba_resp->txed = ba_resp->txed_2_done;
}
IWL_DEBUG_HT(priv, "agg frames sent:%d, acked:%d\n",
ba_resp->txed, ba_resp->txed_2_done);
} else {
u64 bitmap, sent_bitmap;
/* don't use 64-bit values for now */
bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
/* check for success or failure according to the
* transmitted bitmap and block-ack bitmap */
sent_bitmap = bitmap & agg->bitmap;
/* For each frame attempted in aggregation,
* update driver's record of tx frame's status. */
i = 0;
while (sent_bitmap) {
ack = sent_bitmap & 1ULL;
successes += ack;
IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
ack ? "ACK" : "NACK", i,
(agg->start_idx + i) & 0xff,
agg->start_idx + i);
sent_bitmap >>= 1;
++i;
}
IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", /* Find the first ACKed frame to store the TX status */
(unsigned long long)bitmap); while (sent_bitmap && !(sent_bitmap & 1)) {
agg->start_idx = (agg->start_idx + 1) & 0xff;
sent_bitmap >>= 1;
} }
info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb); info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
memset(&info->status, 0, sizeof(info->status)); memset(&info->status, 0, sizeof(info->status));
info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_ACK;
info->flags |= IEEE80211_TX_STAT_AMPDU; info->flags |= IEEE80211_TX_STAT_AMPDU;
if (!priv->cfg->base_params->no_agg_framecnt_info && ba_resp->txed) { info->status.ampdu_ack_len = ba_resp->txed_2_done;
info->status.ampdu_ack_len = ba_resp->txed_2_done; info->status.ampdu_len = ba_resp->txed;
info->status.ampdu_len = ba_resp->txed;
} else {
info->status.ampdu_ack_len = successes;
info->status.ampdu_len = agg->frame_count;
}
iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info); iwlagn_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
return 0; return 0;
......
...@@ -281,8 +281,6 @@ struct iwl_mod_params { ...@@ -281,8 +281,6 @@ struct iwl_mod_params {
* @chain_noise_calib_by_driver: driver has the capability to perform * @chain_noise_calib_by_driver: driver has the capability to perform
* chain noise calibration operation * chain noise calibration operation
* @shadow_reg_enable: HW shadhow register bit * @shadow_reg_enable: HW shadhow register bit
* @no_agg_framecnt_info: uCode do not provide aggregation frame count
* information
*/ */
struct iwl_base_params { struct iwl_base_params {
int eeprom_size; int eeprom_size;
...@@ -312,7 +310,6 @@ struct iwl_base_params { ...@@ -312,7 +310,6 @@ struct iwl_base_params {
const bool sensitivity_calib_by_driver; const bool sensitivity_calib_by_driver;
const bool chain_noise_calib_by_driver; const bool chain_noise_calib_by_driver;
const bool shadow_reg_enable; const bool shadow_reg_enable;
const bool no_agg_framecnt_info;
}; };
/* /*
* @advanced_bt_coexist: support advanced bt coexist * @advanced_bt_coexist: support advanced bt coexist
......
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