/* * 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" #include "debug.h" #include "brcms_trace_events.h" /* max number of mpdus in an ampdu */ #define AMPDU_MAX_MPDU … /* max number of mpdus in an ampdu to a legacy */ #define AMPDU_NUM_MPDU_LEGACY … /* max Tx ba window size (in pdu) */ #define AMPDU_TX_BA_MAX_WSIZE … /* default Tx ba window size (in pdu) */ #define AMPDU_TX_BA_DEF_WSIZE … /* default Rx ba window size (in pdu) */ #define AMPDU_RX_BA_DEF_WSIZE … /* max Rx ba window size (in pdu) */ #define AMPDU_RX_BA_MAX_WSIZE … /* max dur of tx ampdu (in msec) */ #define AMPDU_MAX_DUR … /* default tx retry limit */ #define AMPDU_DEF_RETRY_LIMIT … /* default tx retry limit at reg rate */ #define AMPDU_DEF_RR_RETRY_LIMIT … /* default ffpld reserved bytes */ #define AMPDU_DEF_FFPLD_RSVD … /* # of inis to be freed on detach */ #define AMPDU_INI_FREE … /* max # of mpdus released at a time */ #define AMPDU_SCB_MAX_RELEASE … #define NUM_FFPLD_FIFO … #define FFPLD_TX_MAX_UNFL … #define FFPLD_MPDU_SIZE … #define FFPLD_MAX_MCS … #define FFPLD_PLD_INCR … #define FFPLD_MAX_AMPDU_CNT … #define AMPDU_DELIMITER_LEN … /* max allowed number of mpdus in an ampdu (2 streams) */ #define AMPDU_NUM_MPDU … #define TX_SEQ_TO_INDEX(seq) … /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */ #define AMPDU_MAX_MPDU_OVERHEAD … /* modulo add/sub, bound = 2^k */ #define MODADD_POW2(x, y, bound) … #define MODSUB_POW2(x, y, bound) … /* 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 { … }; /* 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) * 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 { … }; static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur) { … } static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu) { … } static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on) { … } static void brcms_c_ffpld_init(struct ampdu_info *ampdu) { … } struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc) { … } void brcms_c_ampdu_detach(struct ampdu_info *ampdu) { … } static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb) { … } static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu) { … } static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f) { … } /* evaluate the dma transfer rate using the tx underflows as feedback. * If necessary, increase tx fifo preloading. If not enough, * decrease maximum ampdu size for each mcs till underflows stop * Return 1 if pre-loading not active, -1 if not an underflow event, * 0 if pre-loading module took care of the event. */ static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid) { … } void brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid, uint max_rx_ampdu_bytes) /* from ht_cap in beacon */ { … } void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session, struct brcms_c_info *wlc) { … } /* * Preps the given packet for AMPDU based on the session data. If the * frame cannot be accomodated in the current session, -ENOSPC is * returned. */ int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session, struct sk_buff *p) { … } void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session) { … } static void brcms_c_ampdu_rate_status(struct brcms_c_info *wlc, struct ieee80211_tx_info *tx_info, struct tx_status *txs, u8 mcs) { … } static void brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p, struct tx_status *txs, u32 s1, u32 s2) { … } void brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p, struct tx_status *txs) { … } void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc) { … } bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid) { … } void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu) { … } /* * callback function that helps invalidating ampdu packets in a DMA queue */ static void dma_cb_fn_ampdu(void *txi, void *arg_a) { … } /* * When a remote party is no longer available for ampdu communication, any * pending tx ampdu packets in the driver have to be flushed. */ void brcms_c_ampdu_flush(struct brcms_c_info *wlc, struct ieee80211_sta *sta, u16 tid) { … }