linux/drivers/net/wireless/intel/iwlegacy/4965-rs.c

// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
 *
 * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
 *
 * Contact Information:
 *  Intel Linux Wireless <[email protected]>
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/
#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 "common.h"
#include "4965.h"

#define IL4965_RS_NAME

#define NUM_TRY_BEFORE_ANT_TOGGLE
#define IL_NUMBER_TRY
#define IL_HT_NUMBER_TRY

#define RATE_MAX_WINDOW
#define RATE_MIN_FAILURE_TH
#define RATE_MIN_SUCCESS_TH

/* max allowed rate miss before sync LQ cmd */
#define IL_MISSED_RATE_MAX
/* max time to accum history 2 seconds */
#define RATE_SCALE_FLUSH_INTVL

static u8 rs_ht_to_legacy[] =;

static const u8 ant_toggle_lookup[] =;

#define IL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)

/*
 * Parameter order:
 *   rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
 *
 * If there isn't a valid next or previous rate then INV is used which
 * maps to RATE_INVALID
 *
 */
const struct il_rate_info il_rates[RATE_COUNT] =;

static int
il4965_hwrate_to_plcp_idx(u32 rate_n_flags)
{}

static void il4965_rs_rate_scale_perform(struct il_priv *il,
					 struct sk_buff *skb,
					 struct ieee80211_sta *sta,
					 struct il_lq_sta *lq_sta);
static void il4965_rs_fill_link_cmd(struct il_priv *il,
				    struct il_lq_sta *lq_sta, u32 rate_n_flags);
static void il4965_rs_stay_in_table(struct il_lq_sta *lq_sta,
				    bool force_search);

#ifdef CONFIG_MAC80211_DEBUGFS
static void il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta,
				    u32 *rate_n_flags, int idx);
#else
static void
il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx)
{
}
#endif

/*
 * 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 s32 expected_tpt_legacy[RATE_COUNT] =;

static s32 expected_tpt_siso20MHz[4][RATE_COUNT] =;

static s32 expected_tpt_siso40MHz[4][RATE_COUNT] =;

static s32 expected_tpt_mimo2_20MHz[4][RATE_COUNT] =;

static s32 expected_tpt_mimo2_40MHz[4][RATE_COUNT] =;

/* mbps, mcs */
static const struct il_rate_mcs_info il_rate_mcs[RATE_COUNT] =;

#define MCS_IDX_PER_STREAM

static inline u8
il4965_rs_extract_rate(u32 rate_n_flags)
{}

static void
il4965_rs_rate_scale_clear_win(struct il_rate_scale_data *win)
{}

static inline u8
il4965_rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
{}

/*
 *	removes the old data from the stats. All data that is older than
 *	TID_MAX_TIME_DIFF, will be deleted.
 */
static void
il4965_rs_tl_rm_old_stats(struct il_traffic_load *tl, u32 curr_time)
{}

/*
 *	increment traffic load value for tid and also remove
 *	any old values if passed the certain time period
 */
static u8
il4965_rs_tl_add_packet(struct il_lq_sta *lq_data, struct ieee80211_hdr *hdr)
{}

/*
	get the traffic load value for tid
*/
static u32
il4965_rs_tl_get_load(struct il_lq_sta *lq_data, u8 tid)
{}

static int
il4965_rs_tl_turn_on_agg_for_tid(struct il_priv *il, struct il_lq_sta *lq_data,
				 u8 tid, struct ieee80211_sta *sta)
{}

static void
il4965_rs_tl_turn_on_agg(struct il_priv *il, u8 tid, struct il_lq_sta *lq_data,
			 struct ieee80211_sta *sta)
{}

static inline int
il4965_get_il4965_num_of_ant_from_rate(u32 rate_n_flags)
{}

/*
 * Static function to get the expected throughput from an il_scale_tbl_info
 * that wraps a NULL pointer check
 */
static s32
il4965_get_expected_tpt(struct il_scale_tbl_info *tbl, int rs_idx)
{}

