/** * 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; }
/* * Called after adding a new station to initialize rate scaling */ void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id) { struct ieee80211_hw *hw = priv->hw; struct ieee80211_conf *conf = &priv->hw->conf; struct iwl3945_sta_priv *psta; struct iwl3945_rs_sta *rs_sta; struct ieee80211_supported_band *sband; int i; IWL_DEBUG_INFO(priv, "enter\n"); if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id) goto out; psta = (struct iwl3945_sta_priv *) sta->drv_priv; rs_sta = &psta->rs_sta; sband = hw->wiphy->bands[conf->channel->band]; 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->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]); /* 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->_3945.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->_3945.sta_supp_rates = priv->_3945.sta_supp_rates << IWL_FIRST_OFDM_RATE; } out: priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS; IWL_DEBUG_INFO(priv, "leave\n"); }
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; }
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; }