xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/intel/iwlegacy/3945-rs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /******************************************************************************
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Contact Information:
7*4882a593Smuzhiyun  *  Intel Linux Wireless <ilw@linux.intel.com>
8*4882a593Smuzhiyun  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *****************************************************************************/
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/skbuff.h>
14*4882a593Smuzhiyun #include <linux/slab.h>
15*4882a593Smuzhiyun #include <net/mac80211.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/netdevice.h>
18*4882a593Smuzhiyun #include <linux/etherdevice.h>
19*4882a593Smuzhiyun #include <linux/delay.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #include <linux/workqueue.h>
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #include "commands.h"
24*4882a593Smuzhiyun #include "3945.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define RS_NAME "iwl-3945-rs"
27*4882a593Smuzhiyun 
28*4882a593Smuzhiyun static s32 il3945_expected_tpt_g[RATE_COUNT_3945] = {
29*4882a593Smuzhiyun 	7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
30*4882a593Smuzhiyun };
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun static s32 il3945_expected_tpt_g_prot[RATE_COUNT_3945] = {
33*4882a593Smuzhiyun 	7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
34*4882a593Smuzhiyun };
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun static s32 il3945_expected_tpt_a[RATE_COUNT_3945] = {
37*4882a593Smuzhiyun 	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
38*4882a593Smuzhiyun };
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun static s32 il3945_expected_tpt_b[RATE_COUNT_3945] = {
41*4882a593Smuzhiyun 	7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun struct il3945_tpt_entry {
45*4882a593Smuzhiyun 	s8 min_rssi;
46*4882a593Smuzhiyun 	u8 idx;
47*4882a593Smuzhiyun };
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun static struct il3945_tpt_entry il3945_tpt_table_a[] = {
50*4882a593Smuzhiyun 	{-60, RATE_54M_IDX},
51*4882a593Smuzhiyun 	{-64, RATE_48M_IDX},
52*4882a593Smuzhiyun 	{-72, RATE_36M_IDX},
53*4882a593Smuzhiyun 	{-80, RATE_24M_IDX},
54*4882a593Smuzhiyun 	{-84, RATE_18M_IDX},
55*4882a593Smuzhiyun 	{-85, RATE_12M_IDX},
56*4882a593Smuzhiyun 	{-87, RATE_9M_IDX},
57*4882a593Smuzhiyun 	{-89, RATE_6M_IDX}
58*4882a593Smuzhiyun };
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static struct il3945_tpt_entry il3945_tpt_table_g[] = {
61*4882a593Smuzhiyun 	{-60, RATE_54M_IDX},
62*4882a593Smuzhiyun 	{-64, RATE_48M_IDX},
63*4882a593Smuzhiyun 	{-68, RATE_36M_IDX},
64*4882a593Smuzhiyun 	{-80, RATE_24M_IDX},
65*4882a593Smuzhiyun 	{-84, RATE_18M_IDX},
66*4882a593Smuzhiyun 	{-85, RATE_12M_IDX},
67*4882a593Smuzhiyun 	{-86, RATE_11M_IDX},
68*4882a593Smuzhiyun 	{-88, RATE_5M_IDX},
69*4882a593Smuzhiyun 	{-90, RATE_2M_IDX},
70*4882a593Smuzhiyun 	{-92, RATE_1M_IDX}
71*4882a593Smuzhiyun };
72*4882a593Smuzhiyun 
73*4882a593Smuzhiyun #define RATE_MAX_WINDOW		62
74*4882a593Smuzhiyun #define RATE_FLUSH		(3*HZ)
75*4882a593Smuzhiyun #define RATE_WIN_FLUSH		(HZ/2)
76*4882a593Smuzhiyun #define IL39_RATE_HIGH_TH	11520
77*4882a593Smuzhiyun #define IL_SUCCESS_UP_TH	8960
78*4882a593Smuzhiyun #define IL_SUCCESS_DOWN_TH	10880
79*4882a593Smuzhiyun #define RATE_MIN_FAILURE_TH	6
80*4882a593Smuzhiyun #define RATE_MIN_SUCCESS_TH	8
81*4882a593Smuzhiyun #define RATE_DECREASE_TH	1920
82*4882a593Smuzhiyun #define RATE_RETRY_TH		15
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun static u8
il3945_get_rate_idx_by_rssi(s32 rssi,enum nl80211_band band)85*4882a593Smuzhiyun il3945_get_rate_idx_by_rssi(s32 rssi, enum nl80211_band band)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun 	u32 idx = 0;
88*4882a593Smuzhiyun 	u32 table_size = 0;
89*4882a593Smuzhiyun 	struct il3945_tpt_entry *tpt_table = NULL;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	if (rssi < IL_MIN_RSSI_VAL || rssi > IL_MAX_RSSI_VAL)
92*4882a593Smuzhiyun 		rssi = IL_MIN_RSSI_VAL;
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun 	switch (band) {
95*4882a593Smuzhiyun 	case NL80211_BAND_2GHZ:
96*4882a593Smuzhiyun 		tpt_table = il3945_tpt_table_g;
97*4882a593Smuzhiyun 		table_size = ARRAY_SIZE(il3945_tpt_table_g);
98*4882a593Smuzhiyun 		break;
99*4882a593Smuzhiyun 	case NL80211_BAND_5GHZ:
100*4882a593Smuzhiyun 		tpt_table = il3945_tpt_table_a;
101*4882a593Smuzhiyun 		table_size = ARRAY_SIZE(il3945_tpt_table_a);
102*4882a593Smuzhiyun 		break;
103*4882a593Smuzhiyun 	default:
104*4882a593Smuzhiyun 		BUG();
105*4882a593Smuzhiyun 		break;
106*4882a593Smuzhiyun 	}
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	while (idx < table_size && rssi < tpt_table[idx].min_rssi)
109*4882a593Smuzhiyun 		idx++;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	idx = min(idx, table_size - 1);
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	return tpt_table[idx].idx;
114*4882a593Smuzhiyun }
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun static void
il3945_clear_win(struct il3945_rate_scale_data * win)117*4882a593Smuzhiyun il3945_clear_win(struct il3945_rate_scale_data *win)
118*4882a593Smuzhiyun {
119*4882a593Smuzhiyun 	win->data = 0;
120*4882a593Smuzhiyun 	win->success_counter = 0;
121*4882a593Smuzhiyun 	win->success_ratio = -1;
122*4882a593Smuzhiyun 	win->counter = 0;
123*4882a593Smuzhiyun 	win->average_tpt = IL_INVALID_VALUE;
124*4882a593Smuzhiyun 	win->stamp = 0;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun 
127*4882a593Smuzhiyun /*
128*4882a593Smuzhiyun  * il3945_rate_scale_flush_wins - flush out the rate scale wins
129*4882a593Smuzhiyun  *
130*4882a593Smuzhiyun  * Returns the number of wins that have gathered data but were
131*4882a593Smuzhiyun  * not flushed.  If there were any that were not flushed, then
132*4882a593Smuzhiyun  * reschedule the rate flushing routine.
133*4882a593Smuzhiyun  */
134*4882a593Smuzhiyun static int
il3945_rate_scale_flush_wins(struct il3945_rs_sta * rs_sta)135*4882a593Smuzhiyun il3945_rate_scale_flush_wins(struct il3945_rs_sta *rs_sta)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	int unflushed = 0;
138*4882a593Smuzhiyun 	int i;
139*4882a593Smuzhiyun 	unsigned long flags;
140*4882a593Smuzhiyun 	struct il_priv *il __maybe_unused = rs_sta->il;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	/*
143*4882a593Smuzhiyun 	 * For each rate, if we have collected data on that rate
144*4882a593Smuzhiyun 	 * and it has been more than RATE_WIN_FLUSH
145*4882a593Smuzhiyun 	 * since we flushed, clear out the gathered stats
146*4882a593Smuzhiyun 	 */
147*4882a593Smuzhiyun 	for (i = 0; i < RATE_COUNT_3945; i++) {
148*4882a593Smuzhiyun 		if (!rs_sta->win[i].counter)
149*4882a593Smuzhiyun 			continue;
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun 		spin_lock_irqsave(&rs_sta->lock, flags);
152*4882a593Smuzhiyun 		if (time_after(jiffies, rs_sta->win[i].stamp + RATE_WIN_FLUSH)) {
153*4882a593Smuzhiyun 			D_RATE("flushing %d samples of rate " "idx %d\n",
154*4882a593Smuzhiyun 			       rs_sta->win[i].counter, i);
155*4882a593Smuzhiyun 			il3945_clear_win(&rs_sta->win[i]);
156*4882a593Smuzhiyun 		} else
157*4882a593Smuzhiyun 			unflushed++;
158*4882a593Smuzhiyun 		spin_unlock_irqrestore(&rs_sta->lock, flags);
159*4882a593Smuzhiyun 	}
160*4882a593Smuzhiyun 
161*4882a593Smuzhiyun 	return unflushed;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun #define RATE_FLUSH_MAX              5000	/* msec */
165*4882a593Smuzhiyun #define RATE_FLUSH_MIN              50	/* msec */
166*4882a593Smuzhiyun #define IL_AVERAGE_PACKETS             1500
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun static void
il3945_bg_rate_scale_flush(struct timer_list * t)169*4882a593Smuzhiyun il3945_bg_rate_scale_flush(struct timer_list *t)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta = from_timer(rs_sta, t, rate_scale_flush);
172*4882a593Smuzhiyun 	struct il_priv *il __maybe_unused = rs_sta->il;
173*4882a593Smuzhiyun 	int unflushed = 0;
174*4882a593Smuzhiyun 	unsigned long flags;
175*4882a593Smuzhiyun 	u32 packet_count, duration, pps;
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	D_RATE("enter\n");
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	unflushed = il3945_rate_scale_flush_wins(rs_sta);
180*4882a593Smuzhiyun 
181*4882a593Smuzhiyun 	spin_lock_irqsave(&rs_sta->lock, flags);
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	/* Number of packets Rx'd since last time this timer ran */
184*4882a593Smuzhiyun 	packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	if (unflushed) {
189*4882a593Smuzhiyun 		duration =
190*4882a593Smuzhiyun 		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 		D_RATE("Tx'd %d packets in %dms\n", packet_count, duration);
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 		/* Determine packets per second */
195*4882a593Smuzhiyun 		if (duration)
196*4882a593Smuzhiyun 			pps = (packet_count * 1000) / duration;
197*4882a593Smuzhiyun 		else
198*4882a593Smuzhiyun 			pps = 0;
199*4882a593Smuzhiyun 
200*4882a593Smuzhiyun 		if (pps) {
201*4882a593Smuzhiyun 			duration = (IL_AVERAGE_PACKETS * 1000) / pps;
202*4882a593Smuzhiyun 			if (duration < RATE_FLUSH_MIN)
203*4882a593Smuzhiyun 				duration = RATE_FLUSH_MIN;
204*4882a593Smuzhiyun 			else if (duration > RATE_FLUSH_MAX)
205*4882a593Smuzhiyun 				duration = RATE_FLUSH_MAX;
206*4882a593Smuzhiyun 		} else
207*4882a593Smuzhiyun 			duration = RATE_FLUSH_MAX;
208*4882a593Smuzhiyun 
209*4882a593Smuzhiyun 		rs_sta->flush_time = msecs_to_jiffies(duration);
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun 		D_RATE("new flush period: %d msec ave %d\n", duration,
212*4882a593Smuzhiyun 		       packet_count);
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 		mod_timer(&rs_sta->rate_scale_flush,
215*4882a593Smuzhiyun 			  jiffies + rs_sta->flush_time);
216*4882a593Smuzhiyun 
217*4882a593Smuzhiyun 		rs_sta->last_partial_flush = jiffies;
218*4882a593Smuzhiyun 	} else {
219*4882a593Smuzhiyun 		rs_sta->flush_time = RATE_FLUSH;
220*4882a593Smuzhiyun 		rs_sta->flush_pending = 0;
221*4882a593Smuzhiyun 	}
222*4882a593Smuzhiyun 	/* If there weren't any unflushed entries, we don't schedule the timer
223*4882a593Smuzhiyun 	 * to run again */
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	rs_sta->last_flush = jiffies;
226*4882a593Smuzhiyun 
227*4882a593Smuzhiyun 	spin_unlock_irqrestore(&rs_sta->lock, flags);
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	D_RATE("leave\n");
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun 
232*4882a593Smuzhiyun /*
233*4882a593Smuzhiyun  * il3945_collect_tx_data - Update the success/failure sliding win
234*4882a593Smuzhiyun  *
235*4882a593Smuzhiyun  * We keep a sliding win of the last 64 packets transmitted
236*4882a593Smuzhiyun  * at this rate.  win->data contains the bitmask of successful
237*4882a593Smuzhiyun  * packets.
238*4882a593Smuzhiyun  */
239*4882a593Smuzhiyun static void
il3945_collect_tx_data(struct il3945_rs_sta * rs_sta,struct il3945_rate_scale_data * win,int success,int retries,int idx)240*4882a593Smuzhiyun il3945_collect_tx_data(struct il3945_rs_sta *rs_sta,
241*4882a593Smuzhiyun 		       struct il3945_rate_scale_data *win, int success,
242*4882a593Smuzhiyun 		       int retries, int idx)
243*4882a593Smuzhiyun {
244*4882a593Smuzhiyun 	unsigned long flags;
245*4882a593Smuzhiyun 	s32 fail_count;
246*4882a593Smuzhiyun 	struct il_priv *il __maybe_unused = rs_sta->il;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	if (!retries) {
249*4882a593Smuzhiyun 		D_RATE("leave: retries == 0 -- should be at least 1\n");
250*4882a593Smuzhiyun 		return;
251*4882a593Smuzhiyun 	}
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	spin_lock_irqsave(&rs_sta->lock, flags);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	/*
256*4882a593Smuzhiyun 	 * Keep track of only the latest 62 tx frame attempts in this rate's
257*4882a593Smuzhiyun 	 * history win; anything older isn't really relevant any more.
258*4882a593Smuzhiyun 	 * If we have filled up the sliding win, drop the oldest attempt;
259*4882a593Smuzhiyun 	 * if the oldest attempt (highest bit in bitmap) shows "success",
260*4882a593Smuzhiyun 	 * subtract "1" from the success counter (this is the main reason
261*4882a593Smuzhiyun 	 * we keep these bitmaps!).
262*4882a593Smuzhiyun 	 * */
263*4882a593Smuzhiyun 	while (retries > 0) {
264*4882a593Smuzhiyun 		if (win->counter >= RATE_MAX_WINDOW) {
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 			/* remove earliest */
267*4882a593Smuzhiyun 			win->counter = RATE_MAX_WINDOW - 1;
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 			if (win->data & (1ULL << (RATE_MAX_WINDOW - 1))) {
270*4882a593Smuzhiyun 				win->data &= ~(1ULL << (RATE_MAX_WINDOW - 1));
271*4882a593Smuzhiyun 				win->success_counter--;
272*4882a593Smuzhiyun 			}
273*4882a593Smuzhiyun 		}
274*4882a593Smuzhiyun 
275*4882a593Smuzhiyun 		/* Increment frames-attempted counter */
276*4882a593Smuzhiyun 		win->counter++;
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 		/* Shift bitmap by one frame (throw away oldest history),
279*4882a593Smuzhiyun 		 * OR in "1", and increment "success" if this
280*4882a593Smuzhiyun 		 * frame was successful. */
281*4882a593Smuzhiyun 		win->data <<= 1;
282*4882a593Smuzhiyun 		if (success > 0) {
283*4882a593Smuzhiyun 			win->success_counter++;
284*4882a593Smuzhiyun 			win->data |= 0x1;
285*4882a593Smuzhiyun 			success--;
286*4882a593Smuzhiyun 		}
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 		retries--;
289*4882a593Smuzhiyun 	}
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun 	/* Calculate current success ratio, avoid divide-by-0! */
292*4882a593Smuzhiyun 	if (win->counter > 0)
293*4882a593Smuzhiyun 		win->success_ratio =
294*4882a593Smuzhiyun 		    128 * (100 * win->success_counter) / win->counter;
295*4882a593Smuzhiyun 	else
296*4882a593Smuzhiyun 		win->success_ratio = IL_INVALID_VALUE;
297*4882a593Smuzhiyun 
298*4882a593Smuzhiyun 	fail_count = win->counter - win->success_counter;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	/* Calculate average throughput, if we have enough history. */
301*4882a593Smuzhiyun 	if (fail_count >= RATE_MIN_FAILURE_TH ||
302*4882a593Smuzhiyun 	    win->success_counter >= RATE_MIN_SUCCESS_TH)
303*4882a593Smuzhiyun 		win->average_tpt =
304*4882a593Smuzhiyun 		    ((win->success_ratio * rs_sta->expected_tpt[idx] +
305*4882a593Smuzhiyun 		      64) / 128);
306*4882a593Smuzhiyun 	else
307*4882a593Smuzhiyun 		win->average_tpt = IL_INVALID_VALUE;
308*4882a593Smuzhiyun 
309*4882a593Smuzhiyun 	/* Tag this win as having been updated */
310*4882a593Smuzhiyun 	win->stamp = jiffies;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun 	spin_unlock_irqrestore(&rs_sta->lock, flags);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun 
315*4882a593Smuzhiyun /*
316*4882a593Smuzhiyun  * Called after adding a new station to initialize rate scaling
317*4882a593Smuzhiyun  */
318*4882a593Smuzhiyun void
il3945_rs_rate_init(struct il_priv * il,struct ieee80211_sta * sta,u8 sta_id)319*4882a593Smuzhiyun il3945_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	struct ieee80211_hw *hw = il->hw;
322*4882a593Smuzhiyun 	struct ieee80211_conf *conf = &il->hw->conf;
323*4882a593Smuzhiyun 	struct il3945_sta_priv *psta;
324*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta;
325*4882a593Smuzhiyun 	struct ieee80211_supported_band *sband;
326*4882a593Smuzhiyun 	int i;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 	D_INFO("enter\n");
329*4882a593Smuzhiyun 	if (sta_id == il->hw_params.bcast_id)
330*4882a593Smuzhiyun 		goto out;
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	psta = (struct il3945_sta_priv *)sta->drv_priv;
333*4882a593Smuzhiyun 	rs_sta = &psta->rs_sta;
334*4882a593Smuzhiyun 	sband = hw->wiphy->bands[conf->chandef.chan->band];
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	rs_sta->il = il;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	rs_sta->start_rate = RATE_INVALID;
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	/* default to just 802.11b */
341*4882a593Smuzhiyun 	rs_sta->expected_tpt = il3945_expected_tpt_b;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	rs_sta->last_partial_flush = jiffies;
344*4882a593Smuzhiyun 	rs_sta->last_flush = jiffies;
345*4882a593Smuzhiyun 	rs_sta->flush_time = RATE_FLUSH;
346*4882a593Smuzhiyun 	rs_sta->last_tx_packets = 0;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun 	for (i = 0; i < RATE_COUNT_3945; i++)
349*4882a593Smuzhiyun 		il3945_clear_win(&rs_sta->win[i]);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	/* TODO: what is a good starting rate for STA? About middle? Maybe not
352*4882a593Smuzhiyun 	 * the lowest or the highest rate.. Could consider using RSSI from
353*4882a593Smuzhiyun 	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
354*4882a593Smuzhiyun 	 * after assoc.. */
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	for (i = sband->n_bitrates - 1; i >= 0; i--) {
357*4882a593Smuzhiyun 		if (sta->supp_rates[sband->band] & (1 << i)) {
358*4882a593Smuzhiyun 			rs_sta->last_txrate_idx = i;
359*4882a593Smuzhiyun 			break;
360*4882a593Smuzhiyun 		}
361*4882a593Smuzhiyun 	}
362*4882a593Smuzhiyun 
363*4882a593Smuzhiyun 	il->_3945.sta_supp_rates = sta->supp_rates[sband->band];
364*4882a593Smuzhiyun 	/* For 5 GHz band it start at IL_FIRST_OFDM_RATE */
365*4882a593Smuzhiyun 	if (sband->band == NL80211_BAND_5GHZ) {
366*4882a593Smuzhiyun 		rs_sta->last_txrate_idx += IL_FIRST_OFDM_RATE;
367*4882a593Smuzhiyun 		il->_3945.sta_supp_rates <<= IL_FIRST_OFDM_RATE;
368*4882a593Smuzhiyun 	}
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun out:
371*4882a593Smuzhiyun 	il->stations[sta_id].used &= ~IL_STA_UCODE_INPROGRESS;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	D_INFO("leave\n");
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun static void *
il3945_rs_alloc(struct ieee80211_hw * hw)377*4882a593Smuzhiyun il3945_rs_alloc(struct ieee80211_hw *hw)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	return hw->priv;
380*4882a593Smuzhiyun }
381*4882a593Smuzhiyun 
382*4882a593Smuzhiyun /* rate scale requires free function to be implemented */
383*4882a593Smuzhiyun static void
il3945_rs_free(void * il)384*4882a593Smuzhiyun il3945_rs_free(void *il)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun }
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun static void *
il3945_rs_alloc_sta(void * il_priv,struct ieee80211_sta * sta,gfp_t gfp)389*4882a593Smuzhiyun il3945_rs_alloc_sta(void *il_priv, struct ieee80211_sta *sta, gfp_t gfp)
390*4882a593Smuzhiyun {
391*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta;
392*4882a593Smuzhiyun 	struct il3945_sta_priv *psta = (void *)sta->drv_priv;
393*4882a593Smuzhiyun 	struct il_priv *il __maybe_unused = il_priv;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun 	D_RATE("enter\n");
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	rs_sta = &psta->rs_sta;
398*4882a593Smuzhiyun 
399*4882a593Smuzhiyun 	spin_lock_init(&rs_sta->lock);
400*4882a593Smuzhiyun 	timer_setup(&rs_sta->rate_scale_flush, il3945_bg_rate_scale_flush, 0);
401*4882a593Smuzhiyun 	D_RATE("leave\n");
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun 	return rs_sta;
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
406*4882a593Smuzhiyun static void
il3945_rs_free_sta(void * il_priv,struct ieee80211_sta * sta,void * il_sta)407*4882a593Smuzhiyun il3945_rs_free_sta(void *il_priv, struct ieee80211_sta *sta, void *il_sta)
408*4882a593Smuzhiyun {
409*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta = il_sta;
410*4882a593Smuzhiyun 
411*4882a593Smuzhiyun 	/*
412*4882a593Smuzhiyun 	 * Be careful not to use any members of il3945_rs_sta (like trying
413*4882a593Smuzhiyun 	 * to use il_priv to print out debugging) since it may not be fully
414*4882a593Smuzhiyun 	 * initialized at this point.
415*4882a593Smuzhiyun 	 */
416*4882a593Smuzhiyun 	del_timer_sync(&rs_sta->rate_scale_flush);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun /*
420*4882a593Smuzhiyun  * il3945_rs_tx_status - Update rate control values based on Tx results
421*4882a593Smuzhiyun  *
422*4882a593Smuzhiyun  * NOTE: Uses il_priv->retry_rate for the # of retries attempted by
423*4882a593Smuzhiyun  * the hardware for each rate.
424*4882a593Smuzhiyun  */
425*4882a593Smuzhiyun static void
il3945_rs_tx_status(void * il_rate,struct ieee80211_supported_band * sband,struct ieee80211_sta * sta,void * il_sta,struct sk_buff * skb)426*4882a593Smuzhiyun il3945_rs_tx_status(void *il_rate, struct ieee80211_supported_band *sband,
427*4882a593Smuzhiyun 		    struct ieee80211_sta *sta, void *il_sta,
428*4882a593Smuzhiyun 		    struct sk_buff *skb)
429*4882a593Smuzhiyun {
430*4882a593Smuzhiyun 	s8 retries = 0, current_count;
431*4882a593Smuzhiyun 	int scale_rate_idx, first_idx, last_idx;
432*4882a593Smuzhiyun 	unsigned long flags;
433*4882a593Smuzhiyun 	struct il_priv *il = (struct il_priv *)il_rate;
434*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta = il_sta;
435*4882a593Smuzhiyun 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
436*4882a593Smuzhiyun 
437*4882a593Smuzhiyun 	D_RATE("enter\n");
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun 	retries = info->status.rates[0].count;
440*4882a593Smuzhiyun 	/* Sanity Check for retries */
441*4882a593Smuzhiyun 	if (retries > RATE_RETRY_TH)
442*4882a593Smuzhiyun 		retries = RATE_RETRY_TH;
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	first_idx = sband->bitrates[info->status.rates[0].idx].hw_value;
445*4882a593Smuzhiyun 	if (first_idx < 0 || first_idx >= RATE_COUNT_3945) {
446*4882a593Smuzhiyun 		D_RATE("leave: Rate out of bounds: %d\n", first_idx);
447*4882a593Smuzhiyun 		return;
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	if (!il_sta) {
451*4882a593Smuzhiyun 		D_RATE("leave: No STA il data to update!\n");
452*4882a593Smuzhiyun 		return;
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	/* Treat uninitialized rate scaling data same as non-existing. */
456*4882a593Smuzhiyun 	if (!rs_sta->il) {
457*4882a593Smuzhiyun 		D_RATE("leave: STA il data uninitialized!\n");
458*4882a593Smuzhiyun 		return;
459*4882a593Smuzhiyun 	}
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	rs_sta->tx_packets++;
462*4882a593Smuzhiyun 
463*4882a593Smuzhiyun 	scale_rate_idx = first_idx;
464*4882a593Smuzhiyun 	last_idx = first_idx;
465*4882a593Smuzhiyun 
466*4882a593Smuzhiyun 	/*
467*4882a593Smuzhiyun 	 * Update the win for each rate.  We determine which rates
468*4882a593Smuzhiyun 	 * were Tx'd based on the total number of retries vs. the number
469*4882a593Smuzhiyun 	 * of retries configured for each rate -- currently set to the
470*4882a593Smuzhiyun 	 * il value 'retry_rate' vs. rate specific
471*4882a593Smuzhiyun 	 *
472*4882a593Smuzhiyun 	 * On exit from this while loop last_idx indicates the rate
473*4882a593Smuzhiyun 	 * at which the frame was finally transmitted (or failed if no
474*4882a593Smuzhiyun 	 * ACK)
475*4882a593Smuzhiyun 	 */
476*4882a593Smuzhiyun 	while (retries > 1) {
477*4882a593Smuzhiyun 		if ((retries - 1) < il->retry_rate) {
478*4882a593Smuzhiyun 			current_count = (retries - 1);
479*4882a593Smuzhiyun 			last_idx = scale_rate_idx;
480*4882a593Smuzhiyun 		} else {
481*4882a593Smuzhiyun 			current_count = il->retry_rate;
482*4882a593Smuzhiyun 			last_idx = il3945_rs_next_rate(il, scale_rate_idx);
483*4882a593Smuzhiyun 		}
484*4882a593Smuzhiyun 
485*4882a593Smuzhiyun 		/* Update this rate accounting for as many retries
486*4882a593Smuzhiyun 		 * as was used for it (per current_count) */
487*4882a593Smuzhiyun 		il3945_collect_tx_data(rs_sta, &rs_sta->win[scale_rate_idx], 0,
488*4882a593Smuzhiyun 				       current_count, scale_rate_idx);
489*4882a593Smuzhiyun 		D_RATE("Update rate %d for %d retries.\n", scale_rate_idx,
490*4882a593Smuzhiyun 		       current_count);
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 		retries -= current_count;
493*4882a593Smuzhiyun 
494*4882a593Smuzhiyun 		scale_rate_idx = last_idx;
495*4882a593Smuzhiyun 	}
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	/* Update the last idx win with success/failure based on ACK */
498*4882a593Smuzhiyun 	D_RATE("Update rate %d with %s.\n", last_idx,
499*4882a593Smuzhiyun 	       (info->flags & IEEE80211_TX_STAT_ACK) ? "success" : "failure");
500*4882a593Smuzhiyun 	il3945_collect_tx_data(rs_sta, &rs_sta->win[last_idx],
501*4882a593Smuzhiyun 			       info->flags & IEEE80211_TX_STAT_ACK, 1,
502*4882a593Smuzhiyun 			       last_idx);
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	/* We updated the rate scale win -- if its been more than
505*4882a593Smuzhiyun 	 * flush_time since the last run, schedule the flush
506*4882a593Smuzhiyun 	 * again */
507*4882a593Smuzhiyun 	spin_lock_irqsave(&rs_sta->lock, flags);
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun 	if (!rs_sta->flush_pending &&
510*4882a593Smuzhiyun 	    time_after(jiffies, rs_sta->last_flush + rs_sta->flush_time)) {
511*4882a593Smuzhiyun 
512*4882a593Smuzhiyun 		rs_sta->last_partial_flush = jiffies;
513*4882a593Smuzhiyun 		rs_sta->flush_pending = 1;
514*4882a593Smuzhiyun 		mod_timer(&rs_sta->rate_scale_flush,
515*4882a593Smuzhiyun 			  jiffies + rs_sta->flush_time);
516*4882a593Smuzhiyun 	}
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	spin_unlock_irqrestore(&rs_sta->lock, flags);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	D_RATE("leave\n");
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun static u16
il3945_get_adjacent_rate(struct il3945_rs_sta * rs_sta,u8 idx,u16 rate_mask,enum nl80211_band band)524*4882a593Smuzhiyun il3945_get_adjacent_rate(struct il3945_rs_sta *rs_sta, u8 idx, u16 rate_mask,
525*4882a593Smuzhiyun 			 enum nl80211_band band)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun 	u8 high = RATE_INVALID;
528*4882a593Smuzhiyun 	u8 low = RATE_INVALID;
529*4882a593Smuzhiyun 	struct il_priv *il __maybe_unused = rs_sta->il;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 	/* 802.11A walks to the next literal adjacent rate in
532*4882a593Smuzhiyun 	 * the rate table */
533*4882a593Smuzhiyun 	if (unlikely(band == NL80211_BAND_5GHZ)) {
534*4882a593Smuzhiyun 		int i;
535*4882a593Smuzhiyun 		u32 mask;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		/* Find the previous rate that is in the rate mask */
538*4882a593Smuzhiyun 		i = idx - 1;
539*4882a593Smuzhiyun 		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
540*4882a593Smuzhiyun 			if (rate_mask & mask) {
541*4882a593Smuzhiyun 				low = i;
542*4882a593Smuzhiyun 				break;
543*4882a593Smuzhiyun 			}
544*4882a593Smuzhiyun 		}
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 		/* Find the next rate that is in the rate mask */
547*4882a593Smuzhiyun 		i = idx + 1;
548*4882a593Smuzhiyun 		for (mask = (1 << i); i < RATE_COUNT_3945; i++, mask <<= 1) {
549*4882a593Smuzhiyun 			if (rate_mask & mask) {
550*4882a593Smuzhiyun 				high = i;
551*4882a593Smuzhiyun 				break;
552*4882a593Smuzhiyun 			}
553*4882a593Smuzhiyun 		}
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 		return (high << 8) | low;
556*4882a593Smuzhiyun 	}
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	low = idx;
559*4882a593Smuzhiyun 	while (low != RATE_INVALID) {
560*4882a593Smuzhiyun 		if (rs_sta->tgg)
561*4882a593Smuzhiyun 			low = il3945_rates[low].prev_rs_tgg;
562*4882a593Smuzhiyun 		else
563*4882a593Smuzhiyun 			low = il3945_rates[low].prev_rs;
564*4882a593Smuzhiyun 		if (low == RATE_INVALID)
565*4882a593Smuzhiyun 			break;
566*4882a593Smuzhiyun 		if (rate_mask & (1 << low))
567*4882a593Smuzhiyun 			break;
568*4882a593Smuzhiyun 		D_RATE("Skipping masked lower rate: %d\n", low);
569*4882a593Smuzhiyun 	}
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun 	high = idx;
572*4882a593Smuzhiyun 	while (high != RATE_INVALID) {
573*4882a593Smuzhiyun 		if (rs_sta->tgg)
574*4882a593Smuzhiyun 			high = il3945_rates[high].next_rs_tgg;
575*4882a593Smuzhiyun 		else
576*4882a593Smuzhiyun 			high = il3945_rates[high].next_rs;
577*4882a593Smuzhiyun 		if (high == RATE_INVALID)
578*4882a593Smuzhiyun 			break;
579*4882a593Smuzhiyun 		if (rate_mask & (1 << high))
580*4882a593Smuzhiyun 			break;
581*4882a593Smuzhiyun 		D_RATE("Skipping masked higher rate: %d\n", high);
582*4882a593Smuzhiyun 	}
583*4882a593Smuzhiyun 
584*4882a593Smuzhiyun 	return (high << 8) | low;
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
587*4882a593Smuzhiyun /*
588*4882a593Smuzhiyun  * il3945_rs_get_rate - find the rate for the requested packet
589*4882a593Smuzhiyun  *
590*4882a593Smuzhiyun  * Returns the ieee80211_rate structure allocated by the driver.
591*4882a593Smuzhiyun  *
592*4882a593Smuzhiyun  * The rate control algorithm has no internal mapping between hw_mode's
593*4882a593Smuzhiyun  * rate ordering and the rate ordering used by the rate control algorithm.
594*4882a593Smuzhiyun  *
595*4882a593Smuzhiyun  * The rate control algorithm uses a single table of rates that goes across
596*4882a593Smuzhiyun  * the entire A/B/G spectrum vs. being limited to just one particular
597*4882a593Smuzhiyun  * hw_mode.
598*4882a593Smuzhiyun  *
599*4882a593Smuzhiyun  * As such, we can't convert the idx obtained below into the hw_mode's
600*4882a593Smuzhiyun  * rate table and must reference the driver allocated rate table
601*4882a593Smuzhiyun  *
602*4882a593Smuzhiyun  */
603*4882a593Smuzhiyun static void
il3945_rs_get_rate(void * il_r,struct ieee80211_sta * sta,void * il_sta,struct ieee80211_tx_rate_control * txrc)604*4882a593Smuzhiyun il3945_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
605*4882a593Smuzhiyun 		   struct ieee80211_tx_rate_control *txrc)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun 	struct ieee80211_supported_band *sband = txrc->sband;
608*4882a593Smuzhiyun 	struct sk_buff *skb = txrc->skb;
609*4882a593Smuzhiyun 	u8 low = RATE_INVALID;
610*4882a593Smuzhiyun 	u8 high = RATE_INVALID;
611*4882a593Smuzhiyun 	u16 high_low;
612*4882a593Smuzhiyun 	int idx;
613*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta = il_sta;
614*4882a593Smuzhiyun 	struct il3945_rate_scale_data *win = NULL;
615*4882a593Smuzhiyun 	int current_tpt = IL_INVALID_VALUE;
616*4882a593Smuzhiyun 	int low_tpt = IL_INVALID_VALUE;
617*4882a593Smuzhiyun 	int high_tpt = IL_INVALID_VALUE;
618*4882a593Smuzhiyun 	u32 fail_count;
619*4882a593Smuzhiyun 	s8 scale_action = 0;
620*4882a593Smuzhiyun 	unsigned long flags;
621*4882a593Smuzhiyun 	u16 rate_mask;
622*4882a593Smuzhiyun 	s8 max_rate_idx = -1;
623*4882a593Smuzhiyun 	struct il_priv *il __maybe_unused = (struct il_priv *)il_r;
624*4882a593Smuzhiyun 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
625*4882a593Smuzhiyun 
626*4882a593Smuzhiyun 	D_RATE("enter\n");
627*4882a593Smuzhiyun 
628*4882a593Smuzhiyun 	/* Treat uninitialized rate scaling data same as non-existing. */
629*4882a593Smuzhiyun 	if (rs_sta && !rs_sta->il) {
630*4882a593Smuzhiyun 		D_RATE("Rate scaling information not initialized yet.\n");
631*4882a593Smuzhiyun 		il_sta = NULL;
632*4882a593Smuzhiyun 	}
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	rate_mask = sta->supp_rates[sband->band];
635*4882a593Smuzhiyun 
636*4882a593Smuzhiyun 	/* get user max rate if set */
637*4882a593Smuzhiyun 	max_rate_idx = fls(txrc->rate_idx_mask) - 1;
638*4882a593Smuzhiyun 	if (sband->band == NL80211_BAND_5GHZ && max_rate_idx != -1)
639*4882a593Smuzhiyun 		max_rate_idx += IL_FIRST_OFDM_RATE;
640*4882a593Smuzhiyun 	if (max_rate_idx < 0 || max_rate_idx >= RATE_COUNT)
641*4882a593Smuzhiyun 		max_rate_idx = -1;
642*4882a593Smuzhiyun 
643*4882a593Smuzhiyun 	idx = min(rs_sta->last_txrate_idx & 0xffff, RATE_COUNT_3945 - 1);
644*4882a593Smuzhiyun 
645*4882a593Smuzhiyun 	if (sband->band == NL80211_BAND_5GHZ)
646*4882a593Smuzhiyun 		rate_mask = rate_mask << IL_FIRST_OFDM_RATE;
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	spin_lock_irqsave(&rs_sta->lock, flags);
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 	/* for recent assoc, choose best rate regarding
651*4882a593Smuzhiyun 	 * to rssi value
652*4882a593Smuzhiyun 	 */
653*4882a593Smuzhiyun 	if (rs_sta->start_rate != RATE_INVALID) {
654*4882a593Smuzhiyun 		if (rs_sta->start_rate < idx &&
655*4882a593Smuzhiyun 		    (rate_mask & (1 << rs_sta->start_rate)))
656*4882a593Smuzhiyun 			idx = rs_sta->start_rate;
657*4882a593Smuzhiyun 		rs_sta->start_rate = RATE_INVALID;
658*4882a593Smuzhiyun 	}
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	/* force user max rate if set by user */
661*4882a593Smuzhiyun 	if (max_rate_idx != -1 && max_rate_idx < idx) {
662*4882a593Smuzhiyun 		if (rate_mask & (1 << max_rate_idx))
663*4882a593Smuzhiyun 			idx = max_rate_idx;
664*4882a593Smuzhiyun 	}
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	win = &(rs_sta->win[idx]);
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	fail_count = win->counter - win->success_counter;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	if (fail_count < RATE_MIN_FAILURE_TH &&
671*4882a593Smuzhiyun 	    win->success_counter < RATE_MIN_SUCCESS_TH) {
672*4882a593Smuzhiyun 		spin_unlock_irqrestore(&rs_sta->lock, flags);
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 		D_RATE("Invalid average_tpt on rate %d: "
675*4882a593Smuzhiyun 		       "counter: %d, success_counter: %d, "
676*4882a593Smuzhiyun 		       "expected_tpt is %sNULL\n", idx, win->counter,
677*4882a593Smuzhiyun 		       win->success_counter,
678*4882a593Smuzhiyun 		       rs_sta->expected_tpt ? "not " : "");
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 		/* Can't calculate this yet; not enough history */
681*4882a593Smuzhiyun 		win->average_tpt = IL_INVALID_VALUE;
682*4882a593Smuzhiyun 		goto out;
683*4882a593Smuzhiyun 
684*4882a593Smuzhiyun 	}
685*4882a593Smuzhiyun 
686*4882a593Smuzhiyun 	current_tpt = win->average_tpt;
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 	high_low =
689*4882a593Smuzhiyun 	    il3945_get_adjacent_rate(rs_sta, idx, rate_mask, sband->band);
690*4882a593Smuzhiyun 	low = high_low & 0xff;
691*4882a593Smuzhiyun 	high = (high_low >> 8) & 0xff;
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	/* If user set max rate, dont allow higher than user constrain */
694*4882a593Smuzhiyun 	if (max_rate_idx != -1 && max_rate_idx < high)
695*4882a593Smuzhiyun 		high = RATE_INVALID;
696*4882a593Smuzhiyun 
697*4882a593Smuzhiyun 	/* Collect Measured throughputs of adjacent rates */
698*4882a593Smuzhiyun 	if (low != RATE_INVALID)
699*4882a593Smuzhiyun 		low_tpt = rs_sta->win[low].average_tpt;
700*4882a593Smuzhiyun 
701*4882a593Smuzhiyun 	if (high != RATE_INVALID)
702*4882a593Smuzhiyun 		high_tpt = rs_sta->win[high].average_tpt;
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun 	spin_unlock_irqrestore(&rs_sta->lock, flags);
705*4882a593Smuzhiyun 
706*4882a593Smuzhiyun 	scale_action = 0;
707*4882a593Smuzhiyun 
708*4882a593Smuzhiyun 	/* Low success ratio , need to drop the rate */
709*4882a593Smuzhiyun 	if (win->success_ratio < RATE_DECREASE_TH || !current_tpt) {
710*4882a593Smuzhiyun 		D_RATE("decrease rate because of low success_ratio\n");
711*4882a593Smuzhiyun 		scale_action = -1;
712*4882a593Smuzhiyun 		/* No throughput measured yet for adjacent rates,
713*4882a593Smuzhiyun 		 * try increase */
714*4882a593Smuzhiyun 	} else if (low_tpt == IL_INVALID_VALUE && high_tpt == IL_INVALID_VALUE) {
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 		if (high != RATE_INVALID &&
717*4882a593Smuzhiyun 		    win->success_ratio >= RATE_INCREASE_TH)
718*4882a593Smuzhiyun 			scale_action = 1;
719*4882a593Smuzhiyun 		else if (low != RATE_INVALID)
720*4882a593Smuzhiyun 			scale_action = 0;
721*4882a593Smuzhiyun 
722*4882a593Smuzhiyun 		/* Both adjacent throughputs are measured, but neither one has
723*4882a593Smuzhiyun 		 * better throughput; we're using the best rate, don't change
724*4882a593Smuzhiyun 		 * it! */
725*4882a593Smuzhiyun 	} else if (low_tpt != IL_INVALID_VALUE && high_tpt != IL_INVALID_VALUE
726*4882a593Smuzhiyun 		   && low_tpt < current_tpt && high_tpt < current_tpt) {
727*4882a593Smuzhiyun 
728*4882a593Smuzhiyun 		D_RATE("No action -- low [%d] & high [%d] < "
729*4882a593Smuzhiyun 		       "current_tpt [%d]\n", low_tpt, high_tpt, current_tpt);
730*4882a593Smuzhiyun 		scale_action = 0;
731*4882a593Smuzhiyun 
732*4882a593Smuzhiyun 		/* At least one of the rates has better throughput */
733*4882a593Smuzhiyun 	} else {
734*4882a593Smuzhiyun 		if (high_tpt != IL_INVALID_VALUE) {
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 			/* High rate has better throughput, Increase
737*4882a593Smuzhiyun 			 * rate */
738*4882a593Smuzhiyun 			if (high_tpt > current_tpt &&
739*4882a593Smuzhiyun 			    win->success_ratio >= RATE_INCREASE_TH)
740*4882a593Smuzhiyun 				scale_action = 1;
741*4882a593Smuzhiyun 			else {
742*4882a593Smuzhiyun 				D_RATE("decrease rate because of high tpt\n");
743*4882a593Smuzhiyun 				scale_action = 0;
744*4882a593Smuzhiyun 			}
745*4882a593Smuzhiyun 		} else if (low_tpt != IL_INVALID_VALUE) {
746*4882a593Smuzhiyun 			if (low_tpt > current_tpt) {
747*4882a593Smuzhiyun 				D_RATE("decrease rate because of low tpt\n");
748*4882a593Smuzhiyun 				scale_action = -1;
749*4882a593Smuzhiyun 			} else if (win->success_ratio >= RATE_INCREASE_TH) {
750*4882a593Smuzhiyun 				/* Lower rate has better
751*4882a593Smuzhiyun 				 * throughput,decrease rate */
752*4882a593Smuzhiyun 				scale_action = 1;
753*4882a593Smuzhiyun 			}
754*4882a593Smuzhiyun 		}
755*4882a593Smuzhiyun 	}
756*4882a593Smuzhiyun 
757*4882a593Smuzhiyun 	/* Sanity check; asked for decrease, but success rate or throughput
758*4882a593Smuzhiyun 	 * has been good at old rate.  Don't change it. */
759*4882a593Smuzhiyun 	if (scale_action == -1 && low != RATE_INVALID &&
760*4882a593Smuzhiyun 	    (win->success_ratio > RATE_HIGH_TH ||
761*4882a593Smuzhiyun 	     current_tpt > 100 * rs_sta->expected_tpt[low]))
762*4882a593Smuzhiyun 		scale_action = 0;
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	switch (scale_action) {
765*4882a593Smuzhiyun 	case -1:
766*4882a593Smuzhiyun 		/* Decrease rate */
767*4882a593Smuzhiyun 		if (low != RATE_INVALID)
768*4882a593Smuzhiyun 			idx = low;
769*4882a593Smuzhiyun 		break;
770*4882a593Smuzhiyun 	case 1:
771*4882a593Smuzhiyun 		/* Increase rate */
772*4882a593Smuzhiyun 		if (high != RATE_INVALID)
773*4882a593Smuzhiyun 			idx = high;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 		break;
776*4882a593Smuzhiyun 	case 0:
777*4882a593Smuzhiyun 	default:
778*4882a593Smuzhiyun 		/* No change */
779*4882a593Smuzhiyun 		break;
780*4882a593Smuzhiyun 	}
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	D_RATE("Selected %d (action %d) - low %d high %d\n", idx, scale_action,
783*4882a593Smuzhiyun 	       low, high);
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun out:
786*4882a593Smuzhiyun 
787*4882a593Smuzhiyun 	if (sband->band == NL80211_BAND_5GHZ) {
788*4882a593Smuzhiyun 		if (WARN_ON_ONCE(idx < IL_FIRST_OFDM_RATE))
789*4882a593Smuzhiyun 			idx = IL_FIRST_OFDM_RATE;
790*4882a593Smuzhiyun 		rs_sta->last_txrate_idx = idx;
791*4882a593Smuzhiyun 		info->control.rates[0].idx = idx - IL_FIRST_OFDM_RATE;
792*4882a593Smuzhiyun 	} else {
793*4882a593Smuzhiyun 		rs_sta->last_txrate_idx = idx;
794*4882a593Smuzhiyun 		info->control.rates[0].idx = rs_sta->last_txrate_idx;
795*4882a593Smuzhiyun 	}
796*4882a593Smuzhiyun 	info->control.rates[0].count = 1;
797*4882a593Smuzhiyun 
798*4882a593Smuzhiyun 	D_RATE("leave: %d\n", idx);
799*4882a593Smuzhiyun }
800*4882a593Smuzhiyun 
801*4882a593Smuzhiyun #ifdef CONFIG_MAC80211_DEBUGFS
802*4882a593Smuzhiyun 
803*4882a593Smuzhiyun static ssize_t
il3945_sta_dbgfs_stats_table_read(struct file * file,char __user * user_buf,size_t count,loff_t * ppos)804*4882a593Smuzhiyun il3945_sta_dbgfs_stats_table_read(struct file *file, char __user *user_buf,
805*4882a593Smuzhiyun 				  size_t count, loff_t *ppos)
806*4882a593Smuzhiyun {
807*4882a593Smuzhiyun 	char *buff;
808*4882a593Smuzhiyun 	int desc = 0;
809*4882a593Smuzhiyun 	int j;
810*4882a593Smuzhiyun 	ssize_t ret;
811*4882a593Smuzhiyun 	struct il3945_rs_sta *lq_sta = file->private_data;
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun 	buff = kmalloc(1024, GFP_KERNEL);
814*4882a593Smuzhiyun 	if (!buff)
815*4882a593Smuzhiyun 		return -ENOMEM;
816*4882a593Smuzhiyun 
817*4882a593Smuzhiyun 	desc +=
818*4882a593Smuzhiyun 	    sprintf(buff + desc,
819*4882a593Smuzhiyun 		    "tx packets=%d last rate idx=%d\n"
820*4882a593Smuzhiyun 		    "rate=0x%X flush time %d\n", lq_sta->tx_packets,
821*4882a593Smuzhiyun 		    lq_sta->last_txrate_idx, lq_sta->start_rate,
822*4882a593Smuzhiyun 		    jiffies_to_msecs(lq_sta->flush_time));
823*4882a593Smuzhiyun 	for (j = 0; j < RATE_COUNT_3945; j++) {
824*4882a593Smuzhiyun 		desc +=
825*4882a593Smuzhiyun 		    sprintf(buff + desc, "counter=%d success=%d %%=%d\n",
826*4882a593Smuzhiyun 			    lq_sta->win[j].counter,
827*4882a593Smuzhiyun 			    lq_sta->win[j].success_counter,
828*4882a593Smuzhiyun 			    lq_sta->win[j].success_ratio);
829*4882a593Smuzhiyun 	}
830*4882a593Smuzhiyun 	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
831*4882a593Smuzhiyun 	kfree(buff);
832*4882a593Smuzhiyun 	return ret;
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun 
835*4882a593Smuzhiyun static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
836*4882a593Smuzhiyun 	.read = il3945_sta_dbgfs_stats_table_read,
837*4882a593Smuzhiyun 	.open = simple_open,
838*4882a593Smuzhiyun 	.llseek = default_llseek,
839*4882a593Smuzhiyun };
840*4882a593Smuzhiyun 
841*4882a593Smuzhiyun static void
il3945_add_debugfs(void * il,void * il_sta,struct dentry * dir)842*4882a593Smuzhiyun il3945_add_debugfs(void *il, void *il_sta, struct dentry *dir)
843*4882a593Smuzhiyun {
844*4882a593Smuzhiyun 	struct il3945_rs_sta *lq_sta = il_sta;
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	debugfs_create_file("rate_stats_table", 0600, dir, lq_sta,
847*4882a593Smuzhiyun 			    &rs_sta_dbgfs_stats_table_ops);
848*4882a593Smuzhiyun }
849*4882a593Smuzhiyun #endif
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun /*
852*4882a593Smuzhiyun  * Initialization of rate scaling information is done by driver after
853*4882a593Smuzhiyun  * the station is added. Since mac80211 calls this function before a
854*4882a593Smuzhiyun  * station is added we ignore it.
855*4882a593Smuzhiyun  */
856*4882a593Smuzhiyun static void
il3945_rs_rate_init_stub(void * il_r,struct ieee80211_supported_band * sband,struct cfg80211_chan_def * chandef,struct ieee80211_sta * sta,void * il_sta)857*4882a593Smuzhiyun il3945_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
858*4882a593Smuzhiyun 			 struct cfg80211_chan_def *chandef,
859*4882a593Smuzhiyun 			 struct ieee80211_sta *sta, void *il_sta)
860*4882a593Smuzhiyun {
861*4882a593Smuzhiyun }
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun static const struct rate_control_ops rs_ops = {
864*4882a593Smuzhiyun 	.name = RS_NAME,
865*4882a593Smuzhiyun 	.tx_status = il3945_rs_tx_status,
866*4882a593Smuzhiyun 	.get_rate = il3945_rs_get_rate,
867*4882a593Smuzhiyun 	.rate_init = il3945_rs_rate_init_stub,
868*4882a593Smuzhiyun 	.alloc = il3945_rs_alloc,
869*4882a593Smuzhiyun 	.free = il3945_rs_free,
870*4882a593Smuzhiyun 	.alloc_sta = il3945_rs_alloc_sta,
871*4882a593Smuzhiyun 	.free_sta = il3945_rs_free_sta,
872*4882a593Smuzhiyun #ifdef CONFIG_MAC80211_DEBUGFS
873*4882a593Smuzhiyun 	.add_sta_debugfs = il3945_add_debugfs,
874*4882a593Smuzhiyun #endif
875*4882a593Smuzhiyun 
876*4882a593Smuzhiyun };
877*4882a593Smuzhiyun 
878*4882a593Smuzhiyun void
il3945_rate_scale_init(struct ieee80211_hw * hw,s32 sta_id)879*4882a593Smuzhiyun il3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
880*4882a593Smuzhiyun {
881*4882a593Smuzhiyun 	struct il_priv *il = hw->priv;
882*4882a593Smuzhiyun 	s32 rssi = 0;
883*4882a593Smuzhiyun 	unsigned long flags;
884*4882a593Smuzhiyun 	struct il3945_rs_sta *rs_sta;
885*4882a593Smuzhiyun 	struct ieee80211_sta *sta;
886*4882a593Smuzhiyun 	struct il3945_sta_priv *psta;
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun 	D_RATE("enter\n");
889*4882a593Smuzhiyun 
890*4882a593Smuzhiyun 	rcu_read_lock();
891*4882a593Smuzhiyun 
892*4882a593Smuzhiyun 	sta = ieee80211_find_sta(il->vif, il->stations[sta_id].sta.sta.addr);
893*4882a593Smuzhiyun 	if (!sta) {
894*4882a593Smuzhiyun 		D_RATE("Unable to find station to initialize rate scaling.\n");
895*4882a593Smuzhiyun 		rcu_read_unlock();
896*4882a593Smuzhiyun 		return;
897*4882a593Smuzhiyun 	}
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	psta = (void *)sta->drv_priv;
900*4882a593Smuzhiyun 	rs_sta = &psta->rs_sta;
901*4882a593Smuzhiyun 
902*4882a593Smuzhiyun 	spin_lock_irqsave(&rs_sta->lock, flags);
903*4882a593Smuzhiyun 
904*4882a593Smuzhiyun 	rs_sta->tgg = 0;
905*4882a593Smuzhiyun 	switch (il->band) {
906*4882a593Smuzhiyun 	case NL80211_BAND_2GHZ:
907*4882a593Smuzhiyun 		/* TODO: this always does G, not a regression */
908*4882a593Smuzhiyun 		if (il->active.flags & RXON_FLG_TGG_PROTECT_MSK) {
909*4882a593Smuzhiyun 			rs_sta->tgg = 1;
910*4882a593Smuzhiyun 			rs_sta->expected_tpt = il3945_expected_tpt_g_prot;
911*4882a593Smuzhiyun 		} else
912*4882a593Smuzhiyun 			rs_sta->expected_tpt = il3945_expected_tpt_g;
913*4882a593Smuzhiyun 		break;
914*4882a593Smuzhiyun 	case NL80211_BAND_5GHZ:
915*4882a593Smuzhiyun 		rs_sta->expected_tpt = il3945_expected_tpt_a;
916*4882a593Smuzhiyun 		break;
917*4882a593Smuzhiyun 	default:
918*4882a593Smuzhiyun 		BUG();
919*4882a593Smuzhiyun 		break;
920*4882a593Smuzhiyun 	}
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	spin_unlock_irqrestore(&rs_sta->lock, flags);
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	rssi = il->_3945.last_rx_rssi;
925*4882a593Smuzhiyun 	if (rssi == 0)
926*4882a593Smuzhiyun 		rssi = IL_MIN_RSSI_VAL;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	D_RATE("Network RSSI: %d\n", rssi);
929*4882a593Smuzhiyun 
930*4882a593Smuzhiyun 	rs_sta->start_rate = il3945_get_rate_idx_by_rssi(rssi, il->band);
931*4882a593Smuzhiyun 
932*4882a593Smuzhiyun 	D_RATE("leave: rssi %d assign rate idx: " "%d (plcp 0x%x)\n", rssi,
933*4882a593Smuzhiyun 	       rs_sta->start_rate, il3945_rates[rs_sta->start_rate].plcp);
934*4882a593Smuzhiyun 	rcu_read_unlock();
935*4882a593Smuzhiyun }
936*4882a593Smuzhiyun 
937*4882a593Smuzhiyun int
il3945_rate_control_register(void)938*4882a593Smuzhiyun il3945_rate_control_register(void)
939*4882a593Smuzhiyun {
940*4882a593Smuzhiyun 	return ieee80211_rate_control_register(&rs_ops);
941*4882a593Smuzhiyun }
942*4882a593Smuzhiyun 
943*4882a593Smuzhiyun void
il3945_rate_control_unregister(void)944*4882a593Smuzhiyun il3945_rate_control_unregister(void)
945*4882a593Smuzhiyun {
946*4882a593Smuzhiyun 	ieee80211_rate_control_unregister(&rs_ops);
947*4882a593Smuzhiyun }
948