linux/drivers/net/wireless/intel/iwlwifi/mvm/rs.c

// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
 *
 * Copyright(c) 2005 - 2014, 2018 - 2023 Intel Corporation. All rights reserved.
 * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH
 * Copyright(c) 2016 - 2017 Intel Deutschland GmbH
 *****************************************************************************/
#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

/* Calculations of success ratio are done in fixed point where 12800 is 100%.
 * Use this macro when dealing with thresholds consts set as a percentage
 */
#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)

/*
 * Parameter order:
 *   rate, ht rate, prev rate, next rate
 *
 * If there isn't a valid next or previous rate then INV is used which
 * maps to IWL_RATE_INVALID
 *
 */
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);

/*
 * The following tables contain the expected throughput metrics for all rates
 *
 *	1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
 *
 * where invalid entries are zeros.
 *
 * CCK rates are only valid in legacy table and will only be used in G
 * (2.4 GHz) band.
 */
static const u16 expected_tpt_legacy[IWL_RATE_COUNT] =;

/* Expected TpT tables. 4 indexes:
 * 0 - NGI, 1 - SGI, 2 - AGG+NGI, 3 - AGG+SGI
 */
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 function to get the expected throughput from an iwl_scale_tbl_info
 * that wraps a NULL pointer check
 */
static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
{}

/*
 * rs_collect_tx_data - Update the success/failure sliding window
 *
 * We keep a sliding window of the last 62 packets transmitted
 * at this rate.  window->data contains the bitmask of successful
 * packets.
 */
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)
{}

/* Convert rs_rate object into ucode rate bitmask */
static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm,
				  struct rs_rate *rate)
{}

/* Convert a ucode rate into an rs_rate object */
static int rs_rate_from_ucode_rate(const u32 ucode_rate,
				   enum nl80211_band band,
				   struct rs_rate *rate)
{}

/* switch to another antenna/antennas and return 1 */
/* if no other valid antenna found, return 0 */
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)
{}

/* Get the next supported lower rate in the current column.
 * Return true if bottom rate in the current column was reached
 */
static bool rs_get_lower_rate_in_column(struct iwl_lq_sta *lq_sta,
					struct rs_rate *rate)
{}

/* Get the next rate to use following a column downgrade */
static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta,
					  struct rs_rate *rate)
{}

/* Check if both rates share the same column */
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)
{}

/*
 * mac80211 sends us Tx status
 */
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)
{}

/*
 * Begin a period of staying with a selected modulation mode.
 * Set "stay_in_tbl" flag to prevent any mode switches.
 * Set frame tx success limits according to legacy vs. high-throughput,
 * and reset overall (spanning all rates) tx success history statistics.
 * These control how long we stay using same modulation mode before
 * searching for a new mode.
 */
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)
{}

/* rs uses two tables, one is active and the second is for searching better
 * configuration. This function, according to the index of the currently
 * active table returns the search table, which is located at the
 * index complementary to 1 according to the active table (active = 1,
 * search = 0 or active = 0, search = 1).
 * Since lq_info is an arary of size 2, make sure index cannot be out of bounds.
 */
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,	/* "search" */
			    unsigned long rate_mask, s8 index)
{}

static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
{}

/*
 * Check whether we should continue using same modulation mode, or
 * begin search for a new mode, based on:
 * 1) # tx successes or failures while using this mode
 * 2) # times calling this function
 * 3) elapsed time in this mode (not used, for now)
 */
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)
{}

/*
 * setup rate table in uCode
 */
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)
{}

/*
 * Do rate scaling and search for new modulation mode.
 */
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[] =;

/* MCS index 9 is not valid for 20MHz VHT channel width,
 * but is ok for 40, 80 and 160MHz channels.
 */
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

/* Init the optimal rate based on STA caps
 * This combined with rssi is used to report the last tx rate
 * to userspace when we haven't transmitted enough frames.
 */
static void rs_init_optimal_rate(struct iwl_mvm *mvm,
				 struct ieee80211_sta *sta,
				 struct iwl_lq_sta *lq_sta)
{}

/* Compute the optimal rate index based on RSSI */
static struct rs_rate *rs_get_optimal_rate(struct iwl_mvm *mvm,
					   struct iwl_lq_sta *lq_sta)
{}

/* Choose an initial legacy rate and antenna to use based on the RSSI
 * of last Rx
 */
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)
{}

/* Save info about RSSI of last Rx */
void rs_update_last_rssi(struct iwl_mvm *mvm,
			 struct iwl_mvm_sta *mvmsta,
			 struct ieee80211_rx_status *rx_status)
{}

/*
 * rs_initialize_lq - Initialize a station's hardware rate table
 *
 * The uCode's station table contains a table of fallback rates
 * for automatic fallback during transmission.
 *
 * NOTE: This sets up a default set of values.  These will be replaced later
 *       if the driver's iwl-agn-rs rate scaling algorithm is used, instead of
 *       rc80211_simple.
 *
 * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
 *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
 *       which requires station table entry to exist).
 */
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

/*
 * Called after adding a new station to initialize rate scaling
 */
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 /* CONFIG_MAC80211_DEBUGFS */

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)
{}

/* Building the rate table is non trivial. When we're in MIMO2/VHT/80Mhz/SGI
 * column the rate table should look like this:
 *
 * rate[0] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
 * rate[1] 0x400F019 VHT | ANT: AB BW: 80Mhz MCS: 9 NSS: 2 SGI
 * rate[2] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
 * rate[3] 0x400F018 VHT | ANT: AB BW: 80Mhz MCS: 8 NSS: 2 SGI
 * rate[4] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
 * rate[5] 0x400F017 VHT | ANT: AB BW: 80Mhz MCS: 7 NSS: 2 SGI
 * rate[6] 0x4005007 VHT | ANT: A BW: 80Mhz MCS: 7 NSS: 1 NGI
 * rate[7] 0x4009006 VHT | ANT: B BW: 80Mhz MCS: 6 NSS: 1 NGI
 * rate[8] 0x4005005 VHT | ANT: A BW: 80Mhz MCS: 5 NSS: 1 NGI
 * rate[9] 0x800B Legacy | ANT: B Rate: 36 Mbps
 * rate[10] 0x4009 Legacy | ANT: A Rate: 24 Mbps
 * rate[11] 0x8007 Legacy | ANT: B Rate: 18 Mbps
 * rate[12] 0x4005 Legacy | ANT: A Rate: 12 Mbps
 * rate[13] 0x800F Legacy | ANT: B Rate: 9 Mbps
 * rate[14] 0x400D Legacy | ANT: A Rate: 6 Mbps
 * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
 */
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)
{}

/* Returns >0 if sta1 has a higher BFER priority compared to sta2 */
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)
{}

/* rate scale requires free function to be implemented */
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
/*
 * Program the device to use fixed rate for frame transmit
 * This is for debugging/testing only
 * once the device start use fixed rate, we need to reload the module
 * to being back the normal operation.
 */
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

/*
 * Initialization of rate scaling information is done by driver after
 * the station is added. Since mac80211 calls this function before a
 * station is added we ignore it.
 */
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)
{}

/* ops for rate scaling implemented in the driver */
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)
{}

/**
 * iwl_mvm_tx_protection - ask FW to enable RTS/CTS protection
 * @mvm: The mvm component
 * @mvmsta: The station
 * @enable: Enable Tx protection?
 *
 * Returns: an error code
 */
int iwl_mvm_tx_protection(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta,
			  bool enable)
{}