1*b1906ceaSLachlan Hodges // SPDX-License-Identifier: GPL-2.0-only
2*b1906ceaSLachlan Hodges /*
3*b1906ceaSLachlan Hodges * Copyright (c) 2017-2026 Morse Micro
4*b1906ceaSLachlan Hodges */
5*b1906ceaSLachlan Hodges #include "mmrc.h"
6*b1906ceaSLachlan Hodges
7*b1906ceaSLachlan Hodges /*
8*b1906ceaSLachlan Hodges * The default packet size in bits used for calculated throughput of a given
9*b1906ceaSLachlan Hodges * rate
10*b1906ceaSLachlan Hodges */
11*b1906ceaSLachlan Hodges #define DEFAULT_PACKET_SIZE_BITS 9600
12*b1906ceaSLachlan Hodges
13*b1906ceaSLachlan Hodges /*
14*b1906ceaSLachlan Hodges * The default packet size in bytes used for calculating retries for a given
15*b1906ceaSLachlan Hodges * rate
16*b1906ceaSLachlan Hodges */
17*b1906ceaSLachlan Hodges #define DEFAULT_PACKET_SIZE_BYTES 1200
18*b1906ceaSLachlan Hodges
19*b1906ceaSLachlan Hodges /* The sample frequencies at different stages */
20*b1906ceaSLachlan Hodges #define LOOKAROUND_RATE_INIT 5
21*b1906ceaSLachlan Hodges #define LOOKAROUND_RATE_NORMAL 50
22*b1906ceaSLachlan Hodges #define LOOKAROUND_RATE_STABLE 100
23*b1906ceaSLachlan Hodges
24*b1906ceaSLachlan Hodges /* The thresholds for stability stages */
25*b1906ceaSLachlan Hodges #define STABILITY_CNT_THRESHOLD_INIT 20
26*b1906ceaSLachlan Hodges #define STABILITY_CNT_THRESHOLD_NORMAL 50
27*b1906ceaSLachlan Hodges #define STABILITY_CNT_THRESHOLD_STABLE 100
28*b1906ceaSLachlan Hodges
29*b1906ceaSLachlan Hodges /* The backoff step size for the counter */
30*b1906ceaSLachlan Hodges #define STABILITY_BACKOFF_STEP 2
31*b1906ceaSLachlan Hodges
32*b1906ceaSLachlan Hodges /*
33*b1906ceaSLachlan Hodges * The packet success threshold for attempting slower lookaround rates
34*b1906ceaSLachlan Hodges */
35*b1906ceaSLachlan Hodges /*
36*b1906ceaSLachlan Hodges * Force a look around if there haven't been any for this number of cycles
37*b1906ceaSLachlan Hodges */
38*b1906ceaSLachlan Hodges #define LOOKAROUND_MAX_RC_CYCLES 5
39*b1906ceaSLachlan Hodges
40*b1906ceaSLachlan Hodges /*
41*b1906ceaSLachlan Hodges * Number of attempts for each lookaround rate within at most two RC cycles
42*b1906ceaSLachlan Hodges * if there are enough packets
43*b1906ceaSLachlan Hodges */
44*b1906ceaSLachlan Hodges #define LOOKAROUND_RATE_ATTEMPTS 4
45*b1906ceaSLachlan Hodges
46*b1906ceaSLachlan Hodges /*
47*b1906ceaSLachlan Hodges * Limit the number of times we try to pick a theoretically better rate to
48*b1906ceaSLachlan Hodges * sample. Necessary so we don't stall the CPU, due to constantly picking worse
49*b1906ceaSLachlan Hodges * rates.
50*b1906ceaSLachlan Hodges */
51*b1906ceaSLachlan Hodges #define LOOKAROUND_FAIL_MAX 200
52*b1906ceaSLachlan Hodges
53*b1906ceaSLachlan Hodges /*
54*b1906ceaSLachlan Hodges * Initial and reset probability per rate in the table
55*b1906ceaSLachlan Hodges * Changing this value will have a severe implication on the current heuristic
56*b1906ceaSLachlan Hodges * It could mean that some rates will have better probability throughput even
57*b1906ceaSLachlan Hodges * with no edivence and so will cause unexpected changes in the rate table
58*b1906ceaSLachlan Hodges */
59*b1906ceaSLachlan Hodges #define RATE_INIT_PROBABILITY 0
60*b1906ceaSLachlan Hodges
61*b1906ceaSLachlan Hodges /*
62*b1906ceaSLachlan Hodges * The lowest number of MPDUs within acknowledged AMPDUs that can be used for
63*b1906ceaSLachlan Hodges * rate stats
64*b1906ceaSLachlan Hodges */
65*b1906ceaSLachlan Hodges #define AMPDU_STATS_MIN 2
66*b1906ceaSLachlan Hodges
67*b1906ceaSLachlan Hodges /*
68*b1906ceaSLachlan Hodges * The lowest number of stats to be used for processing in NORMAL lookaround
69*b1906ceaSLachlan Hodges * mode
70*b1906ceaSLachlan Hodges */
71*b1906ceaSLachlan Hodges #define STATS_MIN_NORMAL 2
72*b1906ceaSLachlan Hodges
73*b1906ceaSLachlan Hodges /*
74*b1906ceaSLachlan Hodges * The lowest number of stats to be used for processing in INIT lookaround
75*b1906ceaSLachlan Hodges * mode
76*b1906ceaSLachlan Hodges */
77*b1906ceaSLachlan Hodges #define STATS_MIN_INIT 1
78*b1906ceaSLachlan Hodges
79*b1906ceaSLachlan Hodges /* The lowest probability value considered for recognising a dip */
80*b1906ceaSLachlan Hodges #define PROBABILITY_DIP_MIN 20
81*b1906ceaSLachlan Hodges
82*b1906ceaSLachlan Hodges /* The lowest probability value for recovering from a dip */
83*b1906ceaSLachlan Hodges #define PROBABILITY_DIP_RECOVERY_MIN 40
84*b1906ceaSLachlan Hodges
85*b1906ceaSLachlan Hodges /*
86*b1906ceaSLachlan Hodges * The time cap on rate allocation for multiple attempts. If a single attempt
87*b1906ceaSLachlan Hodges * exceeds this window, no additional attempts will be generated
88*b1906ceaSLachlan Hodges */
89*b1906ceaSLachlan Hodges #define MAX_WINDOW_ATTEMPT_TIME 4000
90*b1906ceaSLachlan Hodges
91*b1906ceaSLachlan Hodges /* The time window for all rates in rate table */
92*b1906ceaSLachlan Hodges #define RATE_WINDOW_MICROSECONDS 24000
93*b1906ceaSLachlan Hodges
94*b1906ceaSLachlan Hodges /*
95*b1906ceaSLachlan Hodges * EWMA is the alpha coefficient in the exponential weighting moving average
96*b1906ceaSLachlan Hodges * filter used for probability updates.
97*b1906ceaSLachlan Hodges *
98*b1906ceaSLachlan Hodges * Y[n] = X[n] * (100 - EWMA) + (Y[n-1] * EWMA)
99*b1906ceaSLachlan Hodges * -------------------------------------
100*b1906ceaSLachlan Hodges * 100
101*b1906ceaSLachlan Hodges *
102*b1906ceaSLachlan Hodges */
103*b1906ceaSLachlan Hodges #define EWMA 75
104*b1906ceaSLachlan Hodges
105*b1906ceaSLachlan Hodges /*
106*b1906ceaSLachlan Hodges * Evidence scaling to allow for one decimal place. Needed for low
107*b1906ceaSLachlan Hodges * throughput, otherwise the history decays in a single cycle.
108*b1906ceaSLachlan Hodges */
109*b1906ceaSLachlan Hodges #define EVIDENCE_SCALE 5
110*b1906ceaSLachlan Hodges
111*b1906ceaSLachlan Hodges /*
112*b1906ceaSLachlan Hodges * Evidence maximum to ensure history doesn't decay too slowly when
113*b1906ceaSLachlan Hodges * there is a lot of historical data.
114*b1906ceaSLachlan Hodges */
115*b1906ceaSLachlan Hodges #define EVIDENCE_MAX 100
116*b1906ceaSLachlan Hodges
117*b1906ceaSLachlan Hodges /*
118*b1906ceaSLachlan Hodges * This fixed point conversion multiplies a value by one and shifts it
119*b1906ceaSLachlan Hodges * accordingly to account for the fixed point shifting at the return of a
120*b1906ceaSLachlan Hodges * function
121*b1906ceaSLachlan Hodges */
122*b1906ceaSLachlan Hodges #define FP_8_MULT_1 256
123*b1906ceaSLachlan Hodges
124*b1906ceaSLachlan Hodges /* Fixed point conversion for 2.1 * 2^8 used for 4MHz symbol multiplication */
125*b1906ceaSLachlan Hodges #define FP_8_4MHZ 537
126*b1906ceaSLachlan Hodges
127*b1906ceaSLachlan Hodges /* Fixed point conversion for 4.5 * 2^8 used for 8MHz symbol multiplication */
128*b1906ceaSLachlan Hodges #define FP_8_8MHZ 1152
129*b1906ceaSLachlan Hodges
130*b1906ceaSLachlan Hodges /* Fixed point conversion for 9.0 * 2^8 used for 16MHz symbol multiplication */
131*b1906ceaSLachlan Hodges #define FP_8_16MHZ 2301
132*b1906ceaSLachlan Hodges
133*b1906ceaSLachlan Hodges /*
134*b1906ceaSLachlan Hodges * Fixed point conversion for 3.6 * 2^8 used for long guard symbol tx time
135*b1906ceaSLachlan Hodges * multiplication
136*b1906ceaSLachlan Hodges */
137*b1906ceaSLachlan Hodges #define FP_8_LONG_GUARD_SYMBOL_TIME 1024
138*b1906ceaSLachlan Hodges
139*b1906ceaSLachlan Hodges /*
140*b1906ceaSLachlan Hodges * Fixed point conversion for 4.0 * 2^8 used for short guard symbol tx time
141*b1906ceaSLachlan Hodges * multiplication
142*b1906ceaSLachlan Hodges */
143*b1906ceaSLachlan Hodges #define FP_8_SHORT_GUARD_SYMBOL_TIME 921
144*b1906ceaSLachlan Hodges
145*b1906ceaSLachlan Hodges /*
146*b1906ceaSLachlan Hodges * Shift value to shift back our FP conversions
147*b1906ceaSLachlan Hodges */
148*b1906ceaSLachlan Hodges #define FP_8_SHIFT 8
149*b1906ceaSLachlan Hodges
150*b1906ceaSLachlan Hodges /*
151*b1906ceaSLachlan Hodges * Limit to count of consecutive variations in one direction
152*b1906ceaSLachlan Hodges */
153*b1906ceaSLachlan Hodges #define MAX_VARIATION_DIRECTION 5
154*b1906ceaSLachlan Hodges
155*b1906ceaSLachlan Hodges /*
156*b1906ceaSLachlan Hodges * Threshold for considering consecutive variation direction as variation
157*b1906ceaSLachlan Hodges * or not
158*b1906ceaSLachlan Hodges */
159*b1906ceaSLachlan Hodges #define VARIATION_DIRECTION_THRESHOLD 3
160*b1906ceaSLachlan Hodges
161*b1906ceaSLachlan Hodges /* EWMA percentage value for averaging the best rate probability variation */
162*b1906ceaSLachlan Hodges #define VARIATION_EWMA 95
163*b1906ceaSLachlan Hodges
164*b1906ceaSLachlan Hodges /* Percentage variation regarded as minor */
165*b1906ceaSLachlan Hodges #define MINOR_VARIATION_THRESHOLD 1
166*b1906ceaSLachlan Hodges
167*b1906ceaSLachlan Hodges /* Percentage variation regarded as moderate */
168*b1906ceaSLachlan Hodges #define MODERATE_VARIATION_THRESHOLD 3
169*b1906ceaSLachlan Hodges
170*b1906ceaSLachlan Hodges /* Percentage variation regarded as significant */
171*b1906ceaSLachlan Hodges #define SIGNIFICANT_VARIATION_THRESHOLD 5
172*b1906ceaSLachlan Hodges
173*b1906ceaSLachlan Hodges /* If the best rate changes twice in this number of cycles, it is unstable */
174*b1906ceaSLachlan Hodges #define BEST_RATE_UNSTABLE_THRESHOLD 4
175*b1906ceaSLachlan Hodges
176*b1906ceaSLachlan Hodges /*
177*b1906ceaSLachlan Hodges * Once the best rate is unchanged for this number of cycles it has
178*b1906ceaSLachlan Hodges * converged
179*b1906ceaSLachlan Hodges */
180*b1906ceaSLachlan Hodges #define BEST_RATE_CONVERGED_THRESHOLD 10
181*b1906ceaSLachlan Hodges
182*b1906ceaSLachlan Hodges /* RSSI threshold for short range */
183*b1906ceaSLachlan Hodges #define MMRC_SHORT_RANGE_RSSI_LIMIT -70
184*b1906ceaSLachlan Hodges
185*b1906ceaSLachlan Hodges /* RSSI threshold for mid range */
186*b1906ceaSLachlan Hodges #define MMRC_MID_RANGE_RSSI_LIMIT -85
187*b1906ceaSLachlan Hodges
188*b1906ceaSLachlan Hodges #define MMRC_MAX_BW(bw_caps) \
189*b1906ceaSLachlan Hodges (((bw_caps) & BIT(MMRC_BW_16MHZ)) ? MMRC_BW_16MHZ : \
190*b1906ceaSLachlan Hodges ((bw_caps) & BIT(MMRC_BW_8MHZ)) ? MMRC_BW_8MHZ : \
191*b1906ceaSLachlan Hodges ((bw_caps) & BIT(MMRC_BW_4MHZ)) ? MMRC_BW_4MHZ : \
192*b1906ceaSLachlan Hodges ((bw_caps) & BIT(MMRC_BW_2MHZ)) ? MMRC_BW_2MHZ : \
193*b1906ceaSLachlan Hodges MMRC_BW_1MHZ)
194*b1906ceaSLachlan Hodges
195*b1906ceaSLachlan Hodges /*
196*b1906ceaSLachlan Hodges * This table stores the number of bits per symbols used for MCS0-MCS9 based
197*b1906ceaSLachlan Hodges * on 20MHz and 1SS
198*b1906ceaSLachlan Hodges */
199*b1906ceaSLachlan Hodges static const u32 sym_table[10] = { 24, 36, 48, 72, 96, 144, 192, 216, 256, 288 };
200*b1906ceaSLachlan Hodges
201*b1906ceaSLachlan Hodges /*
202*b1906ceaSLachlan Hodges * Calculate which bit is the nth bit set in an integer based flag.
203*b1906ceaSLachlan Hodges */
nth_bit(u16 in,u16 index)204*b1906ceaSLachlan Hodges static u8 nth_bit(u16 in, u16 index)
205*b1906ceaSLachlan Hodges {
206*b1906ceaSLachlan Hodges u32 i;
207*b1906ceaSLachlan Hodges u8 count = 0;
208*b1906ceaSLachlan Hodges
209*b1906ceaSLachlan Hodges for (i = 0; count != index + 1; i++) {
210*b1906ceaSLachlan Hodges if (((1u << i) & in) != 0)
211*b1906ceaSLachlan Hodges count++;
212*b1906ceaSLachlan Hodges }
213*b1906ceaSLachlan Hodges
214*b1906ceaSLachlan Hodges return i - 1;
215*b1906ceaSLachlan Hodges }
216*b1906ceaSLachlan Hodges
217*b1906ceaSLachlan Hodges /*
218*b1906ceaSLachlan Hodges * Calculate the input bit's index among all the set bits in an integer
219*b1906ceaSLachlan Hodges * based flag.
220*b1906ceaSLachlan Hodges */
bit_index(u16 in,u32 bit_pos)221*b1906ceaSLachlan Hodges static u16 bit_index(u16 in, u32 bit_pos)
222*b1906ceaSLachlan Hodges {
223*b1906ceaSLachlan Hodges u16 i;
224*b1906ceaSLachlan Hodges u16 index = 0;
225*b1906ceaSLachlan Hodges
226*b1906ceaSLachlan Hodges for (i = 0; i != bit_pos + 1; i++) {
227*b1906ceaSLachlan Hodges if (((1u << i) & in) != 0)
228*b1906ceaSLachlan Hodges index++;
229*b1906ceaSLachlan Hodges }
230*b1906ceaSLachlan Hodges
231*b1906ceaSLachlan Hodges if (index == 0) {
232*b1906ceaSLachlan Hodges /* Could not match bit pos to caps */
233*b1906ceaSLachlan Hodges return 0;
234*b1906ceaSLachlan Hodges }
235*b1906ceaSLachlan Hodges
236*b1906ceaSLachlan Hodges return index - 1;
237*b1906ceaSLachlan Hodges }
238*b1906ceaSLachlan Hodges
rows_from_sta_caps(struct mmrc_sta_capabilities * caps)239*b1906ceaSLachlan Hodges static u16 rows_from_sta_caps(struct mmrc_sta_capabilities *caps)
240*b1906ceaSLachlan Hodges {
241*b1906ceaSLachlan Hodges u16 rows = 0;
242*b1906ceaSLachlan Hodges u8 n_rates = hweight_long(caps->rates);
243*b1906ceaSLachlan Hodges
244*b1906ceaSLachlan Hodges /* Taking MCS10 into account as it is relevant for 1 MHz entries */
245*b1906ceaSLachlan Hodges if (caps->rates & BIT(MMRC_MCS10)) {
246*b1906ceaSLachlan Hodges n_rates -= 1;
247*b1906ceaSLachlan Hodges rows = 2;
248*b1906ceaSLachlan Hodges }
249*b1906ceaSLachlan Hodges
250*b1906ceaSLachlan Hodges rows += (hweight_long(caps->bandwidth) * n_rates *
251*b1906ceaSLachlan Hodges hweight_long(caps->guard) *
252*b1906ceaSLachlan Hodges hweight_long(caps->spatial_streams));
253*b1906ceaSLachlan Hodges
254*b1906ceaSLachlan Hodges return rows;
255*b1906ceaSLachlan Hodges }
256*b1906ceaSLachlan Hodges
rate_update_index(struct mmrc_table * tb,struct mmrc_rate * rate)257*b1906ceaSLachlan Hodges static void rate_update_index(struct mmrc_table *tb, struct mmrc_rate *rate)
258*b1906ceaSLachlan Hodges {
259*b1906ceaSLachlan Hodges u16 index = 0;
260*b1906ceaSLachlan Hodges /* Information about our rates */
261*b1906ceaSLachlan Hodges u16 bw = hweight_long(tb->caps.bandwidth);
262*b1906ceaSLachlan Hodges u16 streams = hweight_long(tb->caps.spatial_streams);
263*b1906ceaSLachlan Hodges u16 guard = hweight_long(tb->caps.guard);
264*b1906ceaSLachlan Hodges u16 rows = rows_from_sta_caps(&tb->caps);
265*b1906ceaSLachlan Hodges
266*b1906ceaSLachlan Hodges index = bit_index(tb->caps.guard, rate->guard) +
267*b1906ceaSLachlan Hodges bit_index(tb->caps.bandwidth, rate->bw) * guard +
268*b1906ceaSLachlan Hodges bit_index(tb->caps.spatial_streams, rate->ss) * guard * bw +
269*b1906ceaSLachlan Hodges bit_index(tb->caps.rates, rate->rate) * bw * streams * guard;
270*b1906ceaSLachlan Hodges
271*b1906ceaSLachlan Hodges if (index >= rows)
272*b1906ceaSLachlan Hodges index = 0;
273*b1906ceaSLachlan Hodges
274*b1906ceaSLachlan Hodges rate->index = index;
275*b1906ceaSLachlan Hodges }
276*b1906ceaSLachlan Hodges
get_rate_row(struct mmrc_table * tb,u16 index)277*b1906ceaSLachlan Hodges static struct mmrc_rate get_rate_row(struct mmrc_table *tb, u16 index)
278*b1906ceaSLachlan Hodges {
279*b1906ceaSLachlan Hodges struct mmrc_rate rate;
280*b1906ceaSLachlan Hodges u16 ss_index;
281*b1906ceaSLachlan Hodges
282*b1906ceaSLachlan Hodges /* Information about our rates */
283*b1906ceaSLachlan Hodges u16 mcs = hweight_long(tb->caps.rates);
284*b1906ceaSLachlan Hodges u16 bw = hweight_long(tb->caps.bandwidth);
285*b1906ceaSLachlan Hodges u16 streams = hweight_long(tb->caps.spatial_streams);
286*b1906ceaSLachlan Hodges u16 guard = hweight_long(tb->caps.guard);
287*b1906ceaSLachlan Hodges u16 total_caps = mcs * bw * streams * guard;
288*b1906ceaSLachlan Hodges
289*b1906ceaSLachlan Hodges /* Find our MCS */
290*b1906ceaSLachlan Hodges u16 rows = total_caps / mcs;
291*b1906ceaSLachlan Hodges u16 mcs_index = index / rows;
292*b1906ceaSLachlan Hodges u16 mcs_modulo = index % rows;
293*b1906ceaSLachlan Hodges
294*b1906ceaSLachlan Hodges mcs = nth_bit(tb->caps.rates, mcs_index);
295*b1906ceaSLachlan Hodges
296*b1906ceaSLachlan Hodges /* Find our spatial stream */
297*b1906ceaSLachlan Hodges rows = rows / streams;
298*b1906ceaSLachlan Hodges streams = nth_bit(tb->caps.spatial_streams, mcs_modulo / rows);
299*b1906ceaSLachlan Hodges
300*b1906ceaSLachlan Hodges /* Find our bandwidth */
301*b1906ceaSLachlan Hodges ss_index = index % rows;
302*b1906ceaSLachlan Hodges rows = rows / bw;
303*b1906ceaSLachlan Hodges bw = nth_bit(tb->caps.bandwidth, ss_index / rows);
304*b1906ceaSLachlan Hodges
305*b1906ceaSLachlan Hodges /* Find our guard */
306*b1906ceaSLachlan Hodges guard = nth_bit(tb->caps.guard, index % guard);
307*b1906ceaSLachlan Hodges
308*b1906ceaSLachlan Hodges /* Add range checks to keep scan-build happy */
309*b1906ceaSLachlan Hodges if (bw >= MMRC_BW_MAX)
310*b1906ceaSLachlan Hodges bw = MMRC_BW_1MHZ;
311*b1906ceaSLachlan Hodges
312*b1906ceaSLachlan Hodges if (guard >= MMRC_GUARD_MAX)
313*b1906ceaSLachlan Hodges guard = MMRC_GUARD_LONG;
314*b1906ceaSLachlan Hodges
315*b1906ceaSLachlan Hodges /* Validate guard against capability */
316*b1906ceaSLachlan Hodges if (guard == MMRC_GUARD_SHORT &&
317*b1906ceaSLachlan Hodges !(tb->caps.sgi_per_bw & SGI_PER_BW(bw)))
318*b1906ceaSLachlan Hodges guard = MMRC_GUARD_LONG;
319*b1906ceaSLachlan Hodges
320*b1906ceaSLachlan Hodges /* Create our rate row and send it */
321*b1906ceaSLachlan Hodges rate.bw = MMRC_BW_TO_BITFIELD(bw);
322*b1906ceaSLachlan Hodges rate.ss = MMRC_SS_TO_BITFIELD(streams);
323*b1906ceaSLachlan Hodges rate.rate = MMRC_RATE_TO_BITFIELD(mcs);
324*b1906ceaSLachlan Hodges rate.guard = MMRC_GUARD_TO_BITFIELD(guard);
325*b1906ceaSLachlan Hodges rate.attempts = 0;
326*b1906ceaSLachlan Hodges rate.flags = 0;
327*b1906ceaSLachlan Hodges
328*b1906ceaSLachlan Hodges /* Update index as bw or guard may have changed */
329*b1906ceaSLachlan Hodges rate_update_index(tb, &rate);
330*b1906ceaSLachlan Hodges
331*b1906ceaSLachlan Hodges return rate;
332*b1906ceaSLachlan Hodges }
333*b1906ceaSLachlan Hodges
mmrc_memory_required_for_caps(struct mmrc_sta_capabilities * caps)334*b1906ceaSLachlan Hodges size_t mmrc_memory_required_for_caps(struct mmrc_sta_capabilities *caps)
335*b1906ceaSLachlan Hodges {
336*b1906ceaSLachlan Hodges return sizeof(struct mmrc_table) +
337*b1906ceaSLachlan Hodges rows_from_sta_caps(caps) * sizeof(struct mmrc_stats_table);
338*b1906ceaSLachlan Hodges }
339*b1906ceaSLachlan Hodges
calculate_bits_per_symbol(struct mmrc_rate * rate)340*b1906ceaSLachlan Hodges static u32 calculate_bits_per_symbol(struct mmrc_rate *rate)
341*b1906ceaSLachlan Hodges {
342*b1906ceaSLachlan Hodges u32 bps;
343*b1906ceaSLachlan Hodges
344*b1906ceaSLachlan Hodges /* If MCS10 is selected we return 2*MCS0 Symbols */
345*b1906ceaSLachlan Hodges if (rate->rate == MMRC_MCS10)
346*b1906ceaSLachlan Hodges return 6;
347*b1906ceaSLachlan Hodges
348*b1906ceaSLachlan Hodges /* Confirm that the rate is valid for the sym_table lookup */
349*b1906ceaSLachlan Hodges if (rate->rate >= MMRC_MCS_UNUSED) {
350*b1906ceaSLachlan Hodges pr_err("%s: Invalid MCS rate %d for sym_table lookup\n",
351*b1906ceaSLachlan Hodges __func__, rate->rate);
352*b1906ceaSLachlan Hodges return 1;
353*b1906ceaSLachlan Hodges }
354*b1906ceaSLachlan Hodges
355*b1906ceaSLachlan Hodges /*
356*b1906ceaSLachlan Hodges * Coversion from 20MHz as in sym_table to:
357*b1906ceaSLachlan Hodges * 40MHz == x 2.1
358*b1906ceaSLachlan Hodges * 80MHz == x 4.5
359*b1906ceaSLachlan Hodges * 160MHz == x 9.0
360*b1906ceaSLachlan Hodges */
361*b1906ceaSLachlan Hodges bps = sym_table[rate->rate];
362*b1906ceaSLachlan Hodges switch (rate->bw) {
363*b1906ceaSLachlan Hodges case (MMRC_BW_4MHZ):
364*b1906ceaSLachlan Hodges bps *= FP_8_4MHZ;
365*b1906ceaSLachlan Hodges break;
366*b1906ceaSLachlan Hodges case (MMRC_BW_8MHZ):
367*b1906ceaSLachlan Hodges bps *= FP_8_8MHZ;
368*b1906ceaSLachlan Hodges break;
369*b1906ceaSLachlan Hodges case (MMRC_BW_16MHZ):
370*b1906ceaSLachlan Hodges bps *= FP_8_16MHZ;
371*b1906ceaSLachlan Hodges break;
372*b1906ceaSLachlan Hodges case (MMRC_BW_1MHZ):
373*b1906ceaSLachlan Hodges bps = sym_table[rate->rate] * 24 / 52;
374*b1906ceaSLachlan Hodges bps *= FP_8_MULT_1;
375*b1906ceaSLachlan Hodges break;
376*b1906ceaSLachlan Hodges case (MMRC_BW_2MHZ):
377*b1906ceaSLachlan Hodges case (MMRC_BW_MAX):
378*b1906ceaSLachlan Hodges default:
379*b1906ceaSLachlan Hodges bps *= FP_8_MULT_1;
380*b1906ceaSLachlan Hodges break;
381*b1906ceaSLachlan Hodges }
382*b1906ceaSLachlan Hodges /* SS + 1 because mmrc_spatial_stream starts at 0 */
383*b1906ceaSLachlan Hodges return ((rate->ss + 1) * bps) >> FP_8_SHIFT;
384*b1906ceaSLachlan Hodges }
385*b1906ceaSLachlan Hodges
get_tx_time(struct mmrc_rate * rate)386*b1906ceaSLachlan Hodges static u32 get_tx_time(struct mmrc_rate *rate)
387*b1906ceaSLachlan Hodges {
388*b1906ceaSLachlan Hodges u32 tx = 0;
389*b1906ceaSLachlan Hodges u32 n_sym;
390*b1906ceaSLachlan Hodges u32 avg_bits;
391*b1906ceaSLachlan Hodges
392*b1906ceaSLachlan Hodges /* Calculate tx time based on a default packet size */
393*b1906ceaSLachlan Hodges avg_bits = DEFAULT_PACKET_SIZE_BITS;
394*b1906ceaSLachlan Hodges
395*b1906ceaSLachlan Hodges /* Number of bits per symbol for this rate */
396*b1906ceaSLachlan Hodges n_sym = calculate_bits_per_symbol(rate);
397*b1906ceaSLachlan Hodges
398*b1906ceaSLachlan Hodges /* In case of bad calcuation/parameter use lowest value */
399*b1906ceaSLachlan Hodges n_sym = n_sym == 0 ? sym_table[0] : n_sym;
400*b1906ceaSLachlan Hodges
401*b1906ceaSLachlan Hodges /* number of symbols in default packet size */
402*b1906ceaSLachlan Hodges n_sym = avg_bits / n_sym;
403*b1906ceaSLachlan Hodges
404*b1906ceaSLachlan Hodges /* tx is time to transmit average packet in us */
405*b1906ceaSLachlan Hodges switch (rate->guard) {
406*b1906ceaSLachlan Hodges case (MMRC_GUARD_LONG):
407*b1906ceaSLachlan Hodges tx = n_sym * FP_8_LONG_GUARD_SYMBOL_TIME;
408*b1906ceaSLachlan Hodges break;
409*b1906ceaSLachlan Hodges case (MMRC_GUARD_SHORT):
410*b1906ceaSLachlan Hodges tx = n_sym * FP_8_SHORT_GUARD_SYMBOL_TIME;
411*b1906ceaSLachlan Hodges break;
412*b1906ceaSLachlan Hodges default:
413*b1906ceaSLachlan Hodges return 0;
414*b1906ceaSLachlan Hodges }
415*b1906ceaSLachlan Hodges
416*b1906ceaSLachlan Hodges return (tx * 10) >> FP_8_SHIFT;
417*b1906ceaSLachlan Hodges }
418*b1906ceaSLachlan Hodges
mmrc_calculate_theoretical_throughput(struct mmrc_rate rate)419*b1906ceaSLachlan Hodges u32 mmrc_calculate_theoretical_throughput(struct mmrc_rate rate)
420*b1906ceaSLachlan Hodges {
421*b1906ceaSLachlan Hodges static const u32 s1g_tpt_lgi[4][11] = {
422*b1906ceaSLachlan Hodges { 300, 600, 900, 1200, 1800, 2400, 2700, 3000, 3600, 4000,
423*b1906ceaSLachlan Hodges 150 },
424*b1906ceaSLachlan Hodges { 650, 1300, 1950, 2600, 3900, 5200, 5850, 6500, 7800, 0, 0 },
425*b1906ceaSLachlan Hodges { 1350, 2700, 4050, 5400, 8100, 10800, 12150, 13500, 16200,
426*b1906ceaSLachlan Hodges 18000, 0 },
427*b1906ceaSLachlan Hodges { 2925, 5850, 8775, 11700, 17550, 23400, 26325, 29250, 35100,
428*b1906ceaSLachlan Hodges 39000, 0 },
429*b1906ceaSLachlan Hodges };
430*b1906ceaSLachlan Hodges
431*b1906ceaSLachlan Hodges static const u32 s1g_tpt_sgi[4][11] = {
432*b1906ceaSLachlan Hodges { 333, 666, 1000, 1333, 2000, 2666, 3000, 3333, 4000, 4444,
433*b1906ceaSLachlan Hodges 166 },
434*b1906ceaSLachlan Hodges { 722, 1444, 2166, 2888, 4333, 5777, 6500, 7222, 8666, 0, 0 },
435*b1906ceaSLachlan Hodges { 1500, 3000, 4500, 6000, 9000, 12000, 13500, 15000, 18000,
436*b1906ceaSLachlan Hodges 20000, 0 },
437*b1906ceaSLachlan Hodges { 3250, 6500, 9750, 13000, 19500, 26000, 29250, 32500, 39000,
438*b1906ceaSLachlan Hodges 43333, 0 },
439*b1906ceaSLachlan Hodges };
440*b1906ceaSLachlan Hodges
441*b1906ceaSLachlan Hodges if (rate.guard)
442*b1906ceaSLachlan Hodges return s1g_tpt_sgi[rate.bw][rate.rate] * 1000 * (rate.ss + 1);
443*b1906ceaSLachlan Hodges
444*b1906ceaSLachlan Hodges return s1g_tpt_lgi[rate.bw][rate.rate] * 1000 * (rate.ss + 1);
445*b1906ceaSLachlan Hodges }
446*b1906ceaSLachlan Hodges
calculate_throughput(struct mmrc_table * tb,u8 index)447*b1906ceaSLachlan Hodges static u32 calculate_throughput(struct mmrc_table *tb, u8 index)
448*b1906ceaSLachlan Hodges {
449*b1906ceaSLachlan Hodges struct mmrc_rate rate = get_rate_row(tb, index);
450*b1906ceaSLachlan Hodges
451*b1906ceaSLachlan Hodges /*
452*b1906ceaSLachlan Hodges * Avoid the overflow (observed for 8MHz MCS9 rate: 43333) by dividing
453*b1906ceaSLachlan Hodges * first before multiplying. Should not experience any loss of
454*b1906ceaSLachlan Hodges * precision as the throughput is already multiplied by 1000 in
455*b1906ceaSLachlan Hodges * mmrc_calculate_theoretical_throughput (returned as bits/sec)
456*b1906ceaSLachlan Hodges */
457*b1906ceaSLachlan Hodges if (tb->table[rate.index].prob < 10)
458*b1906ceaSLachlan Hodges return 0;
459*b1906ceaSLachlan Hodges else if (rate.index == tb->best_tp.index && tb->interference_likely)
460*b1906ceaSLachlan Hodges /*
461*b1906ceaSLachlan Hodges * Assist the best rate by increasing the probability by the
462*b1906ceaSLachlan Hodges * averaged variation
463*b1906ceaSLachlan Hodges */
464*b1906ceaSLachlan Hodges return (mmrc_calculate_theoretical_throughput(rate) / 100) *
465*b1906ceaSLachlan Hodges (tb->table[rate.index].prob + tb->probability_variation);
466*b1906ceaSLachlan Hodges else
467*b1906ceaSLachlan Hodges return (mmrc_calculate_theoretical_throughput(rate) / 100) *
468*b1906ceaSLachlan Hodges tb->table[rate.index].prob;
469*b1906ceaSLachlan Hodges }
470*b1906ceaSLachlan Hodges
validate_rate(struct mmrc_table * tb,struct mmrc_rate * rate)471*b1906ceaSLachlan Hodges static bool validate_rate(struct mmrc_table *tb, struct mmrc_rate *rate)
472*b1906ceaSLachlan Hodges {
473*b1906ceaSLachlan Hodges if (rate->rate == MMRC_MCS10 &&
474*b1906ceaSLachlan Hodges (rate->bw != MMRC_BW_1MHZ || rate->ss != MMRC_SPATIAL_STREAM_1)) {
475*b1906ceaSLachlan Hodges /*
476*b1906ceaSLachlan Hodges * 802.11ah does not support MCS10 with BW that is not 1MHz or
477*b1906ceaSLachlan Hodges * not 1 spatial stream.
478*b1906ceaSLachlan Hodges */
479*b1906ceaSLachlan Hodges return false;
480*b1906ceaSLachlan Hodges }
481*b1906ceaSLachlan Hodges
482*b1906ceaSLachlan Hodges if (rate->rate == MMRC_MCS9 && rate->bw == MMRC_BW_2MHZ &&
483*b1906ceaSLachlan Hodges rate->ss != MMRC_SPATIAL_STREAM_3) {
484*b1906ceaSLachlan Hodges /*
485*b1906ceaSLachlan Hodges * 802.11ah does not support MCS9 at 2MHz for 1, 2 or 4 spatial
486*b1906ceaSLachlan Hodges * streams
487*b1906ceaSLachlan Hodges */
488*b1906ceaSLachlan Hodges return false;
489*b1906ceaSLachlan Hodges }
490*b1906ceaSLachlan Hodges
491*b1906ceaSLachlan Hodges if (rate->guard == MMRC_GUARD_SHORT &&
492*b1906ceaSLachlan Hodges !(tb->caps.sgi_per_bw & SGI_PER_BW(rate->bw)))
493*b1906ceaSLachlan Hodges return false;
494*b1906ceaSLachlan Hodges
495*b1906ceaSLachlan Hodges return true;
496*b1906ceaSLachlan Hodges }
497*b1906ceaSLachlan Hodges
find_baseline_index(struct mmrc_table * tb)498*b1906ceaSLachlan Hodges static u16 find_baseline_index(struct mmrc_table *tb)
499*b1906ceaSLachlan Hodges {
500*b1906ceaSLachlan Hodges u32 i, theoretical_tp, min_theoretical_tp;
501*b1906ceaSLachlan Hodges u16 row_count = rows_from_sta_caps(&tb->caps);
502*b1906ceaSLachlan Hodges u16 min_theoretical_tp_index = 0;
503*b1906ceaSLachlan Hodges struct mmrc_rate rate;
504*b1906ceaSLachlan Hodges
505*b1906ceaSLachlan Hodges if (tb->caps.rates & BIT(MMRC_MCS10))
506*b1906ceaSLachlan Hodges return 0;
507*b1906ceaSLachlan Hodges
508*b1906ceaSLachlan Hodges min_theoretical_tp =
509*b1906ceaSLachlan Hodges mmrc_calculate_theoretical_throughput(get_rate_row(tb, 0));
510*b1906ceaSLachlan Hodges for (i = 0; i < row_count; i++) {
511*b1906ceaSLachlan Hodges rate = get_rate_row(tb, i);
512*b1906ceaSLachlan Hodges if (!validate_rate(tb, &rate))
513*b1906ceaSLachlan Hodges continue;
514*b1906ceaSLachlan Hodges
515*b1906ceaSLachlan Hodges theoretical_tp = mmrc_calculate_theoretical_throughput(rate);
516*b1906ceaSLachlan Hodges if (min_theoretical_tp > theoretical_tp) {
517*b1906ceaSLachlan Hodges min_theoretical_tp = theoretical_tp;
518*b1906ceaSLachlan Hodges min_theoretical_tp_index = rate.index;
519*b1906ceaSLachlan Hodges }
520*b1906ceaSLachlan Hodges }
521*b1906ceaSLachlan Hodges
522*b1906ceaSLachlan Hodges return min_theoretical_tp_index;
523*b1906ceaSLachlan Hodges }
524*b1906ceaSLachlan Hodges
525*b1906ceaSLachlan Hodges /*
526*b1906ceaSLachlan Hodges * Fill out the remaining rates to be used once the best rate is selected.
527*b1906ceaSLachlan Hodges * Normally the retry rates are one MCS lower than the previous, however in
528*b1906ceaSLachlan Hodges * unconverged mode we limit the 3 respective retry rates to MCS 4, 2 and 0
529*b1906ceaSLachlan Hodges * respectively. The last retry rate is always MCS 0
530*b1906ceaSLachlan Hodges */
mmrc_fill_retry_rates(struct mmrc_table * tb)531*b1906ceaSLachlan Hodges static void mmrc_fill_retry_rates(struct mmrc_table *tb)
532*b1906ceaSLachlan Hodges {
533*b1906ceaSLachlan Hodges tb->second_tp = tb->best_tp;
534*b1906ceaSLachlan Hodges if (tb->second_tp.rate != MMRC_MCS0) {
535*b1906ceaSLachlan Hodges tb->second_tp.rate--;
536*b1906ceaSLachlan Hodges if (tb->unconverged && tb->second_tp.rate > MMRC_MCS4)
537*b1906ceaSLachlan Hodges tb->second_tp.rate = MMRC_MCS4;
538*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->second_tp);
539*b1906ceaSLachlan Hodges } else if (tb->second_tp.bw > MMRC_BW_1MHZ) {
540*b1906ceaSLachlan Hodges tb->second_tp.bw--;
541*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->second_tp);
542*b1906ceaSLachlan Hodges }
543*b1906ceaSLachlan Hodges
544*b1906ceaSLachlan Hodges tb->best_prob = tb->second_tp;
545*b1906ceaSLachlan Hodges if (tb->best_prob.rate != MMRC_MCS0) {
546*b1906ceaSLachlan Hodges tb->best_prob.rate--;
547*b1906ceaSLachlan Hodges if (tb->unconverged && tb->best_prob.rate > MMRC_MCS2)
548*b1906ceaSLachlan Hodges tb->best_prob.rate = MMRC_MCS2;
549*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->best_prob);
550*b1906ceaSLachlan Hodges } else if (tb->best_prob.bw > MMRC_BW_1MHZ) {
551*b1906ceaSLachlan Hodges tb->best_prob.bw--;
552*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->best_prob);
553*b1906ceaSLachlan Hodges }
554*b1906ceaSLachlan Hodges
555*b1906ceaSLachlan Hodges tb->baseline = tb->best_prob;
556*b1906ceaSLachlan Hodges if (tb->baseline.rate != MMRC_MCS0) {
557*b1906ceaSLachlan Hodges tb->baseline.rate = MMRC_MCS0;
558*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->baseline);
559*b1906ceaSLachlan Hodges } else if (tb->baseline.bw > MMRC_BW_1MHZ) {
560*b1906ceaSLachlan Hodges tb->baseline.bw--;
561*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->baseline);
562*b1906ceaSLachlan Hodges }
563*b1906ceaSLachlan Hodges }
564*b1906ceaSLachlan Hodges
565*b1906ceaSLachlan Hodges /*
566*b1906ceaSLachlan Hodges * Updates the mmrc_table with the appropriate rate priority based on the
567*b1906ceaSLachlan Hodges * latest update statistics
568*b1906ceaSLachlan Hodges */
generate_table_priority(struct mmrc_table * tb,u32 new_stats)569*b1906ceaSLachlan Hodges static void generate_table_priority(struct mmrc_table *tb, u32 new_stats)
570*b1906ceaSLachlan Hodges {
571*b1906ceaSLachlan Hodges u16 i;
572*b1906ceaSLachlan Hodges u16 best_row = tb->best_tp.index;
573*b1906ceaSLachlan Hodges u16 prev_best_row = best_row;
574*b1906ceaSLachlan Hodges u8 prev_best_rate = tb->best_tp.rate;
575*b1906ceaSLachlan Hodges u16 second_best_row = tb->second_tp.index;
576*b1906ceaSLachlan Hodges u32 best_tp = calculate_throughput(tb, best_row);
577*b1906ceaSLachlan Hodges u32 second_best_tp = calculate_throughput(tb, second_best_row);
578*b1906ceaSLachlan Hodges u32 last_nonzero_prob = 0;
579*b1906ceaSLachlan Hodges struct mmrc_rate tmp;
580*b1906ceaSLachlan Hodges u32 tmp_tp;
581*b1906ceaSLachlan Hodges
582*b1906ceaSLachlan Hodges /* Use fixed rate if set */
583*b1906ceaSLachlan Hodges if (tb->fixed_rate.rate != MMRC_MCS_UNUSED) {
584*b1906ceaSLachlan Hodges tb->best_tp = tb->fixed_rate;
585*b1906ceaSLachlan Hodges tb->second_tp = tb->fixed_rate;
586*b1906ceaSLachlan Hodges tb->best_prob = tb->fixed_rate;
587*b1906ceaSLachlan Hodges return;
588*b1906ceaSLachlan Hodges }
589*b1906ceaSLachlan Hodges
590*b1906ceaSLachlan Hodges for (i = 0; i < rows_from_sta_caps(&tb->caps); i++) {
591*b1906ceaSLachlan Hodges tmp = get_rate_row(tb, i);
592*b1906ceaSLachlan Hodges if (!validate_rate(tb, &tmp))
593*b1906ceaSLachlan Hodges continue;
594*b1906ceaSLachlan Hodges
595*b1906ceaSLachlan Hodges if (tb->table[tmp.index].evidence == 0)
596*b1906ceaSLachlan Hodges continue;
597*b1906ceaSLachlan Hodges
598*b1906ceaSLachlan Hodges /*
599*b1906ceaSLachlan Hodges * Besides better throughput, also consider this rate better if
600*b1906ceaSLachlan Hodges * lower rates had worse probability. That indicates the rate
601*b1906ceaSLachlan Hodges * itself is not the problem. Only do the probability check for
602*b1906ceaSLachlan Hodges * rates up to the previous best rate.
603*b1906ceaSLachlan Hodges */
604*b1906ceaSLachlan Hodges tmp_tp = calculate_throughput(tb, tmp.index);
605*b1906ceaSLachlan Hodges
606*b1906ceaSLachlan Hodges if (tmp_tp > best_tp ||
607*b1906ceaSLachlan Hodges (tb->table[tmp.index].max_throughput <=
608*b1906ceaSLachlan Hodges tb->table[prev_best_row].max_throughput &&
609*b1906ceaSLachlan Hodges tb->table[tmp.index].prob >=
610*b1906ceaSLachlan Hodges PROBABILITY_DIP_RECOVERY_MIN &&
611*b1906ceaSLachlan Hodges tb->table[tmp.index].prob >
612*b1906ceaSLachlan Hodges tb->table[last_nonzero_prob].prob)) {
613*b1906ceaSLachlan Hodges second_best_row = best_row;
614*b1906ceaSLachlan Hodges second_best_tp = best_tp;
615*b1906ceaSLachlan Hodges
616*b1906ceaSLachlan Hodges best_tp = tmp_tp;
617*b1906ceaSLachlan Hodges best_row = tmp.index;
618*b1906ceaSLachlan Hodges } else if (tmp_tp > second_best_tp && best_row != tmp.index) {
619*b1906ceaSLachlan Hodges second_best_tp = tmp_tp;
620*b1906ceaSLachlan Hodges second_best_row = tmp.index;
621*b1906ceaSLachlan Hodges }
622*b1906ceaSLachlan Hodges
623*b1906ceaSLachlan Hodges if (tb->table[tmp.index].prob >= PROBABILITY_DIP_MIN &&
624*b1906ceaSLachlan Hodges tb->table[tmp.index].max_throughput >=
625*b1906ceaSLachlan Hodges tb->table[last_nonzero_prob].max_throughput)
626*b1906ceaSLachlan Hodges last_nonzero_prob = tmp.index;
627*b1906ceaSLachlan Hodges }
628*b1906ceaSLachlan Hodges
629*b1906ceaSLachlan Hodges /* Only update rates and stability when there are new statistics */
630*b1906ceaSLachlan Hodges if (!new_stats)
631*b1906ceaSLachlan Hodges return;
632*b1906ceaSLachlan Hodges
633*b1906ceaSLachlan Hodges tb->best_tp = get_rate_row(tb, best_row);
634*b1906ceaSLachlan Hodges if (best_tp == 0 && tb->best_tp.rate > MMRC_MCS0) {
635*b1906ceaSLachlan Hodges /* Drop one rate, as the best throughput is zero */
636*b1906ceaSLachlan Hodges tb->best_tp.rate--;
637*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->best_tp);
638*b1906ceaSLachlan Hodges }
639*b1906ceaSLachlan Hodges tb->second_tp = get_rate_row(tb, second_best_row);
640*b1906ceaSLachlan Hodges mmrc_fill_retry_rates(tb);
641*b1906ceaSLachlan Hodges
642*b1906ceaSLachlan Hodges if (tb->best_tp.rate > MMRC_MCS1 && prev_best_row == best_row) {
643*b1906ceaSLachlan Hodges /* Increase the counter when the best rate is not changed */
644*b1906ceaSLachlan Hodges tb->stability_cnt++;
645*b1906ceaSLachlan Hodges } else if (tb->stability_cnt > STABILITY_BACKOFF_STEP) {
646*b1906ceaSLachlan Hodges /* Back off the counter when there is a new best rate */
647*b1906ceaSLachlan Hodges tb->stability_cnt -= STABILITY_BACKOFF_STEP;
648*b1906ceaSLachlan Hodges } else {
649*b1906ceaSLachlan Hodges tb->stability_cnt = 0;
650*b1906ceaSLachlan Hodges }
651*b1906ceaSLachlan Hodges
652*b1906ceaSLachlan Hodges if (prev_best_row != best_row) {
653*b1906ceaSLachlan Hodges s8 latest_best_rate_diff = prev_best_rate - tb->best_tp.rate;
654*b1906ceaSLachlan Hodges u8 total_abs_best_rate_diff =
655*b1906ceaSLachlan Hodges abs(tb->best_rate_diff[0] + tb->best_rate_diff[1] +
656*b1906ceaSLachlan Hodges latest_best_rate_diff);
657*b1906ceaSLachlan Hodges
658*b1906ceaSLachlan Hodges if (!tb->interference_likely) {
659*b1906ceaSLachlan Hodges tb->probability_variation = 0;
660*b1906ceaSLachlan Hodges if (!tb->unconverged &&
661*b1906ceaSLachlan Hodges tb->best_rate_cycle_count <=
662*b1906ceaSLachlan Hodges BEST_RATE_UNSTABLE_THRESHOLD &&
663*b1906ceaSLachlan Hodges total_abs_best_rate_diff >= 2) {
664*b1906ceaSLachlan Hodges /*
665*b1906ceaSLachlan Hodges * Best rate has changed twice in a few cycles
666*b1906ceaSLachlan Hodges * and moved at least 2 MCSs from where it was
667*b1906ceaSLachlan Hodges * 3 best rate changes ago
668*b1906ceaSLachlan Hodges */
669*b1906ceaSLachlan Hodges tb->unconverged = true;
670*b1906ceaSLachlan Hodges tb->newly_unconverged = true;
671*b1906ceaSLachlan Hodges }
672*b1906ceaSLachlan Hodges }
673*b1906ceaSLachlan Hodges if (tb->unconverged && !tb->newly_unconverged &&
674*b1906ceaSLachlan Hodges total_abs_best_rate_diff < 2) {
675*b1906ceaSLachlan Hodges /*
676*b1906ceaSLachlan Hodges * Best rate has been relatively stable (not moved more
677*b1906ceaSLachlan Hodges * than 1 MCS after the last 3 rate changes), go back
678*b1906ceaSLachlan Hodges * to converged
679*b1906ceaSLachlan Hodges */
680*b1906ceaSLachlan Hodges tb->unconverged = false;
681*b1906ceaSLachlan Hodges }
682*b1906ceaSLachlan Hodges tb->probability_variation_direction = 0;
683*b1906ceaSLachlan Hodges tb->best_rate_cycle_count = 0;
684*b1906ceaSLachlan Hodges tb->best_rate_diff[0] = tb->best_rate_diff[1];
685*b1906ceaSLachlan Hodges tb->best_rate_diff[1] = latest_best_rate_diff;
686*b1906ceaSLachlan Hodges } else {
687*b1906ceaSLachlan Hodges tb->best_rate_cycle_count++;
688*b1906ceaSLachlan Hodges if (tb->unconverged && !tb->newly_unconverged &&
689*b1906ceaSLachlan Hodges tb->best_rate_cycle_count >=
690*b1906ceaSLachlan Hodges BEST_RATE_CONVERGED_THRESHOLD) {
691*b1906ceaSLachlan Hodges /*
692*b1906ceaSLachlan Hodges * Best rate has been stable for a while, go back to
693*b1906ceaSLachlan Hodges * converged
694*b1906ceaSLachlan Hodges */
695*b1906ceaSLachlan Hodges tb->unconverged = false;
696*b1906ceaSLachlan Hodges }
697*b1906ceaSLachlan Hodges }
698*b1906ceaSLachlan Hodges
699*b1906ceaSLachlan Hodges if (tb->newly_unconverged)
700*b1906ceaSLachlan Hodges tb->newly_unconverged = false;
701*b1906ceaSLachlan Hodges }
702*b1906ceaSLachlan Hodges
calculate_attempt_time(struct mmrc_rate * rate,size_t size)703*b1906ceaSLachlan Hodges static u32 calculate_attempt_time(struct mmrc_rate *rate, size_t size)
704*b1906ceaSLachlan Hodges {
705*b1906ceaSLachlan Hodges u32 time;
706*b1906ceaSLachlan Hodges
707*b1906ceaSLachlan Hodges time = get_tx_time(rate);
708*b1906ceaSLachlan Hodges
709*b1906ceaSLachlan Hodges if (size > DEFAULT_PACKET_SIZE_BYTES)
710*b1906ceaSLachlan Hodges time = (time * ((size * 1000) / DEFAULT_PACKET_SIZE_BYTES)) /
711*b1906ceaSLachlan Hodges 1000;
712*b1906ceaSLachlan Hodges else
713*b1906ceaSLachlan Hodges time = (time * 1000) /
714*b1906ceaSLachlan Hodges ((DEFAULT_PACKET_SIZE_BYTES * 1000) / size);
715*b1906ceaSLachlan Hodges
716*b1906ceaSLachlan Hodges return time;
717*b1906ceaSLachlan Hodges }
718*b1906ceaSLachlan Hodges
mmrc_calculate_rate_tx_time(struct mmrc_rate * rate,size_t size)719*b1906ceaSLachlan Hodges u32 mmrc_calculate_rate_tx_time(struct mmrc_rate *rate, size_t size)
720*b1906ceaSLachlan Hodges {
721*b1906ceaSLachlan Hodges u8 i;
722*b1906ceaSLachlan Hodges u32 total_time = 0;
723*b1906ceaSLachlan Hodges
724*b1906ceaSLachlan Hodges for (i = 0; i < rate->attempts; i++)
725*b1906ceaSLachlan Hodges total_time += calculate_attempt_time(rate, size);
726*b1906ceaSLachlan Hodges
727*b1906ceaSLachlan Hodges return total_time;
728*b1906ceaSLachlan Hodges }
729*b1906ceaSLachlan Hodges
730*b1906ceaSLachlan Hodges /*
731*b1906ceaSLachlan Hodges * Calculates the appropriate amount of additional attempts to make based on
732*b1906ceaSLachlan Hodges * packet size and theoretical throughput.
733*b1906ceaSLachlan Hodges */
calculate_remaining_attempts(struct mmrc_table * tb,struct mmrc_rate_table * rate,s32 * rem_time,size_t size)734*b1906ceaSLachlan Hodges static void calculate_remaining_attempts(struct mmrc_table *tb,
735*b1906ceaSLachlan Hodges struct mmrc_rate_table *rate,
736*b1906ceaSLachlan Hodges s32 *rem_time, size_t size)
737*b1906ceaSLachlan Hodges {
738*b1906ceaSLachlan Hodges size_t i;
739*b1906ceaSLachlan Hodges
740*b1906ceaSLachlan Hodges if (*rem_time <= 0)
741*b1906ceaSLachlan Hodges return;
742*b1906ceaSLachlan Hodges
743*b1906ceaSLachlan Hodges for (i = 0; i < MMRC_MAX_CHAIN_LENGTH; i++) {
744*b1906ceaSLachlan Hodges u32 attempt_time;
745*b1906ceaSLachlan Hodges u32 attempt;
746*b1906ceaSLachlan Hodges
747*b1906ceaSLachlan Hodges if (rate->rates[i].rate == MMRC_MCS_UNUSED)
748*b1906ceaSLachlan Hodges break;
749*b1906ceaSLachlan Hodges
750*b1906ceaSLachlan Hodges /*
751*b1906ceaSLachlan Hodges * The attempts for these rates were calculated in the initial
752*b1906ceaSLachlan Hodges * attempt allocation
753*b1906ceaSLachlan Hodges */
754*b1906ceaSLachlan Hodges if (tb->table[rate->rates[i].index].prob < 20)
755*b1906ceaSLachlan Hodges continue;
756*b1906ceaSLachlan Hodges
757*b1906ceaSLachlan Hodges if (i == 0 && (calculate_throughput(tb, rate->rates[i].index) <
758*b1906ceaSLachlan Hodges calculate_throughput(tb, tb->best_prob.index)))
759*b1906ceaSLachlan Hodges continue;
760*b1906ceaSLachlan Hodges
761*b1906ceaSLachlan Hodges attempt_time = calculate_attempt_time(&rate->rates[i], size);
762*b1906ceaSLachlan Hodges if (!attempt_time)
763*b1906ceaSLachlan Hodges continue;
764*b1906ceaSLachlan Hodges
765*b1906ceaSLachlan Hodges attempt = (*rem_time / tb->caps.max_rates) / attempt_time;
766*b1906ceaSLachlan Hodges attempt += rate->rates[i].attempts;
767*b1906ceaSLachlan Hodges
768*b1906ceaSLachlan Hodges rate->rates[i].attempts = MMRC_ATTEMPTS_TO_BITFIELD(
769*b1906ceaSLachlan Hodges attempt > MMRC_MAX_CHAIN_ATTEMPTS ?
770*b1906ceaSLachlan Hodges MMRC_MAX_CHAIN_ATTEMPTS :
771*b1906ceaSLachlan Hodges attempt);
772*b1906ceaSLachlan Hodges }
773*b1906ceaSLachlan Hodges }
774*b1906ceaSLachlan Hodges
775*b1906ceaSLachlan Hodges /* Allocate initial attempts to all rates in a rate table */
allocate_initial_attempts(struct mmrc_rate_table * rate,s32 * rem_time,size_t size)776*b1906ceaSLachlan Hodges static void allocate_initial_attempts(struct mmrc_rate_table *rate,
777*b1906ceaSLachlan Hodges s32 *rem_time, size_t size)
778*b1906ceaSLachlan Hodges {
779*b1906ceaSLachlan Hodges u32 i;
780*b1906ceaSLachlan Hodges
781*b1906ceaSLachlan Hodges for (i = 0; i < MMRC_MAX_CHAIN_LENGTH; i++) {
782*b1906ceaSLachlan Hodges u32 attempt_time;
783*b1906ceaSLachlan Hodges
784*b1906ceaSLachlan Hodges if (rate->rates[i].rate == MMRC_MCS_UNUSED)
785*b1906ceaSLachlan Hodges break;
786*b1906ceaSLachlan Hodges
787*b1906ceaSLachlan Hodges attempt_time = calculate_attempt_time(&rate->rates[i], size);
788*b1906ceaSLachlan Hodges
789*b1906ceaSLachlan Hodges /*
790*b1906ceaSLachlan Hodges * if the time for a single attempt is very long, lets just
791*b1906ceaSLachlan Hodges * try once
792*b1906ceaSLachlan Hodges */
793*b1906ceaSLachlan Hodges if (attempt_time > MAX_WINDOW_ATTEMPT_TIME) {
794*b1906ceaSLachlan Hodges *rem_time -= attempt_time;
795*b1906ceaSLachlan Hodges rate->rates[i].attempts = MMRC_ATTEMPTS_TO_BITFIELD(1);
796*b1906ceaSLachlan Hodges } else {
797*b1906ceaSLachlan Hodges *rem_time -= attempt_time * 2;
798*b1906ceaSLachlan Hodges rate->rates[i].attempts = MMRC_ATTEMPTS_TO_BITFIELD(2);
799*b1906ceaSLachlan Hodges }
800*b1906ceaSLachlan Hodges }
801*b1906ceaSLachlan Hodges }
802*b1906ceaSLachlan Hodges
mmrc_get_rates(struct mmrc_table * tb,struct mmrc_rate_table * out,size_t size)803*b1906ceaSLachlan Hodges void mmrc_get_rates(struct mmrc_table *tb, struct mmrc_rate_table *out,
804*b1906ceaSLachlan Hodges size_t size)
805*b1906ceaSLachlan Hodges {
806*b1906ceaSLachlan Hodges u8 i;
807*b1906ceaSLachlan Hodges u16 random_index;
808*b1906ceaSLachlan Hodges struct mmrc_rate random;
809*b1906ceaSLachlan Hodges struct mmrc_rate lookaround0 = tb->best_tp;
810*b1906ceaSLachlan Hodges struct mmrc_rate lookaround1 = tb->second_tp;
811*b1906ceaSLachlan Hodges bool is_lookaround;
812*b1906ceaSLachlan Hodges int lookaround_index = -1;
813*b1906ceaSLachlan Hodges int best_index = 0;
814*b1906ceaSLachlan Hodges int random_tp = 0;
815*b1906ceaSLachlan Hodges int best_tp;
816*b1906ceaSLachlan Hodges int lookaround_fail_count;
817*b1906ceaSLachlan Hodges bool try_current_lookaround = false;
818*b1906ceaSLachlan Hodges
819*b1906ceaSLachlan Hodges s32 rem_time = RATE_WINDOW_MICROSECONDS;
820*b1906ceaSLachlan Hodges
821*b1906ceaSLachlan Hodges memset(out, 0, sizeof(*out));
822*b1906ceaSLachlan Hodges
823*b1906ceaSLachlan Hodges tb->lookaround_cnt = (tb->lookaround_cnt + 1) % tb->lookaround_wrap;
824*b1906ceaSLachlan Hodges /*
825*b1906ceaSLachlan Hodges * Look around if the counter wraps or there has been no look around
826*b1906ceaSLachlan Hodges * for a number of rate control cycles.
827*b1906ceaSLachlan Hodges */
828*b1906ceaSLachlan Hodges is_lookaround = (tb->fixed_rate.rate == MMRC_MCS_UNUSED) &&
829*b1906ceaSLachlan Hodges ((tb->lookaround_cnt == 0) ||
830*b1906ceaSLachlan Hodges ((tb->last_lookaround_cycle +
831*b1906ceaSLachlan Hodges LOOKAROUND_MAX_RC_CYCLES) <= tb->cycle_cnt));
832*b1906ceaSLachlan Hodges
833*b1906ceaSLachlan Hodges /* Also skip sampling if we don't yet have data for our best rate */
834*b1906ceaSLachlan Hodges if (tb->table[tb->best_tp.index].evidence == 0)
835*b1906ceaSLachlan Hodges is_lookaround = false;
836*b1906ceaSLachlan Hodges
837*b1906ceaSLachlan Hodges if (tb->lookaround_wrap != LOOKAROUND_RATE_STABLE) {
838*b1906ceaSLachlan Hodges if (tb->stability_cnt >= tb->stability_cnt_threshold) {
839*b1906ceaSLachlan Hodges tb->lookaround_wrap = LOOKAROUND_RATE_STABLE;
840*b1906ceaSLachlan Hodges tb->stability_cnt_threshold =
841*b1906ceaSLachlan Hodges STABILITY_CNT_THRESHOLD_STABLE;
842*b1906ceaSLachlan Hodges tb->stability_cnt = STABILITY_CNT_THRESHOLD_STABLE * 2;
843*b1906ceaSLachlan Hodges is_lookaround = false;
844*b1906ceaSLachlan Hodges }
845*b1906ceaSLachlan Hodges } else if (tb->stability_cnt < tb->stability_cnt_threshold) {
846*b1906ceaSLachlan Hodges tb->stability_cnt_threshold = STABILITY_CNT_THRESHOLD_NORMAL;
847*b1906ceaSLachlan Hodges tb->lookaround_wrap = LOOKAROUND_RATE_NORMAL;
848*b1906ceaSLachlan Hodges tb->stability_cnt = 0;
849*b1906ceaSLachlan Hodges }
850*b1906ceaSLachlan Hodges
851*b1906ceaSLachlan Hodges /* Look around only when the fixed rate is not set */
852*b1906ceaSLachlan Hodges if (is_lookaround) {
853*b1906ceaSLachlan Hodges tb->total_lookaround++;
854*b1906ceaSLachlan Hodges tb->forced_lookaround =
855*b1906ceaSLachlan Hodges (tb->forced_lookaround + 1) % LOOKAROUND_RATE_NORMAL;
856*b1906ceaSLachlan Hodges tb->last_lookaround_cycle = tb->cycle_cnt;
857*b1906ceaSLachlan Hodges
858*b1906ceaSLachlan Hodges if (tb->current_lookaround_rate_attempts <
859*b1906ceaSLachlan Hodges LOOKAROUND_RATE_ATTEMPTS)
860*b1906ceaSLachlan Hodges try_current_lookaround = true;
861*b1906ceaSLachlan Hodges
862*b1906ceaSLachlan Hodges best_tp = calculate_throughput(tb, tb->best_tp.index);
863*b1906ceaSLachlan Hodges
864*b1906ceaSLachlan Hodges for (lookaround_fail_count = 0;
865*b1906ceaSLachlan Hodges lookaround_fail_count < LOOKAROUND_FAIL_MAX;
866*b1906ceaSLachlan Hodges lookaround_fail_count++) {
867*b1906ceaSLachlan Hodges if (try_current_lookaround) {
868*b1906ceaSLachlan Hodges random_index =
869*b1906ceaSLachlan Hodges tb->current_lookaround_rate_index;
870*b1906ceaSLachlan Hodges try_current_lookaround = false;
871*b1906ceaSLachlan Hodges } else {
872*b1906ceaSLachlan Hodges random_index = get_random_u32_below(
873*b1906ceaSLachlan Hodges rows_from_sta_caps(&tb->caps));
874*b1906ceaSLachlan Hodges }
875*b1906ceaSLachlan Hodges random = get_rate_row(tb, random_index);
876*b1906ceaSLachlan Hodges
877*b1906ceaSLachlan Hodges if (!validate_rate(tb, &random))
878*b1906ceaSLachlan Hodges continue;
879*b1906ceaSLachlan Hodges
880*b1906ceaSLachlan Hodges if (random.rate == MMRC_MCS10)
881*b1906ceaSLachlan Hodges continue;
882*b1906ceaSLachlan Hodges
883*b1906ceaSLachlan Hodges if (tb->table[random_index].evidence > 0)
884*b1906ceaSLachlan Hodges random_tp =
885*b1906ceaSLachlan Hodges calculate_throughput(tb, random_index);
886*b1906ceaSLachlan Hodges else
887*b1906ceaSLachlan Hodges random_tp =
888*b1906ceaSLachlan Hodges mmrc_calculate_theoretical_throughput(
889*b1906ceaSLachlan Hodges random);
890*b1906ceaSLachlan Hodges
891*b1906ceaSLachlan Hodges /*
892*b1906ceaSLachlan Hodges * Skip rates that can only be worse than the current
893*b1906ceaSLachlan Hodges * best
894*b1906ceaSLachlan Hodges */
895*b1906ceaSLachlan Hodges if (random_tp <= best_tp)
896*b1906ceaSLachlan Hodges continue;
897*b1906ceaSLachlan Hodges
898*b1906ceaSLachlan Hodges /*
899*b1906ceaSLachlan Hodges * Force looking up the rate no more that one MCS.
900*b1906ceaSLachlan Hodges * It will avoid looking for rates with very low
901*b1906ceaSLachlan Hodges * success rate. In case of better environment
902*b1906ceaSLachlan Hodges * conditions MMRC will collect enough statistics to
903*b1906ceaSLachlan Hodges * climb up the rates one by one.
904*b1906ceaSLachlan Hodges */
905*b1906ceaSLachlan Hodges if (random.rate > tb->best_tp.rate + 1 ||
906*b1906ceaSLachlan Hodges random.bw > tb->best_tp.bw + 1 ||
907*b1906ceaSLachlan Hodges (random.rate > tb->best_tp.rate &&
908*b1906ceaSLachlan Hodges random.bw > tb->best_tp.bw))
909*b1906ceaSLachlan Hodges continue;
910*b1906ceaSLachlan Hodges
911*b1906ceaSLachlan Hodges if (tb->current_lookaround_rate_index == random_index) {
912*b1906ceaSLachlan Hodges tb->current_lookaround_rate_attempts++;
913*b1906ceaSLachlan Hodges } else {
914*b1906ceaSLachlan Hodges tb->current_lookaround_rate_attempts = 0;
915*b1906ceaSLachlan Hodges tb->current_lookaround_rate_index =
916*b1906ceaSLachlan Hodges random_index;
917*b1906ceaSLachlan Hodges }
918*b1906ceaSLachlan Hodges
919*b1906ceaSLachlan Hodges break;
920*b1906ceaSLachlan Hodges }
921*b1906ceaSLachlan Hodges
922*b1906ceaSLachlan Hodges if (lookaround_fail_count >= LOOKAROUND_FAIL_MAX) {
923*b1906ceaSLachlan Hodges is_lookaround = false;
924*b1906ceaSLachlan Hodges tb->current_lookaround_rate_index = tb->best_tp.index;
925*b1906ceaSLachlan Hodges } else {
926*b1906ceaSLachlan Hodges lookaround0 = random;
927*b1906ceaSLachlan Hodges lookaround1 = tb->best_tp;
928*b1906ceaSLachlan Hodges lookaround_index = 0;
929*b1906ceaSLachlan Hodges best_index = 1;
930*b1906ceaSLachlan Hodges }
931*b1906ceaSLachlan Hodges }
932*b1906ceaSLachlan Hodges
933*b1906ceaSLachlan Hodges if (tb->caps.max_rates == 1) {
934*b1906ceaSLachlan Hodges out->rates[0] = (is_lookaround) ? lookaround0 : tb->best_tp;
935*b1906ceaSLachlan Hodges out->rates[1].rate = MMRC_MCS_UNUSED;
936*b1906ceaSLachlan Hodges out->rates[2].rate = MMRC_MCS_UNUSED;
937*b1906ceaSLachlan Hodges out->rates[3].rate = MMRC_MCS_UNUSED;
938*b1906ceaSLachlan Hodges } else if (tb->caps.max_rates == 2) {
939*b1906ceaSLachlan Hodges out->rates[0] = (is_lookaround) ? lookaround0 : tb->best_tp;
940*b1906ceaSLachlan Hodges out->rates[1] = (is_lookaround) ? lookaround1 : tb->best_prob;
941*b1906ceaSLachlan Hodges out->rates[2].rate = MMRC_MCS_UNUSED;
942*b1906ceaSLachlan Hodges out->rates[3].rate = MMRC_MCS_UNUSED;
943*b1906ceaSLachlan Hodges } else if (tb->caps.max_rates == 3) {
944*b1906ceaSLachlan Hodges out->rates[0] = (is_lookaround) ? lookaround0 : tb->best_tp;
945*b1906ceaSLachlan Hodges out->rates[1] = (is_lookaround) ? lookaround1 : tb->second_tp;
946*b1906ceaSLachlan Hodges out->rates[2] = tb->best_prob;
947*b1906ceaSLachlan Hodges out->rates[3].rate = MMRC_MCS_UNUSED;
948*b1906ceaSLachlan Hodges } else {
949*b1906ceaSLachlan Hodges out->rates[0] = (is_lookaround) ? lookaround0 : tb->best_tp;
950*b1906ceaSLachlan Hodges out->rates[1] = (is_lookaround) ? lookaround1 : tb->second_tp;
951*b1906ceaSLachlan Hodges out->rates[2] = tb->best_prob;
952*b1906ceaSLachlan Hodges out->rates[3] = tb->baseline;
953*b1906ceaSLachlan Hodges }
954*b1906ceaSLachlan Hodges
955*b1906ceaSLachlan Hodges /* For fallback rates, set RTS/CTS */
956*b1906ceaSLachlan Hodges for (i = 1; i < MMRC_MAX_CHAIN_LENGTH; i++)
957*b1906ceaSLachlan Hodges out->rates[i].flags |= BIT(MMRC_FLAGS_CTS_RTS);
958*b1906ceaSLachlan Hodges
959*b1906ceaSLachlan Hodges /* Allocate initial attempts for rate */
960*b1906ceaSLachlan Hodges allocate_initial_attempts(out, &rem_time, size);
961*b1906ceaSLachlan Hodges
962*b1906ceaSLachlan Hodges /* Calculate and allocate remaining attempts */
963*b1906ceaSLachlan Hodges calculate_remaining_attempts(tb, out, &rem_time, size);
964*b1906ceaSLachlan Hodges
965*b1906ceaSLachlan Hodges /* Enforce limits on each attempts */
966*b1906ceaSLachlan Hodges for (i = 0; i < MMRC_MAX_CHAIN_LENGTH; i++) {
967*b1906ceaSLachlan Hodges if (out->rates[i].rate != MMRC_MCS_UNUSED) {
968*b1906ceaSLachlan Hodges out->rates[i].attempts =
969*b1906ceaSLachlan Hodges out->rates[i].attempts == 0 ?
970*b1906ceaSLachlan Hodges MMRC_ATTEMPTS_TO_BITFIELD(
971*b1906ceaSLachlan Hodges MMRC_MIN_CHAIN_ATTEMPTS) :
972*b1906ceaSLachlan Hodges out->rates[i].attempts;
973*b1906ceaSLachlan Hodges out->rates[i].attempts =
974*b1906ceaSLachlan Hodges out->rates[i].attempts >
975*b1906ceaSLachlan Hodges MMRC_MAX_CHAIN_ATTEMPTS ?
976*b1906ceaSLachlan Hodges MMRC_ATTEMPTS_TO_BITFIELD(
977*b1906ceaSLachlan Hodges MMRC_MAX_CHAIN_ATTEMPTS) :
978*b1906ceaSLachlan Hodges out->rates[i].attempts;
979*b1906ceaSLachlan Hodges if (i == lookaround_index &&
980*b1906ceaSLachlan Hodges tb->lookaround_wrap != LOOKAROUND_RATE_INIT)
981*b1906ceaSLachlan Hodges out->rates[i].attempts =
982*b1906ceaSLachlan Hodges MMRC_ATTEMPTS_TO_BITFIELD(1);
983*b1906ceaSLachlan Hodges }
984*b1906ceaSLachlan Hodges }
985*b1906ceaSLachlan Hodges
986*b1906ceaSLachlan Hodges /*
987*b1906ceaSLachlan Hodges * Give the best rate at least 2 attempts to keep peak throughput
988*b1906ceaSLachlan Hodges * unless it is too low
989*b1906ceaSLachlan Hodges */
990*b1906ceaSLachlan Hodges if (out->rates[best_index].attempts == 1 &&
991*b1906ceaSLachlan Hodges out->rates[best_index].rate > MMRC_MCS1)
992*b1906ceaSLachlan Hodges out->rates[best_index].attempts = MMRC_ATTEMPTS_TO_BITFIELD(2);
993*b1906ceaSLachlan Hodges else if (out->rates[best_index].rate <= MMRC_MCS1)
994*b1906ceaSLachlan Hodges out->rates[best_index].attempts = 1;
995*b1906ceaSLachlan Hodges }
996*b1906ceaSLachlan Hodges
calc_ewma_average(u32 avg,u32 latest,u32 weight)997*b1906ceaSLachlan Hodges static u32 calc_ewma_average(u32 avg, u32 latest, u32 weight)
998*b1906ceaSLachlan Hodges {
999*b1906ceaSLachlan Hodges WARN_ON_ONCE(!(weight <= 100));
1000*b1906ceaSLachlan Hodges
1001*b1906ceaSLachlan Hodges if (avg == 0)
1002*b1906ceaSLachlan Hodges return latest;
1003*b1906ceaSLachlan Hodges
1004*b1906ceaSLachlan Hodges return ((latest * (100 - weight)) + (avg * weight)) / 100;
1005*b1906ceaSLachlan Hodges }
1006*b1906ceaSLachlan Hodges
mmrc_process_variation(struct mmrc_table * tb,u16 current_success,u32 index)1007*b1906ceaSLachlan Hodges static void mmrc_process_variation(struct mmrc_table *tb, u16 current_success,
1008*b1906ceaSLachlan Hodges u32 index)
1009*b1906ceaSLachlan Hodges {
1010*b1906ceaSLachlan Hodges u32 current_variation;
1011*b1906ceaSLachlan Hodges
1012*b1906ceaSLachlan Hodges /*
1013*b1906ceaSLachlan Hodges * Only process probability variation for the best rate. It is likely
1014*b1906ceaSLachlan Hodges * the only rate to have enough data to see the variation and its
1015*b1906ceaSLachlan Hodges * statistics are more affected because they are usually collected over
1016*b1906ceaSLachlan Hodges * the full period.
1017*b1906ceaSLachlan Hodges */
1018*b1906ceaSLachlan Hodges if (index != tb->best_tp.index)
1019*b1906ceaSLachlan Hodges return;
1020*b1906ceaSLachlan Hodges
1021*b1906ceaSLachlan Hodges if (current_success == 0) {
1022*b1906ceaSLachlan Hodges if (!tb->unconverged) {
1023*b1906ceaSLachlan Hodges /*
1024*b1906ceaSLachlan Hodges * Best rate is failing completely, go to unconverged
1025*b1906ceaSLachlan Hodges * mode
1026*b1906ceaSLachlan Hodges */
1027*b1906ceaSLachlan Hodges tb->unconverged = true;
1028*b1906ceaSLachlan Hodges tb->newly_unconverged = true;
1029*b1906ceaSLachlan Hodges }
1030*b1906ceaSLachlan Hodges return;
1031*b1906ceaSLachlan Hodges }
1032*b1906ceaSLachlan Hodges
1033*b1906ceaSLachlan Hodges if (tb->table[index].prob == 0)
1034*b1906ceaSLachlan Hodges return;
1035*b1906ceaSLachlan Hodges
1036*b1906ceaSLachlan Hodges /* Don't process variation while converging after association */
1037*b1906ceaSLachlan Hodges if (tb->lookaround_wrap == LOOKAROUND_RATE_INIT)
1038*b1906ceaSLachlan Hodges return;
1039*b1906ceaSLachlan Hodges
1040*b1906ceaSLachlan Hodges current_variation = abs(current_success - tb->table[index].prob);
1041*b1906ceaSLachlan Hodges
1042*b1906ceaSLachlan Hodges /* Calculate the EWMA of the probability variation */
1043*b1906ceaSLachlan Hodges tb->probability_variation = calc_ewma_average(
1044*b1906ceaSLachlan Hodges tb->probability_variation, current_variation, VARIATION_EWMA);
1045*b1906ceaSLachlan Hodges
1046*b1906ceaSLachlan Hodges /*
1047*b1906ceaSLachlan Hodges * Process the variation direction to distinguish converged and
1048*b1906ceaSLachlan Hodges * unconverged scenarios
1049*b1906ceaSLachlan Hodges */
1050*b1906ceaSLachlan Hodges if (tb->probability_variation >= MODERATE_VARIATION_THRESHOLD ||
1051*b1906ceaSLachlan Hodges tb->interference_likely) {
1052*b1906ceaSLachlan Hodges if ((current_success - tb->table[index].prob) *
1053*b1906ceaSLachlan Hodges tb->probability_variation_direction <
1054*b1906ceaSLachlan Hodges 0)
1055*b1906ceaSLachlan Hodges tb->probability_variation_direction = 0;
1056*b1906ceaSLachlan Hodges else if (current_success > tb->table[index].prob)
1057*b1906ceaSLachlan Hodges tb->probability_variation_direction =
1058*b1906ceaSLachlan Hodges min(tb->probability_variation_direction + 1,
1059*b1906ceaSLachlan Hodges MAX_VARIATION_DIRECTION);
1060*b1906ceaSLachlan Hodges else if (current_success < tb->table[index].prob)
1061*b1906ceaSLachlan Hodges tb->probability_variation_direction =
1062*b1906ceaSLachlan Hodges max(tb->probability_variation_direction - 1,
1063*b1906ceaSLachlan Hodges -MAX_VARIATION_DIRECTION);
1064*b1906ceaSLachlan Hodges }
1065*b1906ceaSLachlan Hodges
1066*b1906ceaSLachlan Hodges if (tb->best_rate_cycle_count > VARIATION_DIRECTION_THRESHOLD &&
1067*b1906ceaSLachlan Hodges tb->probability_variation >= SIGNIFICANT_VARIATION_THRESHOLD) {
1068*b1906ceaSLachlan Hodges /*
1069*b1906ceaSLachlan Hodges * Only enter interference mode if the best rate is stable for
1070*b1906ceaSLachlan Hodges * enough cycles to determine the direction is random and not
1071*b1906ceaSLachlan Hodges * in one direction only
1072*b1906ceaSLachlan Hodges */
1073*b1906ceaSLachlan Hodges if (abs(tb->probability_variation_direction) <=
1074*b1906ceaSLachlan Hodges VARIATION_DIRECTION_THRESHOLD &&
1075*b1906ceaSLachlan Hodges !tb->interference_likely) {
1076*b1906ceaSLachlan Hodges tb->interference_likely = true;
1077*b1906ceaSLachlan Hodges }
1078*b1906ceaSLachlan Hodges } else if (tb->interference_likely &&
1079*b1906ceaSLachlan Hodges (tb->probability_variation <= MINOR_VARIATION_THRESHOLD ||
1080*b1906ceaSLachlan Hodges abs(tb->probability_variation_direction) ==
1081*b1906ceaSLachlan Hodges MAX_VARIATION_DIRECTION)) {
1082*b1906ceaSLachlan Hodges /*
1083*b1906ceaSLachlan Hodges * Exit interference mode if the variability drops or the
1084*b1906ceaSLachlan Hodges * direction stops being random
1085*b1906ceaSLachlan Hodges */
1086*b1906ceaSLachlan Hodges tb->interference_likely = false;
1087*b1906ceaSLachlan Hodges }
1088*b1906ceaSLachlan Hodges }
1089*b1906ceaSLachlan Hodges
mmrc_update(struct mmrc_table * tb)1090*b1906ceaSLachlan Hodges void mmrc_update(struct mmrc_table *tb)
1091*b1906ceaSLachlan Hodges {
1092*b1906ceaSLachlan Hodges u32 i;
1093*b1906ceaSLachlan Hodges u16 this_success;
1094*b1906ceaSLachlan Hodges u32 scale;
1095*b1906ceaSLachlan Hodges u32 scaled_ewma;
1096*b1906ceaSLachlan Hodges u32 new_stats = 0;
1097*b1906ceaSLachlan Hodges u32 attempts_for_stats;
1098*b1906ceaSLachlan Hodges u32 success_for_stats;
1099*b1906ceaSLachlan Hodges u32 min_stats;
1100*b1906ceaSLachlan Hodges u32 throughput;
1101*b1906ceaSLachlan Hodges u32 evidence_sent;
1102*b1906ceaSLachlan Hodges
1103*b1906ceaSLachlan Hodges tb->cycle_cnt++;
1104*b1906ceaSLachlan Hodges
1105*b1906ceaSLachlan Hodges /* Allow less minimum stats when converging */
1106*b1906ceaSLachlan Hodges if (tb->lookaround_wrap != LOOKAROUND_RATE_INIT)
1107*b1906ceaSLachlan Hodges min_stats = STATS_MIN_NORMAL;
1108*b1906ceaSLachlan Hodges else
1109*b1906ceaSLachlan Hodges min_stats = STATS_MIN_INIT;
1110*b1906ceaSLachlan Hodges
1111*b1906ceaSLachlan Hodges for (i = 0; i < rows_from_sta_caps(&tb->caps); i++) {
1112*b1906ceaSLachlan Hodges /* This algorithm is keeping track of the amount of evidence,
1113*b1906ceaSLachlan Hodges * being packets that have been recently sent at this rate.
1114*b1906ceaSLachlan Hodges * This value is smoothed with an EWMA function over time and
1115*b1906ceaSLachlan Hodges * used to update the probability of a rate succeeding
1116*b1906ceaSLachlan Hodges * dynamically. This method allows MMRC to react timely if a
1117*b1906ceaSLachlan Hodges * new rate is used that hasn't been used recently
1118*b1906ceaSLachlan Hodges */
1119*b1906ceaSLachlan Hodges
1120*b1906ceaSLachlan Hodges /* Necessary to prevent a divide by 0 */
1121*b1906ceaSLachlan Hodges if (tb->table[i].evidence == 0)
1122*b1906ceaSLachlan Hodges scale = 0;
1123*b1906ceaSLachlan Hodges else
1124*b1906ceaSLachlan Hodges scale = ((tb->table[i].evidence * 2) * 100) /
1125*b1906ceaSLachlan Hodges ((tb->table[i].sent * EVIDENCE_SCALE) +
1126*b1906ceaSLachlan Hodges tb->table[i].evidence);
1127*b1906ceaSLachlan Hodges
1128*b1906ceaSLachlan Hodges /* Restrict scale to appropriate values */
1129*b1906ceaSLachlan Hodges if (scale > 100)
1130*b1906ceaSLachlan Hodges scale = 100;
1131*b1906ceaSLachlan Hodges
1132*b1906ceaSLachlan Hodges scaled_ewma = scale * EWMA / 100;
1133*b1906ceaSLachlan Hodges
1134*b1906ceaSLachlan Hodges /*
1135*b1906ceaSLachlan Hodges * Only count new packets for evidence if we will process
1136*b1906ceaSLachlan Hodges * them
1137*b1906ceaSLachlan Hodges */
1138*b1906ceaSLachlan Hodges evidence_sent =
1139*b1906ceaSLachlan Hodges tb->table[i].sent >= min_stats ? tb->table[i].sent : 0;
1140*b1906ceaSLachlan Hodges tb->table[i].evidence = calc_ewma_average(
1141*b1906ceaSLachlan Hodges tb->table[i].evidence, evidence_sent * EVIDENCE_SCALE,
1142*b1906ceaSLachlan Hodges scaled_ewma);
1143*b1906ceaSLachlan Hodges
1144*b1906ceaSLachlan Hodges if (tb->table[i].evidence > EVIDENCE_MAX)
1145*b1906ceaSLachlan Hodges tb->table[i].evidence = EVIDENCE_MAX;
1146*b1906ceaSLachlan Hodges
1147*b1906ceaSLachlan Hodges /* Try to use statistics from acknowledged AMPDUs first */
1148*b1906ceaSLachlan Hodges attempts_for_stats = tb->table[i].back_mpdu_success +
1149*b1906ceaSLachlan Hodges tb->table[i].back_mpdu_failure;
1150*b1906ceaSLachlan Hodges success_for_stats = tb->table[i].back_mpdu_success;
1151*b1906ceaSLachlan Hodges
1152*b1906ceaSLachlan Hodges /*
1153*b1906ceaSLachlan Hodges * Use the full statistics if rates are not converged or there
1154*b1906ceaSLachlan Hodges * were no AMPDUs for this rate or the remaining attempts are
1155*b1906ceaSLachlan Hodges * less than half of what we have from AMPDUs.
1156*b1906ceaSLachlan Hodges */
1157*b1906ceaSLachlan Hodges if (!tb->table[i].have_sent_ampdus || tb->unconverged ||
1158*b1906ceaSLachlan Hodges attempts_for_stats < AMPDU_STATS_MIN ||
1159*b1906ceaSLachlan Hodges (tb->table[i].sent - attempts_for_stats <
1160*b1906ceaSLachlan Hodges attempts_for_stats / 2)) {
1161*b1906ceaSLachlan Hodges attempts_for_stats = tb->table[i].sent;
1162*b1906ceaSLachlan Hodges success_for_stats = tb->table[i].sent_success;
1163*b1906ceaSLachlan Hodges }
1164*b1906ceaSLachlan Hodges
1165*b1906ceaSLachlan Hodges if (attempts_for_stats >= min_stats ||
1166*b1906ceaSLachlan Hodges (attempts_for_stats > 0 && tb->table[i].prob > 0)) {
1167*b1906ceaSLachlan Hodges new_stats = 1;
1168*b1906ceaSLachlan Hodges this_success =
1169*b1906ceaSLachlan Hodges (100 * success_for_stats) / attempts_for_stats;
1170*b1906ceaSLachlan Hodges
1171*b1906ceaSLachlan Hodges if (scaled_ewma)
1172*b1906ceaSLachlan Hodges mmrc_process_variation(tb, this_success, i);
1173*b1906ceaSLachlan Hodges
1174*b1906ceaSLachlan Hodges tb->table[i].prob = calc_ewma_average(
1175*b1906ceaSLachlan Hodges tb->table[i].prob, this_success, scaled_ewma);
1176*b1906ceaSLachlan Hodges
1177*b1906ceaSLachlan Hodges /* Clear our sent statistics and update totals */
1178*b1906ceaSLachlan Hodges tb->table[i].total_sent += tb->table[i].sent;
1179*b1906ceaSLachlan Hodges tb->table[i].sent = 0;
1180*b1906ceaSLachlan Hodges
1181*b1906ceaSLachlan Hodges tb->table[i].total_success += tb->table[i].sent_success;
1182*b1906ceaSLachlan Hodges tb->table[i].sent_success = 0;
1183*b1906ceaSLachlan Hodges
1184*b1906ceaSLachlan Hodges tb->table[i].back_mpdu_failure = 0;
1185*b1906ceaSLachlan Hodges tb->table[i].back_mpdu_success = 0;
1186*b1906ceaSLachlan Hodges tb->table[i].have_sent_ampdus = false;
1187*b1906ceaSLachlan Hodges }
1188*b1906ceaSLachlan Hodges
1189*b1906ceaSLachlan Hodges throughput = calculate_throughput(tb, i);
1190*b1906ceaSLachlan Hodges if (tb->table[i].max_throughput < throughput)
1191*b1906ceaSLachlan Hodges tb->table[i].max_throughput = throughput;
1192*b1906ceaSLachlan Hodges
1193*b1906ceaSLachlan Hodges /*
1194*b1906ceaSLachlan Hodges * Reset the running average windows if reached collector
1195*b1906ceaSLachlan Hodges * limits
1196*b1906ceaSLachlan Hodges */
1197*b1906ceaSLachlan Hodges if (tb->table[i].sum_throughput > (0xFFFFFFFF - throughput)) {
1198*b1906ceaSLachlan Hodges tb->table[i].sum_throughput /=
1199*b1906ceaSLachlan Hodges tb->table[i].avg_throughput_counter;
1200*b1906ceaSLachlan Hodges tb->table[i].avg_throughput_counter = 1;
1201*b1906ceaSLachlan Hodges }
1202*b1906ceaSLachlan Hodges /* Update the sum and counter so it will be possible later to
1203*b1906ceaSLachlan Hodges * calculate the running average throughput
1204*b1906ceaSLachlan Hodges */
1205*b1906ceaSLachlan Hodges tb->table[i].sum_throughput += throughput;
1206*b1906ceaSLachlan Hodges tb->table[i].avg_throughput_counter++;
1207*b1906ceaSLachlan Hodges }
1208*b1906ceaSLachlan Hodges
1209*b1906ceaSLachlan Hodges generate_table_priority(tb, new_stats);
1210*b1906ceaSLachlan Hodges
1211*b1906ceaSLachlan Hodges /*
1212*b1906ceaSLachlan Hodges * Switch to faster lookaround mode if rates drop low at very low
1213*b1906ceaSLachlan Hodges * bandwidth or we are in unconverged mode. Switching at low bandwidth
1214*b1906ceaSLachlan Hodges * and rate is to help recover quickly from rates where we would need
1215*b1906ceaSLachlan Hodges * to fragment standard MTU size packets.
1216*b1906ceaSLachlan Hodges */
1217*b1906ceaSLachlan Hodges if (tb->lookaround_wrap != LOOKAROUND_RATE_INIT &&
1218*b1906ceaSLachlan Hodges (tb->unconverged || (tb->best_tp.bw == MMRC_BW_1MHZ &&
1219*b1906ceaSLachlan Hodges tb->best_tp.rate <= MMRC_MCS2))) {
1220*b1906ceaSLachlan Hodges tb->lookaround_cnt = 0;
1221*b1906ceaSLachlan Hodges tb->lookaround_wrap = LOOKAROUND_RATE_INIT;
1222*b1906ceaSLachlan Hodges tb->stability_cnt_threshold = STABILITY_CNT_THRESHOLD_INIT;
1223*b1906ceaSLachlan Hodges }
1224*b1906ceaSLachlan Hodges
1225*b1906ceaSLachlan Hodges /*
1226*b1906ceaSLachlan Hodges * If it is unlikely we can do the lookaround attempts in two RC cycles
1227*b1906ceaSLachlan Hodges * choose a new rate
1228*b1906ceaSLachlan Hodges */
1229*b1906ceaSLachlan Hodges if (tb->current_lookaround_rate_attempts <=
1230*b1906ceaSLachlan Hodges (LOOKAROUND_RATE_ATTEMPTS / 2))
1231*b1906ceaSLachlan Hodges tb->current_lookaround_rate_attempts = LOOKAROUND_RATE_ATTEMPTS;
1232*b1906ceaSLachlan Hodges }
1233*b1906ceaSLachlan Hodges
mmrc_feedback(struct mmrc_table * tb,struct mmrc_rate_table * rates,s32 retry_count,bool was_aggregated)1234*b1906ceaSLachlan Hodges void mmrc_feedback(struct mmrc_table *tb, struct mmrc_rate_table *rates,
1235*b1906ceaSLachlan Hodges s32 retry_count, bool was_aggregated)
1236*b1906ceaSLachlan Hodges {
1237*b1906ceaSLachlan Hodges s32 ind = retry_count;
1238*b1906ceaSLachlan Hodges u32 i;
1239*b1906ceaSLachlan Hodges
1240*b1906ceaSLachlan Hodges for (i = 0; i < MMRC_MAX_CHAIN_LENGTH; i++) {
1241*b1906ceaSLachlan Hodges rate_update_index(tb, &rates->rates[i]);
1242*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index].have_sent_ampdus |=
1243*b1906ceaSLachlan Hodges was_aggregated;
1244*b1906ceaSLachlan Hodges
1245*b1906ceaSLachlan Hodges if ((s32)rates->rates[i].attempts < ind) {
1246*b1906ceaSLachlan Hodges ind = ind - rates->rates[i].attempts;
1247*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index].sent +=
1248*b1906ceaSLachlan Hodges rates->rates[i].attempts;
1249*b1906ceaSLachlan Hodges if (was_aggregated) {
1250*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index]
1251*b1906ceaSLachlan Hodges .back_mpdu_failure +=
1252*b1906ceaSLachlan Hodges rates->rates[i].attempts;
1253*b1906ceaSLachlan Hodges }
1254*b1906ceaSLachlan Hodges } else {
1255*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index].sent += ind;
1256*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index].sent_success += 1;
1257*b1906ceaSLachlan Hodges if (was_aggregated) {
1258*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index]
1259*b1906ceaSLachlan Hodges .back_mpdu_success += 1;
1260*b1906ceaSLachlan Hodges tb->table[rates->rates[i].index]
1261*b1906ceaSLachlan Hodges .back_mpdu_failure +=
1262*b1906ceaSLachlan Hodges ind > 1 ? ind - 1 : 0;
1263*b1906ceaSLachlan Hodges }
1264*b1906ceaSLachlan Hodges return;
1265*b1906ceaSLachlan Hodges }
1266*b1906ceaSLachlan Hodges }
1267*b1906ceaSLachlan Hodges }
1268*b1906ceaSLachlan Hodges
1269*b1906ceaSLachlan Hodges /*
1270*b1906ceaSLachlan Hodges * Chooses a reasonable starting rate based on range (gathered from
1271*b1906ceaSLachlan Hodges * RSSI measurements) or bandwidth. Then fills out the 3 retry rates
1272*b1906ceaSLachlan Hodges * so a full set of rates is available.
1273*b1906ceaSLachlan Hodges */
mmrc_init_rates(struct mmrc_table * tb,s8 rssi)1274*b1906ceaSLachlan Hodges static void mmrc_init_rates(struct mmrc_table *tb, s8 rssi)
1275*b1906ceaSLachlan Hodges {
1276*b1906ceaSLachlan Hodges tb->best_tp.bw = MMRC_MAX_BW(tb->caps.bandwidth);
1277*b1906ceaSLachlan Hodges if (tb->caps.sgi_per_bw & SGI_PER_BW(tb->best_tp.bw))
1278*b1906ceaSLachlan Hodges tb->best_tp.guard = MMRC_GUARD_TO_BITFIELD(MMRC_GUARD_SHORT);
1279*b1906ceaSLachlan Hodges else
1280*b1906ceaSLachlan Hodges tb->best_tp.guard = MMRC_GUARD_TO_BITFIELD(MMRC_GUARD_LONG);
1281*b1906ceaSLachlan Hodges tb->best_tp.rate = MMRC_RATE_TO_BITFIELD(MMRC_MCS0);
1282*b1906ceaSLachlan Hodges
1283*b1906ceaSLachlan Hodges if (rssi >= MMRC_SHORT_RANGE_RSSI_LIMIT)
1284*b1906ceaSLachlan Hodges tb->best_tp.rate = MMRC_RATE_TO_BITFIELD(MMRC_MCS7);
1285*b1906ceaSLachlan Hodges else if (rssi < MMRC_SHORT_RANGE_RSSI_LIMIT &&
1286*b1906ceaSLachlan Hodges rssi >= MMRC_MID_RANGE_RSSI_LIMIT)
1287*b1906ceaSLachlan Hodges tb->best_tp.rate = MMRC_RATE_TO_BITFIELD(MMRC_MCS3);
1288*b1906ceaSLachlan Hodges else if (tb->best_tp.bw == MMRC_BW_1MHZ ||
1289*b1906ceaSLachlan Hodges tb->best_tp.bw == MMRC_BW_2MHZ)
1290*b1906ceaSLachlan Hodges /*
1291*b1906ceaSLachlan Hodges * To compensate for slow feedback when running with 1 and 2
1292*b1906ceaSLachlan Hodges * MHz bandwidth, we start from MCS3 which will correspond to
1293*b1906ceaSLachlan Hodges * reasonable feedback and will avoid resetting the rate table
1294*b1906ceaSLachlan Hodges * evidence.
1295*b1906ceaSLachlan Hodges */
1296*b1906ceaSLachlan Hodges tb->best_tp.rate = MMRC_RATE_TO_BITFIELD(MMRC_MCS3);
1297*b1906ceaSLachlan Hodges
1298*b1906ceaSLachlan Hodges tb->best_tp.ss = MMRC_SS_TO_BITFIELD(MMRC_SPATIAL_STREAM_1);
1299*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->best_tp);
1300*b1906ceaSLachlan Hodges /* Init every rate in case they are needed to set the retry rates */
1301*b1906ceaSLachlan Hodges tb->second_tp = tb->best_tp;
1302*b1906ceaSLachlan Hodges tb->best_prob = tb->best_tp;
1303*b1906ceaSLachlan Hodges tb->baseline = tb->best_tp;
1304*b1906ceaSLachlan Hodges mmrc_fill_retry_rates(tb);
1305*b1906ceaSLachlan Hodges }
1306*b1906ceaSLachlan Hodges
mmrc_sta_init(struct mmrc_table * tb,struct mmrc_sta_capabilities * caps,s8 rssi)1307*b1906ceaSLachlan Hodges void mmrc_sta_init(struct mmrc_table *tb, struct mmrc_sta_capabilities *caps,
1308*b1906ceaSLachlan Hodges s8 rssi)
1309*b1906ceaSLachlan Hodges {
1310*b1906ceaSLachlan Hodges u32 i;
1311*b1906ceaSLachlan Hodges u16 row_count = rows_from_sta_caps(caps);
1312*b1906ceaSLachlan Hodges
1313*b1906ceaSLachlan Hodges memset(tb, 0, mmrc_memory_required_for_caps(caps));
1314*b1906ceaSLachlan Hodges memcpy(&tb->caps, caps, sizeof(tb->caps));
1315*b1906ceaSLachlan Hodges
1316*b1906ceaSLachlan Hodges for (i = 0; i < row_count; i++) {
1317*b1906ceaSLachlan Hodges tb->table[i].prob = RATE_INIT_PROBABILITY;
1318*b1906ceaSLachlan Hodges tb->table[i].evidence = 0;
1319*b1906ceaSLachlan Hodges tb->table[i].sum_throughput = 0;
1320*b1906ceaSLachlan Hodges tb->table[i].avg_throughput_counter = 0;
1321*b1906ceaSLachlan Hodges tb->table[i].max_throughput = 0;
1322*b1906ceaSLachlan Hodges }
1323*b1906ceaSLachlan Hodges
1324*b1906ceaSLachlan Hodges tb->fixed_rate.rate = MMRC_MCS_UNUSED;
1325*b1906ceaSLachlan Hodges tb->cycle_cnt = 0;
1326*b1906ceaSLachlan Hodges tb->last_lookaround_cycle = 0;
1327*b1906ceaSLachlan Hodges tb->lookaround_cnt = 0;
1328*b1906ceaSLachlan Hodges tb->lookaround_wrap = LOOKAROUND_RATE_INIT;
1329*b1906ceaSLachlan Hodges tb->unconverged = true;
1330*b1906ceaSLachlan Hodges tb->newly_unconverged = true;
1331*b1906ceaSLachlan Hodges tb->stability_cnt_threshold = STABILITY_CNT_THRESHOLD_INIT;
1332*b1906ceaSLachlan Hodges tb->baseline = get_rate_row(tb, find_baseline_index(tb));
1333*b1906ceaSLachlan Hodges mmrc_init_rates(tb, rssi);
1334*b1906ceaSLachlan Hodges }
1335*b1906ceaSLachlan Hodges
mmrc_set_fixed_rate(struct mmrc_table * tb,struct mmrc_rate fixed_rate)1336*b1906ceaSLachlan Hodges bool mmrc_set_fixed_rate(struct mmrc_table *tb, struct mmrc_rate fixed_rate)
1337*b1906ceaSLachlan Hodges {
1338*b1906ceaSLachlan Hodges bool caps_support_rate = true;
1339*b1906ceaSLachlan Hodges
1340*b1906ceaSLachlan Hodges /* Do not accept rate which does not support the STA capabilities */
1341*b1906ceaSLachlan Hodges if ((BIT(fixed_rate.rate) & tb->caps.rates) == 0 ||
1342*b1906ceaSLachlan Hodges (BIT(fixed_rate.bw) & tb->caps.bandwidth) == 0 ||
1343*b1906ceaSLachlan Hodges (BIT(fixed_rate.ss) & tb->caps.spatial_streams) == 0 ||
1344*b1906ceaSLachlan Hodges (BIT(fixed_rate.guard) & tb->caps.guard) == 0)
1345*b1906ceaSLachlan Hodges caps_support_rate = false;
1346*b1906ceaSLachlan Hodges
1347*b1906ceaSLachlan Hodges if (validate_rate(tb, &fixed_rate) && caps_support_rate) {
1348*b1906ceaSLachlan Hodges tb->fixed_rate = fixed_rate;
1349*b1906ceaSLachlan Hodges rate_update_index(tb, &tb->fixed_rate);
1350*b1906ceaSLachlan Hodges return true;
1351*b1906ceaSLachlan Hodges }
1352*b1906ceaSLachlan Hodges
1353*b1906ceaSLachlan Hodges return false;
1354*b1906ceaSLachlan Hodges }
1355