/*
 * il4965_rs_collect_tx_data - Update the success/failure sliding win
 *
 * We keep a sliding win of the last 62 packets transmitted
 * at this rate.  win->data contains the bitmask of successful
 * packets.
 */
static int
il4965_rs_collect_tx_data(struct il_scale_tbl_info *tbl, int scale_idx,
			  int attempts, int successes)
{}

/*
 * Fill uCode API rate_n_flags field, based on "search" or "active" table.
 */
static u32
il4965_rate_n_flags_from_tbl(struct il_priv *il, struct il_scale_tbl_info *tbl,
			     int idx, u8 use_green)
{}

/*
 * Interpret uCode API's rate_n_flags format,
 * fill "search" or "active" tx mode table.
 */
static int
il4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
				enum nl80211_band band,
				struct il_scale_tbl_info *tbl, int *rate_idx)
{}

/* switch to another antenna/antennas and return 1 */
/* if no other valid antenna found, return 0 */
static int
il4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
			 struct il_scale_tbl_info *tbl)
{}

/*
 * Green-field mode is valid if the station supports it and
 * there are no non-GF stations present in the BSS.
 */
static bool
il4965_rs_use_green(struct il_priv *il, struct ieee80211_sta *sta)
{}

/*
 * il4965_rs_get_supported_rates - get the available rates
 *
 * if management frame or broadcast frame only return
 * basic available rates.
 *
 */
static u16
il4965_rs_get_supported_rates(struct il_lq_sta *lq_sta,
			      struct ieee80211_hdr *hdr,
			      enum il_table_type rate_type)
{}

static u16
il4965_rs_get_adjacent_rate(struct il_priv *il, u8 idx, u16 rate_mask,
			    int rate_type)
{}

static u32
il4965_rs_get_lower_rate(struct il_lq_sta *lq_sta,
			 struct il_scale_tbl_info *tbl, u8 scale_idx,
			 u8 ht_possible)
{}

/*
 * Simple function to compare two rate scale table types
 */
static bool
il4965_table_type_matches(struct il_scale_tbl_info *a,
			  struct il_scale_tbl_info *b)
{}

/*
 * mac80211 sends us Tx status
 */
