#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <net/mac80211.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include "rs.h"
#include "fw-api.h"
#include "sta.h"
#include "iwl-op-mode.h"
#include "mvm.h"
#include "debugfs.h"
#define IWL_RATE_MAX_WINDOW …
#define RS_PERCENT(x) …
static u8 rs_ht_to_legacy[] = …;
static const u8 ant_toggle_lookup[] = …;
#define IWL_DECLARE_RATE_INFO(r, s, rp, rn) …
#define IWL_DECLARE_MCS_RATE(s) …
static const struct iwl_rs_rate_info iwl_rates[IWL_RATE_COUNT] = …;
enum rs_action { … };
enum rs_column_mode { … };
#define MAX_NEXT_COLUMNS …
#define MAX_COLUMN_CHECKS …
struct rs_tx_column;
allow_column_func_t;
struct rs_tx_column { … };
static bool rs_ant_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct rs_rate *rate,
const struct rs_tx_column *next_col)
{ … }
static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct rs_rate *rate,
const struct rs_tx_column *next_col)
{ … }
static bool rs_siso_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct rs_rate *rate,
const struct rs_tx_column *next_col)
{ … }
static bool rs_sgi_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct rs_rate *rate,
const struct rs_tx_column *next_col)
{ … }
static const struct rs_tx_column rs_tx_columns[] = …;
static inline u8 rs_extract_rate(u32 rate_n_flags)
{ … }
static int iwl_hwrate_to_plcp_idx(u32 rate_n_flags)
{ … }
static void rs_rate_scale_perform(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
int tid, bool ndp);
static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate);
static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search);
static const u16 expected_tpt_legacy[IWL_RATE_COUNT] = …;
static const u16 expected_tpt_siso_20MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_siso_40MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_siso_80MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_siso_160MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_mimo2_80MHz[4][IWL_RATE_COUNT] = …;
static const u16 expected_tpt_mimo2_160MHz[4][IWL_RATE_COUNT] = …;
static const char *rs_pretty_lq_type(enum iwl_table_type type)
{ … }
static char *rs_pretty_rate(const struct rs_rate *rate)
{ … }
static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
const char *prefix)
{ … }
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
{ … }
static void rs_rate_scale_clear_tbl_windows(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl)
{ … }
static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
{ … }
static int rs_tl_turn_on_agg_for_tid(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_data, u8 tid,
struct ieee80211_sta *sta)
{ … }
static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
u8 tid, struct iwl_lq_sta *lq_sta,
struct ieee80211_sta *sta)
{ … }
static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
{ … }
static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
{ … }
static int _rs_collect_tx_data(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl,
int scale_index, int attempts, int successes,
struct iwl_rate_scale_data *window)
{ … }
static int rs_collect_tpc_data(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl,
int scale_index, int attempts, int successes,
u8 reduced_txp)
{ … }
static void rs_update_tid_tpt_stats(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta,
u8 tid, int successes)
{ … }
static int rs_collect_tlc_data(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta, u8 tid,
struct iwl_scale_tbl_info *tbl,
int scale_index, int attempts, int successes)
{ … }
static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
struct rs_rate *rate)
{ … }
static int rs_rate_from_ucode_rate(const u32 ucode_rate,
enum nl80211_band band,
struct rs_rate *rate)
{ … }
static int rs_toggle_antenna(u32 valid_ant, struct rs_rate *rate)
{ … }
static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
struct rs_rate *rate)
{ … }
static u16 rs_get_adjacent_rate(struct iwl_mvm *mvm, u8 index, u16 rate_mask,
int rate_type)
{ … }
static inline bool rs_rate_supported(struct iwl_lq_sta *lq_sta,
struct rs_rate *rate)
{ … }
static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,
struct rs_rate *rate)
{ … }
static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
struct rs_rate *rate)
{ … }
static inline bool rs_rate_column_match(struct rs_rate *a,
struct rs_rate *b)
{ … }
static inline enum rs_column rs_get_column_from_rate(struct rs_rate *rate)
{ … }
static u8 rs_get_tid(struct ieee80211_hdr *hdr)
{ … }
static void rs_drv_mac80211_tx_status(void *mvm_r,
struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb)
{ … }
static void rs_set_stay_in_table(struct iwl_mvm *mvm, u8 is_legacy,
struct iwl_lq_sta *lq_sta)
{ … }
static inline int rs_get_max_rate_from_mask(unsigned long rate_mask)
{ … }
static int rs_get_max_allowed_rate(struct iwl_lq_sta *lq_sta,
const struct rs_tx_column *column)
{ … }
static const u16 *rs_get_expected_tpt_table(struct iwl_lq_sta *lq_sta,
const struct rs_tx_column *column,
u32 bw)
{ … }
static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl)
{ … }
static inline u8 rs_search_tbl(u8 active_tbl)
{ … }
static s32 rs_get_best_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl,
unsigned long rate_mask, s8 index)
{ … }
static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
{ … }
static void rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
{ … }
static void rs_set_amsdu_len(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl,
enum rs_action scale_action)
{ … }
static void rs_update_rate_tbl(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl)
{ … }
static bool rs_tweak_rate_tbl(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl,
enum rs_action scale_action)
{ … }
static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl)
{ … }
static int rs_switch_to_column(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct ieee80211_sta *sta,
enum rs_column col_id)
{ … }
static enum rs_action rs_get_rate_action(struct iwl_mvm *mvm,
struct iwl_scale_tbl_info *tbl,
s32 sr, int low, int high,
int current_tpt,
int low_tpt, int high_tpt)
{ … }
static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta)
{ … }
static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
int *weaker, int *stronger)
{ … }
static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct rs_rate *rate, enum nl80211_band band)
{ … }
enum tpc_action { … };
static enum tpc_action rs_get_tpc_action(struct iwl_mvm *mvm,
s32 sr, int weak, int strong,
int current_tpt,
int weak_tpt, int strong_tpt)
{ … }
static bool rs_tpc_perform(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl)
{ … }
static void rs_rate_scale_perform(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
int tid, bool ndp)
{ … }
struct rs_init_rate_info { … };
static const struct rs_init_rate_info rs_optimal_rates_24ghz_legacy[] = …;
static const struct rs_init_rate_info rs_optimal_rates_5ghz_legacy[] = …;
static const struct rs_init_rate_info rs_optimal_rates_ht[] = …;
static const struct rs_init_rate_info rs_optimal_rates_vht_20mhz[] = …;
static const struct rs_init_rate_info rs_optimal_rates_vht[] = …;
#define IWL_RS_LOW_RSSI_THRESHOLD …
static void rs_init_optimal_rate(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta)
{ … }
static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta)
{ … }
static void rs_get_initial_rate(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
enum nl80211_band band,
struct rs_rate *rate)
{ … }
void rs_update_last_rssi(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvmsta,
struct ieee80211_rx_status *rx_status)
{ … }
static void rs_initialize_lq(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
enum nl80211_band band)
{ … }
static void rs_drv_get_rate(void *mvm_r, struct ieee80211_sta *sta,
void *mvm_sta,
struct ieee80211_tx_rate_control *txrc)
{ … }
static void *rs_drv_alloc_sta(void *mvm_rate, struct ieee80211_sta *sta,
gfp_t gfp)
{ … }
static int rs_vht_highest_rx_mcs_index(struct ieee80211_sta_vht_cap *vht_cap,
int nss)
{ … }
static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
struct ieee80211_sta_vht_cap *vht_cap,
struct iwl_lq_sta *lq_sta)
{ … }
static void rs_ht_init(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
struct ieee80211_sta_ht_cap *ht_cap)
{ … }
static void rs_vht_init(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
struct ieee80211_sta_vht_cap *vht_cap)
{ … }
#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_reset_frame_stats(struct iwl_mvm *mvm)
{ … }
void iwl_mvm_update_frame_stats(struct iwl_mvm *mvm, u32 rate, bool agg)
{ … }
#endif
static void rs_drv_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
enum nl80211_band band)
{ … }
static void rs_drv_rate_update(void *mvm_r,
struct ieee80211_supported_band *sband,
struct cfg80211_chan_def *chandef,
struct ieee80211_sta *sta,
void *priv_sta, u32 changed)
{ … }
static void __iwl_mvm_rs_tx_status(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
int tid, struct ieee80211_tx_info *info,
bool ndp)
{ … }
void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
int tid, struct ieee80211_tx_info *info, bool ndp)
{ … }
#ifdef CONFIG_MAC80211_DEBUGFS
static void rs_build_rates_table_from_fixed(struct iwl_mvm *mvm,
struct iwl_lq_cmd *lq_cmd,
enum nl80211_band band,
u32 ucode_rate)
{ … }
#endif
static void rs_fill_rates_for_column(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct rs_rate *rate,
__le32 *rs_table, int *rs_table_index,
int num_rates, int num_retries,
u8 valid_tx_ant, bool toggle_ant)
{ … }
static void rs_build_rates_table(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate)
{ … }
struct rs_bfer_active_iter_data { … };
static void rs_bfer_active_iter(void *_data,
struct ieee80211_sta *sta)
{ … }
static int rs_bfer_priority(struct iwl_mvm_sta *sta)
{ … }
static int rs_bfer_priority_cmp(struct iwl_mvm_sta *sta1,
struct iwl_mvm_sta *sta2)
{ … }
static void rs_set_lq_ss_params(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate)
{ … }
static void rs_fill_lq_cmd(struct iwl_mvm *mvm,
struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate)
{ … }
static void *rs_alloc(struct ieee80211_hw *hw)
{ … }
static void rs_free(void *mvm_rate)
{ … }
static void rs_free_sta(void *mvm_r, struct ieee80211_sta *sta, void *mvm_sta)
{ … }
int rs_pretty_print_rate_v1(char *buf, int bufsz, const u32 rate)
{ … }
#ifdef CONFIG_MAC80211_DEBUGFS
static void rs_program_fix_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta)
{ … }
static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file,
const char __user *user_buf, size_t count, loff_t *ppos)
{ … }
static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{ … }
static const struct file_operations rs_sta_dbgfs_scale_table_ops = …;
static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file,
char __user *user_buf, size_t count, loff_t *ppos)
{ … }
static const struct file_operations rs_sta_dbgfs_stats_table_ops = …;
static ssize_t rs_sta_dbgfs_drv_tx_stats_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{ … }
static ssize_t rs_sta_dbgfs_drv_tx_stats_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{ … }
static const struct file_operations rs_sta_dbgfs_drv_tx_stats_ops = …;
static ssize_t iwl_dbgfs_ss_force_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{ … }
static ssize_t iwl_dbgfs_ss_force_write(struct iwl_lq_sta *lq_sta, char *buf,
size_t count, loff_t *ppos)
{ … }
#define MVM_DEBUGFS_READ_WRITE_FILE_OPS(name, bufsz) …
#define MVM_DEBUGFS_ADD_FILE_RS(name, parent, mode) …
MVM_DEBUGFS_READ_WRITE_FILE_OPS(ss_force, 32);
static void rs_drv_add_sta_debugfs(void *mvm, void *priv_sta,
struct dentry *dir)
{ … }
#endif
static void rs_rate_init_ops(void *mvm_r,
struct ieee80211_supported_band *sband,
struct cfg80211_chan_def *chandef,
struct ieee80211_sta *sta, void *mvm_sta)
{ … }
static const struct rate_control_ops rs_mvm_ops_drv = …;
void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_bss_conf *link_conf,
struct ieee80211_link_sta *link_sta,
enum nl80211_band band)
{ … }
int iwl_mvm_rate_control_register(void)
{ … }
void iwl_mvm_rate_control_unregister(void)
{ … }
static int rs_drv_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool enable)
{ … }
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
bool enable)
{ … }