static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl3945_priv *priv = (struct iwl3945_priv *)priv_r; int i; IWL_DEBUG_RATE("enter\n"); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately * after assoc.. */ for (i = sband->n_bitrates - 1; i >= 0; i--) { if (sta->supp_rates[sband->band] & (1 << i)) { rs_sta->last_txrate_idx = i; break; } } priv->sta_supp_rates = sta->supp_rates[sband->band]; /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ if (sband->band == IEEE80211_BAND_5GHZ) { rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; priv->sta_supp_rates = priv->sta_supp_rates << IWL_FIRST_OFDM_RATE; } IWL_DEBUG_RATE("leave\n"); }
static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta) { struct iwl3945_rs_sta *rs_sta = priv_sta; struct iwl_priv *priv = (struct iwl_priv *)priv_r; int i; IWL_DEBUG_RATE(priv, "enter\n"); for (i = sband->n_bitrates - 1; i >= 0; i--) { if (sta->supp_rates[sband->band] & (1 << i)) { rs_sta->last_txrate_idx = i; break; } } priv->sta_supp_rates = sta->supp_rates[sband->band]; if (sband->band == IEEE80211_BAND_5GHZ) { rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; priv->sta_supp_rates = priv->sta_supp_rates << IWL_FIRST_OFDM_RATE; } IWL_DEBUG_RATE(priv, "leave\n"); }
static void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv, struct iwl_link_quality_cmd *lq) { int i; IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id); IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n", lq->general_params.single_stream_ant_msk, lq->general_params.dual_stream_ant_msk); for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n", i, lq->rs_table[i].rate_n_flags); }
static void rs_free_sta(void *priv, struct ieee80211_sta *sta, void *priv_sta) { struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl3945_rs_sta *rs_sta = priv_sta; psta->rs_sta = NULL; IWL_DEBUG_RATE("enter\n"); del_timer_sync(&rs_sta->rate_scale_flush); kfree(rs_sta); IWL_DEBUG_RATE("leave\n"); }
static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl_priv *priv = iwl_priv; int i; /* * XXX: If it's using sta->drv_priv anyway, it might * as well just put all the information there. */ IWL_DEBUG_RATE(priv, "enter\n"); rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); if (!rs_sta) { IWL_DEBUG_RATE(priv, "leave: ENOMEM\n"); return NULL; } psta->rs_sta = rs_sta; spin_lock_init(&rs_sta->lock); rs_sta->priv = priv; rs_sta->start_rate = IWL_RATE_INVALID; /* default to just 802.11b */ rs_sta->expected_tpt = iwl3945_expected_tpt_b; rs_sta->last_partial_flush = jiffies; rs_sta->last_flush = jiffies; rs_sta->flush_time = IWL_RATE_FLUSH; rs_sta->last_tx_packets = 0; rs_sta->ibss_sta_added = 0; init_timer(&rs_sta->rate_scale_flush); rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; for (i = 0; i < IWL_RATE_COUNT_3945; i++) iwl3945_clear_window(&rs_sta->win[i]); IWL_DEBUG_RATE(priv, "leave\n"); return rs_sta; }
/** * Program the device to use fixed rate for frame transmit * This is for debugging/testing only * once the device start use fixed rate, we need to reload the module * to being back the normal operation. */ static void rs_program_fix_rate(struct iwl_priv *priv, struct iwl_lq_sta *lq_sta) { struct iwl_station_priv *sta_priv = container_of(lq_sta, struct iwl_station_priv, lq_sta); struct iwl_rxon_context *ctx = sta_priv->ctx; lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ #ifdef CONFIG_IWLWIFI_DEVICE_TESTMODE /* testmode has higher priority to overwirte the fixed rate */ if (priv->tm_fixed_rate) lq_sta->dbg_fixed_rate = priv->tm_fixed_rate; #endif IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); if (lq_sta->dbg_fixed_rate) { rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); iwl_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC, false); } }
static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) { int unflushed = 0; int i; unsigned long flags; struct iwl_priv *priv __maybe_unused = rs_sta->priv; for (i = 0; i < IWL_RATE_COUNT_3945; i++) { if (!rs_sta->win[i].counter) continue; spin_lock_irqsave(&rs_sta->lock, flags); if (time_after(jiffies, rs_sta->win[i].stamp + IWL_RATE_WIN_FLUSH)) { IWL_DEBUG_RATE(priv, "flushing %d samples of rate " "index %d\n", rs_sta->win[i].counter, i); iwl3945_clear_window(&rs_sta->win[i]); } else unflushed++; spin_unlock_irqrestore(&rs_sta->lock, flags); } return unflushed; }
/** * iwl3945_rate_scale_flush_windows - flush out the rate scale windows * * Returns the number of windows that have gathered data but were * not flushed. If there were any that were not flushed, then * reschedule the rate flushing routine. */ static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) { int unflushed = 0; int i; unsigned long flags; /* * For each rate, if we have collected data on that rate * and it has been more than IWL_RATE_WIN_FLUSH * since we flushed, clear out the gathered statistics */ for (i = 0; i < IWL_RATE_COUNT; i++) { if (!rs_sta->win[i].counter) continue; spin_lock_irqsave(&rs_sta->lock, flags); if (time_after(jiffies, rs_sta->win[i].stamp + IWL_RATE_WIN_FLUSH)) { IWL_DEBUG_RATE("flushing %d samples of rate " "index %d\n", rs_sta->win[i].counter, i); iwl3945_clear_window(&rs_sta->win[i]); } else unflushed++; spin_unlock_irqrestore(&rs_sta->lock, flags); } return unflushed; }
void iwl_set_rate(struct iwl_priv *priv) { const struct ieee80211_supported_band *hw = NULL; struct ieee80211_rate *rate; struct iwl_rxon_context *ctx; int i; hw = iwl_get_hw_mode(priv, priv->band); if (!hw) { IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); return; } priv->active_rate = 0; for (i = 0; i < hw->n_bitrates; i++) { rate = &(hw->bitrates[i]); if (rate->hw_value < IWL_RATE_COUNT_LEGACY) priv->active_rate |= (1 << rate->hw_value); } IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate); for_each_context(priv, ctx) { ctx->staging.cck_basic_rates = (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; ctx->staging.ofdm_basic_rates = (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; }
static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) { struct iwl3945_rs_sta *rs_sta; struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; struct iwl_priv *priv __maybe_unused = iwl_priv; IWL_DEBUG_RATE(priv, "enter\n"); rs_sta = &psta->rs_sta; spin_lock_init(&rs_sta->lock); init_timer(&rs_sta->rate_scale_flush); IWL_DEBUG_RATE(priv, "leave\n"); return rs_sta; }
/** * iwl3945_collect_tx_data - Update the success/failure sliding window * * We keep a sliding window of the last 64 packets transmitted * at this rate. window->data contains the bitmask of successful * packets. */ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, struct iwl3945_rate_scale_data *window, int success, int retries, int index) { unsigned long flags; s32 fail_count; if (!retries) { IWL_DEBUG_RATE("leave: retries == 0 -- should be at least 1\n"); return; } spin_lock_irqsave(&rs_sta->lock, flags); while (retries--) { /* If we have filled up the window then subtract one from the * success counter if the high-bit is counting toward * success */ if (window->counter == IWL_RATE_MAX_WINDOW) { if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) window->success_counter--; } else window->counter++; /* Slide the window to the left one bit */ window->data = (window->data << 1); /* If this packet was a success then set the low bit high */ if (success) { window->success_counter++; window->data |= 1; } /* window->counter can't be 0 -- it is either >0 or * IWL_RATE_MAX_WINDOW */ window->success_ratio = 12800 * window->success_counter / window->counter; /* Tag this window as having been updated */ window->stamp = jiffies; } fail_count = window->counter - window->success_counter; if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) window->average_tpt = ((window->success_ratio * rs_sta->expected_tpt[index] + 64) / 128); else window->average_tpt = IWL_INV_TPT; spin_unlock_irqrestore(&rs_sta->lock, flags); }
/** * 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 iwl3945_bg_rate_scale_flush(unsigned long data) { struct iwl3945_rs_sta *rs_sta = (void *)data; int unflushed = 0; unsigned long flags; u32 packet_count, duration, pps; IWL_DEBUG_RATE("enter\n"); unflushed = iwl3945_rate_scale_flush_windows(rs_sta); spin_lock_irqsave(&rs_sta->lock, flags); /* Number of packets Rx'd since last time this timer ran */ packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; rs_sta->last_tx_packets = rs_sta->tx_packets + 1; if (unflushed) { duration = jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); IWL_DEBUG_RATE("Tx'd %d packets in %dms\n", packet_count, duration); /* Determine packets per second */ if (duration) pps = (packet_count * 1000) / duration; else pps = 0; if (pps) { duration = (IWL_AVERAGE_PACKETS * 1000) / pps; if (duration < IWL_RATE_FLUSH_MIN) duration = IWL_RATE_FLUSH_MIN; else if (duration > IWL_RATE_FLUSH_MAX) duration = IWL_RATE_FLUSH_MAX; } else duration = IWL_RATE_FLUSH_MAX; rs_sta->flush_time = msecs_to_jiffies(duration); IWL_DEBUG_RATE("new flush period: %d msec ave %d\n", duration, packet_count); mod_timer(&rs_sta->rate_scale_flush, jiffies + rs_sta->flush_time); rs_sta->last_partial_flush = jiffies; } else { rs_sta->flush_time = IWL_RATE_FLUSH; rs_sta->flush_pending = 0; } /* If there weren't any unflushed entries, we don't schedule the timer * to run again */ rs_sta->last_flush = jiffies; spin_unlock_irqrestore(&rs_sta->lock, flags); IWL_DEBUG_RATE("leave\n"); }
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; }
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, enum ieee80211_band band) { int i, j; struct ieee80211_hw *hw = mvm->hw; struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; struct iwl_mvm_sta *sta_priv; struct iwl_lq_sta *lq_sta; struct ieee80211_supported_band *sband; unsigned long supp; /* must be unsigned long for for_each_set_bit */ sta_priv = (struct iwl_mvm_sta *)sta->drv_priv; lq_sta = &sta_priv->lq_sta; sband = hw->wiphy->bands[band]; lq_sta->lq.sta_id = sta_priv->sta_id; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); lq_sta->flush_timer = 0; lq_sta->supp_rates = sta->supp_rates[sband->band]; for (j = 0; j < LQ_SIZE; j++) for (i = 0; i < IWL_RATE_COUNT; i++) rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); IWL_DEBUG_RATE(mvm, "LQ: *** rate scale station global init for station %d ***\n", sta_priv->sta_id); /* TODO: what is a good starting rate for STA? About middle? Maybe not * the lowest or the highest rate.. Could consider using RSSI from * previous packets? Need to have IEEE 802.1X auth succeed immediately * after assoc.. */ lq_sta->max_rate_idx = -1; lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; lq_sta->is_green = rs_use_green(sta); lq_sta->band = sband->band; /* * active legacy rates as per supported rates bitmap */ supp = sta->supp_rates[sband->band]; lq_sta->active_legacy_rate = 0; for_each_set_bit(i, &supp, BITS_PER_LONG) lq_sta->active_legacy_rate |= BIT(sband->bitrates[i].hw_value); /* * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), * supp_rates[] does not; shift to convert format, force 9 MBits off. */ lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; lq_sta->active_siso_rate &= ~((u16)0x2); lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; /* Same here */ lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; lq_sta->active_mimo2_rate &= ~((u16)0x2); lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1; lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1; lq_sta->active_mimo3_rate &= ~((u16)0x2); lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; IWL_DEBUG_RATE(mvm, "SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", lq_sta->active_siso_rate, lq_sta->active_mimo2_rate, lq_sta->active_mimo3_rate); /* These values will be overridden later */ lq_sta->lq.single_stream_ant_msk = first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); lq_sta->lq.dual_stream_ant_msk = iwl_fw_valid_tx_ant(mvm->fw) & ~first_antenna(iwl_fw_valid_tx_ant(mvm->fw)); if (!lq_sta->lq.dual_stream_ant_msk) { lq_sta->lq.dual_stream_ant_msk = ANT_AB; } else if (num_of_ant(iwl_fw_valid_tx_ant(mvm->fw)) == 2) { lq_sta->lq.dual_stream_ant_msk = iwl_fw_valid_tx_ant(mvm->fw); } /* as default allow aggregation for all tids */ lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; lq_sta->drv = mvm; /* Set last_txrate_idx to lowest rate */ lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); if (sband->band == IEEE80211_BAND_5GHZ) lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; lq_sta->is_agg = 0; #ifdef CONFIG_MAC80211_DEBUGFS lq_sta->dbg_fixed_rate = 0; #endif rs_initialize_lq(mvm, sta, lq_sta, band); }
static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, struct iwl3945_rate_scale_data *window, int success, int retries, int index) { unsigned long flags; s32 fail_count; struct iwl_priv *priv __maybe_unused = rs_sta->priv; if (!retries) { IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n"); return; } spin_lock_irqsave(&rs_sta->lock, flags); while (retries > 0) { if (window->counter >= IWL_RATE_MAX_WINDOW) { window->counter = IWL_RATE_MAX_WINDOW - 1; if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); window->success_counter--; } } window->counter++; window->data <<= 1; if (success > 0) { window->success_counter++; window->data |= 0x1; success--; } retries--; } if (window->counter > 0) window->success_ratio = 128 * (100 * window->success_counter) / window->counter; else window->success_ratio = IWL_INVALID_VALUE; fail_count = window->counter - window->success_counter; if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) window->average_tpt = ((window->success_ratio * rs_sta->expected_tpt[index] + 64) / 128); else window->average_tpt = IWL_INVALID_VALUE; window->stamp = jiffies; spin_unlock_irqrestore(&rs_sta->lock, flags); }
static void iwl3945_bg_rate_scale_flush(unsigned long data) { struct iwl3945_rs_sta *rs_sta = (void *)data; struct iwl_priv *priv __maybe_unused = rs_sta->priv; int unflushed = 0; unsigned long flags; u32 packet_count, duration, pps; IWL_DEBUG_RATE(priv, "enter\n"); unflushed = iwl3945_rate_scale_flush_windows(rs_sta); spin_lock_irqsave(&rs_sta->lock, flags); packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; rs_sta->last_tx_packets = rs_sta->tx_packets + 1; if (unflushed) { duration = jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n", packet_count, duration); if (duration) pps = (packet_count * 1000) / duration; else pps = 0; if (pps) { duration = (IWL_AVERAGE_PACKETS * 1000) / pps; if (duration < IWL_RATE_FLUSH_MIN) duration = IWL_RATE_FLUSH_MIN; else if (duration > IWL_RATE_FLUSH_MAX) duration = IWL_RATE_FLUSH_MAX; } else duration = IWL_RATE_FLUSH_MAX; rs_sta->flush_time = msecs_to_jiffies(duration); IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n", duration, packet_count); mod_timer(&rs_sta->rate_scale_flush, jiffies + rs_sta->flush_time); rs_sta->last_partial_flush = jiffies; } else { rs_sta->flush_time = IWL_RATE_FLUSH; rs_sta->flush_pending = 0; } rs_sta->last_flush = jiffies; spin_unlock_irqrestore(&rs_sta->lock, flags); IWL_DEBUG_RATE(priv, "leave\n"); }
/** * iwl3945_collect_tx_data - Update the success/failure sliding window * * We keep a sliding window of the last 64 packets transmitted * at this rate. window->data contains the bitmask of successful * packets. */ static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, struct iwl3945_rate_scale_data *window, int success, int retries, int index) { unsigned long flags; s32 fail_count; struct iwl_priv *priv __maybe_unused = rs_sta->priv; if (!retries) { IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n"); return; } spin_lock_irqsave(&rs_sta->lock, flags); /* * Keep track of only the latest 62 tx frame attempts in this rate's * history window; anything older isn't really relevant any more. * If we have filled up the sliding window, drop the oldest attempt; * if the oldest attempt (highest bit in bitmap) shows "success", * subtract "1" from the success counter (this is the main reason * we keep these bitmaps!). * */ while (retries > 0) { if (window->counter >= IWL_RATE_MAX_WINDOW) { /* remove earliest */ window->counter = IWL_RATE_MAX_WINDOW - 1; if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); window->success_counter--; } } /* Increment frames-attempted counter */ window->counter++; /* Shift bitmap by one frame (throw away oldest history), * OR in "1", and increment "success" if this * frame was successful. */ window->data <<= 1; if (success > 0) { window->success_counter++; window->data |= 0x1; success--; } retries--; } /* Calculate current success ratio, avoid divide-by-0! */ if (window->counter > 0) window->success_ratio = 128 * (100 * window->success_counter) / window->counter; else window->success_ratio = IWL_INVALID_VALUE; fail_count = window->counter - window->success_counter; /* Calculate average throughput, if we have enough history. */ if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) window->average_tpt = ((window->success_ratio * rs_sta->expected_tpt[index] + 64) / 128); else window->average_tpt = IWL_INVALID_VALUE; /* Tag this window as having been updated */ window->stamp = jiffies; spin_unlock_irqrestore(&rs_sta->lock, flags); }