17ac9a364SKalle Valo /****************************************************************************** 27ac9a364SKalle Valo * 37ac9a364SKalle Valo * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved. 47ac9a364SKalle Valo * 57ac9a364SKalle Valo * This program is free software; you can redistribute it and/or modify it 67ac9a364SKalle Valo * under the terms of version 2 of the GNU General Public License as 77ac9a364SKalle Valo * published by the Free Software Foundation. 87ac9a364SKalle Valo * 97ac9a364SKalle Valo * This program is distributed in the hope that it will be useful, but WITHOUT 107ac9a364SKalle Valo * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 117ac9a364SKalle Valo * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 127ac9a364SKalle Valo * more details. 137ac9a364SKalle Valo * 147ac9a364SKalle Valo * You should have received a copy of the GNU General Public License along with 157ac9a364SKalle Valo * this program; if not, write to the Free Software Foundation, Inc., 167ac9a364SKalle Valo * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 177ac9a364SKalle Valo * 187ac9a364SKalle Valo * The full GNU General Public License is included in this distribution in the 197ac9a364SKalle Valo * file called LICENSE. 207ac9a364SKalle Valo * 217ac9a364SKalle Valo * Contact Information: 227ac9a364SKalle Valo * Intel Linux Wireless <ilw@linux.intel.com> 237ac9a364SKalle Valo * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 247ac9a364SKalle Valo * 257ac9a364SKalle Valo *****************************************************************************/ 267ac9a364SKalle Valo 277ac9a364SKalle Valo #include <linux/kernel.h> 287ac9a364SKalle Valo #include <linux/skbuff.h> 297ac9a364SKalle Valo #include <linux/slab.h> 307ac9a364SKalle Valo #include <net/mac80211.h> 317ac9a364SKalle Valo 327ac9a364SKalle Valo #include <linux/netdevice.h> 337ac9a364SKalle Valo #include <linux/etherdevice.h> 347ac9a364SKalle Valo #include <linux/delay.h> 357ac9a364SKalle Valo 367ac9a364SKalle Valo #include <linux/workqueue.h> 377ac9a364SKalle Valo 387ac9a364SKalle Valo #include "commands.h" 397ac9a364SKalle Valo #include "3945.h" 407ac9a364SKalle Valo 417ac9a364SKalle Valo #define RS_NAME "iwl-3945-rs" 427ac9a364SKalle Valo 437ac9a364SKalle Valo static s32 il3945_expected_tpt_g[RATE_COUNT_3945] = { 447ac9a364SKalle Valo 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 457ac9a364SKalle Valo }; 467ac9a364SKalle Valo 477ac9a364SKalle Valo static s32 il3945_expected_tpt_g_prot[RATE_COUNT_3945] = { 487ac9a364SKalle Valo 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 497ac9a364SKalle Valo }; 507ac9a364SKalle Valo 517ac9a364SKalle Valo static s32 il3945_expected_tpt_a[RATE_COUNT_3945] = { 527ac9a364SKalle Valo 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 537ac9a364SKalle Valo }; 547ac9a364SKalle Valo 557ac9a364SKalle Valo static s32 il3945_expected_tpt_b[RATE_COUNT_3945] = { 567ac9a364SKalle Valo 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 577ac9a364SKalle Valo }; 587ac9a364SKalle Valo 597ac9a364SKalle Valo struct il3945_tpt_entry { 607ac9a364SKalle Valo s8 min_rssi; 617ac9a364SKalle Valo u8 idx; 627ac9a364SKalle Valo }; 637ac9a364SKalle Valo 647ac9a364SKalle Valo static struct il3945_tpt_entry il3945_tpt_table_a[] = { 657ac9a364SKalle Valo {-60, RATE_54M_IDX}, 667ac9a364SKalle Valo {-64, RATE_48M_IDX}, 677ac9a364SKalle Valo {-72, RATE_36M_IDX}, 687ac9a364SKalle Valo {-80, RATE_24M_IDX}, 697ac9a364SKalle Valo {-84, RATE_18M_IDX}, 707ac9a364SKalle Valo {-85, RATE_12M_IDX}, 717ac9a364SKalle Valo {-87, RATE_9M_IDX}, 727ac9a364SKalle Valo {-89, RATE_6M_IDX} 737ac9a364SKalle Valo }; 747ac9a364SKalle Valo 757ac9a364SKalle Valo static struct il3945_tpt_entry il3945_tpt_table_g[] = { 767ac9a364SKalle Valo {-60, RATE_54M_IDX}, 777ac9a364SKalle Valo {-64, RATE_48M_IDX}, 787ac9a364SKalle Valo {-68, RATE_36M_IDX}, 797ac9a364SKalle Valo {-80, RATE_24M_IDX}, 807ac9a364SKalle Valo {-84, RATE_18M_IDX}, 817ac9a364SKalle Valo {-85, RATE_12M_IDX}, 827ac9a364SKalle Valo {-86, RATE_11M_IDX}, 837ac9a364SKalle Valo {-88, RATE_5M_IDX}, 847ac9a364SKalle Valo {-90, RATE_2M_IDX}, 857ac9a364SKalle Valo {-92, RATE_1M_IDX} 867ac9a364SKalle Valo }; 877ac9a364SKalle Valo 887ac9a364SKalle Valo #define RATE_MAX_WINDOW 62 897ac9a364SKalle Valo #define RATE_FLUSH (3*HZ) 907ac9a364SKalle Valo #define RATE_WIN_FLUSH (HZ/2) 917ac9a364SKalle Valo #define IL39_RATE_HIGH_TH 11520 927ac9a364SKalle Valo #define IL_SUCCESS_UP_TH 8960 937ac9a364SKalle Valo #define IL_SUCCESS_DOWN_TH 10880 947ac9a364SKalle Valo #define RATE_MIN_FAILURE_TH 6 957ac9a364SKalle Valo #define RATE_MIN_SUCCESS_TH 8 967ac9a364SKalle Valo #define RATE_DECREASE_TH 1920 977ac9a364SKalle Valo #define RATE_RETRY_TH 15 987ac9a364SKalle Valo 997ac9a364SKalle Valo static u8 10057fbcce3SJohannes Berg il3945_get_rate_idx_by_rssi(s32 rssi, enum nl80211_band band) 1017ac9a364SKalle Valo { 1027ac9a364SKalle Valo u32 idx = 0; 1037ac9a364SKalle Valo u32 table_size = 0; 1047ac9a364SKalle Valo struct il3945_tpt_entry *tpt_table = NULL; 1057ac9a364SKalle Valo 1067ac9a364SKalle Valo if (rssi < IL_MIN_RSSI_VAL || rssi > IL_MAX_RSSI_VAL) 1077ac9a364SKalle Valo rssi = IL_MIN_RSSI_VAL; 1087ac9a364SKalle Valo 1097ac9a364SKalle Valo switch (band) { 11057fbcce3SJohannes Berg case NL80211_BAND_2GHZ: 1117ac9a364SKalle Valo tpt_table = il3945_tpt_table_g; 1127ac9a364SKalle Valo table_size = ARRAY_SIZE(il3945_tpt_table_g); 1137ac9a364SKalle Valo break; 11457fbcce3SJohannes Berg case NL80211_BAND_5GHZ: 1157ac9a364SKalle Valo tpt_table = il3945_tpt_table_a; 1167ac9a364SKalle Valo table_size = ARRAY_SIZE(il3945_tpt_table_a); 1177ac9a364SKalle Valo break; 1187ac9a364SKalle Valo default: 1197ac9a364SKalle Valo BUG(); 1207ac9a364SKalle Valo break; 1217ac9a364SKalle Valo } 1227ac9a364SKalle Valo 1237ac9a364SKalle Valo while (idx < table_size && rssi < tpt_table[idx].min_rssi) 1247ac9a364SKalle Valo idx++; 1257ac9a364SKalle Valo 1267ac9a364SKalle Valo idx = min(idx, table_size - 1); 1277ac9a364SKalle Valo 1287ac9a364SKalle Valo return tpt_table[idx].idx; 1297ac9a364SKalle Valo } 1307ac9a364SKalle Valo 1317ac9a364SKalle Valo static void 1327ac9a364SKalle Valo il3945_clear_win(struct il3945_rate_scale_data *win) 1337ac9a364SKalle Valo { 1347ac9a364SKalle Valo win->data = 0; 1357ac9a364SKalle Valo win->success_counter = 0; 1367ac9a364SKalle Valo win->success_ratio = -1; 1377ac9a364SKalle Valo win->counter = 0; 1387ac9a364SKalle Valo win->average_tpt = IL_INVALID_VALUE; 1397ac9a364SKalle Valo win->stamp = 0; 1407ac9a364SKalle Valo } 1417ac9a364SKalle Valo 1427ac9a364SKalle Valo /** 1437ac9a364SKalle Valo * il3945_rate_scale_flush_wins - flush out the rate scale wins 1447ac9a364SKalle Valo * 1457ac9a364SKalle Valo * Returns the number of wins that have gathered data but were 1467ac9a364SKalle Valo * not flushed. If there were any that were not flushed, then 1477ac9a364SKalle Valo * reschedule the rate flushing routine. 1487ac9a364SKalle Valo */ 1497ac9a364SKalle Valo static int 1507ac9a364SKalle Valo il3945_rate_scale_flush_wins(struct il3945_rs_sta *rs_sta) 1517ac9a364SKalle Valo { 1527ac9a364SKalle Valo int unflushed = 0; 1537ac9a364SKalle Valo int i; 1547ac9a364SKalle Valo unsigned long flags; 1557ac9a364SKalle Valo struct il_priv *il __maybe_unused = rs_sta->il; 1567ac9a364SKalle Valo 1577ac9a364SKalle Valo /* 1587ac9a364SKalle Valo * For each rate, if we have collected data on that rate 1597ac9a364SKalle Valo * and it has been more than RATE_WIN_FLUSH 1607ac9a364SKalle Valo * since we flushed, clear out the gathered stats 1617ac9a364SKalle Valo */ 1627ac9a364SKalle Valo for (i = 0; i < RATE_COUNT_3945; i++) { 1637ac9a364SKalle Valo if (!rs_sta->win[i].counter) 1647ac9a364SKalle Valo continue; 1657ac9a364SKalle Valo 1667ac9a364SKalle Valo spin_lock_irqsave(&rs_sta->lock, flags); 1677ac9a364SKalle Valo if (time_after(jiffies, rs_sta->win[i].stamp + RATE_WIN_FLUSH)) { 1687ac9a364SKalle Valo D_RATE("flushing %d samples of rate " "idx %d\n", 1697ac9a364SKalle Valo rs_sta->win[i].counter, i); 1707ac9a364SKalle Valo il3945_clear_win(&rs_sta->win[i]); 1717ac9a364SKalle Valo } else 1727ac9a364SKalle Valo unflushed++; 1737ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 1747ac9a364SKalle Valo } 1757ac9a364SKalle Valo 1767ac9a364SKalle Valo return unflushed; 1777ac9a364SKalle Valo } 1787ac9a364SKalle Valo 1797ac9a364SKalle Valo #define RATE_FLUSH_MAX 5000 /* msec */ 1807ac9a364SKalle Valo #define RATE_FLUSH_MIN 50 /* msec */ 1817ac9a364SKalle Valo #define IL_AVERAGE_PACKETS 1500 1827ac9a364SKalle Valo 1837ac9a364SKalle Valo static void 1842b77839bSKees Cook il3945_bg_rate_scale_flush(struct timer_list *t) 1857ac9a364SKalle Valo { 1862b77839bSKees Cook struct il3945_rs_sta *rs_sta = from_timer(rs_sta, t, rate_scale_flush); 1877ac9a364SKalle Valo struct il_priv *il __maybe_unused = rs_sta->il; 1887ac9a364SKalle Valo int unflushed = 0; 1897ac9a364SKalle Valo unsigned long flags; 1907ac9a364SKalle Valo u32 packet_count, duration, pps; 1917ac9a364SKalle Valo 1927ac9a364SKalle Valo D_RATE("enter\n"); 1937ac9a364SKalle Valo 1947ac9a364SKalle Valo unflushed = il3945_rate_scale_flush_wins(rs_sta); 1957ac9a364SKalle Valo 1967ac9a364SKalle Valo spin_lock_irqsave(&rs_sta->lock, flags); 1977ac9a364SKalle Valo 1987ac9a364SKalle Valo /* Number of packets Rx'd since last time this timer ran */ 1997ac9a364SKalle Valo packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; 2007ac9a364SKalle Valo 2017ac9a364SKalle Valo rs_sta->last_tx_packets = rs_sta->tx_packets + 1; 2027ac9a364SKalle Valo 2037ac9a364SKalle Valo if (unflushed) { 2047ac9a364SKalle Valo duration = 2057ac9a364SKalle Valo jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); 2067ac9a364SKalle Valo 2077ac9a364SKalle Valo D_RATE("Tx'd %d packets in %dms\n", packet_count, duration); 2087ac9a364SKalle Valo 2097ac9a364SKalle Valo /* Determine packets per second */ 2107ac9a364SKalle Valo if (duration) 2117ac9a364SKalle Valo pps = (packet_count * 1000) / duration; 2127ac9a364SKalle Valo else 2137ac9a364SKalle Valo pps = 0; 2147ac9a364SKalle Valo 2157ac9a364SKalle Valo if (pps) { 2167ac9a364SKalle Valo duration = (IL_AVERAGE_PACKETS * 1000) / pps; 2177ac9a364SKalle Valo if (duration < RATE_FLUSH_MIN) 2187ac9a364SKalle Valo duration = RATE_FLUSH_MIN; 2197ac9a364SKalle Valo else if (duration > RATE_FLUSH_MAX) 2207ac9a364SKalle Valo duration = RATE_FLUSH_MAX; 2217ac9a364SKalle Valo } else 2227ac9a364SKalle Valo duration = RATE_FLUSH_MAX; 2237ac9a364SKalle Valo 2247ac9a364SKalle Valo rs_sta->flush_time = msecs_to_jiffies(duration); 2257ac9a364SKalle Valo 2267ac9a364SKalle Valo D_RATE("new flush period: %d msec ave %d\n", duration, 2277ac9a364SKalle Valo packet_count); 2287ac9a364SKalle Valo 2297ac9a364SKalle Valo mod_timer(&rs_sta->rate_scale_flush, 2307ac9a364SKalle Valo jiffies + rs_sta->flush_time); 2317ac9a364SKalle Valo 2327ac9a364SKalle Valo rs_sta->last_partial_flush = jiffies; 2337ac9a364SKalle Valo } else { 2347ac9a364SKalle Valo rs_sta->flush_time = RATE_FLUSH; 2357ac9a364SKalle Valo rs_sta->flush_pending = 0; 2367ac9a364SKalle Valo } 2377ac9a364SKalle Valo /* If there weren't any unflushed entries, we don't schedule the timer 2387ac9a364SKalle Valo * to run again */ 2397ac9a364SKalle Valo 2407ac9a364SKalle Valo rs_sta->last_flush = jiffies; 2417ac9a364SKalle Valo 2427ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 2437ac9a364SKalle Valo 2447ac9a364SKalle Valo D_RATE("leave\n"); 2457ac9a364SKalle Valo } 2467ac9a364SKalle Valo 2477ac9a364SKalle Valo /** 2487ac9a364SKalle Valo * il3945_collect_tx_data - Update the success/failure sliding win 2497ac9a364SKalle Valo * 2507ac9a364SKalle Valo * We keep a sliding win of the last 64 packets transmitted 2517ac9a364SKalle Valo * at this rate. win->data contains the bitmask of successful 2527ac9a364SKalle Valo * packets. 2537ac9a364SKalle Valo */ 2547ac9a364SKalle Valo static void 2557ac9a364SKalle Valo il3945_collect_tx_data(struct il3945_rs_sta *rs_sta, 2567ac9a364SKalle Valo struct il3945_rate_scale_data *win, int success, 2577ac9a364SKalle Valo int retries, int idx) 2587ac9a364SKalle Valo { 2597ac9a364SKalle Valo unsigned long flags; 2607ac9a364SKalle Valo s32 fail_count; 2617ac9a364SKalle Valo struct il_priv *il __maybe_unused = rs_sta->il; 2627ac9a364SKalle Valo 2637ac9a364SKalle Valo if (!retries) { 2647ac9a364SKalle Valo D_RATE("leave: retries == 0 -- should be at least 1\n"); 2657ac9a364SKalle Valo return; 2667ac9a364SKalle Valo } 2677ac9a364SKalle Valo 2687ac9a364SKalle Valo spin_lock_irqsave(&rs_sta->lock, flags); 2697ac9a364SKalle Valo 2707ac9a364SKalle Valo /* 2717ac9a364SKalle Valo * Keep track of only the latest 62 tx frame attempts in this rate's 2727ac9a364SKalle Valo * history win; anything older isn't really relevant any more. 2737ac9a364SKalle Valo * If we have filled up the sliding win, drop the oldest attempt; 2747ac9a364SKalle Valo * if the oldest attempt (highest bit in bitmap) shows "success", 2757ac9a364SKalle Valo * subtract "1" from the success counter (this is the main reason 2767ac9a364SKalle Valo * we keep these bitmaps!). 2777ac9a364SKalle Valo * */ 2787ac9a364SKalle Valo while (retries > 0) { 2797ac9a364SKalle Valo if (win->counter >= RATE_MAX_WINDOW) { 2807ac9a364SKalle Valo 2817ac9a364SKalle Valo /* remove earliest */ 2827ac9a364SKalle Valo win->counter = RATE_MAX_WINDOW - 1; 2837ac9a364SKalle Valo 2847ac9a364SKalle Valo if (win->data & (1ULL << (RATE_MAX_WINDOW - 1))) { 2857ac9a364SKalle Valo win->data &= ~(1ULL << (RATE_MAX_WINDOW - 1)); 2867ac9a364SKalle Valo win->success_counter--; 2877ac9a364SKalle Valo } 2887ac9a364SKalle Valo } 2897ac9a364SKalle Valo 2907ac9a364SKalle Valo /* Increment frames-attempted counter */ 2917ac9a364SKalle Valo win->counter++; 2927ac9a364SKalle Valo 2937ac9a364SKalle Valo /* Shift bitmap by one frame (throw away oldest history), 2947ac9a364SKalle Valo * OR in "1", and increment "success" if this 2957ac9a364SKalle Valo * frame was successful. */ 2967ac9a364SKalle Valo win->data <<= 1; 2977ac9a364SKalle Valo if (success > 0) { 2987ac9a364SKalle Valo win->success_counter++; 2997ac9a364SKalle Valo win->data |= 0x1; 3007ac9a364SKalle Valo success--; 3017ac9a364SKalle Valo } 3027ac9a364SKalle Valo 3037ac9a364SKalle Valo retries--; 3047ac9a364SKalle Valo } 3057ac9a364SKalle Valo 3067ac9a364SKalle Valo /* Calculate current success ratio, avoid divide-by-0! */ 3077ac9a364SKalle Valo if (win->counter > 0) 3087ac9a364SKalle Valo win->success_ratio = 3097ac9a364SKalle Valo 128 * (100 * win->success_counter) / win->counter; 3107ac9a364SKalle Valo else 3117ac9a364SKalle Valo win->success_ratio = IL_INVALID_VALUE; 3127ac9a364SKalle Valo 3137ac9a364SKalle Valo fail_count = win->counter - win->success_counter; 3147ac9a364SKalle Valo 3157ac9a364SKalle Valo /* Calculate average throughput, if we have enough history. */ 3167ac9a364SKalle Valo if (fail_count >= RATE_MIN_FAILURE_TH || 3177ac9a364SKalle Valo win->success_counter >= RATE_MIN_SUCCESS_TH) 3187ac9a364SKalle Valo win->average_tpt = 3197ac9a364SKalle Valo ((win->success_ratio * rs_sta->expected_tpt[idx] + 3207ac9a364SKalle Valo 64) / 128); 3217ac9a364SKalle Valo else 3227ac9a364SKalle Valo win->average_tpt = IL_INVALID_VALUE; 3237ac9a364SKalle Valo 3247ac9a364SKalle Valo /* Tag this win as having been updated */ 3257ac9a364SKalle Valo win->stamp = jiffies; 3267ac9a364SKalle Valo 3277ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 3287ac9a364SKalle Valo } 3297ac9a364SKalle Valo 3307ac9a364SKalle Valo /* 3317ac9a364SKalle Valo * Called after adding a new station to initialize rate scaling 3327ac9a364SKalle Valo */ 3337ac9a364SKalle Valo void 3347ac9a364SKalle Valo il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id) 3357ac9a364SKalle Valo { 3367ac9a364SKalle Valo struct ieee80211_hw *hw = il->hw; 3377ac9a364SKalle Valo struct ieee80211_conf *conf = &il->hw->conf; 3387ac9a364SKalle Valo struct il3945_sta_priv *psta; 3397ac9a364SKalle Valo struct il3945_rs_sta *rs_sta; 3407ac9a364SKalle Valo struct ieee80211_supported_band *sband; 3417ac9a364SKalle Valo int i; 3427ac9a364SKalle Valo 3437ac9a364SKalle Valo D_INFO("enter\n"); 3447ac9a364SKalle Valo if (sta_id == il->hw_params.bcast_id) 3457ac9a364SKalle Valo goto out; 3467ac9a364SKalle Valo 3477ac9a364SKalle Valo psta = (struct il3945_sta_priv *)sta->drv_priv; 3487ac9a364SKalle Valo rs_sta = &psta->rs_sta; 3497ac9a364SKalle Valo sband = hw->wiphy->bands[conf->chandef.chan->band]; 3507ac9a364SKalle Valo 3517ac9a364SKalle Valo rs_sta->il = il; 3527ac9a364SKalle Valo 3537ac9a364SKalle Valo rs_sta->start_rate = RATE_INVALID; 3547ac9a364SKalle Valo 3557ac9a364SKalle Valo /* default to just 802.11b */ 3567ac9a364SKalle Valo rs_sta->expected_tpt = il3945_expected_tpt_b; 3577ac9a364SKalle Valo 3587ac9a364SKalle Valo rs_sta->last_partial_flush = jiffies; 3597ac9a364SKalle Valo rs_sta->last_flush = jiffies; 3607ac9a364SKalle Valo rs_sta->flush_time = RATE_FLUSH; 3617ac9a364SKalle Valo rs_sta->last_tx_packets = 0; 3627ac9a364SKalle Valo 3637ac9a364SKalle Valo for (i = 0; i < RATE_COUNT_3945; i++) 3647ac9a364SKalle Valo il3945_clear_win(&rs_sta->win[i]); 3657ac9a364SKalle Valo 3667ac9a364SKalle Valo /* TODO: what is a good starting rate for STA? About middle? Maybe not 3677ac9a364SKalle Valo * the lowest or the highest rate.. Could consider using RSSI from 3687ac9a364SKalle Valo * previous packets? Need to have IEEE 802.1X auth succeed immediately 3697ac9a364SKalle Valo * after assoc.. */ 3707ac9a364SKalle Valo 3717ac9a364SKalle Valo for (i = sband->n_bitrates - 1; i >= 0; i--) { 3727ac9a364SKalle Valo if (sta->supp_rates[sband->band] & (1 << i)) { 3737ac9a364SKalle Valo rs_sta->last_txrate_idx = i; 3747ac9a364SKalle Valo break; 3757ac9a364SKalle Valo } 3767ac9a364SKalle Valo } 3777ac9a364SKalle Valo 3787ac9a364SKalle Valo il->_3945.sta_supp_rates = sta->supp_rates[sband->band]; 3797ac9a364SKalle Valo /* For 5 GHz band it start at IL_FIRST_OFDM_RATE */ 38057fbcce3SJohannes Berg if (sband->band == NL80211_BAND_5GHZ) { 3817ac9a364SKalle Valo rs_sta->last_txrate_idx += IL_FIRST_OFDM_RATE; 3827ac9a364SKalle Valo il->_3945.sta_supp_rates <<= IL_FIRST_OFDM_RATE; 3837ac9a364SKalle Valo } 3847ac9a364SKalle Valo 3857ac9a364SKalle Valo out: 3867ac9a364SKalle Valo il->stations[sta_id].used &= ~IL_STA_UCODE_INPROGRESS; 3877ac9a364SKalle Valo 3887ac9a364SKalle Valo D_INFO("leave\n"); 3897ac9a364SKalle Valo } 3907ac9a364SKalle Valo 3917ac9a364SKalle Valo static void * 3927ac9a364SKalle Valo il3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) 3937ac9a364SKalle Valo { 3947ac9a364SKalle Valo return hw->priv; 3957ac9a364SKalle Valo } 3967ac9a364SKalle Valo 3977ac9a364SKalle Valo /* rate scale requires free function to be implemented */ 3987ac9a364SKalle Valo static void 3997ac9a364SKalle Valo il3945_rs_free(void *il) 4007ac9a364SKalle Valo { 4017ac9a364SKalle Valo } 4027ac9a364SKalle Valo 4037ac9a364SKalle Valo static void * 4047ac9a364SKalle Valo il3945_rs_alloc_sta(void *il_priv, struct ieee80211_sta *sta, gfp_t gfp) 4057ac9a364SKalle Valo { 4067ac9a364SKalle Valo struct il3945_rs_sta *rs_sta; 4077ac9a364SKalle Valo struct il3945_sta_priv *psta = (void *)sta->drv_priv; 4087ac9a364SKalle Valo struct il_priv *il __maybe_unused = il_priv; 4097ac9a364SKalle Valo 4107ac9a364SKalle Valo D_RATE("enter\n"); 4117ac9a364SKalle Valo 4127ac9a364SKalle Valo rs_sta = &psta->rs_sta; 4137ac9a364SKalle Valo 4147ac9a364SKalle Valo spin_lock_init(&rs_sta->lock); 4152b77839bSKees Cook timer_setup(&rs_sta->rate_scale_flush, il3945_bg_rate_scale_flush, 0); 4167ac9a364SKalle Valo D_RATE("leave\n"); 4177ac9a364SKalle Valo 4187ac9a364SKalle Valo return rs_sta; 4197ac9a364SKalle Valo } 4207ac9a364SKalle Valo 4217ac9a364SKalle Valo static void 4227ac9a364SKalle Valo il3945_rs_free_sta(void *il_priv, struct ieee80211_sta *sta, void *il_sta) 4237ac9a364SKalle Valo { 4247ac9a364SKalle Valo struct il3945_rs_sta *rs_sta = il_sta; 4257ac9a364SKalle Valo 4267ac9a364SKalle Valo /* 4277ac9a364SKalle Valo * Be careful not to use any members of il3945_rs_sta (like trying 4287ac9a364SKalle Valo * to use il_priv to print out debugging) since it may not be fully 4297ac9a364SKalle Valo * initialized at this point. 4307ac9a364SKalle Valo */ 4317ac9a364SKalle Valo del_timer_sync(&rs_sta->rate_scale_flush); 4327ac9a364SKalle Valo } 4337ac9a364SKalle Valo 4347ac9a364SKalle Valo /** 4357ac9a364SKalle Valo * il3945_rs_tx_status - Update rate control values based on Tx results 4367ac9a364SKalle Valo * 4377ac9a364SKalle Valo * NOTE: Uses il_priv->retry_rate for the # of retries attempted by 4387ac9a364SKalle Valo * the hardware for each rate. 4397ac9a364SKalle Valo */ 4407ac9a364SKalle Valo static void 4417ac9a364SKalle Valo il3945_rs_tx_status(void *il_rate, struct ieee80211_supported_band *sband, 4427ac9a364SKalle Valo struct ieee80211_sta *sta, void *il_sta, 4437ac9a364SKalle Valo struct sk_buff *skb) 4447ac9a364SKalle Valo { 4457ac9a364SKalle Valo s8 retries = 0, current_count; 4467ac9a364SKalle Valo int scale_rate_idx, first_idx, last_idx; 4477ac9a364SKalle Valo unsigned long flags; 4487ac9a364SKalle Valo struct il_priv *il = (struct il_priv *)il_rate; 4497ac9a364SKalle Valo struct il3945_rs_sta *rs_sta = il_sta; 4507ac9a364SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 4517ac9a364SKalle Valo 4527ac9a364SKalle Valo D_RATE("enter\n"); 4537ac9a364SKalle Valo 4547ac9a364SKalle Valo retries = info->status.rates[0].count; 4557ac9a364SKalle Valo /* Sanity Check for retries */ 4567ac9a364SKalle Valo if (retries > RATE_RETRY_TH) 4577ac9a364SKalle Valo retries = RATE_RETRY_TH; 4587ac9a364SKalle Valo 4597ac9a364SKalle Valo first_idx = sband->bitrates[info->status.rates[0].idx].hw_value; 4607ac9a364SKalle Valo if (first_idx < 0 || first_idx >= RATE_COUNT_3945) { 4617ac9a364SKalle Valo D_RATE("leave: Rate out of bounds: %d\n", first_idx); 4627ac9a364SKalle Valo return; 4637ac9a364SKalle Valo } 4647ac9a364SKalle Valo 4657ac9a364SKalle Valo if (!il_sta) { 4667ac9a364SKalle Valo D_RATE("leave: No STA il data to update!\n"); 4677ac9a364SKalle Valo return; 4687ac9a364SKalle Valo } 4697ac9a364SKalle Valo 4707ac9a364SKalle Valo /* Treat uninitialized rate scaling data same as non-existing. */ 4717ac9a364SKalle Valo if (!rs_sta->il) { 4727ac9a364SKalle Valo D_RATE("leave: STA il data uninitialized!\n"); 4737ac9a364SKalle Valo return; 4747ac9a364SKalle Valo } 4757ac9a364SKalle Valo 4767ac9a364SKalle Valo rs_sta->tx_packets++; 4777ac9a364SKalle Valo 4787ac9a364SKalle Valo scale_rate_idx = first_idx; 4797ac9a364SKalle Valo last_idx = first_idx; 4807ac9a364SKalle Valo 4817ac9a364SKalle Valo /* 4827ac9a364SKalle Valo * Update the win for each rate. We determine which rates 4837ac9a364SKalle Valo * were Tx'd based on the total number of retries vs. the number 4847ac9a364SKalle Valo * of retries configured for each rate -- currently set to the 4857ac9a364SKalle Valo * il value 'retry_rate' vs. rate specific 4867ac9a364SKalle Valo * 4877ac9a364SKalle Valo * On exit from this while loop last_idx indicates the rate 4887ac9a364SKalle Valo * at which the frame was finally transmitted (or failed if no 4897ac9a364SKalle Valo * ACK) 4907ac9a364SKalle Valo */ 4917ac9a364SKalle Valo while (retries > 1) { 4927ac9a364SKalle Valo if ((retries - 1) < il->retry_rate) { 4937ac9a364SKalle Valo current_count = (retries - 1); 4947ac9a364SKalle Valo last_idx = scale_rate_idx; 4957ac9a364SKalle Valo } else { 4967ac9a364SKalle Valo current_count = il->retry_rate; 4977ac9a364SKalle Valo last_idx = il3945_rs_next_rate(il, scale_rate_idx); 4987ac9a364SKalle Valo } 4997ac9a364SKalle Valo 5007ac9a364SKalle Valo /* Update this rate accounting for as many retries 5017ac9a364SKalle Valo * as was used for it (per current_count) */ 5027ac9a364SKalle Valo il3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_idx], 0, 5037ac9a364SKalle Valo current_count, scale_rate_idx); 5047ac9a364SKalle Valo D_RATE("Update rate %d for %d retries.\n", scale_rate_idx, 5057ac9a364SKalle Valo current_count); 5067ac9a364SKalle Valo 5077ac9a364SKalle Valo retries -= current_count; 5087ac9a364SKalle Valo 5097ac9a364SKalle Valo scale_rate_idx = last_idx; 5107ac9a364SKalle Valo } 5117ac9a364SKalle Valo 5127ac9a364SKalle Valo /* Update the last idx win with success/failure based on ACK */ 5137ac9a364SKalle Valo D_RATE("Update rate %d with %s.\n", last_idx, 5147ac9a364SKalle Valo (info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure"); 5157ac9a364SKalle Valo il3945_collect_tx_data(rs_sta, &rs_sta->win[last_idx], 5167ac9a364SKalle Valo info->flags & IEEE80211_TX_STAT_ACK, 1, 5177ac9a364SKalle Valo last_idx); 5187ac9a364SKalle Valo 5197ac9a364SKalle Valo /* We updated the rate scale win -- if its been more than 5207ac9a364SKalle Valo * flush_time since the last run, schedule the flush 5217ac9a364SKalle Valo * again */ 5227ac9a364SKalle Valo spin_lock_irqsave(&rs_sta->lock, flags); 5237ac9a364SKalle Valo 5247ac9a364SKalle Valo if (!rs_sta->flush_pending && 5257ac9a364SKalle Valo time_after(jiffies, rs_sta->last_flush + rs_sta->flush_time)) { 5267ac9a364SKalle Valo 5277ac9a364SKalle Valo rs_sta->last_partial_flush = jiffies; 5287ac9a364SKalle Valo rs_sta->flush_pending = 1; 5297ac9a364SKalle Valo mod_timer(&rs_sta->rate_scale_flush, 5307ac9a364SKalle Valo jiffies + rs_sta->flush_time); 5317ac9a364SKalle Valo } 5327ac9a364SKalle Valo 5337ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 5347ac9a364SKalle Valo 5357ac9a364SKalle Valo D_RATE("leave\n"); 5367ac9a364SKalle Valo } 5377ac9a364SKalle Valo 5387ac9a364SKalle Valo static u16 5397ac9a364SKalle Valo il3945_get_adjacent_rate(struct il3945_rs_sta *rs_sta, u8 idx, u16 rate_mask, 54057fbcce3SJohannes Berg enum nl80211_band band) 5417ac9a364SKalle Valo { 5427ac9a364SKalle Valo u8 high = RATE_INVALID; 5437ac9a364SKalle Valo u8 low = RATE_INVALID; 5447ac9a364SKalle Valo struct il_priv *il __maybe_unused = rs_sta->il; 5457ac9a364SKalle Valo 5467ac9a364SKalle Valo /* 802.11A walks to the next literal adjacent rate in 5477ac9a364SKalle Valo * the rate table */ 54857fbcce3SJohannes Berg if (unlikely(band == NL80211_BAND_5GHZ)) { 5497ac9a364SKalle Valo int i; 5507ac9a364SKalle Valo u32 mask; 5517ac9a364SKalle Valo 5527ac9a364SKalle Valo /* Find the previous rate that is in the rate mask */ 5537ac9a364SKalle Valo i = idx - 1; 5547ac9a364SKalle Valo for (mask = (1 << i); i >= 0; i--, mask >>= 1) { 5557ac9a364SKalle Valo if (rate_mask & mask) { 5567ac9a364SKalle Valo low = i; 5577ac9a364SKalle Valo break; 5587ac9a364SKalle Valo } 5597ac9a364SKalle Valo } 5607ac9a364SKalle Valo 5617ac9a364SKalle Valo /* Find the next rate that is in the rate mask */ 5627ac9a364SKalle Valo i = idx + 1; 5637ac9a364SKalle Valo for (mask = (1 << i); i < RATE_COUNT_3945; i++, mask <<= 1) { 5647ac9a364SKalle Valo if (rate_mask & mask) { 5657ac9a364SKalle Valo high = i; 5667ac9a364SKalle Valo break; 5677ac9a364SKalle Valo } 5687ac9a364SKalle Valo } 5697ac9a364SKalle Valo 5707ac9a364SKalle Valo return (high << 8) | low; 5717ac9a364SKalle Valo } 5727ac9a364SKalle Valo 5737ac9a364SKalle Valo low = idx; 5747ac9a364SKalle Valo while (low != RATE_INVALID) { 5757ac9a364SKalle Valo if (rs_sta->tgg) 5767ac9a364SKalle Valo low = il3945_rates[low].prev_rs_tgg; 5777ac9a364SKalle Valo else 5787ac9a364SKalle Valo low = il3945_rates[low].prev_rs; 5797ac9a364SKalle Valo if (low == RATE_INVALID) 5807ac9a364SKalle Valo break; 5817ac9a364SKalle Valo if (rate_mask & (1 << low)) 5827ac9a364SKalle Valo break; 5837ac9a364SKalle Valo D_RATE("Skipping masked lower rate: %d\n", low); 5847ac9a364SKalle Valo } 5857ac9a364SKalle Valo 5867ac9a364SKalle Valo high = idx; 5877ac9a364SKalle Valo while (high != RATE_INVALID) { 5887ac9a364SKalle Valo if (rs_sta->tgg) 5897ac9a364SKalle Valo high = il3945_rates[high].next_rs_tgg; 5907ac9a364SKalle Valo else 5917ac9a364SKalle Valo high = il3945_rates[high].next_rs; 5927ac9a364SKalle Valo if (high == RATE_INVALID) 5937ac9a364SKalle Valo break; 5947ac9a364SKalle Valo if (rate_mask & (1 << high)) 5957ac9a364SKalle Valo break; 5967ac9a364SKalle Valo D_RATE("Skipping masked higher rate: %d\n", high); 5977ac9a364SKalle Valo } 5987ac9a364SKalle Valo 5997ac9a364SKalle Valo return (high << 8) | low; 6007ac9a364SKalle Valo } 6017ac9a364SKalle Valo 6027ac9a364SKalle Valo /** 6037ac9a364SKalle Valo * il3945_rs_get_rate - find the rate for the requested packet 6047ac9a364SKalle Valo * 6057ac9a364SKalle Valo * Returns the ieee80211_rate structure allocated by the driver. 6067ac9a364SKalle Valo * 6077ac9a364SKalle Valo * The rate control algorithm has no internal mapping between hw_mode's 6087ac9a364SKalle Valo * rate ordering and the rate ordering used by the rate control algorithm. 6097ac9a364SKalle Valo * 6107ac9a364SKalle Valo * The rate control algorithm uses a single table of rates that goes across 6117ac9a364SKalle Valo * the entire A/B/G spectrum vs. being limited to just one particular 6127ac9a364SKalle Valo * hw_mode. 6137ac9a364SKalle Valo * 6147ac9a364SKalle Valo * As such, we can't convert the idx obtained below into the hw_mode's 6157ac9a364SKalle Valo * rate table and must reference the driver allocated rate table 6167ac9a364SKalle Valo * 6177ac9a364SKalle Valo */ 6187ac9a364SKalle Valo static void 6197ac9a364SKalle Valo il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta, 6207ac9a364SKalle Valo struct ieee80211_tx_rate_control *txrc) 6217ac9a364SKalle Valo { 6227ac9a364SKalle Valo struct ieee80211_supported_band *sband = txrc->sband; 6237ac9a364SKalle Valo struct sk_buff *skb = txrc->skb; 6247ac9a364SKalle Valo u8 low = RATE_INVALID; 6257ac9a364SKalle Valo u8 high = RATE_INVALID; 6267ac9a364SKalle Valo u16 high_low; 6277ac9a364SKalle Valo int idx; 6287ac9a364SKalle Valo struct il3945_rs_sta *rs_sta = il_sta; 6297ac9a364SKalle Valo struct il3945_rate_scale_data *win = NULL; 6307ac9a364SKalle Valo int current_tpt = IL_INVALID_VALUE; 6317ac9a364SKalle Valo int low_tpt = IL_INVALID_VALUE; 6327ac9a364SKalle Valo int high_tpt = IL_INVALID_VALUE; 6337ac9a364SKalle Valo u32 fail_count; 6347ac9a364SKalle Valo s8 scale_action = 0; 6357ac9a364SKalle Valo unsigned long flags; 6367ac9a364SKalle Valo u16 rate_mask; 6377ac9a364SKalle Valo s8 max_rate_idx = -1; 6387ac9a364SKalle Valo struct il_priv *il __maybe_unused = (struct il_priv *)il_r; 6397ac9a364SKalle Valo struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 6407ac9a364SKalle Valo 6417ac9a364SKalle Valo D_RATE("enter\n"); 6427ac9a364SKalle Valo 6437ac9a364SKalle Valo /* Treat uninitialized rate scaling data same as non-existing. */ 6447ac9a364SKalle Valo if (rs_sta && !rs_sta->il) { 6457ac9a364SKalle Valo D_RATE("Rate scaling information not initialized yet.\n"); 6467ac9a364SKalle Valo il_sta = NULL; 6477ac9a364SKalle Valo } 6487ac9a364SKalle Valo 6497ac9a364SKalle Valo if (rate_control_send_low(sta, il_sta, txrc)) 6507ac9a364SKalle Valo return; 6517ac9a364SKalle Valo 6527ac9a364SKalle Valo rate_mask = sta->supp_rates[sband->band]; 6537ac9a364SKalle Valo 6547ac9a364SKalle Valo /* get user max rate if set */ 655a3f9d596SJohannes Berg max_rate_idx = fls(txrc->rate_idx_mask) - 1; 65657fbcce3SJohannes Berg if (sband->band == NL80211_BAND_5GHZ && max_rate_idx != -1) 6577ac9a364SKalle Valo max_rate_idx += IL_FIRST_OFDM_RATE; 6587ac9a364SKalle Valo if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT) 6597ac9a364SKalle Valo max_rate_idx = -1; 6607ac9a364SKalle Valo 6617ac9a364SKalle Valo idx = min(rs_sta->last_txrate_idx & 0xffff, RATE_COUNT_3945 - 1); 6627ac9a364SKalle Valo 66357fbcce3SJohannes Berg if (sband->band == NL80211_BAND_5GHZ) 6647ac9a364SKalle Valo rate_mask = rate_mask << IL_FIRST_OFDM_RATE; 6657ac9a364SKalle Valo 6667ac9a364SKalle Valo spin_lock_irqsave(&rs_sta->lock, flags); 6677ac9a364SKalle Valo 6687ac9a364SKalle Valo /* for recent assoc, choose best rate regarding 6697ac9a364SKalle Valo * to rssi value 6707ac9a364SKalle Valo */ 6717ac9a364SKalle Valo if (rs_sta->start_rate != RATE_INVALID) { 6727ac9a364SKalle Valo if (rs_sta->start_rate < idx && 6737ac9a364SKalle Valo (rate_mask & (1 << rs_sta->start_rate))) 6747ac9a364SKalle Valo idx = rs_sta->start_rate; 6757ac9a364SKalle Valo rs_sta->start_rate = RATE_INVALID; 6767ac9a364SKalle Valo } 6777ac9a364SKalle Valo 6787ac9a364SKalle Valo /* force user max rate if set by user */ 6797ac9a364SKalle Valo if (max_rate_idx != -1 && max_rate_idx < idx) { 6807ac9a364SKalle Valo if (rate_mask & (1 << max_rate_idx)) 6817ac9a364SKalle Valo idx = max_rate_idx; 6827ac9a364SKalle Valo } 6837ac9a364SKalle Valo 6847ac9a364SKalle Valo win = &(rs_sta->win[idx]); 6857ac9a364SKalle Valo 6867ac9a364SKalle Valo fail_count = win->counter - win->success_counter; 6877ac9a364SKalle Valo 6887ac9a364SKalle Valo if (fail_count < RATE_MIN_FAILURE_TH && 6897ac9a364SKalle Valo win->success_counter < RATE_MIN_SUCCESS_TH) { 6907ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 6917ac9a364SKalle Valo 6927ac9a364SKalle Valo D_RATE("Invalid average_tpt on rate %d: " 6937ac9a364SKalle Valo "counter: %d, success_counter: %d, " 6947ac9a364SKalle Valo "expected_tpt is %sNULL\n", idx, win->counter, 6957ac9a364SKalle Valo win->success_counter, 6967ac9a364SKalle Valo rs_sta->expected_tpt ? "not " : ""); 6977ac9a364SKalle Valo 6987ac9a364SKalle Valo /* Can't calculate this yet; not enough history */ 6997ac9a364SKalle Valo win->average_tpt = IL_INVALID_VALUE; 7007ac9a364SKalle Valo goto out; 7017ac9a364SKalle Valo 7027ac9a364SKalle Valo } 7037ac9a364SKalle Valo 7047ac9a364SKalle Valo current_tpt = win->average_tpt; 7057ac9a364SKalle Valo 7067ac9a364SKalle Valo high_low = 7077ac9a364SKalle Valo il3945_get_adjacent_rate(rs_sta, idx, rate_mask, sband->band); 7087ac9a364SKalle Valo low = high_low & 0xff; 7097ac9a364SKalle Valo high = (high_low >> 8) & 0xff; 7107ac9a364SKalle Valo 7117ac9a364SKalle Valo /* If user set max rate, dont allow higher than user constrain */ 7127ac9a364SKalle Valo if (max_rate_idx != -1 && max_rate_idx < high) 7137ac9a364SKalle Valo high = RATE_INVALID; 7147ac9a364SKalle Valo 7157ac9a364SKalle Valo /* Collect Measured throughputs of adjacent rates */ 7167ac9a364SKalle Valo if (low != RATE_INVALID) 7177ac9a364SKalle Valo low_tpt = rs_sta->win[low].average_tpt; 7187ac9a364SKalle Valo 7197ac9a364SKalle Valo if (high != RATE_INVALID) 7207ac9a364SKalle Valo high_tpt = rs_sta->win[high].average_tpt; 7217ac9a364SKalle Valo 7227ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 7237ac9a364SKalle Valo 7247ac9a364SKalle Valo scale_action = 0; 7257ac9a364SKalle Valo 7267ac9a364SKalle Valo /* Low success ratio , need to drop the rate */ 7277ac9a364SKalle Valo if (win->success_ratio < RATE_DECREASE_TH || !current_tpt) { 7287ac9a364SKalle Valo D_RATE("decrease rate because of low success_ratio\n"); 7297ac9a364SKalle Valo scale_action = -1; 7307ac9a364SKalle Valo /* No throughput measured yet for adjacent rates, 7317ac9a364SKalle Valo * try increase */ 7327ac9a364SKalle Valo } else if (low_tpt == IL_INVALID_VALUE && high_tpt == IL_INVALID_VALUE) { 7337ac9a364SKalle Valo 7347ac9a364SKalle Valo if (high != RATE_INVALID && 7357ac9a364SKalle Valo win->success_ratio >= RATE_INCREASE_TH) 7367ac9a364SKalle Valo scale_action = 1; 7377ac9a364SKalle Valo else if (low != RATE_INVALID) 7387ac9a364SKalle Valo scale_action = 0; 7397ac9a364SKalle Valo 7407ac9a364SKalle Valo /* Both adjacent throughputs are measured, but neither one has 7417ac9a364SKalle Valo * better throughput; we're using the best rate, don't change 7427ac9a364SKalle Valo * it! */ 7437ac9a364SKalle Valo } else if (low_tpt != IL_INVALID_VALUE && high_tpt != IL_INVALID_VALUE 7447ac9a364SKalle Valo && low_tpt < current_tpt && high_tpt < current_tpt) { 7457ac9a364SKalle Valo 7467ac9a364SKalle Valo D_RATE("No action -- low [%d] & high [%d] < " 7477ac9a364SKalle Valo "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt); 7487ac9a364SKalle Valo scale_action = 0; 7497ac9a364SKalle Valo 7507ac9a364SKalle Valo /* At least one of the rates has better throughput */ 7517ac9a364SKalle Valo } else { 7527ac9a364SKalle Valo if (high_tpt != IL_INVALID_VALUE) { 7537ac9a364SKalle Valo 7547ac9a364SKalle Valo /* High rate has better throughput, Increase 7557ac9a364SKalle Valo * rate */ 7567ac9a364SKalle Valo if (high_tpt > current_tpt && 7577ac9a364SKalle Valo win->success_ratio >= RATE_INCREASE_TH) 7587ac9a364SKalle Valo scale_action = 1; 7597ac9a364SKalle Valo else { 7607ac9a364SKalle Valo D_RATE("decrease rate because of high tpt\n"); 7617ac9a364SKalle Valo scale_action = 0; 7627ac9a364SKalle Valo } 7637ac9a364SKalle Valo } else if (low_tpt != IL_INVALID_VALUE) { 7647ac9a364SKalle Valo if (low_tpt > current_tpt) { 7657ac9a364SKalle Valo D_RATE("decrease rate because of low tpt\n"); 7667ac9a364SKalle Valo scale_action = -1; 7677ac9a364SKalle Valo } else if (win->success_ratio >= RATE_INCREASE_TH) { 7687ac9a364SKalle Valo /* Lower rate has better 7697ac9a364SKalle Valo * throughput,decrease rate */ 7707ac9a364SKalle Valo scale_action = 1; 7717ac9a364SKalle Valo } 7727ac9a364SKalle Valo } 7737ac9a364SKalle Valo } 7747ac9a364SKalle Valo 7757ac9a364SKalle Valo /* Sanity check; asked for decrease, but success rate or throughput 7767ac9a364SKalle Valo * has been good at old rate. Don't change it. */ 7777ac9a364SKalle Valo if (scale_action == -1 && low != RATE_INVALID && 7787ac9a364SKalle Valo (win->success_ratio > RATE_HIGH_TH || 7797ac9a364SKalle Valo current_tpt > 100 * rs_sta->expected_tpt[low])) 7807ac9a364SKalle Valo scale_action = 0; 7817ac9a364SKalle Valo 7827ac9a364SKalle Valo switch (scale_action) { 7837ac9a364SKalle Valo case -1: 784*ac9ccb8bSYangtao Li /* Decrease rate */ 7857ac9a364SKalle Valo if (low != RATE_INVALID) 7867ac9a364SKalle Valo idx = low; 7877ac9a364SKalle Valo break; 7887ac9a364SKalle Valo case 1: 7897ac9a364SKalle Valo /* Increase rate */ 7907ac9a364SKalle Valo if (high != RATE_INVALID) 7917ac9a364SKalle Valo idx = high; 7927ac9a364SKalle Valo 7937ac9a364SKalle Valo break; 7947ac9a364SKalle Valo case 0: 7957ac9a364SKalle Valo default: 7967ac9a364SKalle Valo /* No change */ 7977ac9a364SKalle Valo break; 7987ac9a364SKalle Valo } 7997ac9a364SKalle Valo 8007ac9a364SKalle Valo D_RATE("Selected %d (action %d) - low %d high %d\n", idx, scale_action, 8017ac9a364SKalle Valo low, high); 8027ac9a364SKalle Valo 8037ac9a364SKalle Valo out: 8047ac9a364SKalle Valo 80557fbcce3SJohannes Berg if (sband->band == NL80211_BAND_5GHZ) { 8067ac9a364SKalle Valo if (WARN_ON_ONCE(idx < IL_FIRST_OFDM_RATE)) 8077ac9a364SKalle Valo idx = IL_FIRST_OFDM_RATE; 8087ac9a364SKalle Valo rs_sta->last_txrate_idx = idx; 8097ac9a364SKalle Valo info->control.rates[0].idx = idx - IL_FIRST_OFDM_RATE; 8107ac9a364SKalle Valo } else { 8117ac9a364SKalle Valo rs_sta->last_txrate_idx = idx; 8127ac9a364SKalle Valo info->control.rates[0].idx = rs_sta->last_txrate_idx; 8137ac9a364SKalle Valo } 8147ac9a364SKalle Valo info->control.rates[0].count = 1; 8157ac9a364SKalle Valo 8167ac9a364SKalle Valo D_RATE("leave: %d\n", idx); 8177ac9a364SKalle Valo } 8187ac9a364SKalle Valo 8197ac9a364SKalle Valo #ifdef CONFIG_MAC80211_DEBUGFS 8207ac9a364SKalle Valo 8217ac9a364SKalle Valo static ssize_t 8227ac9a364SKalle Valo il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf, 8237ac9a364SKalle Valo size_t count, loff_t *ppos) 8247ac9a364SKalle Valo { 8257ac9a364SKalle Valo char *buff; 8267ac9a364SKalle Valo int desc = 0; 8277ac9a364SKalle Valo int j; 8287ac9a364SKalle Valo ssize_t ret; 8297ac9a364SKalle Valo struct il3945_rs_sta *lq_sta = file->private_data; 8307ac9a364SKalle Valo 8317ac9a364SKalle Valo buff = kmalloc(1024, GFP_KERNEL); 8327ac9a364SKalle Valo if (!buff) 8337ac9a364SKalle Valo return -ENOMEM; 8347ac9a364SKalle Valo 8357ac9a364SKalle Valo desc += 8367ac9a364SKalle Valo sprintf(buff + desc, 8377ac9a364SKalle Valo "tx packets=%d last rate idx=%d\n" 8387ac9a364SKalle Valo "rate=0x%X flush time %d\n", lq_sta->tx_packets, 8397ac9a364SKalle Valo lq_sta->last_txrate_idx, lq_sta->start_rate, 8407ac9a364SKalle Valo jiffies_to_msecs(lq_sta->flush_time)); 8417ac9a364SKalle Valo for (j = 0; j < RATE_COUNT_3945; j++) { 8427ac9a364SKalle Valo desc += 8437ac9a364SKalle Valo sprintf(buff + desc, "counter=%d success=%d %%=%d\n", 8447ac9a364SKalle Valo lq_sta->win[j].counter, 8457ac9a364SKalle Valo lq_sta->win[j].success_counter, 8467ac9a364SKalle Valo lq_sta->win[j].success_ratio); 8477ac9a364SKalle Valo } 8487ac9a364SKalle Valo ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); 8497ac9a364SKalle Valo kfree(buff); 8507ac9a364SKalle Valo return ret; 8517ac9a364SKalle Valo } 8527ac9a364SKalle Valo 8537ac9a364SKalle Valo static const struct file_operations rs_sta_dbgfs_stats_table_ops = { 8547ac9a364SKalle Valo .read = il3945_sta_dbgfs_stats_table_read, 8557ac9a364SKalle Valo .open = simple_open, 8567ac9a364SKalle Valo .llseek = default_llseek, 8577ac9a364SKalle Valo }; 8587ac9a364SKalle Valo 8597ac9a364SKalle Valo static void 8607ac9a364SKalle Valo il3945_add_debugfs(void *il, void *il_sta, struct dentry *dir) 8617ac9a364SKalle Valo { 8627ac9a364SKalle Valo struct il3945_rs_sta *lq_sta = il_sta; 8637ac9a364SKalle Valo 8647ac9a364SKalle Valo lq_sta->rs_sta_dbgfs_stats_table_file = 8657ac9a364SKalle Valo debugfs_create_file("rate_stats_table", 0600, dir, lq_sta, 8667ac9a364SKalle Valo &rs_sta_dbgfs_stats_table_ops); 8677ac9a364SKalle Valo 8687ac9a364SKalle Valo } 8697ac9a364SKalle Valo 8707ac9a364SKalle Valo static void 8717ac9a364SKalle Valo il3945_remove_debugfs(void *il, void *il_sta) 8727ac9a364SKalle Valo { 8737ac9a364SKalle Valo struct il3945_rs_sta *lq_sta = il_sta; 8747ac9a364SKalle Valo debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); 8757ac9a364SKalle Valo } 8767ac9a364SKalle Valo #endif 8777ac9a364SKalle Valo 8787ac9a364SKalle Valo /* 8797ac9a364SKalle Valo * Initialization of rate scaling information is done by driver after 8807ac9a364SKalle Valo * the station is added. Since mac80211 calls this function before a 8817ac9a364SKalle Valo * station is added we ignore it. 8827ac9a364SKalle Valo */ 8837ac9a364SKalle Valo static void 8847ac9a364SKalle Valo il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband, 8857ac9a364SKalle Valo struct cfg80211_chan_def *chandef, 8867ac9a364SKalle Valo struct ieee80211_sta *sta, void *il_sta) 8877ac9a364SKalle Valo { 8887ac9a364SKalle Valo } 8897ac9a364SKalle Valo 8907ac9a364SKalle Valo static const struct rate_control_ops rs_ops = { 8917ac9a364SKalle Valo .name = RS_NAME, 8927ac9a364SKalle Valo .tx_status = il3945_rs_tx_status, 8937ac9a364SKalle Valo .get_rate = il3945_rs_get_rate, 8947ac9a364SKalle Valo .rate_init = il3945_rs_rate_init_stub, 8957ac9a364SKalle Valo .alloc = il3945_rs_alloc, 8967ac9a364SKalle Valo .free = il3945_rs_free, 8977ac9a364SKalle Valo .alloc_sta = il3945_rs_alloc_sta, 8987ac9a364SKalle Valo .free_sta = il3945_rs_free_sta, 8997ac9a364SKalle Valo #ifdef CONFIG_MAC80211_DEBUGFS 9007ac9a364SKalle Valo .add_sta_debugfs = il3945_add_debugfs, 9017ac9a364SKalle Valo .remove_sta_debugfs = il3945_remove_debugfs, 9027ac9a364SKalle Valo #endif 9037ac9a364SKalle Valo 9047ac9a364SKalle Valo }; 9057ac9a364SKalle Valo 9067ac9a364SKalle Valo void 9077ac9a364SKalle Valo il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) 9087ac9a364SKalle Valo { 9097ac9a364SKalle Valo struct il_priv *il = hw->priv; 9107ac9a364SKalle Valo s32 rssi = 0; 9117ac9a364SKalle Valo unsigned long flags; 9127ac9a364SKalle Valo struct il3945_rs_sta *rs_sta; 9137ac9a364SKalle Valo struct ieee80211_sta *sta; 9147ac9a364SKalle Valo struct il3945_sta_priv *psta; 9157ac9a364SKalle Valo 9167ac9a364SKalle Valo D_RATE("enter\n"); 9177ac9a364SKalle Valo 9187ac9a364SKalle Valo rcu_read_lock(); 9197ac9a364SKalle Valo 9207ac9a364SKalle Valo sta = ieee80211_find_sta(il->vif, il->stations[sta_id].sta.sta.addr); 9217ac9a364SKalle Valo if (!sta) { 9227ac9a364SKalle Valo D_RATE("Unable to find station to initialize rate scaling.\n"); 9237ac9a364SKalle Valo rcu_read_unlock(); 9247ac9a364SKalle Valo return; 9257ac9a364SKalle Valo } 9267ac9a364SKalle Valo 9277ac9a364SKalle Valo psta = (void *)sta->drv_priv; 9287ac9a364SKalle Valo rs_sta = &psta->rs_sta; 9297ac9a364SKalle Valo 9307ac9a364SKalle Valo spin_lock_irqsave(&rs_sta->lock, flags); 9317ac9a364SKalle Valo 9327ac9a364SKalle Valo rs_sta->tgg = 0; 9337ac9a364SKalle Valo switch (il->band) { 93457fbcce3SJohannes Berg case NL80211_BAND_2GHZ: 9357ac9a364SKalle Valo /* TODO: this always does G, not a regression */ 9367ac9a364SKalle Valo if (il->active.flags & RXON_FLG_TGG_PROTECT_MSK) { 9377ac9a364SKalle Valo rs_sta->tgg = 1; 9387ac9a364SKalle Valo rs_sta->expected_tpt = il3945_expected_tpt_g_prot; 9397ac9a364SKalle Valo } else 9407ac9a364SKalle Valo rs_sta->expected_tpt = il3945_expected_tpt_g; 9417ac9a364SKalle Valo break; 94257fbcce3SJohannes Berg case NL80211_BAND_5GHZ: 9437ac9a364SKalle Valo rs_sta->expected_tpt = il3945_expected_tpt_a; 9447ac9a364SKalle Valo break; 9457ac9a364SKalle Valo default: 9467ac9a364SKalle Valo BUG(); 9477ac9a364SKalle Valo break; 9487ac9a364SKalle Valo } 9497ac9a364SKalle Valo 9507ac9a364SKalle Valo spin_unlock_irqrestore(&rs_sta->lock, flags); 9517ac9a364SKalle Valo 9527ac9a364SKalle Valo rssi = il->_3945.last_rx_rssi; 9537ac9a364SKalle Valo if (rssi == 0) 9547ac9a364SKalle Valo rssi = IL_MIN_RSSI_VAL; 9557ac9a364SKalle Valo 9567ac9a364SKalle Valo D_RATE("Network RSSI: %d\n", rssi); 9577ac9a364SKalle Valo 9587ac9a364SKalle Valo rs_sta->start_rate = il3945_get_rate_idx_by_rssi(rssi, il->band); 9597ac9a364SKalle Valo 9607ac9a364SKalle Valo D_RATE("leave: rssi %d assign rate idx: " "%d (plcp 0x%x)\n", rssi, 9617ac9a364SKalle Valo rs_sta->start_rate, il3945_rates[rs_sta->start_rate].plcp); 9627ac9a364SKalle Valo rcu_read_unlock(); 9637ac9a364SKalle Valo } 9647ac9a364SKalle Valo 9657ac9a364SKalle Valo int 9667ac9a364SKalle Valo il3945_rate_control_register(void) 9677ac9a364SKalle Valo { 9687ac9a364SKalle Valo return ieee80211_rate_control_register(&rs_ops); 9697ac9a364SKalle Valo } 9707ac9a364SKalle Valo 9717ac9a364SKalle Valo void 9727ac9a364SKalle Valo il3945_rate_control_unregister(void) 9737ac9a364SKalle Valo { 9747ac9a364SKalle Valo ieee80211_rate_control_unregister(&rs_ops); 9757ac9a364SKalle Valo } 976