/** * rs_tx_status - Update rate control values based on Tx results * * NOTE: Uses iwl3945_priv->retry_rate for the # of retries attempted by * the hardware for each rate. */ static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { s8 retries = 0, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_rate; struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE("enter\n"); retries = info->status.rates[0].count; first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT)) { IWL_DEBUG_RATE("leave: Rate out of bounds: %d\n", first_index); return; } if (!priv_sta) { IWL_DEBUG_RATE("leave: No STA priv data to update!\n"); return; } rs_sta->tx_packets++; scale_rate_index = first_index; last_index = first_index; /* * Update the window for each rate. We determine which rates * were Tx'd based on the total number of retries vs. the number * of retries configured for each rate -- currently set to the * priv value 'retry_rate' vs. rate specific * * On exit from this while loop last_index indicates the rate * at which the frame was finally transmitted (or failed if no * ACK) */ while (retries > 1) { if ((retries - 1) < priv->retry_rate) { current_count = (retries - 1); last_index = scale_rate_index; } else { current_count = priv->retry_rate; last_index = iwl3945_rs_next_rate(priv, scale_rate_index); } /* Update this rate accounting for as many retries * as was used for it (per current_count) */ iwl3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_index], 0, current_count, scale_rate_index); IWL_DEBUG_RATE("Update rate %d for %d retries.\n", scale_rate_index, current_count); retries -= current_count; scale_rate_index = last_index; } /* Update the last index window with success/failure based on ACK */ IWL_DEBUG_RATE("Update rate %d with %s.\n", last_index, (info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure"); iwl3945_collect_tx_data(rs_sta, &rs_sta->win[last_index], info->flags & IEEE80211_TX_STAT_ACK, 1, last_index); /* We updated the rate scale window -- if its been more than * flush_time since the last run, schedule the flush * again */ spin_lock_irqsave(&rs_sta->lock, flags); if (!rs_sta->flush_pending && time_after(jiffies, rs_sta->last_flush + rs_sta->flush_time)) { rs_sta->last_partial_flush = jiffies; rs_sta->flush_pending = 1; mod_timer(&rs_sta->rate_scale_flush, jiffies + rs_sta->flush_time); } spin_unlock_irqrestore(&rs_sta->lock, flags); IWL_DEBUG_RATE("leave\n"); return; }
static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, struct sk_buff *skb) { s8 retries = 0, current_count; int scale_rate_index, first_index, last_index; unsigned long flags; struct iwl_priv *priv = (struct iwl_priv *)priv_rate; struct iwl3945_rs_sta *rs_sta = priv_sta; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); IWL_DEBUG_RATE(priv, "enter\n"); retries = info->status.rates[0].count; if (retries > IWL_RATE_RETRY_TH) retries = IWL_RATE_RETRY_TH; first_index = sband->bitrates[info->status.rates[0].idx].hw_value; if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index); return; } if (!priv_sta) { IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); return; } rs_sta->tx_packets++; scale_rate_index = first_index; last_index = first_index; while (retries > 1) { if ((retries - 1) < priv->retry_rate) { current_count = (retries - 1); last_index = scale_rate_index; } else { current_count = priv->retry_rate; last_index = iwl3945_rs_next_rate(priv, scale_rate_index); } iwl3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_index], 0, current_count, scale_rate_index); IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n", scale_rate_index, current_count); retries -= current_count; scale_rate_index = last_index; } IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n", last_index, (info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure"); iwl3945_collect_tx_data(rs_sta, &rs_sta->win[last_index], info->flags & IEEE80211_TX_STAT_ACK, 1, last_index); spin_lock_irqsave(&rs_sta->lock, flags); if (!rs_sta->flush_pending && time_after(jiffies, rs_sta->last_flush + rs_sta->flush_time)) { rs_sta->last_partial_flush = jiffies; rs_sta->flush_pending = 1; mod_timer(&rs_sta->rate_scale_flush, jiffies + rs_sta->flush_time); } spin_unlock_irqrestore(&rs_sta->lock, flags); IWL_DEBUG_RATE(priv, "leave\n"); return; }