blob: 02971273ca4d258ff747956a120f9c7cd4274477 [file] [log] [blame]
/** @file mlan_11n.h
*
* @brief Interface for the 802.11n mlan_11n module implemented in mlan_11n.c
*
* Driver interface functions and type declarations for the 11n module
* implemented in mlan_11n.c.
*
* Copyright (C) 2008-2014, Marvell International Ltd.
*
* This software file (the "File") is distributed by Marvell International
* Ltd. under the terms of the GNU General Public License Version 2, June 1991
* (the "License"). You may use, redistribute and/or modify this File in
* accordance with the terms and conditions of the License, a copy of which
* is available by writing to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
* worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
* IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
* ARE EXPRESSLY DISCLAIMED. The License provides additional details about
* this warranty disclaimer.
*
*/
/********************************************************
Change log:
12/01/2008: initial version
********************************************************/
#ifndef _MLAN_11N_H_
#define _MLAN_11N_H_
#include "mlan_11n_aggr.h"
#include "mlan_11n_rxreorder.h"
#include "mlan_wmm.h"
/** Print the 802.11n device capability */
void wlan_show_dot11ndevcap(pmlan_adapter pmadapter, t_u32 cap);
/** Print the 802.11n device MCS */
void wlan_show_devmcssupport(pmlan_adapter pmadapter, t_u8 support);
/** Handle the command response of a delete block ack request */
mlan_status wlan_ret_11n_delba(mlan_private * priv, HostCmd_DS_COMMAND * resp);
/** Handle the command response of an add block ack request */
mlan_status wlan_ret_11n_addba_req(mlan_private * priv,
HostCmd_DS_COMMAND * resp);
/** Handle the command response of 11ncfg command */
mlan_status wlan_ret_11n_cfg(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND * resp,
IN mlan_ioctl_req * pioctl_buf);
/** Prepare 11ncfg command */
mlan_status wlan_cmd_11n_cfg(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND * cmd, IN t_u16 cmd_action,
IN t_void * pdata_buf);
/** Prepare reject addba requst command */
mlan_status wlan_cmd_reject_addba_req(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND * cmd,
IN t_u16 cmd_action,
IN t_void * pdata_buf);
/** Handle the command response of rejecting addba request */
mlan_status wlan_ret_reject_addba_req(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND * resp,
IN mlan_ioctl_req * pioctl_buf);
/** Prepare TX BF configuration command */
mlan_status wlan_cmd_tx_bf_cfg(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND * cmd,
IN t_u16 cmd_action, IN t_void * pdata_buf);
/** Handle the command response TX BF configuration */
mlan_status wlan_ret_tx_bf_cfg(IN pmlan_private pmpriv,
IN HostCmd_DS_COMMAND * resp,
IN mlan_ioctl_req * pioctl_buf);
#ifdef STA_SUPPORT
/** Append the 802_11N tlv */
int wlan_cmd_append_11n_tlv(IN mlan_private * pmpriv,
IN BSSDescriptor_t * pbss_desc,
OUT t_u8 ** ppbuffer);
/** wlan fill HT cap tlv */
void wlan_fill_ht_cap_tlv(mlan_private * priv, MrvlIETypes_HTCap_t * pht_cap,
t_u8 band);
/** wlan fill HT cap IE */
void wlan_fill_ht_cap_ie(mlan_private * priv, IEEEtypes_HTCap_t * pht_cap,
t_u8 bands);
#endif /* STA_SUPPORT */
/** Miscellaneous configuration handler */
mlan_status wlan_11n_cfg_ioctl(IN pmlan_adapter pmadapter,
IN pmlan_ioctl_req pioctl_req);
/** Delete Tx BA stream table entry */
void wlan_11n_delete_txbastream_tbl_entry(mlan_private * priv,
TxBAStreamTbl * ptx_tbl);
/** Delete all Tx BA stream table entries */
void wlan_11n_deleteall_txbastream_tbl(mlan_private * priv);
/** Get Tx BA stream table */
TxBAStreamTbl *wlan_11n_get_txbastream_tbl(mlan_private * priv, int tid,
t_u8 * ra);
/** Create Tx BA stream table */
void wlan_11n_create_txbastream_tbl(mlan_private * priv, t_u8 * ra, int tid,
baStatus_e ba_status);
/** Send ADD BA request */
int wlan_send_addba(mlan_private * priv, int tid, t_u8 * peer_mac);
/** Send DEL BA request */
int wlan_send_delba(mlan_private * priv, pmlan_ioctl_req pioctl_req, int tid,
t_u8 * peer_mac, int initiator);
/** This function handles the command response of delete a block ack request*/
void wlan_11n_delete_bastream(mlan_private * priv, t_u8 * del_ba);
/** get rx reorder table */
int wlan_get_rxreorder_tbl(mlan_private * priv, rx_reorder_tbl * buf);
/** get tx ba stream table */
int wlan_get_txbastream_tbl(mlan_private * priv, tx_ba_stream_tbl * buf);
/** send delba */
void wlan_11n_delba(mlan_private * priv, int tid);
/** Minimum number of AMSDU */
#define MIN_NUM_AMSDU 2
/** AMSDU Aggr control cmd resp */
mlan_status wlan_ret_amsdu_aggr_ctrl(pmlan_private pmpriv,
HostCmd_DS_COMMAND * resp,
mlan_ioctl_req * pioctl_buf);
/** reconfigure tx buf size */
mlan_status wlan_cmd_recfg_tx_buf(mlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf);
/** AMSDU aggr control cmd */
mlan_status wlan_cmd_amsdu_aggr_ctrl(mlan_private * priv,
HostCmd_DS_COMMAND * cmd,
int cmd_action, void *pdata_buf);
/** get channel offset */
t_u8 wlan_get_second_channel_offset(int chan);
/** clean up txbastream_tbl */
void wlan_11n_cleanup_txbastream_tbl(mlan_private * priv, t_u8 * ra);
/**
* @brief This function checks whether a station has 11N enabled or not
*
* @param priv A pointer to mlan_private
* @param mac station mac address
* @return MTRUE or MFALSE
*/
static INLINE t_u8
is_station_11n_enabled(mlan_private * priv, t_u8 * mac)
{
sta_node *sta_ptr = MNULL;
sta_ptr = wlan_get_station_entry(priv, mac);
if (sta_ptr)
return (sta_ptr->is_11n_enabled) ? MTRUE : MFALSE;
return MFALSE;
}
/**
* @brief This function get station max amsdu size
*
* @param priv A pointer to mlan_private
* @param mac station mac address
* @return max amsdu size statio supported
*/
static INLINE t_u16
get_station_max_amsdu_size(mlan_private * priv, t_u8 * mac)
{
sta_node *sta_ptr = MNULL;
sta_ptr = wlan_get_station_entry(priv, mac);
if (sta_ptr)
return sta_ptr->max_amsdu;
return 0;
}
/**
* @brief This function checks whether a station allows AMPDU or not
*
* @param priv A pointer to mlan_private
* @param ptr A pointer to RA list table
* @param tid TID value for ptr
* @return MTRUE or MFALSE
*/
static INLINE t_u8
is_station_ampdu_allowed(mlan_private * priv, raListTbl * ptr, int tid)
{
sta_node *sta_ptr = MNULL;
sta_ptr = wlan_get_station_entry(priv, ptr->ra);
if (sta_ptr) {
if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
if (priv->sec_info.wapi_enabled &&
!sta_ptr->wapi_key_on)
return MFALSE;
}
return (sta_ptr->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED)
? MTRUE : MFALSE;
}
return MFALSE;
}
/**
* @brief This function disable station ampdu for specific tid
*
* @param priv A pointer to mlan_private
* @param tid tid index
* @param ra station mac address
* @return N/A
*/
static INLINE void
disable_station_ampdu(mlan_private * priv, t_u8 tid, t_u8 * ra)
{
sta_node *sta_ptr = MNULL;
sta_ptr = wlan_get_station_entry(priv, ra);
if (sta_ptr)
sta_ptr->ampdu_sta[tid] = BA_STREAM_NOT_ALLOWED;
return;
}
/**
* @brief This function checks whether current BA stream is high priority or not
*
* @param priv A pointer to mlan_private
* @param tid TID
*
* @return MTRUE or MFALSE
*/
static INLINE t_u8
wlan_is_cur_bastream_high_prio(mlan_private * priv, int tid)
{
TxBAStreamTbl *ptx_tbl;
ENTER();
ptx_tbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
&priv->tx_ba_stream_tbl_ptr,
priv->adapter->callbacks.
moal_spin_lock,
priv->adapter->callbacks.
moal_spin_unlock);
if (!ptx_tbl)
return MFALSE;
while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) {
if (priv->aggr_prio_tbl[tid].ampdu_user >
priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user) {
LEAVE();
return MTRUE;
}
ptx_tbl = ptx_tbl->pnext;
}
LEAVE();
return MFALSE;
}
/**
* @brief This function checks whether AMPDU is allowed or not
*
* @param priv A pointer to mlan_private
* @param ptr A pointer to RA list table
* @param tid TID value for ptr
*
* @return MTRUE or MFALSE
*/
static INLINE t_u8
wlan_is_ampdu_allowed(mlan_private * priv, raListTbl * ptr, int tid)
{
#ifdef UAP_SUPPORT
if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP)
return is_station_ampdu_allowed(priv, ptr, tid);
#endif /* UAP_SUPPORT */
if (priv->sec_info.wapi_enabled && !priv->sec_info.wapi_key_on)
return MFALSE;
if (ptr->is_tdls_link)
return is_station_ampdu_allowed(priv, ptr, tid);
if (priv->adapter->tdls_status != TDLS_NOT_SETUP && !priv->txaggrctrl)
return MFALSE;
return (priv->aggr_prio_tbl[tid].ampdu_ap != BA_STREAM_NOT_ALLOWED)
? MTRUE : MFALSE;
}
/**
* @brief This function checks whether AMSDU is allowed for BA stream
*
* @param priv A pointer to mlan_private
* @param ptr A pointer to RA list table
* @param tid TID value for ptr
*
* @return MTRUE or MFALSE
*/
static int INLINE
wlan_is_amsdu_in_ampdu_allowed(mlan_private * priv, raListTbl * ptr, int tid)
{
TxBAStreamTbl *ptx_tbl;
ENTER();
ptx_tbl = wlan_11n_get_txbastream_tbl(priv, tid, ptr->ra);
if (ptx_tbl) {
LEAVE();
return ptx_tbl->amsdu;
}
LEAVE();
return MFALSE;
}
/**
* @brief This function checks whether AMSDU is allowed or not
*
* @param priv A pointer to mlan_private
* @param ptr A pointer to RA list table
* @param tid TID value for ptr
*
* @return MTRUE or MFALSE
*/
static INLINE t_u8
wlan_is_amsdu_allowed(mlan_private * priv, raListTbl * ptr, int tid)
{
#ifdef UAP_SUPPORT
sta_node *sta_ptr = MNULL;
if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
sta_ptr = wlan_get_station_entry(priv, ptr->ra);
if (sta_ptr) {
if (priv->sec_info.wapi_enabled &&
!sta_ptr->wapi_key_on)
return MFALSE;
}
}
#endif /* UAP_SUPPORT */
#define TXRATE_BITMAP_INDEX_MCS0_7 2
return ((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)
&& ((priv->is_data_rate_auto)
|| !((priv->bitmap_rates[TXRATE_BITMAP_INDEX_MCS0_7]) &
0x03))) ? MTRUE : MFALSE;
}
/**
* @brief This function checks whether a BA stream is available or not
*
* @param priv A pointer to mlan_private
*
* @return MTRUE or MFALSE
*/
static INLINE t_u8
wlan_is_bastream_avail(mlan_private * priv)
{
mlan_private *pmpriv = MNULL;
t_u8 i = 0;
t_u32 bastream_num = 0;
for (i = 0; i < priv->adapter->priv_num; i++) {
pmpriv = priv->adapter->priv[i];
if (pmpriv)
bastream_num +=
wlan_wmm_list_len(priv->adapter,
(pmlan_list_head) & pmpriv->
tx_ba_stream_tbl_ptr);
}
return (bastream_num < MLAN_MAX_TX_BASTREAM_SUPPORTED) ? MTRUE : MFALSE;
}
/**
* @brief This function finds the stream to delete
*
* @param priv A pointer to mlan_private
* @param ptr A pointer to RA list table
* @param ptr_tid TID value of ptr
* @param ptid A pointer to TID of stream to delete, if return MTRUE
* @param ra RA of stream to delete, if return MTRUE
*
* @return MTRUE or MFALSE
*/
static INLINE t_u8
wlan_find_stream_to_delete(mlan_private * priv,
raListTbl * ptr, int ptr_tid, int *ptid, t_u8 * ra)
{
int tid;
t_u8 ret = MFALSE;
TxBAStreamTbl *ptx_tbl;
ENTER();
ptx_tbl = (TxBAStreamTbl *) util_peek_list(priv->adapter->pmoal_handle,
&priv->tx_ba_stream_tbl_ptr,
priv->adapter->callbacks.
moal_spin_lock,
priv->adapter->callbacks.
moal_spin_unlock);
if (!ptx_tbl) {
LEAVE();
return ret;
}
tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user;
while (ptx_tbl != (TxBAStreamTbl *) & priv->tx_ba_stream_tbl_ptr) {
if (tid > priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user) {
tid = priv->aggr_prio_tbl[ptx_tbl->tid].ampdu_user;
*ptid = ptx_tbl->tid;
memcpy(priv->adapter, ra, ptx_tbl->ra,
MLAN_MAC_ADDR_LENGTH);
ret = MTRUE;
}
ptx_tbl = ptx_tbl->pnext;
}
LEAVE();
return ret;
}
/**
* @brief This function checks whether BA stream is setup
*
* @param priv A pointer to mlan_private
* @param ptr A pointer to RA list table
* @param tid TID value for ptr
*
* @return MTRUE or MFALSE
*/
static int INLINE
wlan_is_bastream_setup(mlan_private * priv, raListTbl * ptr, int tid)
{
TxBAStreamTbl *ptx_tbl;
ENTER();
ptx_tbl = wlan_11n_get_txbastream_tbl(priv, tid, ptr->ra);
if (ptx_tbl) {
LEAVE();
return IS_BASTREAM_SETUP(ptx_tbl) ? MTRUE : MFALSE;
}
LEAVE();
return MFALSE;
}
/**
* @brief This function checks whether 11n is supported
*
* @param priv A pointer to mlan_private
* @param ra Address of the receiver STA
*
* @return MTRUE or MFALSE
*/
static int INLINE
wlan_is_11n_enabled(mlan_private * priv, t_u8 * ra)
{
int ret = MFALSE;
ENTER();
#ifdef UAP_SUPPORT
if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
if ((!(ra[0] & 0x01)) && (priv->is_11n_enabled))
ret = is_station_11n_enabled(priv, ra);
}
#endif /* UAP_SUPPORT */
LEAVE();
return ret;
}
#endif /* !_MLAN_11N_H_ */