1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 4 */ 5 6#ifndef __RC_MINSTREL_H 7#define __RC_MINSTREL_H 8 9#define EWMA_LEVEL 96 /* ewma weighting factor [/EWMA_DIV] */ 10#define EWMA_DIV 128 11#define SAMPLE_COLUMNS 10 /* number of columns in sample table */ 12 13/* scaled fraction values */ 14#define MINSTREL_SCALE 12 15#define MINSTREL_FRAC(val, div) (((val) << MINSTREL_SCALE) / div) 16#define MINSTREL_TRUNC(val) ((val) >> MINSTREL_SCALE) 17 18/* number of highest throughput rates to consider*/ 19#define MAX_THR_RATES 4 20 21/* 22 * Coefficients for moving average with noise filter (period=16), 23 * scaled by 10 bits 24 * 25 * a1 = exp(-pi * sqrt(2) / period) 26 * coeff2 = 2 * a1 * cos(sqrt(2) * 2 * pi / period) 27 * coeff3 = -sqr(a1) 28 * coeff1 = 1 - coeff2 - coeff3 29 */ 30#define MINSTREL_AVG_COEFF1 (MINSTREL_FRAC(1, 1) - \ 31 MINSTREL_AVG_COEFF2 - \ 32 MINSTREL_AVG_COEFF3) 33#define MINSTREL_AVG_COEFF2 0x00001499 34#define MINSTREL_AVG_COEFF3 -0x0000092e 35 36/* 37 * Perform EWMA (Exponentially Weighted Moving Average) calculation 38 */ 39static inline int 40minstrel_ewma(int old, int new, int weight) 41{ 42 int diff, incr; 43 44 diff = new - old; 45 incr = (EWMA_DIV - weight) * diff / EWMA_DIV; 46 47 return old + incr; 48} 49 50static inline int minstrel_filter_avg_add(u16 *prev_1, u16 *prev_2, s32 in) 51{ 52 s32 out_1 = *prev_1; 53 s32 out_2 = *prev_2; 54 s32 val; 55 56 if (!in) 57 in += 1; 58 59 if (!out_1) { 60 val = out_1 = in; 61 goto out; 62 } 63 64 val = MINSTREL_AVG_COEFF1 * in; 65 val += MINSTREL_AVG_COEFF2 * out_1; 66 val += MINSTREL_AVG_COEFF3 * out_2; 67 val >>= MINSTREL_SCALE; 68 69 if (val > 1 << MINSTREL_SCALE) 70 val = 1 << MINSTREL_SCALE; 71 if (val < 0) 72 val = 1; 73 74out: 75 *prev_2 = out_1; 76 *prev_1 = val; 77 78 return val; 79} 80 81struct minstrel_rate_stats { 82 /* current / last sampling period attempts/success counters */ 83 u16 attempts, last_attempts; 84 u16 success, last_success; 85 86 /* total attempts/success counters */ 87 u32 att_hist, succ_hist; 88 89 /* prob_avg - moving average of prob */ 90 u16 prob_avg; 91 u16 prob_avg_1; 92 93 /* maximum retry counts */ 94 u8 retry_count; 95 u8 retry_count_rtscts; 96 97 u8 sample_skipped; 98 bool retry_updated; 99}; 100 101struct minstrel_rate { 102 int bitrate; 103 104 s8 rix; 105 u8 retry_count_cts; 106 u8 adjusted_retry_count; 107 108 unsigned int perfect_tx_time; 109 unsigned int ack_time; 110 111 int sample_limit; 112 113 struct minstrel_rate_stats stats; 114}; 115 116struct minstrel_sta_info { 117 struct ieee80211_sta *sta; 118 119 unsigned long last_stats_update; 120 unsigned int sp_ack_dur; 121 unsigned int rate_avg; 122 123 unsigned int lowest_rix; 124 125 u8 max_tp_rate[MAX_THR_RATES]; 126 u8 max_prob_rate; 127 unsigned int total_packets; 128 unsigned int sample_packets; 129 130 unsigned int sample_row; 131 unsigned int sample_column; 132 133 int n_rates; 134 struct minstrel_rate *r; 135 bool prev_sample; 136 137 /* sampling table */ 138 u8 *sample_table; 139}; 140 141struct minstrel_priv { 142 struct ieee80211_hw *hw; 143 bool has_mrr; 144 bool new_avg; 145 u32 sample_switch; 146 unsigned int cw_min; 147 unsigned int cw_max; 148 unsigned int max_retry; 149 unsigned int segment_size; 150 unsigned int update_interval; 151 unsigned int lookaround_rate; 152 unsigned int lookaround_rate_mrr; 153 154 u8 cck_rates[4]; 155 156#ifdef CONFIG_MAC80211_DEBUGFS 157 /* 158 * enable fixed rate processing per RC 159 * - write static index to debugfs:ieee80211/phyX/rc/fixed_rate_idx 160 * - write -1 to enable RC processing again 161 * - setting will be applied on next update 162 */ 163 u32 fixed_rate_idx; 164#endif 165}; 166 167struct minstrel_debugfs_info { 168 size_t len; 169 char buf[]; 170}; 171 172extern const struct rate_control_ops mac80211_minstrel; 173void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); 174 175/* Recalculate success probabilities and counters for a given rate using EWMA */ 176void minstrel_calc_rate_stats(struct minstrel_priv *mp, 177 struct minstrel_rate_stats *mrs); 178int minstrel_get_tp_avg(struct minstrel_rate *mr, int prob_avg); 179 180/* debugfs */ 181int minstrel_stats_open(struct inode *inode, struct file *file); 182int minstrel_stats_csv_open(struct inode *inode, struct file *file); 183 184#endif 185