/*
* Copyright (c) 2010 Broadcom Corporation
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <net/mac80211.h>
#include "rate.h"
#include "scb.h"
#include "phy/phy_hal.h"
#include "antsel.h"
#include "main.h"
#include "ampdu.h"
/* max number of mpdus in an ampdu */
#define AMPDU_MAX_MPDU 32
/* max number of mpdus in an ampdu to a legacy */
#define AMPDU_NUM_MPDU_LEGACY 16
/* max Tx ba window size (in pdu) */
#define AMPDU_TX_BA_MAX_WSIZE 64
/* default Tx ba window size (in pdu) */
#define AMPDU_TX_BA_DEF_WSIZE 64
/* default Rx ba window size (in pdu) */
#define AMPDU_RX_BA_DEF_WSIZE 64
/* max Rx ba window size (in pdu) */
#define AMPDU_RX_BA_MAX_WSIZE 64
/* max dur of tx ampdu (in msec) */
#define AMPDU_MAX_DUR 5
/* default tx retry limit */
#define AMPDU_DEF_RETRY_LIMIT 5
/* default tx retry limit at reg rate */
#define AMPDU_DEF_RR_RETRY_LIMIT 2
/* default weight of ampdu in txfifo */
#define AMPDU_DEF_TXPKT_WEIGHT 2
/* default ffpld reserved bytes */
#define AMPDU_DEF_FFPLD_RSVD 2048
/* # of inis to be freed on detach */
#define AMPDU_INI_FREE 10
/* max # of mpdus released at a time */
#define AMPDU_SCB_MAX_RELEASE 20
#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
* without underflows
*/
#define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
#define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
#define FFPLD_PLD_INCR 1000 /* increments in bytes */
#define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
* accumulate between resets.
*/
#define AMPDU_DELIMITER_LEN 4
/* max allowed number of mpdus in an ampdu (2 streams) */
#define AMPDU_NUM_MPDU 16
#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
AMPDU_DELIMITER_LEN + 3\
+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
/* modulo add/sub, bound = 2^k */
#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
/* structure to hold tx fifo information and pre-loading state
* counters specific to tx underflows of ampdus
* some counters might be redundant with the ones in wlc or ampdu structures.
* This allows to maintain a specific state independently of
* how often and/or when the wlc counters are updated.
*
* ampdu_pld_size: number of bytes to be pre-loaded
* mcs2ampdu_table: per-mcs max # of mpdus in an ampdu
* prev_txfunfl: num of underflows last read from the HW macstats counter
* accum_txfunfl: num of underflows since we modified pld params
* accum_txampdu: num of tx ampdu since we modified pld params
* prev_txampdu: previous reading of tx ampdu
* dmaxferrate: estimated dma avg xfer rate in kbits/sec
*/
struct brcms_fifo_info {
u16 ampdu_pld_size;
u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
u16 prev_txfunfl;
u32 accum_txfunfl;
u32 accum_txampdu;
u32 prev_txampdu;
u32 dmaxferrate;
};
/* AMPDU module specific state
*
* wlc: pointer to main wlc structure
* scb_handle: scb cubby handle to retrieve data from scb
* ini_enable: per-tid initiator enable/disable of ampdu
* ba_tx_wsize: Tx ba window size (in pdu)
* ba_rx_wsize: Rx ba window size (in pdu)
* retry_limit: mpdu transmit retry limit
* rr_retry_limit: mpdu transmit retry limit at regular rate
* retry_limit_tid: per-tid mpdu transmit retry limit
* rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate
* mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
* max_pdu: max pdus allowed in ampdu
* dur: max duration of an ampdu (in msec)
* txpkt_weight: weight of ampdu in txfifo; reduces rate lag
* rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
* ffpld_rsvd: number of bytes to reserve for preload
* max_txlen: max size of ampdu per mcs, bw and sgi
* mfbr: enable multiple fallback rate
* tx_max_funl: underflows should be kept such that
* (tx_max_funfl*underflows) < tx frames
* fifo_tb: table of fifo infos
*/
struct ampdu_info {
struct brcms_c_info *wlc;
int scb_handle;
u8 ini_enable[AMPDU_MAX_SCB_TID];
u8 ba_tx_wsize;
u8 ba_rx_wsize;
u8 retry_limit;
u8 rr_retry_limit;
u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
u8 mpdu_density;
s8 max_pdu;
u8 dur;
u8 txpkt_weight;
u8 rx_factor;
u32 ffpld_rsvd;
u32 max_txlen[MCS_TABLE_SIZE][2][2];
bool mfbr;
u32 tx_max_funl;
struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
};
/* used for flushing ampdu packets */
struct cb_del_ampdu_pars {
struct ieee80211_sta *sta;
u16 tid;
};
static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
{
u32 rate, mcs;
for (mcs<