xref: /linux/drivers/net/wireless/intel/iwlegacy/3945-rs.c (revision ac9ccb8b991cfca7f5847734089115f992bef7ff)
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