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 6*b1906ceaSLachlan Hodges #ifndef _MM81X_MMRC_H_ 7*b1906ceaSLachlan Hodges #define _MM81X_MMRC_H_ 8*b1906ceaSLachlan Hodges 9*b1906ceaSLachlan Hodges #include <linux/version.h> 10*b1906ceaSLachlan Hodges #include <linux/types.h> 11*b1906ceaSLachlan Hodges #include <linux/slab.h> 12*b1906ceaSLachlan Hodges #include <linux/bitops.h> 13*b1906ceaSLachlan Hodges #include <linux/random.h> 14*b1906ceaSLachlan Hodges #include <linux/time.h> 15*b1906ceaSLachlan Hodges 16*b1906ceaSLachlan Hodges /* The max length of a retry chain for a single packet transmission */ 17*b1906ceaSLachlan Hodges #define MMRC_MAX_CHAIN_LENGTH 4 18*b1906ceaSLachlan Hodges 19*b1906ceaSLachlan Hodges /* Rate minimum allowed attempts */ 20*b1906ceaSLachlan Hodges #define MMRC_MIN_CHAIN_ATTEMPTS 1 21*b1906ceaSLachlan Hodges 22*b1906ceaSLachlan Hodges /* Rate upper limit for attempts */ 23*b1906ceaSLachlan Hodges #define MMRC_MAX_CHAIN_ATTEMPTS 2 24*b1906ceaSLachlan Hodges 25*b1906ceaSLachlan Hodges /* The frequency of MMRC stat table updates */ 26*b1906ceaSLachlan Hodges #define MMRC_UPDATE_FREQUENCY_MS 100 27*b1906ceaSLachlan Hodges 28*b1906ceaSLachlan Hodges enum mmrc_flags { 29*b1906ceaSLachlan Hodges MMRC_FLAGS_CTS_RTS, 30*b1906ceaSLachlan Hodges }; 31*b1906ceaSLachlan Hodges 32*b1906ceaSLachlan Hodges enum mmrc_mcs_rate { 33*b1906ceaSLachlan Hodges MMRC_MCS0, 34*b1906ceaSLachlan Hodges MMRC_MCS1, 35*b1906ceaSLachlan Hodges MMRC_MCS2, 36*b1906ceaSLachlan Hodges MMRC_MCS3, 37*b1906ceaSLachlan Hodges MMRC_MCS4, 38*b1906ceaSLachlan Hodges MMRC_MCS5, 39*b1906ceaSLachlan Hodges MMRC_MCS6, 40*b1906ceaSLachlan Hodges MMRC_MCS7, 41*b1906ceaSLachlan Hodges MMRC_MCS8, 42*b1906ceaSLachlan Hodges MMRC_MCS9, 43*b1906ceaSLachlan Hodges MMRC_MCS10, 44*b1906ceaSLachlan Hodges MMRC_MCS_UNUSED, 45*b1906ceaSLachlan Hodges }; 46*b1906ceaSLachlan Hodges 47*b1906ceaSLachlan Hodges enum mmrc_bw { 48*b1906ceaSLachlan Hodges MMRC_BW_1MHZ = 0, 49*b1906ceaSLachlan Hodges MMRC_BW_2MHZ = 1, 50*b1906ceaSLachlan Hodges MMRC_BW_4MHZ = 2, 51*b1906ceaSLachlan Hodges MMRC_BW_8MHZ = 3, 52*b1906ceaSLachlan Hodges MMRC_BW_16MHZ = 4, 53*b1906ceaSLachlan Hodges MMRC_BW_MAX = 5, 54*b1906ceaSLachlan Hodges }; 55*b1906ceaSLachlan Hodges 56*b1906ceaSLachlan Hodges enum mmrc_spatial_stream { 57*b1906ceaSLachlan Hodges MMRC_SPATIAL_STREAM_1 = 0, 58*b1906ceaSLachlan Hodges MMRC_SPATIAL_STREAM_2 = 1, 59*b1906ceaSLachlan Hodges MMRC_SPATIAL_STREAM_3 = 2, 60*b1906ceaSLachlan Hodges MMRC_SPATIAL_STREAM_4 = 3, 61*b1906ceaSLachlan Hodges MMRC_SPATIAL_STREAM_MAX, 62*b1906ceaSLachlan Hodges }; 63*b1906ceaSLachlan Hodges 64*b1906ceaSLachlan Hodges enum mmrc_guard { 65*b1906ceaSLachlan Hodges MMRC_GUARD_LONG = 0, 66*b1906ceaSLachlan Hodges MMRC_GUARD_SHORT = 1, 67*b1906ceaSLachlan Hodges MMRC_GUARD_MAX, 68*b1906ceaSLachlan Hodges }; 69*b1906ceaSLachlan Hodges 70*b1906ceaSLachlan Hodges #define MMRC_RATE_TO_BITFIELD(x) ((x) & 0xF) 71*b1906ceaSLachlan Hodges #define MMRC_ATTEMPTS_TO_BITFIELD(x) ((x) & 0x7) 72*b1906ceaSLachlan Hodges #define MMRC_GUARD_TO_BITFIELD(x) ((x) & 0x1) 73*b1906ceaSLachlan Hodges #define MMRC_SS_TO_BITFIELD(x) ((x) & 0x3) 74*b1906ceaSLachlan Hodges #define MMRC_BW_TO_BITFIELD(x) ((x) & 0x7) 75*b1906ceaSLachlan Hodges #define MMRC_FLAGS_TO_BITFIELD(x) ((x) & 0x7) 76*b1906ceaSLachlan Hodges 77*b1906ceaSLachlan Hodges struct mmrc_rate { 78*b1906ceaSLachlan Hodges u8 rate : 4; 79*b1906ceaSLachlan Hodges u8 attempts : 3; 80*b1906ceaSLachlan Hodges u8 guard : 1; 81*b1906ceaSLachlan Hodges u8 ss : 2; 82*b1906ceaSLachlan Hodges u8 bw : 3; 83*b1906ceaSLachlan Hodges u8 flags : 3; 84*b1906ceaSLachlan Hodges u16 index; 85*b1906ceaSLachlan Hodges }; 86*b1906ceaSLachlan Hodges 87*b1906ceaSLachlan Hodges struct mmrc_rate_table { 88*b1906ceaSLachlan Hodges struct mmrc_rate rates[MMRC_MAX_CHAIN_LENGTH]; 89*b1906ceaSLachlan Hodges }; 90*b1906ceaSLachlan Hodges 91*b1906ceaSLachlan Hodges #define SGI_PER_BW(bw) (1 << (bw)) 92*b1906ceaSLachlan Hodges 93*b1906ceaSLachlan Hodges struct mmrc_sta_capabilities { 94*b1906ceaSLachlan Hodges u8 max_rates : 3; 95*b1906ceaSLachlan Hodges u8 max_retries : 3; 96*b1906ceaSLachlan Hodges u8 bandwidth : 5; 97*b1906ceaSLachlan Hodges u8 spatial_streams : 4; 98*b1906ceaSLachlan Hodges u16 rates : 11; 99*b1906ceaSLachlan Hodges u8 guard : 2; 100*b1906ceaSLachlan Hodges u8 sta_flags : 4; 101*b1906ceaSLachlan Hodges u8 sgi_per_bw : 5; 102*b1906ceaSLachlan Hodges }; 103*b1906ceaSLachlan Hodges 104*b1906ceaSLachlan Hodges struct mmrc_stats_table { 105*b1906ceaSLachlan Hodges u32 avg_throughput_counter; 106*b1906ceaSLachlan Hodges u32 sum_throughput; 107*b1906ceaSLachlan Hodges u32 max_throughput; 108*b1906ceaSLachlan Hodges u16 sent; 109*b1906ceaSLachlan Hodges u16 sent_success; 110*b1906ceaSLachlan Hodges u16 back_mpdu_success; 111*b1906ceaSLachlan Hodges u16 back_mpdu_failure; 112*b1906ceaSLachlan Hodges u32 total_sent; 113*b1906ceaSLachlan Hodges u32 total_success; 114*b1906ceaSLachlan Hodges u16 evidence; 115*b1906ceaSLachlan Hodges u8 prob; 116*b1906ceaSLachlan Hodges bool have_sent_ampdus; 117*b1906ceaSLachlan Hodges }; 118*b1906ceaSLachlan Hodges 119*b1906ceaSLachlan Hodges struct mmrc_table { 120*b1906ceaSLachlan Hodges struct mmrc_sta_capabilities caps; 121*b1906ceaSLachlan Hodges struct mmrc_rate best_tp; 122*b1906ceaSLachlan Hodges struct mmrc_rate second_tp; 123*b1906ceaSLachlan Hodges struct mmrc_rate baseline; 124*b1906ceaSLachlan Hodges struct mmrc_rate best_prob; 125*b1906ceaSLachlan Hodges struct mmrc_rate fixed_rate; 126*b1906ceaSLachlan Hodges u32 cycle_cnt; 127*b1906ceaSLachlan Hodges u32 last_lookaround_cycle; 128*b1906ceaSLachlan Hodges u8 lookaround_cnt; 129*b1906ceaSLachlan Hodges 130*b1906ceaSLachlan Hodges /* The ratio of using normal rate and sampling */ 131*b1906ceaSLachlan Hodges u8 lookaround_wrap; 132*b1906ceaSLachlan Hodges 133*b1906ceaSLachlan Hodges /* 134*b1906ceaSLachlan Hodges * A counter that is used to determine when we should force a 135*b1906ceaSLachlan Hodges * lookaround. Should be a portion of the above lookaround with 136*b1906ceaSLachlan Hodges * less constraints 137*b1906ceaSLachlan Hodges */ 138*b1906ceaSLachlan Hodges u8 forced_lookaround; 139*b1906ceaSLachlan Hodges 140*b1906ceaSLachlan Hodges u8 current_lookaround_rate_attempts; 141*b1906ceaSLachlan Hodges u16 current_lookaround_rate_index; 142*b1906ceaSLachlan Hodges u32 total_lookaround; 143*b1906ceaSLachlan Hodges 144*b1906ceaSLachlan Hodges /* 145*b1906ceaSLachlan Hodges * A counter to detect if the current best rate is optimal 146*b1906ceaSLachlan Hodges * and may slow down sample frequency. 147*b1906ceaSLachlan Hodges */ 148*b1906ceaSLachlan Hodges u32 stability_cnt; 149*b1906ceaSLachlan Hodges 150*b1906ceaSLachlan Hodges u32 stability_cnt_threshold; 151*b1906ceaSLachlan Hodges u8 probability_variation; 152*b1906ceaSLachlan Hodges 153*b1906ceaSLachlan Hodges /* The difference in MCS from each of the last 2 rate changes */ 154*b1906ceaSLachlan Hodges s8 best_rate_diff[2]; 155*b1906ceaSLachlan Hodges 156*b1906ceaSLachlan Hodges /* Indication of random versus consistently one-sided variation */ 157*b1906ceaSLachlan Hodges s8 probability_variation_direction; 158*b1906ceaSLachlan Hodges 159*b1906ceaSLachlan Hodges /* Has rate control detected possible interference */ 160*b1906ceaSLachlan Hodges bool interference_likely; 161*b1906ceaSLachlan Hodges 162*b1906ceaSLachlan Hodges /* Has rate control detected the best rate is no longer converged */ 163*b1906ceaSLachlan Hodges bool unconverged; 164*b1906ceaSLachlan Hodges 165*b1906ceaSLachlan Hodges /* Is rate control just entering unconverged state */ 166*b1906ceaSLachlan Hodges bool newly_unconverged; 167*b1906ceaSLachlan Hodges 168*b1906ceaSLachlan Hodges /* 169*b1906ceaSLachlan Hodges * Number of rate control cycles the best rate has remained 170*b1906ceaSLachlan Hodges * unchanged 171*b1906ceaSLachlan Hodges */ 172*b1906ceaSLachlan Hodges s32 best_rate_cycle_count; 173*b1906ceaSLachlan Hodges 174*b1906ceaSLachlan Hodges /* 175*b1906ceaSLachlan Hodges * The probability table for the STA. This MUST always be the last 176*b1906ceaSLachlan Hodges * element in the struct. 177*b1906ceaSLachlan Hodges */ 178*b1906ceaSLachlan Hodges struct mmrc_stats_table table[]; 179*b1906ceaSLachlan Hodges }; 180*b1906ceaSLachlan Hodges 181*b1906ceaSLachlan Hodges void mmrc_sta_init(struct mmrc_table *tb, struct mmrc_sta_capabilities *caps, 182*b1906ceaSLachlan Hodges s8 rssi); 183*b1906ceaSLachlan Hodges size_t mmrc_memory_required_for_caps(struct mmrc_sta_capabilities *caps); 184*b1906ceaSLachlan Hodges void mmrc_get_rates(struct mmrc_table *tb, struct mmrc_rate_table *out, 185*b1906ceaSLachlan Hodges size_t size); 186*b1906ceaSLachlan Hodges void mmrc_feedback(struct mmrc_table *tb, struct mmrc_rate_table *rates, 187*b1906ceaSLachlan Hodges s32 retry_count, bool was_aggregated); 188*b1906ceaSLachlan Hodges void mmrc_update(struct mmrc_table *tb); 189*b1906ceaSLachlan Hodges bool mmrc_set_fixed_rate(struct mmrc_table *tb, struct mmrc_rate fixed_rate); 190*b1906ceaSLachlan Hodges u32 mmrc_calculate_theoretical_throughput(struct mmrc_rate rate); 191*b1906ceaSLachlan Hodges u32 mmrc_calculate_rate_tx_time(struct mmrc_rate *rate, size_t size); 192*b1906ceaSLachlan Hodges 193*b1906ceaSLachlan Hodges #endif /* _MMRC_H_ */ 194