static void
il4965_rs_tx_status(void *il_r, struct ieee80211_supported_band *sband,
		    struct ieee80211_sta *sta, void *il_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 stats.
 * These control how long we stay using same modulation mode before
 * searching for a new mode.
 */
static void
il4965_rs_set_stay_in_table(struct il_priv *il, u8 is_legacy,
			    struct il_lq_sta *lq_sta)
{}

/*
 * Find correct throughput table for given mode of modulation
 */
static void
il4965_rs_set_expected_tpt_table(struct il_lq_sta *lq_sta,
				 struct il_scale_tbl_info *tbl)
{}

/*
 * Find starting rate for new "search" high-throughput mode of modulation.
 * Goal is to find lowest expected rate (under perfect conditions) that is
 * above the current measured throughput of "active" mode, to give new mode
 * a fair chance to prove itself without too many challenges.
 *
 * This gets called when transitioning to more aggressive modulation
 * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
 * (i.e. MIMO to SISO).  When moving to MIMO, bit rate will typically need
 * to decrease to match "active" throughput.  When moving from MIMO to SISO,
 * bit rate will typically need to increase, but not if performance was bad.
 */
static s32
il4965_rs_get_best_rate(struct il_priv *il, struct il_lq_sta *lq_sta,
			struct il_scale_tbl_info *tbl,	/* "search" */
			u16 rate_mask, s8 idx)
{}

/*
 * Set up search table for MIMO2
 */
static int
il4965_rs_switch_to_mimo2(struct il_priv *il, struct il_lq_sta *lq_sta,
			  struct ieee80211_conf *conf,
			  struct ieee80211_sta *sta,
			  struct il_scale_tbl_info *tbl, int idx)
{}

/*
 * Set up search table for SISO
 */
static int
il4965_rs_switch_to_siso(struct il_priv *il, struct il_lq_sta *lq_sta,
			 struct ieee80211_conf *conf, struct ieee80211_sta *sta,
			 struct il_scale_tbl_info *tbl, int idx)
{}

/*
 * Try to switch to new modulation mode from legacy
 */
static int
il4965_rs_move_legacy_other(struct il_priv *il, struct il_lq_sta *lq_sta,
			    struct ieee80211_conf *conf,
			    struct ieee80211_sta *sta, int idx)
{}

/*
 * Try to switch to new modulation mode from SISO
 */
static int
il4965_rs_move_siso_to_other(struct il_priv *il, struct il_lq_sta *lq_sta,
			     struct ieee80211_conf *conf,
			     struct ieee80211_sta *sta, int idx)
{}

/*
 * Try to switch to new modulation mode from MIMO2
 */
static int
il4965_rs_move_mimo2_to_other(struct il_priv *il, struct il_lq_sta *lq_sta,
			      struct ieee80211_conf *conf,
			      struct ieee80211_sta *sta, int idx)
{}

/*
 * 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
il4965_rs_stay_in_table(struct il_lq_sta *lq_sta, bool force_search)
{}

/*
 * setup rate table in uCode
 */
static void
il4965_rs_update_rate_tbl(struct il_priv *il, struct il_lq_sta *lq_sta,
			  struct il_scale_tbl_info *tbl, int idx, u8 is_green)
{}

/*
 * Do rate scaling and search for new modulation mode.
 */
static void
il4965_rs_rate_scale_perform(struct il_priv *il, struct sk_buff *skb,
			     struct ieee80211_sta *sta,
			     struct il_lq_sta *lq_sta)
{}

/*
 * il4965_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-4965-rs rate scaling algorithm is used, instead of
 *       rc80211_simple.
 *
 * NOTE: Run C_ADD_STA command to set up station table entry, before
 *       calling this function (which runs C_TX_LINK_QUALITY_CMD,
 *       which requires station table entry to exist).
 */
static void
il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
			struct ieee80211_sta *sta, struct il_lq_sta *lq_sta)
{}

static void
il4965_rs_get_rate(void *il_r, struct ieee80211_sta *sta, void *il_sta,
		   struct ieee80211_tx_rate_control *txrc)
{}

static void *
il4965_rs_alloc_sta(void *il_rate, struct ieee80211_sta *sta, gfp_t gfp)
{}

/*
 * Called after adding a new station to initialize rate scaling
 */
void
il4965_rs_rate_init(struct il_priv *il, struct ieee80211_sta *sta, u8 sta_id)
{}

static void
il4965_rs_fill_link_cmd(struct il_priv *il, struct il_lq_sta *lq_sta,
			u32 new_rate)
{}

static void *
il4965_rs_alloc(struct ieee80211_hw *hw)
{}

/* rate scale requires free function to be implemented */
static void
il4965_rs_free(void *il_rate)
{}

static void
il4965_rs_free_sta(void *il_r, struct ieee80211_sta *sta, void *il_sta)
{}

#ifdef CONFIG_MAC80211_DEBUGFS

static void
il4965_rs_dbgfs_set_mcs(struct il_lq_sta *lq_sta, u32 * rate_n_flags, int idx)
{}

static ssize_t
il4965_rs_sta_dbgfs_scale_table_write(struct file *file,
				      const char __user *user_buf,
				      size_t count, loff_t *ppos)
{}

static ssize_t
il4965_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
il4965_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
il4965_rs_sta_dbgfs_rate_scale_data_read(struct file *file,
					 char __user *user_buf, size_t count,
					 loff_t *ppos)
{}

static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops =;

static void
il4965_rs_add_debugfs(void *il, void *il_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
il4965_rs_rate_init_stub(void *il_r, struct ieee80211_supported_band *sband,
			 struct cfg80211_chan_def *chandef,
			 struct ieee80211_sta *sta, void *il_sta)
{}

static const struct rate_control_ops rs_4965_ops =;

int
il4965_rate_control_register(void)
{}

void
il4965_rate_control_unregister(void)
{}