Path: blob/master/ALFA-W1F1/RTL8814AU/core/rtw_xmit.c
1307 views
/******************************************************************************1*2* Copyright(c) 2007 - 2019 Realtek Corporation.3*4* This program is free software; you can redistribute it and/or modify it5* under the terms of version 2 of the GNU General Public License as6* published by the Free Software Foundation.7*8* This program is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for11* more details.12*13*****************************************************************************/14#define _RTW_XMIT_C_1516#include <drv_types.h>17#include <hal_data.h>1819static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };20static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };2122static void _init_txservq(struct tx_servq *ptxservq)23{24_rtw_init_listhead(&ptxservq->tx_pending);25_rtw_init_queue(&ptxservq->sta_pending);26ptxservq->qcnt = 0;27}282930void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)31{323334_rtw_memset((unsigned char *)psta_xmitpriv, 0, sizeof(struct sta_xmit_priv));3536_rtw_spinlock_init(&psta_xmitpriv->lock);3738/* for(i = 0 ; i < MAX_NUMBLKS; i++) */39/* _init_txservq(&(psta_xmitpriv->blk_q[i])); */4041_init_txservq(&psta_xmitpriv->be_q);42_init_txservq(&psta_xmitpriv->bk_q);43_init_txservq(&psta_xmitpriv->vi_q);44_init_txservq(&psta_xmitpriv->vo_q);45_rtw_init_listhead(&psta_xmitpriv->legacy_dz);46_rtw_init_listhead(&psta_xmitpriv->apsd);474849}5051void rtw_init_xmit_block(_adapter *padapter)52{53struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);5455_rtw_spinlock_init(&dvobj->xmit_block_lock);56dvobj->xmit_block = XMIT_BLOCK_NONE;5758}59void rtw_free_xmit_block(_adapter *padapter)60{61struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);6263_rtw_spinlock_free(&dvobj->xmit_block_lock);64}6566s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, _adapter *padapter)67{68int i;69struct xmit_buf *pxmitbuf;70struct xmit_frame *pxframe;71sint res = _SUCCESS;727374/* We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc(). */75/* _rtw_memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv)); */7677_rtw_spinlock_init(&pxmitpriv->lock);78_rtw_spinlock_init(&pxmitpriv->lock_sctx);79_rtw_init_sema(&pxmitpriv->xmit_sema, 0);8081/*82Please insert all the queue initializaiton using _rtw_init_queue below83*/8485pxmitpriv->adapter = padapter;8687/* for(i = 0 ; i < MAX_NUMBLKS; i++) */88/* _rtw_init_queue(&pxmitpriv->blk_strms[i]); */8990_rtw_init_queue(&pxmitpriv->be_pending);91_rtw_init_queue(&pxmitpriv->bk_pending);92_rtw_init_queue(&pxmitpriv->vi_pending);93_rtw_init_queue(&pxmitpriv->vo_pending);94_rtw_init_queue(&pxmitpriv->bm_pending);9596/* _rtw_init_queue(&pxmitpriv->legacy_dz_queue); */97/* _rtw_init_queue(&pxmitpriv->apsd_queue); */9899_rtw_init_queue(&pxmitpriv->free_xmit_queue);100101/*102Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME,103and initialize free_xmit_frame below.104Please also apply free_txobj to link_up all the xmit_frames...105*/106107pxmitpriv->pallocated_frame_buf = rtw_zvmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);108109if (pxmitpriv->pallocated_frame_buf == NULL) {110pxmitpriv->pxmit_frame_buf = NULL;111res = _FAIL;112goto exit;113}114pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_frame_buf), 4);115/* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */116/* ((SIZE_PTR) (pxmitpriv->pallocated_frame_buf) &3); */117118pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;119120for (i = 0; i < NR_XMITFRAME; i++) {121_rtw_init_listhead(&(pxframe->list));122123pxframe->padapter = padapter;124pxframe->frame_tag = NULL_FRAMETAG;125126pxframe->pkt = NULL;127128pxframe->buf_addr = NULL;129pxframe->pxmitbuf = NULL;130131rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));132133pxframe++;134}135136pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;137138pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;139140141/* init xmit_buf */142_rtw_init_queue(&pxmitpriv->free_xmitbuf_queue);143_rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue);144145pxmitpriv->pallocated_xmitbuf = rtw_zvmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);146147if (pxmitpriv->pallocated_xmitbuf == NULL) {148res = _FAIL;149goto exit;150}151152pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmitbuf), 4);153/* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */154/* ((SIZE_PTR) (pxmitpriv->pallocated_xmitbuf) &3); */155156pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;157158for (i = 0; i < NR_XMITBUFF; i++) {159_rtw_init_listhead(&pxmitbuf->list);160161pxmitbuf->priv_data = NULL;162pxmitbuf->padapter = padapter;163pxmitbuf->buf_tag = XMITBUF_DATA;164165/* Tx buf allocation may fail sometimes, so sleep and retry. */166res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);167if (res == _FAIL) {168rtw_msleep_os(10);169res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);170if (res == _FAIL)171goto exit;172}173174#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)175pxmitbuf->phead = pxmitbuf->pbuf;176pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMITBUF_SZ;177pxmitbuf->len = 0;178pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;179#endif180181pxmitbuf->flags = XMIT_VO_QUEUE;182183rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));184#ifdef DBG_XMIT_BUF185pxmitbuf->no = i;186#endif187188pxmitbuf++;189190}191192pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;193194/* init xframe_ext queue, the same count as extbuf */195_rtw_init_queue(&pxmitpriv->free_xframe_ext_queue);196197pxmitpriv->xframe_ext_alloc_addr = rtw_zvmalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);198199if (pxmitpriv->xframe_ext_alloc_addr == NULL) {200pxmitpriv->xframe_ext = NULL;201res = _FAIL;202goto exit;203}204pxmitpriv->xframe_ext = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->xframe_ext_alloc_addr), 4);205pxframe = (struct xmit_frame *)pxmitpriv->xframe_ext;206207for (i = 0; i < NR_XMIT_EXTBUFF; i++) {208_rtw_init_listhead(&(pxframe->list));209210pxframe->padapter = padapter;211pxframe->frame_tag = NULL_FRAMETAG;212213pxframe->pkt = NULL;214215pxframe->buf_addr = NULL;216pxframe->pxmitbuf = NULL;217218pxframe->ext_tag = 1;219220rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xframe_ext_queue.queue));221222pxframe++;223}224pxmitpriv->free_xframe_ext_cnt = NR_XMIT_EXTBUFF;225226/* Init xmit extension buff */227_rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);228229pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);230231if (pxmitpriv->pallocated_xmit_extbuf == NULL) {232res = _FAIL;233goto exit;234}235236pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmit_extbuf), 4);237238pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;239240for (i = 0; i < NR_XMIT_EXTBUFF; i++) {241_rtw_init_listhead(&pxmitbuf->list);242243pxmitbuf->priv_data = NULL;244pxmitbuf->padapter = padapter;245pxmitbuf->buf_tag = XMITBUF_MGNT;246247res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ, _TRUE);248if (res == _FAIL) {249res = _FAIL;250goto exit;251}252253#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)254pxmitbuf->phead = pxmitbuf->pbuf;255pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMIT_EXTBUF_SZ;256pxmitbuf->len = 0;257pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;258#endif259260rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));261#ifdef DBG_XMIT_BUF_EXT262pxmitbuf->no = i;263#endif264pxmitbuf++;265266}267268pxmitpriv->free_xmit_extbuf_cnt = NR_XMIT_EXTBUFF;269270for (i = 0; i < CMDBUF_MAX; i++) {271pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];272if (pxmitbuf) {273_rtw_init_listhead(&pxmitbuf->list);274275pxmitbuf->priv_data = NULL;276pxmitbuf->padapter = padapter;277pxmitbuf->buf_tag = XMITBUF_CMD;278279res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_CMDBUF_SZ + XMITBUF_ALIGN_SZ, _TRUE);280if (res == _FAIL) {281res = _FAIL;282goto exit;283}284285#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)286pxmitbuf->phead = pxmitbuf->pbuf;287pxmitbuf->pend = pxmitbuf->pbuf + MAX_CMDBUF_SZ;288pxmitbuf->len = 0;289pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;290#endif291pxmitbuf->alloc_sz = MAX_CMDBUF_SZ + XMITBUF_ALIGN_SZ;292}293}294295rtw_alloc_hwxmits(padapter);296rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);297298for (i = 0; i < 4; i++)299pxmitpriv->wmm_para_seq[i] = i;300301#ifdef CONFIG_USB_HCI302pxmitpriv->txirp_cnt = 1;303304_rtw_init_sema(&(pxmitpriv->tx_retevt), 0);305306/* per AC pending irp */307pxmitpriv->beq_cnt = 0;308pxmitpriv->bkq_cnt = 0;309pxmitpriv->viq_cnt = 0;310pxmitpriv->voq_cnt = 0;311#endif312313314#ifdef CONFIG_XMIT_ACK315pxmitpriv->ack_tx = _FALSE;316_rtw_mutex_init(&pxmitpriv->ack_tx_mutex);317rtw_sctx_init(&pxmitpriv->ack_tx_ops, 0);318#endif319320#ifdef CONFIG_TX_AMSDU321rtw_init_timer(&(pxmitpriv->amsdu_vo_timer), padapter,322rtw_amsdu_vo_timeout_handler, padapter);323pxmitpriv->amsdu_vo_timeout = RTW_AMSDU_TIMER_UNSET;324325rtw_init_timer(&(pxmitpriv->amsdu_vi_timer), padapter,326rtw_amsdu_vi_timeout_handler, padapter);327pxmitpriv->amsdu_vi_timeout = RTW_AMSDU_TIMER_UNSET;328329rtw_init_timer(&(pxmitpriv->amsdu_be_timer), padapter,330rtw_amsdu_be_timeout_handler, padapter);331pxmitpriv->amsdu_be_timeout = RTW_AMSDU_TIMER_UNSET;332333rtw_init_timer(&(pxmitpriv->amsdu_bk_timer), padapter,334rtw_amsdu_bk_timeout_handler, padapter);335pxmitpriv->amsdu_bk_timeout = RTW_AMSDU_TIMER_UNSET;336337pxmitpriv->amsdu_debug_set_timer = 0;338pxmitpriv->amsdu_debug_timeout = 0;339pxmitpriv->amsdu_debug_coalesce_one = 0;340pxmitpriv->amsdu_debug_coalesce_two = 0;341#endif342#ifdef DBG_TXBD_DESC_DUMP343pxmitpriv->dump_txbd_desc = 0;344#endif345rtw_init_xmit_block(padapter);346rtw_hal_init_xmit_priv(padapter);347348exit:349350351return res;352}353354void rtw_mfree_xmit_priv_lock(struct xmit_priv *pxmitpriv);355void rtw_mfree_xmit_priv_lock(struct xmit_priv *pxmitpriv)356{357_rtw_spinlock_free(&pxmitpriv->lock);358_rtw_free_sema(&pxmitpriv->xmit_sema);359360_rtw_spinlock_free(&pxmitpriv->be_pending.lock);361_rtw_spinlock_free(&pxmitpriv->bk_pending.lock);362_rtw_spinlock_free(&pxmitpriv->vi_pending.lock);363_rtw_spinlock_free(&pxmitpriv->vo_pending.lock);364_rtw_spinlock_free(&pxmitpriv->bm_pending.lock);365366/* _rtw_spinlock_free(&pxmitpriv->legacy_dz_queue.lock); */367/* _rtw_spinlock_free(&pxmitpriv->apsd_queue.lock); */368369_rtw_spinlock_free(&pxmitpriv->free_xmit_queue.lock);370_rtw_spinlock_free(&pxmitpriv->free_xmitbuf_queue.lock);371_rtw_spinlock_free(&pxmitpriv->pending_xmitbuf_queue.lock);372}373374375void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv)376{377int i;378_adapter *padapter = pxmitpriv->adapter;379struct xmit_frame *pxmitframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;380struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;381382383rtw_hal_free_xmit_priv(padapter);384385rtw_mfree_xmit_priv_lock(pxmitpriv);386387if (pxmitpriv->pxmit_frame_buf == NULL)388goto out;389390for (i = 0; i < NR_XMITFRAME; i++) {391rtw_os_xmit_complete(padapter, pxmitframe);392393pxmitframe++;394}395396for (i = 0; i < NR_XMITBUFF; i++) {397rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);398399pxmitbuf++;400}401402if (pxmitpriv->pallocated_frame_buf)403rtw_vmfree(pxmitpriv->pallocated_frame_buf, NR_XMITFRAME * sizeof(struct xmit_frame) + 4);404405406if (pxmitpriv->pallocated_xmitbuf)407rtw_vmfree(pxmitpriv->pallocated_xmitbuf, NR_XMITBUFF * sizeof(struct xmit_buf) + 4);408409/* free xframe_ext queue, the same count as extbuf */410if ((pxmitframe = (struct xmit_frame *)pxmitpriv->xframe_ext)) {411for (i = 0; i < NR_XMIT_EXTBUFF; i++) {412rtw_os_xmit_complete(padapter, pxmitframe);413pxmitframe++;414}415}416if (pxmitpriv->xframe_ext_alloc_addr)417rtw_vmfree(pxmitpriv->xframe_ext_alloc_addr, NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);418_rtw_spinlock_free(&pxmitpriv->free_xframe_ext_queue.lock);419420/* free xmit extension buff */421_rtw_spinlock_free(&pxmitpriv->free_xmit_extbuf_queue.lock);422423pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;424for (i = 0; i < NR_XMIT_EXTBUFF; i++) {425rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);426427pxmitbuf++;428}429430if (pxmitpriv->pallocated_xmit_extbuf)431rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);432433for (i = 0; i < CMDBUF_MAX; i++) {434pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];435if (pxmitbuf != NULL)436rtw_os_xmit_resource_free(padapter, pxmitbuf, MAX_CMDBUF_SZ + XMITBUF_ALIGN_SZ , _TRUE);437}438439rtw_free_hwxmits(padapter);440441#ifdef CONFIG_XMIT_ACK442_rtw_mutex_free(&pxmitpriv->ack_tx_mutex);443#endif444rtw_free_xmit_block(padapter);445out:446return;447}448449u8 rtw_get_tx_bw_mode(_adapter *adapter, struct sta_info *sta)450{451u8 bw;452453bw = sta->cmn.bw_mode;454if (MLME_STATE(adapter) & WIFI_ASOC_STATE) {455if (adapter->mlmeextpriv.cur_channel <= 14)456bw = rtw_min(bw, ADAPTER_TX_BW_2G(adapter));457else458bw = rtw_min(bw, ADAPTER_TX_BW_5G(adapter));459}460461return bw;462}463464void rtw_get_adapter_tx_rate_bmp_by_bw(_adapter *adapter, u8 bw, u16 *r_bmp_cck_ofdm, u32 *r_bmp_ht, u64 *r_bmp_vht)465{466struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);467struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);468u8 fix_bw = 0xFF;469u16 bmp_cck_ofdm = 0;470u32 bmp_ht = 0;471u64 bmp_vht = 0;472int i;473474if (adapter->fix_rate != 0xFF && adapter->fix_bw != 0xFF)475fix_bw = adapter->fix_bw;476477/* TODO: adapter->fix_rate */478479for (i = 0; i < macid_ctl->num; i++) {480if (!rtw_macid_is_used(macid_ctl, i))481continue;482if (!rtw_macid_is_iface_specific(macid_ctl, i, adapter))483continue;484485if (bw == CHANNEL_WIDTH_20) /* CCK, OFDM always 20MHz */486bmp_cck_ofdm |= macid_ctl->rate_bmp0[i] & 0x00000FFF;487488/* bypass mismatch bandwidth for HT, VHT */489if ((fix_bw != 0xFF && fix_bw != bw) || (fix_bw == 0xFF && macid_ctl->bw[i] != bw))490continue;491492if (macid_ctl->vht_en[i])493bmp_vht |= (macid_ctl->rate_bmp0[i] >> 12) | (macid_ctl->rate_bmp1[i] << 20);494else495bmp_ht |= (macid_ctl->rate_bmp0[i] >> 12) | (macid_ctl->rate_bmp1[i] << 20);496}497498/* TODO: mlmeext->tx_rate*/499500if (r_bmp_cck_ofdm)501*r_bmp_cck_ofdm = bmp_cck_ofdm;502if (r_bmp_ht)503*r_bmp_ht = bmp_ht;504if (r_bmp_vht)505*r_bmp_vht = bmp_vht;506}507508void rtw_get_shared_macid_tx_rate_bmp_by_bw(struct dvobj_priv *dvobj, u8 bw, u16 *r_bmp_cck_ofdm, u32 *r_bmp_ht, u64 *r_bmp_vht)509{510struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);511u16 bmp_cck_ofdm = 0;512u32 bmp_ht = 0;513u64 bmp_vht = 0;514int i;515516for (i = 0; i < macid_ctl->num; i++) {517if (!rtw_macid_is_used(macid_ctl, i))518continue;519if (!rtw_macid_is_iface_shared(macid_ctl, i))520continue;521522if (bw == CHANNEL_WIDTH_20) /* CCK, OFDM always 20MHz */523bmp_cck_ofdm |= macid_ctl->rate_bmp0[i] & 0x00000FFF;524525/* bypass mismatch bandwidth for HT, VHT */526if (macid_ctl->bw[i] != bw)527continue;528529if (macid_ctl->vht_en[i])530bmp_vht |= (macid_ctl->rate_bmp0[i] >> 12) | (macid_ctl->rate_bmp1[i] << 20);531else532bmp_ht |= (macid_ctl->rate_bmp0[i] >> 12) | (macid_ctl->rate_bmp1[i] << 20);533}534535if (r_bmp_cck_ofdm)536*r_bmp_cck_ofdm = bmp_cck_ofdm;537if (r_bmp_ht)538*r_bmp_ht = bmp_ht;539if (r_bmp_vht)540*r_bmp_vht = bmp_vht;541}542543void rtw_update_tx_rate_bmp(struct dvobj_priv *dvobj)544{545struct rf_ctl_t *rf_ctl = dvobj_to_rfctl(dvobj);546_adapter *adapter = dvobj_get_primary_adapter(dvobj);547HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);548u8 bw;549u16 bmp_cck_ofdm, tmp_cck_ofdm;550u32 bmp_ht, tmp_ht, ori_bmp_ht[2];551u64 bmp_vht, tmp_vht, ori_bmp_vht[4];552int i;553554for (bw = CHANNEL_WIDTH_20; bw <= CHANNEL_WIDTH_160; bw++) {555/* backup the original ht & vht bmp */556if (bw <= CHANNEL_WIDTH_40)557ori_bmp_ht[bw] = rf_ctl->rate_bmp_ht_by_bw[bw];558if (bw <= CHANNEL_WIDTH_160)559ori_bmp_vht[bw] = rf_ctl->rate_bmp_vht_by_bw[bw];560561bmp_cck_ofdm = bmp_ht = bmp_vht = 0;562if (hal_is_bw_support(dvobj_get_primary_adapter(dvobj), bw)) {563for (i = 0; i < dvobj->iface_nums; i++) {564if (!dvobj->padapters[i])565continue;566rtw_get_adapter_tx_rate_bmp_by_bw(dvobj->padapters[i], bw, &tmp_cck_ofdm, &tmp_ht, &tmp_vht);567bmp_cck_ofdm |= tmp_cck_ofdm;568bmp_ht |= tmp_ht;569bmp_vht |= tmp_vht;570}571rtw_get_shared_macid_tx_rate_bmp_by_bw(dvobj, bw, &tmp_cck_ofdm, &tmp_ht, &tmp_vht);572bmp_cck_ofdm |= tmp_cck_ofdm;573bmp_ht |= tmp_ht;574bmp_vht |= tmp_vht;575}576if (bw == CHANNEL_WIDTH_20)577rf_ctl->rate_bmp_cck_ofdm = bmp_cck_ofdm;578if (bw <= CHANNEL_WIDTH_40)579rf_ctl->rate_bmp_ht_by_bw[bw] = bmp_ht;580if (bw <= CHANNEL_WIDTH_160)581rf_ctl->rate_bmp_vht_by_bw[bw] = bmp_vht;582}583584#if CONFIG_TXPWR_LIMIT585#ifndef DBG_HIGHEST_RATE_BMP_BW_CHANGE586#define DBG_HIGHEST_RATE_BMP_BW_CHANGE 0587#endif588589if (hal_data->txpwr_limit_loaded) {590u8 ori_highest_ht_rate_bw_bmp;591u8 ori_highest_vht_rate_bw_bmp;592u8 highest_rate_bw;593u8 highest_rate_bw_bmp;594u8 update_ht_rs = _FALSE;595u8 update_vht_rs = _FALSE;596597/* backup the original ht & vht highest bw bmp */598ori_highest_ht_rate_bw_bmp = rf_ctl->highest_ht_rate_bw_bmp;599ori_highest_vht_rate_bw_bmp = rf_ctl->highest_vht_rate_bw_bmp;600601highest_rate_bw_bmp = BW_CAP_20M;602highest_rate_bw = CHANNEL_WIDTH_20;603for (bw = CHANNEL_WIDTH_20; bw <= CHANNEL_WIDTH_40; bw++) {604if (rf_ctl->rate_bmp_ht_by_bw[highest_rate_bw] < rf_ctl->rate_bmp_ht_by_bw[bw]) {605highest_rate_bw_bmp = ch_width_to_bw_cap(bw);606highest_rate_bw = bw;607} else if (rf_ctl->rate_bmp_ht_by_bw[highest_rate_bw] == rf_ctl->rate_bmp_ht_by_bw[bw])608highest_rate_bw_bmp |= ch_width_to_bw_cap(bw);609}610rf_ctl->highest_ht_rate_bw_bmp = highest_rate_bw_bmp;611612if (ori_highest_ht_rate_bw_bmp != rf_ctl->highest_ht_rate_bw_bmp613|| largest_bit(ori_bmp_ht[highest_rate_bw]) != largest_bit(rf_ctl->rate_bmp_ht_by_bw[highest_rate_bw])614) {615if (DBG_HIGHEST_RATE_BMP_BW_CHANGE) {616RTW_INFO("highest_ht_rate_bw_bmp:0x%02x=>0x%02x\n", ori_highest_ht_rate_bw_bmp, rf_ctl->highest_ht_rate_bw_bmp);617RTW_INFO("rate_bmp_ht_by_bw[%u]:0x%08x=>0x%08x\n", highest_rate_bw, ori_bmp_ht[highest_rate_bw], rf_ctl->rate_bmp_ht_by_bw[highest_rate_bw]);618}619if (rf_ctl->rate_bmp_ht_by_bw[highest_rate_bw])620update_ht_rs = _TRUE;621}622623highest_rate_bw_bmp = BW_CAP_20M;624highest_rate_bw = CHANNEL_WIDTH_20;625for (bw = CHANNEL_WIDTH_20; bw <= CHANNEL_WIDTH_160; bw++) {626if (rf_ctl->rate_bmp_vht_by_bw[highest_rate_bw] < rf_ctl->rate_bmp_vht_by_bw[bw]) {627highest_rate_bw_bmp = ch_width_to_bw_cap(bw);628highest_rate_bw = bw;629} else if (rf_ctl->rate_bmp_vht_by_bw[highest_rate_bw] == rf_ctl->rate_bmp_vht_by_bw[bw])630highest_rate_bw_bmp |= ch_width_to_bw_cap(bw);631}632rf_ctl->highest_vht_rate_bw_bmp = highest_rate_bw_bmp;633634if (ori_highest_vht_rate_bw_bmp != rf_ctl->highest_vht_rate_bw_bmp635|| largest_bit_64(ori_bmp_vht[highest_rate_bw]) != largest_bit_64(rf_ctl->rate_bmp_vht_by_bw[highest_rate_bw])636) {637if (DBG_HIGHEST_RATE_BMP_BW_CHANGE) {638RTW_INFO("highest_vht_rate_bw_bmp:0x%02x=>0x%02x\n", ori_highest_vht_rate_bw_bmp, rf_ctl->highest_vht_rate_bw_bmp);639RTW_INFO("rate_bmp_vht_by_bw[%u]:0x%016llx=>0x%016llx\n", highest_rate_bw, ori_bmp_vht[highest_rate_bw], rf_ctl->rate_bmp_vht_by_bw[highest_rate_bw]);640}641if (rf_ctl->rate_bmp_vht_by_bw[highest_rate_bw])642update_vht_rs = _TRUE;643}644645/* TODO: per rfpath and rate section handling? */646if (update_ht_rs == _TRUE || update_vht_rs == _TRUE)647rtw_hal_set_tx_power_level(dvobj_get_primary_adapter(dvobj), hal_data->current_channel);648}649#endif /* CONFIG_TXPWR_LIMIT */650}651652u8 rtw_get_tx_bw_bmp_of_ht_rate(struct dvobj_priv *dvobj, u8 rate, u8 max_bw)653{654struct rf_ctl_t *rf_ctl = dvobj_to_rfctl(dvobj);655u8 bw;656u8 bw_bmp = 0;657u32 rate_bmp;658659if (!IS_HT_RATE(rate)) {660rtw_warn_on(1);661goto exit;662}663664rate_bmp = 1 << (rate - MGN_MCS0);665666if (max_bw > CHANNEL_WIDTH_40)667max_bw = CHANNEL_WIDTH_40;668669for (bw = CHANNEL_WIDTH_20; bw <= max_bw; bw++) {670/* RA may use lower rate for retry */671if (rf_ctl->rate_bmp_ht_by_bw[bw] >= rate_bmp)672bw_bmp |= ch_width_to_bw_cap(bw);673}674675exit:676return bw_bmp;677}678679u8 rtw_get_tx_bw_bmp_of_vht_rate(struct dvobj_priv *dvobj, u8 rate, u8 max_bw)680{681struct rf_ctl_t *rf_ctl = dvobj_to_rfctl(dvobj);682u8 bw;683u8 bw_bmp = 0;684u64 rate_bmp;685686if (!IS_VHT_RATE(rate)) {687rtw_warn_on(1);688goto exit;689}690691rate_bmp = 1ULL << (rate - MGN_VHT1SS_MCS0);692693if (max_bw > CHANNEL_WIDTH_160)694max_bw = CHANNEL_WIDTH_160;695696for (bw = CHANNEL_WIDTH_20; bw <= max_bw; bw++) {697/* RA may use lower rate for retry */698if (rf_ctl->rate_bmp_vht_by_bw[bw] >= rate_bmp)699bw_bmp |= ch_width_to_bw_cap(bw);700}701702exit:703return bw_bmp;704}705706u8 query_ra_short_GI(struct sta_info *psta, u8 bw)707{708u8 sgi = _FALSE, sgi_20m = _FALSE, sgi_40m = _FALSE, sgi_80m = _FALSE;709710#ifdef CONFIG_80211N_HT711#ifdef CONFIG_80211AC_VHT712if (psta->vhtpriv.vht_option)713sgi_80m = psta->vhtpriv.sgi_80m;714#endif715sgi_20m = psta->htpriv.sgi_20m;716sgi_40m = psta->htpriv.sgi_40m;717#endif718719switch (bw) {720case CHANNEL_WIDTH_80:721sgi = sgi_80m;722break;723case CHANNEL_WIDTH_40:724sgi = sgi_40m;725break;726case CHANNEL_WIDTH_20:727default:728sgi = sgi_20m;729break;730}731732return sgi;733}734735static void update_attrib_vcs_info(_adapter *padapter, struct xmit_frame *pxmitframe)736{737u32 sz;738struct pkt_attrib *pattrib = &pxmitframe->attrib;739/* struct sta_info *psta = pattrib->psta; */740struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);741struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);742743/*744if(pattrib->psta)745{746psta = pattrib->psta;747}748else749{750RTW_INFO("%s, call rtw_get_stainfo()\n", __func__);751psta=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0] );752}753754if(psta==NULL)755{756RTW_INFO("%s, psta==NUL\n", __func__);757return;758}759760if(!(psta->state &_FW_LINKED))761{762RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);763return;764}765*/766767if (pattrib->nr_frags != 1)768sz = padapter->xmitpriv.frag_len;769else /* no frag */770sz = pattrib->last_txcmdsz;771772/* (1) RTS_Threshold is compared to the MPDU, not MSDU. */773/* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */774/* Other fragments are protected by previous fragment. */775/* So we only need to check the length of first fragment. */776if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {777if (sz > padapter->registrypriv.rts_thresh)778pattrib->vcs_mode = RTS_CTS;779else {780if (pattrib->rtsen)781pattrib->vcs_mode = RTS_CTS;782else if (pattrib->cts2self)783pattrib->vcs_mode = CTS_TO_SELF;784else785pattrib->vcs_mode = NONE_VCS;786}787} else {788while (_TRUE) {789#if 0 /* Todo */790/* check IOT action */791if (pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF) {792pattrib->vcs_mode = CTS_TO_SELF;793pattrib->rts_rate = MGN_24M;794break;795} else if (pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS | HT_IOT_ACT_PURE_N_MODE)) {796pattrib->vcs_mode = RTS_CTS;797pattrib->rts_rate = MGN_24M;798break;799}800#endif801802/* IOT action */803if ((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) && (pattrib->ampdu_en == _TRUE) &&804(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)) {805pattrib->vcs_mode = CTS_TO_SELF;806break;807}808809810/* check ERP protection */811if (pattrib->rtsen || pattrib->cts2self) {812if (pattrib->rtsen)813pattrib->vcs_mode = RTS_CTS;814else if (pattrib->cts2self)815pattrib->vcs_mode = CTS_TO_SELF;816817break;818}819820/* check HT op mode */821if (pattrib->ht_en) {822u8 HTOpMode = pmlmeinfo->HT_protection;823if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) ||824(!pmlmeext->cur_bwmode && HTOpMode == 3)) {825pattrib->vcs_mode = RTS_CTS;826break;827}828}829830/* check rts */831if (sz > padapter->registrypriv.rts_thresh) {832pattrib->vcs_mode = RTS_CTS;833break;834}835836/* to do list: check MIMO power save condition. */837838/* check AMPDU aggregation for TXOP */839if ((pattrib->ampdu_en == _TRUE) && (!IS_HARDWARE_TYPE_8812(padapter))) {840pattrib->vcs_mode = RTS_CTS;841break;842}843844pattrib->vcs_mode = NONE_VCS;845break;846}847}848849/* for debug : force driver control vrtl_carrier_sense. */850if (padapter->driver_vcs_en == 1) {851/* u8 driver_vcs_en; */ /* Enable=1, Disable=0 driver control vrtl_carrier_sense. */852/* u8 driver_vcs_type; */ /* force 0:disable VCS, 1:RTS-CTS, 2:CTS-to-self when vcs_en=1. */853pattrib->vcs_mode = padapter->driver_vcs_type;854}855856}857858#ifdef CONFIG_WMMPS_STA859/*860* update_attrib_trigger_frame_info861* For Station mode, if a specific TID of driver setting and an AP support uapsd function, the data862* frame with corresponding TID will be a trigger frame when driver is in wmm power saving mode.863*864* Arguments:865* @padapter: _adapter pointer.866* @pattrib: pkt_attrib pointer.867*868* Auther: Arvin Liu869* Date: 2017/06/05870*/871static void update_attrib_trigger_frame_info(_adapter *padapter, struct pkt_attrib *pattrib) {872struct mlme_priv *pmlmepriv = &padapter->mlmepriv;873struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);874struct qos_priv *pqospriv = &pmlmepriv->qospriv;875u8 trigger_frame_en = 0;876877if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE) {878if ((pwrpriv->pwr_mode == PS_MODE_MIN) || (pwrpriv->pwr_mode == PS_MODE_MAX)) {879if((pqospriv->uapsd_ap_supported) && ((pqospriv->uapsd_tid & BIT(pattrib->priority)) == _TRUE)) {880trigger_frame_en = 1;881RTW_INFO("[WMMPS]"FUNC_ADPT_FMT": This is a Trigger Frame\n", FUNC_ADPT_ARG(padapter));882}883}884}885886pattrib->trigger_frame = trigger_frame_en;887}888#endif /* CONFIG_WMMPS_STA */889890static void update_attrib_phy_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)891{892struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;893u8 bw;894895pattrib->rtsen = psta->rtsen;896pattrib->cts2self = psta->cts2self;897898pattrib->mdata = 0;899pattrib->eosp = 0;900pattrib->triggered = 0;901pattrib->ampdu_spacing = 0;902903/* ht_en, init rate, ,bw, ch_offset, sgi */904905pattrib->raid = psta->cmn.ra_info.rate_id;906907bw = rtw_get_tx_bw_mode(padapter, psta);908pattrib->bwmode = rtw_min(bw, mlmeext->cur_bwmode);909pattrib->sgi = query_ra_short_GI(psta, pattrib->bwmode);910911pattrib->ldpc = psta->cmn.ldpc_en;912pattrib->stbc = psta->cmn.stbc_en;913914#ifdef CONFIG_80211N_HT915if(padapter->registrypriv.ht_enable &&916is_supported_ht(padapter->registrypriv.wireless_mode)) {917pattrib->ht_en = psta->htpriv.ht_option;918pattrib->ch_offset = psta->htpriv.ch_offset;919pattrib->ampdu_en = _FALSE;920921if (padapter->driver_ampdu_spacing != 0xFF) /* driver control AMPDU Density for peer sta's rx */922pattrib->ampdu_spacing = padapter->driver_ampdu_spacing;923else924pattrib->ampdu_spacing = psta->htpriv.rx_ampdu_min_spacing;925926/* check if enable ampdu */927if (pattrib->ht_en && psta->htpriv.ampdu_enable) {928if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority)) {929pattrib->ampdu_en = _TRUE;930if (psta->htpriv.tx_amsdu_enable == _TRUE)931pattrib->amsdu_ampdu_en = _TRUE;932else933pattrib->amsdu_ampdu_en = _FALSE;934}935}936}937#endif /* CONFIG_80211N_HT */938/* if(pattrib->ht_en && psta->htpriv.ampdu_enable) */939/* { */940/* if(psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority)) */941/* pattrib->ampdu_en = _TRUE; */942/* } */943944#ifdef CONFIG_TDLS945if (pattrib->direct_link == _TRUE) {946psta = pattrib->ptdls_sta;947948pattrib->raid = psta->cmn.ra_info.rate_id;949#ifdef CONFIG_80211N_HT950if(padapter->registrypriv.ht_enable &&951is_supported_ht(padapter->registrypriv.wireless_mode)) {952pattrib->bwmode = rtw_get_tx_bw_mode(padapter, psta);953pattrib->ht_en = psta->htpriv.ht_option;954pattrib->ch_offset = psta->htpriv.ch_offset;955pattrib->sgi = query_ra_short_GI(psta, pattrib->bwmode);956}957#endif /* CONFIG_80211N_HT */958}959#endif /* CONFIG_TDLS */960961pattrib->retry_ctrl = _FALSE;962}963964static s32 update_attrib_sec_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)965{966sint res = _SUCCESS;967struct mlme_priv *pmlmepriv = &padapter->mlmepriv;968struct security_priv *psecuritypriv = &padapter->securitypriv;969sint bmcast = IS_MCAST(pattrib->ra);970971_rtw_memset(pattrib->dot118021x_UncstKey.skey, 0, 16);972_rtw_memset(pattrib->dot11tkiptxmickey.skey, 0, 16);973pattrib->mac_id = psta->cmn.mac_id;974975if (psta->ieee8021x_blocked == _TRUE) {976977pattrib->encrypt = 0;978979if ((pattrib->ether_type != 0x888e) && (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _FALSE)) {980#ifdef DBG_TX_DROP_FRAME981RTW_INFO("DBG_TX_DROP_FRAME %s psta->ieee8021x_blocked == _TRUE, pattrib->ether_type(%04x) != 0x888e\n", __FUNCTION__, pattrib->ether_type);982#endif983res = _FAIL;984goto exit;985}986} else {987GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);988989#ifdef CONFIG_WAPI_SUPPORT990if (pattrib->ether_type == 0x88B4)991pattrib->encrypt = _NO_PRIVACY_;992#endif993994switch (psecuritypriv->dot11AuthAlgrthm) {995case dot11AuthAlgrthm_Open:996case dot11AuthAlgrthm_Shared:997case dot11AuthAlgrthm_Auto:998pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;999break;1000case dot11AuthAlgrthm_8021X:1001if (bmcast)1002pattrib->key_idx = (u8)psecuritypriv->dot118021XGrpKeyid;1003else1004pattrib->key_idx = 0;1005break;1006default:1007pattrib->key_idx = 0;1008break;1009}10101011/* For WPS 1.0 WEP, driver should not encrypt EAPOL Packet for WPS handshake. */1012if (((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) && (pattrib->ether_type == 0x888e))1013pattrib->encrypt = _NO_PRIVACY_;10141015}10161017#ifdef CONFIG_TDLS1018if (pattrib->direct_link == _TRUE) {1019if (pattrib->encrypt > 0)1020pattrib->encrypt = _AES_;1021}1022#endif10231024switch (pattrib->encrypt) {1025case _WEP40_:1026case _WEP104_:1027pattrib->iv_len = 4;1028pattrib->icv_len = 4;1029WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);1030break;10311032case _TKIP_:1033pattrib->iv_len = 8;1034pattrib->icv_len = 4;10351036if (psecuritypriv->busetkipkey == _FAIL) {1037#ifdef DBG_TX_DROP_FRAME1038RTW_INFO("DBG_TX_DROP_FRAME %s psecuritypriv->busetkipkey(%d)==_FAIL drop packet\n", __FUNCTION__, psecuritypriv->busetkipkey);1039#endif1040res = _FAIL;1041goto exit;1042}10431044if (bmcast)1045TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);1046else1047TKIP_IV(pattrib->iv, psta->dot11txpn, 0);104810491050_rtw_memcpy(pattrib->dot11tkiptxmickey.skey, psta->dot11tkiptxmickey.skey, 16);10511052break;10531054case _AES_:10551056pattrib->iv_len = 8;1057pattrib->icv_len = 8;10581059if (bmcast)1060AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);1061else1062AES_IV(pattrib->iv, psta->dot11txpn, 0);10631064break;10651066#ifdef CONFIG_WAPI_SUPPORT1067case _SMS4_:1068pattrib->iv_len = 18;1069pattrib->icv_len = 16;1070rtw_wapi_get_iv(padapter, pattrib->ra, pattrib->iv);1071break;1072#endif1073default:1074pattrib->iv_len = 0;1075pattrib->icv_len = 0;1076break;1077}10781079if (pattrib->encrypt > 0)1080_rtw_memcpy(pattrib->dot118021x_UncstKey.skey, psta->dot118021x_UncstKey.skey, 16);108110821083if (pattrib->encrypt &&1084((padapter->securitypriv.sw_encrypt == _TRUE) || (psecuritypriv->hw_decrypted == _FALSE))) {1085pattrib->bswenc = _TRUE;1086} else {1087pattrib->bswenc = _FALSE;1088}10891090#if defined(CONFIG_CONCURRENT_MODE)1091pattrib->bmc_camid = padapter->securitypriv.dot118021x_bmc_cam_id;1092#endif10931094if (pattrib->encrypt && bmcast && _rtw_camctl_chk_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH))1095pattrib->bswenc = _TRUE;10961097#ifdef CONFIG_WAPI_SUPPORT1098if (pattrib->encrypt == _SMS4_)1099pattrib->bswenc = _FALSE;1100#endif11011102exit:11031104return res;11051106}11071108u8 qos_acm(u8 acm_mask, u8 priority)1109{1110u8 change_priority = priority;11111112switch (priority) {1113case 0:1114case 3:1115if (acm_mask & BIT(1))1116change_priority = 1;1117break;1118case 1:1119case 2:1120break;1121case 4:1122case 5:1123if (acm_mask & BIT(2))1124change_priority = 0;1125break;1126case 6:1127case 7:1128if (acm_mask & BIT(3))1129change_priority = 5;1130break;1131default:1132RTW_INFO("qos_acm(): invalid pattrib->priority: %d!!!\n", priority);1133break;1134}11351136return change_priority;1137}11381139/* refer to IEEE802.11-2016 Table R-3; Comply with IETF RFC4594 */1140static u8 tos_to_up(u8 tos)1141{1142u8 up = 0;1143u8 dscp;1144u8 mode = CONFIG_RTW_UP_MAPPING_RULE;114511461147/* tos precedence mapping */1148if (mode == 0) {1149up = tos >> 5;1150return up;1151}11521153/* refer to IEEE802.11-2016 Table R-3;1154* DCSP 32(CS4) comply with IETF RFC45941155*/1156dscp = (tos >> 2);11571158if ( dscp == 0 )1159up = 0;1160else if ( dscp >= 1 && dscp <= 9)1161up = 1;1162else if ( dscp >= 10 && dscp <= 16)1163up = 2;1164else if ( dscp >= 17 && dscp <= 23)1165up = 3;1166else if ( dscp >= 24 && dscp <= 31)1167up = 4;1168else if ( dscp >= 33 && dscp <= 40)1169up = 5;1170else if ((dscp >= 41 && dscp <= 47) || (dscp == 32))1171up = 6;1172else if ( dscp >= 48 && dscp <= 63)1173up = 7;11741175return up;1176}11771178static void set_qos(_pkt *pkt, struct pkt_attrib *pattrib)1179{1180s32 UserPriority = 0;11811182if (!pkt)1183goto null_pkt;11841185/* get UserPriority from IP hdr */1186if (pattrib->ether_type == 0x0800) {1187struct pkt_file ppktfile;1188struct ethhdr etherhdr;1189struct iphdr ip_hdr;11901191_rtw_open_pktfile(pkt, &ppktfile);1192_rtw_pktfile_read(&ppktfile, (unsigned char *)ðerhdr, ETH_HLEN);1193_rtw_pktfile_read(&ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr));1194/* UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3; */1195UserPriority = tos_to_up(ip_hdr.tos);1196}1197/*1198else if (pattrib->ether_type == 0x888e) {119912001201UserPriority = 7;1202}1203*/12041205#ifdef CONFIG_ICMP_VOQ1206if(pattrib->icmp_pkt==1)/*use VO queue to send icmp packet*/1207UserPriority = 7;1208#endif1209#ifdef CONFIG_IP_R_MONITOR1210if (pattrib->ether_type == ETH_P_ARP)1211UserPriority = 7;1212#endif/*CONFIG_IP_R_MONITOR*/12131214null_pkt:1215pattrib->priority = UserPriority;1216pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;1217pattrib->subtype = WIFI_QOS_DATA_TYPE;1218}12191220#ifdef CONFIG_TDLS1221u8 rtw_check_tdls_established(_adapter *padapter, struct pkt_attrib *pattrib)1222{1223pattrib->ptdls_sta = NULL;12241225pattrib->direct_link = _FALSE;1226if (padapter->tdlsinfo.link_established == _TRUE) {1227pattrib->ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);1228#if 11229if ((pattrib->ptdls_sta != NULL) &&1230(pattrib->ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) &&1231(pattrib->ether_type != 0x0806)) {1232pattrib->direct_link = _TRUE;1233/* RTW_INFO("send ptk to "MAC_FMT" using direct link\n", MAC_ARG(pattrib->dst)); */1234}1235#else1236if (pattrib->ptdls_sta != NULL &&1237pattrib->ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {1238pattrib->direct_link = _TRUE;1239#if 01240RTW_INFO("send ptk to "MAC_FMT" using direct link\n", MAC_ARG(pattrib->dst));1241#endif1242}12431244/* ARP frame may be helped by AP*/1245if (pattrib->ether_type != 0x0806)1246pattrib->direct_link = _FALSE;1247#endif1248}12491250return pattrib->direct_link;1251}12521253s32 update_tdls_attrib(_adapter *padapter, struct pkt_attrib *pattrib)1254{12551256struct sta_info *psta = NULL;1257struct sta_priv *pstapriv = &padapter->stapriv;1258struct security_priv *psecuritypriv = &padapter->securitypriv;1259struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1260struct qos_priv *pqospriv = &pmlmepriv->qospriv;12611262s32 res = _SUCCESS;12631264psta = rtw_get_stainfo(pstapriv, pattrib->ra);1265if (psta == NULL) {1266res = _FAIL;1267goto exit;1268}12691270pattrib->mac_id = psta->cmn.mac_id;1271pattrib->psta = psta;1272pattrib->ack_policy = 0;1273/* get ether_hdr_len */1274pattrib->pkt_hdrlen = ETH_HLEN;12751276pattrib->qos_en = psta->qos_option;12771278/* [TDLS] TODO: setup req/rsp should be AC_BK */1279if (pqospriv->qos_option && psta->qos_option) {1280pattrib->priority = 4; /* tdls management frame should be AC_VI */1281pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;1282pattrib->subtype = WIFI_QOS_DATA_TYPE;1283} else {1284pattrib->priority = 0;1285pattrib->hdrlen = WLAN_HDR_A3_LEN;1286pattrib->subtype = WIFI_DATA_TYPE;1287}12881289/* TODO:_lock */1290if (update_attrib_sec_info(padapter, pattrib, psta) == _FAIL) {1291res = _FAIL;1292goto exit;1293}12941295update_attrib_phy_info(padapter, pattrib, psta);129612971298exit:12991300return res;1301}13021303#endif /* CONFIG_TDLS */13041305/*get non-qos hw_ssn control register,mapping to REG_HW_SEQ 0,1,2,3*/1306inline u8 rtw_get_hwseq_no(_adapter *padapter)1307{1308u8 hwseq_num = 0;13091310#ifdef CONFIG_CONCURRENT_MODE1311#if defined(CONFIG_RTL8822B) || defined(CONFIG_RTL8821C) || defined(CONFIG_RTL8822C) || defined(CONFIG_RTL8814B)1312hwseq_num = padapter->iface_id;1313if (hwseq_num > 3)1314hwseq_num = 3;1315#else1316if (!is_primary_adapter(padapter))1317hwseq_num = 1;1318#endif1319#endif /* CONFIG_CONCURRENT_MODE */1320return hwseq_num;1321}1322#ifdef CONFIG_LPS1323#define LPS_PT_NORMAL 01324#define LPS_PT_SP 1/* only DHCP packets is as SPECIAL_PACKET*/1325#define LPS_PT_ICMP 213261327/*If EAPOL , ARP , OR DHCP packet, driver must be in active mode.*/1328static u8 _rtw_lps_chk_packet_type(struct pkt_attrib *pattrib)1329{1330u8 pkt_type = LPS_PT_NORMAL; /*normal data frame*/13311332#ifdef CONFIG_WAPI_SUPPORT1333if ((pattrib->ether_type == 0x88B4) || (pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1))1334pkt_type = LPS_PT_SP;1335#else /* !CONFIG_WAPI_SUPPORT */13361337#ifndef CONFIG_LPS_NOT_LEAVE_FOR_ICMP1338if (pattrib->icmp_pkt == 1)1339pkt_type = LPS_PT_ICMP;1340else1341#endif1342if (pattrib->dhcp_pkt == 1)1343pkt_type = LPS_PT_SP;1344#endif1345return pkt_type;1346}1347#endif1348static s32 update_attrib(_adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib)1349{1350uint i;1351struct pkt_file pktfile;1352struct sta_info *psta = NULL;1353struct ethhdr etherhdr;13541355sint bmcast;1356struct sta_priv *pstapriv = &padapter->stapriv;1357struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1358struct qos_priv *pqospriv = &pmlmepriv->qospriv;1359struct xmit_priv *pxmitpriv = &padapter->xmitpriv;1360sint res = _SUCCESS;1361#ifdef CONFIG_LPS1362u8 pkt_type = 0;1363#endif13641365DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib);13661367_rtw_open_pktfile(pkt, &pktfile);1368i = _rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN);13691370pattrib->ether_type = ntohs(etherhdr.h_proto);13711372if (MLME_IS_MESH(padapter)) /* address resolve is done for mesh */1373goto get_sta_info;13741375_rtw_memcpy(pattrib->dst, ðerhdr.h_dest, ETH_ALEN);1376_rtw_memcpy(pattrib->src, ðerhdr.h_source, ETH_ALEN);13771378if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ||1379(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {1380_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);1381_rtw_memcpy(pattrib->ta, adapter_mac_addr(padapter), ETH_ALEN);1382DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_adhoc);1383} else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {1384#ifdef CONFIG_TDLS1385if (rtw_check_tdls_established(padapter, pattrib) == _TRUE)1386_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN); /* For TDLS direct link Tx, set ra to be same to dst */1387else1388#endif1389_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);1390_rtw_memcpy(pattrib->ta, adapter_mac_addr(padapter), ETH_ALEN);1391DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_sta);1392} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {1393_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);1394_rtw_memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);1395DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_ap);1396} else1397DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_unknown);13981399get_sta_info:1400bmcast = IS_MCAST(pattrib->ra);1401if (bmcast) {1402psta = rtw_get_bcmc_stainfo(padapter);1403if (psta == NULL) { /* if we cannot get psta => drop the pkt */1404DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sta);1405#ifdef DBG_TX_DROP_FRAME1406RTW_INFO("DBG_TX_DROP_FRAME %s get sta_info fail, ra:" MAC_FMT"\n", __func__, MAC_ARG(pattrib->ra));1407#endif1408res = _FAIL;1409goto exit;1410}1411} else {1412psta = rtw_get_stainfo(pstapriv, pattrib->ra);1413if (psta == NULL) { /* if we cannot get psta => drop the pkt */1414DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_sta);1415#ifdef DBG_TX_DROP_FRAME1416RTW_INFO("DBG_TX_DROP_FRAME %s get sta_info fail, ra:" MAC_FMT"\n", __func__, MAC_ARG(pattrib->ra));1417#endif1418res = _FAIL;1419goto exit;1420} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE && !(psta->state & _FW_LINKED)) {1421DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_ap_link);1422res = _FAIL;1423goto exit;1424}1425}14261427if (!(psta->state & _FW_LINKED)) {1428DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_link);1429RTW_INFO("%s-"ADPT_FMT" psta("MAC_FMT")->state(0x%x) != _FW_LINKED\n",1430__func__, ADPT_ARG(padapter), MAC_ARG(psta->cmn.mac_addr), psta->state);1431res = _FAIL;1432goto exit;1433}14341435pattrib->pktlen = pktfile.pkt_len;14361437/* TODO: 802.1Q VLAN header */1438/* TODO: IPV6 */14391440if (ETH_P_IP == pattrib->ether_type) {1441u8 ip[20];14421443_rtw_pktfile_read(&pktfile, ip, 20);14441445if (GET_IPV4_IHL(ip) * 4 > 20)1446_rtw_pktfile_read(&pktfile, NULL, GET_IPV4_IHL(ip) - 20);14471448pattrib->icmp_pkt = 0;1449pattrib->dhcp_pkt = 0;1450pattrib->hipriority_pkt = 0;14511452if (GET_IPV4_PROTOCOL(ip) == 0x01) { /* ICMP */1453pattrib->icmp_pkt = 1;1454DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_icmp);14551456} else if (GET_IPV4_PROTOCOL(ip) == 0x11) { /* UDP */1457u8 udp[24];14581459_rtw_pktfile_read(&pktfile, udp, 24);14601461if ((GET_UDP_SRC(udp) == 68 && GET_UDP_DST(udp) == 67)1462|| (GET_UDP_SRC(udp) == 67 && GET_UDP_DST(udp) == 68)1463) {1464/* 67 : UDP BOOTP server, 68 : UDP BOOTP client */1465if (pattrib->pktlen > 282) { /* MINIMUM_DHCP_PACKET_SIZE */1466pattrib->dhcp_pkt = 1;1467DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_dhcp);1468if (0)1469RTW_INFO("send DHCP packet\n");1470}1471}14721473/* WaveAgent packet, increase priority so that the system can read data in time */1474if (((GET_UDP_SIG1(udp) == 0xcc) || (GET_UDP_SIG1(udp) == 0xdd)) &&1475(GET_UDP_SIG2(udp) == 0xe2)) {1476pattrib->hipriority_pkt = 1;1477}14781479} else if (GET_IPV4_PROTOCOL(ip) == 0x06 /* TCP */1480&& rtw_st_ctl_chk_reg_s_proto(&psta->st_ctl, 0x06) == _TRUE1481) {1482u8 tcp[20];14831484_rtw_pktfile_read(&pktfile, tcp, 20);14851486if (rtw_st_ctl_chk_reg_rule(&psta->st_ctl, padapter, IPV4_SRC(ip), TCP_SRC(tcp), IPV4_DST(ip), TCP_DST(tcp)) == _TRUE) {1487if (GET_TCP_SYN(tcp) && GET_TCP_ACK(tcp)) {1488session_tracker_add_cmd(padapter, psta1489, IPV4_SRC(ip), TCP_SRC(tcp)1490, IPV4_SRC(ip), TCP_DST(tcp));1491if (DBG_SESSION_TRACKER)1492RTW_INFO(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" SYN-ACK\n"1493, FUNC_ADPT_ARG(padapter)1494, IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp))1495, IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)));1496}1497if (GET_TCP_FIN(tcp)) {1498session_tracker_del_cmd(padapter, psta1499, IPV4_SRC(ip), TCP_SRC(tcp)1500, IPV4_SRC(ip), TCP_DST(tcp));1501if (DBG_SESSION_TRACKER)1502RTW_INFO(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" FIN\n"1503, FUNC_ADPT_ARG(padapter)1504, IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp))1505, IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)));1506}1507}1508}15091510} else if (0x888e == pattrib->ether_type)1511parsing_eapol_packet(padapter, pktfile.cur_addr, psta, 1);1512#if defined (DBG_ARP_DUMP) || defined (DBG_IP_R_MONITOR)1513else if (pattrib->ether_type == ETH_P_ARP) {1514u8 arp[28] = {0};15151516_rtw_pktfile_read(&pktfile, arp, 28);1517dump_arp_pkt(RTW_DBGDUMP, etherhdr.h_dest, etherhdr.h_source, arp, 1);1518}1519#endif15201521if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1))1522rtw_mi_set_scan_deny(padapter, 3000);15231524if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&1525pattrib->ether_type == ETH_P_ARP &&1526!IS_MCAST(pattrib->dst)) {1527rtw_mi_set_scan_deny(padapter, 1000);1528rtw_mi_scan_abort(padapter, _FALSE); /*rtw_scan_abort_no_wait*/1529}15301531#ifdef CONFIG_LPS1532pkt_type = _rtw_lps_chk_packet_type(pattrib);15331534if (pkt_type == LPS_PT_SP) {/*packet is as SPECIAL_PACKET*/1535DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_active);1536rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 0);1537} else if (pkt_type == LPS_PT_ICMP)1538rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 0);1539#endif /* CONFIG_LPS */15401541#ifdef CONFIG_BEAMFORMING1542update_attrib_txbf_info(padapter, pattrib, psta);1543#endif15441545/* TODO:_lock */1546if (update_attrib_sec_info(padapter, pattrib, psta) == _FAIL) {1547DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sec);1548res = _FAIL;1549goto exit;1550}15511552/* get ether_hdr_len */1553pattrib->pkt_hdrlen = ETH_HLEN;/* (pattrib->ether_type == 0x8100) ? (14 + 4 ): 14; */ /* vlan tag */15541555pattrib->hdrlen = WLAN_HDR_A3_LEN;1556pattrib->subtype = WIFI_DATA_TYPE;1557pattrib->qos_en = psta->qos_option;1558pattrib->priority = 0;15591560if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_MESH_STATE1561| WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)1562) {1563if (pattrib->qos_en) {1564set_qos(pkt, pattrib);1565#ifdef CONFIG_RTW_MESH1566if (MLME_IS_MESH(padapter))1567rtw_mesh_tx_set_whdr_mctrl_len(pattrib->mesh_frame_mode, pattrib);1568#endif1569}1570} else {1571#ifdef CONFIG_TDLS1572if (pattrib->direct_link == _TRUE) {1573if (pattrib->qos_en)1574set_qos(pkt, pattrib);1575} else1576#endif1577{1578if (pqospriv->qos_option) {1579set_qos(pkt, pattrib);15801581if (pmlmepriv->acm_mask != 0)1582pattrib->priority = qos_acm(pmlmepriv->acm_mask, pattrib->priority);1583}1584}1585}15861587update_attrib_phy_info(padapter, pattrib, psta);15881589/* RTW_INFO("%s ==> mac_id(%d)\n",__FUNCTION__,pattrib->mac_id ); */15901591pattrib->psta = psta;1592/* TODO:_unlock */15931594#ifdef CONFIG_AUTO_AP_MODE1595if (psta->isrc && psta->pid > 0)1596pattrib->pctrl = _TRUE;1597else1598#endif1599pattrib->pctrl = 0;16001601pattrib->ack_policy = 0;16021603if (bmcast)1604pattrib->rate = psta->init_rate;160516061607#ifdef CONFIG_WMMPS_STA1608update_attrib_trigger_frame_info(padapter, pattrib);1609#endif /* CONFIG_WMMPS_STA */16101611/* pattrib->priority = 5; */ /* force to used VI queue, for testing */1612pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;1613rtw_set_tx_chksum_offload(pkt, pattrib);16141615exit:161616171618return res;1619}16201621static s32 xmitframe_addmic(_adapter *padapter, struct xmit_frame *pxmitframe)1622{1623sint curfragnum, length;1624u8 *pframe, *payload, mic[8];1625struct mic_data micdata;1626/* struct sta_info *stainfo; */1627struct pkt_attrib *pattrib = &pxmitframe->attrib;1628struct security_priv *psecuritypriv = &padapter->securitypriv;1629struct xmit_priv *pxmitpriv = &padapter->xmitpriv;1630u8 priority[4] = {0x0, 0x0, 0x0, 0x0};1631u8 hw_hdr_offset = 0;1632sint bmcst = IS_MCAST(pattrib->ra);16331634/*1635if(pattrib->psta)1636{1637stainfo = pattrib->psta;1638}1639else1640{1641RTW_INFO("%s, call rtw_get_stainfo()\n", __func__);1642stainfo=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);1643}16441645if(stainfo==NULL)1646{1647RTW_INFO("%s, psta==NUL\n", __func__);1648return _FAIL;1649}16501651if(!(stainfo->state &_FW_LINKED))1652{1653RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);1654return _FAIL;1655}1656*/165716581659#ifdef CONFIG_USB_TX_AGGREGATION1660hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);;1661#else1662#ifdef CONFIG_TX_EARLY_MODE1663hw_hdr_offset = TXDESC_OFFSET + EARLY_MODE_INFO_SIZE;1664#else1665hw_hdr_offset = TXDESC_OFFSET;1666#endif1667#endif16681669if (pattrib->encrypt == _TKIP_) { /* if(psecuritypriv->dot11PrivacyAlgrthm==_TKIP_PRIVACY_) */1670/* encode mic code */1671/* if(stainfo!= NULL) */1672{1673u8 null_key[16] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};16741675pframe = pxmitframe->buf_addr + hw_hdr_offset;16761677if (bmcst) {1678if (_rtw_memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16) == _TRUE) {1679/* DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey==0\n"); */1680/* rtw_msleep_os(10); */1681return _FAIL;1682}1683/* start to calculate the mic code */1684rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);1685} else {1686if (_rtw_memcmp(&pattrib->dot11tkiptxmickey.skey[0], null_key, 16) == _TRUE) {1687/* DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey==0\n"); */1688/* rtw_msleep_os(10); */1689return _FAIL;1690}1691/* start to calculate the mic code */1692rtw_secmicsetkey(&micdata, &pattrib->dot11tkiptxmickey.skey[0]);1693}16941695if (pframe[1] & 1) { /* ToDS==1 */1696rtw_secmicappend(&micdata, &pframe[16], 6); /* DA */1697if (pframe[1] & 2) /* From Ds==1 */1698rtw_secmicappend(&micdata, &pframe[24], 6);1699else1700rtw_secmicappend(&micdata, &pframe[10], 6);1701} else { /* ToDS==0 */1702rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */1703if (pframe[1] & 2) /* From Ds==1 */1704rtw_secmicappend(&micdata, &pframe[16], 6);1705else1706rtw_secmicappend(&micdata, &pframe[10], 6);17071708}17091710if (pattrib->qos_en)1711priority[0] = (u8)pxmitframe->attrib.priority;171217131714rtw_secmicappend(&micdata, &priority[0], 4);17151716payload = pframe;17171718for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) {1719payload = (u8 *)RND4((SIZE_PTR)(payload));17201721payload = payload + pattrib->hdrlen + pattrib->iv_len;1722if ((curfragnum + 1) == pattrib->nr_frags) {1723length = pattrib->last_txcmdsz - pattrib->hdrlen - pattrib->iv_len - ((pattrib->bswenc) ? pattrib->icv_len : 0);1724rtw_secmicappend(&micdata, payload, length);1725payload = payload + length;1726} else {1727length = pxmitpriv->frag_len - pattrib->hdrlen - pattrib->iv_len - ((pattrib->bswenc) ? pattrib->icv_len : 0);1728rtw_secmicappend(&micdata, payload, length);1729payload = payload + length + pattrib->icv_len;1730}1731}1732rtw_secgetmic(&micdata, &(mic[0]));1733/* add mic code and add the mic code length in last_txcmdsz */17341735_rtw_memcpy(payload, &(mic[0]), 8);1736pattrib->last_txcmdsz += 8;17371738payload = payload - pattrib->last_txcmdsz + 8;1739}1740}174117421743return _SUCCESS;1744}17451746/*#define DBG_TX_SW_ENCRYPTOR*/17471748static s32 xmitframe_swencrypt(_adapter *padapter, struct xmit_frame *pxmitframe)1749{17501751struct pkt_attrib *pattrib = &pxmitframe->attrib;1752/* struct security_priv *psecuritypriv=&padapter->securitypriv; */175317541755/* if((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */1756if (pattrib->bswenc) {1757#ifdef DBG_TX_SW_ENCRYPTOR1758RTW_INFO(ADPT_FMT" - sec_type:%s DO SW encryption\n",1759ADPT_ARG(padapter), security_type_str(pattrib->encrypt));1760#endif17611762switch (pattrib->encrypt) {1763case _WEP40_:1764case _WEP104_:1765rtw_wep_encrypt(padapter, (u8 *)pxmitframe);1766break;1767case _TKIP_:1768rtw_tkip_encrypt(padapter, (u8 *)pxmitframe);1769break;1770case _AES_:1771rtw_aes_encrypt(padapter, (u8 *)pxmitframe);1772break;1773#ifdef CONFIG_WAPI_SUPPORT1774case _SMS4_:1775rtw_sms4_encrypt(padapter, (u8 *)pxmitframe);1776#endif1777default:1778break;1779}17801781}178217831784return _SUCCESS;1785}17861787s32 rtw_make_wlanhdr(_adapter *padapter , u8 *hdr, struct pkt_attrib *pattrib)1788{1789u16 *qc;17901791struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr;1792struct mlme_priv *pmlmepriv = &padapter->mlmepriv;1793struct qos_priv *pqospriv = &pmlmepriv->qospriv;1794u8 qos_option = _FALSE;1795sint res = _SUCCESS;1796u16 *fctrl = &pwlanhdr->frame_ctl;17971798/* struct sta_info *psta; */17991800/* sint bmcst = IS_MCAST(pattrib->ra); */180118021803/*1804psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);1805if(pattrib->psta != psta)1806{1807RTW_INFO("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);1808return;1809}18101811if(psta==NULL)1812{1813RTW_INFO("%s, psta==NUL\n", __func__);1814return _FAIL;1815}18161817if(!(psta->state &_FW_LINKED))1818{1819RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);1820return _FAIL;1821}1822*/18231824_rtw_memset(hdr, 0, WLANHDR_OFFSET);18251826set_frame_sub_type(fctrl, pattrib->subtype);18271828if (pattrib->subtype & WIFI_DATA_TYPE) {1829if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)) {1830#ifdef CONFIG_TDLS1831if (pattrib->direct_link == _TRUE) {1832/* TDLS data transfer, ToDS=0, FrDs=0 */1833_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);1834_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);1835_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);18361837if (pattrib->qos_en)1838qos_option = _TRUE;1839} else1840#endif /* CONFIG_TDLS */1841{1842/* to_ds = 1, fr_ds = 0; */1843/* 1.Data transfer to AP */1844/* 2.Arp pkt will relayed by AP */1845SetToDs(fctrl);1846_rtw_memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);1847_rtw_memcpy(pwlanhdr->addr2, pattrib->ta, ETH_ALEN);1848_rtw_memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);18491850if (pqospriv->qos_option)1851qos_option = _TRUE;1852}1853} else if ((check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)) {1854/* to_ds = 0, fr_ds = 1; */1855SetFrDs(fctrl);1856_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);1857_rtw_memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);1858_rtw_memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);18591860if (pattrib->qos_en)1861qos_option = _TRUE;1862} else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ||1863(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {1864_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);1865_rtw_memcpy(pwlanhdr->addr2, pattrib->ta, ETH_ALEN);1866_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);18671868if (pattrib->qos_en)1869qos_option = _TRUE;1870#ifdef CONFIG_RTW_MESH1871} else if (check_fwstate(pmlmepriv, WIFI_MESH_STATE) == _TRUE) {1872rtw_mesh_tx_build_whdr(padapter, pattrib, fctrl, pwlanhdr);1873if (pattrib->qos_en)1874qos_option = _TRUE;1875else {1876RTW_WARN("[%s] !qos_en in Mesh\n", __FUNCTION__);1877res = _FAIL;1878goto exit;1879}1880#endif1881} else {1882res = _FAIL;1883goto exit;1884}18851886if (pattrib->mdata)1887SetMData(fctrl);18881889if (pattrib->encrypt)1890SetPrivacy(fctrl);18911892if (qos_option) {1893qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);18941895if (pattrib->priority)1896SetPriority(qc, pattrib->priority);18971898SetEOSP(qc, pattrib->eosp);18991900SetAckpolicy(qc, pattrib->ack_policy);19011902if(pattrib->amsdu)1903SetAMsdu(qc, pattrib->amsdu);1904#ifdef CONFIG_RTW_MESH1905if (MLME_IS_MESH(padapter)) {1906/* active: don't care, light sleep: 0, deep sleep: 1*/1907set_mps_lv(qc, 0); //TBD19081909/* TBD: temporary set (rspi, eosp) = (0, 1) which means End MPSP */1910set_rspi(qc, 0);1911SetEOSP(qc, 1);19121913set_mctrl_present(qc, 1);1914}1915#endif1916}19171918/* TODO: fill HT Control Field */19191920/* Update Seq Num will be handled by f/w */1921{1922struct sta_info *psta;1923psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);1924if (pattrib->psta != psta) {1925RTW_INFO("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);1926return _FAIL;1927}19281929if (psta == NULL) {1930RTW_INFO("%s, psta==NUL\n", __func__);1931return _FAIL;1932}19331934if (!(psta->state & _FW_LINKED)) {1935RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);1936return _FAIL;1937}193819391940if (psta) {1941psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;1942psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;1943pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];19441945SetSeqNum(hdr, pattrib->seqnum);19461947#ifdef CONFIG_80211N_HT1948#if 0 /* move into update_attrib_phy_info(). */1949/* check if enable ampdu */1950if (pattrib->ht_en && psta->htpriv.ampdu_enable) {1951if (psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))1952pattrib->ampdu_en = _TRUE;1953}1954#endif1955/* re-check if enable ampdu by BA_starting_seqctrl */1956if (pattrib->ampdu_en == _TRUE) {1957u16 tx_seq;19581959tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];19601961/* check BA_starting_seqctrl */1962if (SN_LESS(pattrib->seqnum, tx_seq)) {1963/* RTW_INFO("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */1964pattrib->ampdu_en = _FALSE;/* AGG BK */1965} else if (SN_EQUAL(pattrib->seqnum, tx_seq)) {1966psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq + 1) & 0xfff;19671968pattrib->ampdu_en = _TRUE;/* AGG EN */1969} else {1970/* RTW_INFO("tx ampdu over run\n"); */1971psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum + 1) & 0xfff;1972pattrib->ampdu_en = _TRUE;/* AGG EN */1973}19741975}1976#endif /* CONFIG_80211N_HT */1977}1978}19791980} else {19811982}19831984exit:198519861987return res;1988}19891990s32 rtw_txframes_pending(_adapter *padapter)1991{1992struct xmit_priv *pxmitpriv = &padapter->xmitpriv;19931994return ((_rtw_queue_empty(&pxmitpriv->be_pending) == _FALSE) ||1995(_rtw_queue_empty(&pxmitpriv->bk_pending) == _FALSE) ||1996(_rtw_queue_empty(&pxmitpriv->vi_pending) == _FALSE) ||1997(_rtw_queue_empty(&pxmitpriv->vo_pending) == _FALSE));1998}19992000s32 rtw_txframes_sta_ac_pending(_adapter *padapter, struct pkt_attrib *pattrib)2001{2002struct sta_info *psta;2003struct tx_servq *ptxservq;2004int priority = pattrib->priority;2005/*2006if(pattrib->psta)2007{2008psta = pattrib->psta;2009}2010else2011{2012RTW_INFO("%s, call rtw_get_stainfo()\n", __func__);2013psta=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);2014}2015*/2016psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);2017if (pattrib->psta != psta) {2018RTW_INFO("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);2019return 0;2020}20212022if (psta == NULL) {2023RTW_INFO("%s, psta==NUL\n", __func__);2024return 0;2025}20262027if (!(psta->state & _FW_LINKED)) {2028RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);2029return 0;2030}20312032switch (priority) {2033case 1:2034case 2:2035ptxservq = &(psta->sta_xmitpriv.bk_q);2036break;2037case 4:2038case 5:2039ptxservq = &(psta->sta_xmitpriv.vi_q);2040break;2041case 6:2042case 7:2043ptxservq = &(psta->sta_xmitpriv.vo_q);2044break;2045case 0:2046case 3:2047default:2048ptxservq = &(psta->sta_xmitpriv.be_q);2049break;20502051}20522053return ptxservq->qcnt;2054}20552056#ifdef CONFIG_TDLS20572058int rtw_build_tdls_ies(_adapter *padapter, struct xmit_frame *pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)2059{2060struct pkt_attrib *pattrib = &pxmitframe->attrib;2061struct sta_info *ptdls_sta = NULL;2062int res = _SUCCESS;20632064ptdls_sta = rtw_get_stainfo((&padapter->stapriv), pattrib->dst);2065if (ptdls_sta == NULL) {2066switch (ptxmgmt->action_code) {2067case TDLS_DISCOVERY_REQUEST:2068case TUNNELED_PROBE_REQ:2069case TUNNELED_PROBE_RSP:2070break;2071default:2072RTW_INFO("[TDLS] %s - Direct Link Peer = "MAC_FMT" not found for action = %d\n", __func__, MAC_ARG(pattrib->dst), ptxmgmt->action_code);2073res = _FAIL;2074goto exit;2075}2076}20772078switch (ptxmgmt->action_code) {2079case TDLS_SETUP_REQUEST:2080rtw_build_tdls_setup_req_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2081break;2082case TDLS_SETUP_RESPONSE:2083rtw_build_tdls_setup_rsp_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2084break;2085case TDLS_SETUP_CONFIRM:2086rtw_build_tdls_setup_cfm_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2087break;2088case TDLS_TEARDOWN:2089rtw_build_tdls_teardown_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2090break;2091case TDLS_DISCOVERY_REQUEST:2092rtw_build_tdls_dis_req_ies(padapter, pxmitframe, pframe, ptxmgmt);2093break;2094case TDLS_PEER_TRAFFIC_INDICATION:2095rtw_build_tdls_peer_traffic_indication_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2096break;2097#ifdef CONFIG_TDLS_CH_SW2098case TDLS_CHANNEL_SWITCH_REQUEST:2099rtw_build_tdls_ch_switch_req_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2100break;2101case TDLS_CHANNEL_SWITCH_RESPONSE:2102rtw_build_tdls_ch_switch_rsp_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2103break;2104#endif2105case TDLS_PEER_TRAFFIC_RESPONSE:2106rtw_build_tdls_peer_traffic_rsp_ies(padapter, pxmitframe, pframe, ptxmgmt, ptdls_sta);2107break;2108#ifdef CONFIG_WFD2109case TUNNELED_PROBE_REQ:2110rtw_build_tunneled_probe_req_ies(padapter, pxmitframe, pframe);2111break;2112case TUNNELED_PROBE_RSP:2113rtw_build_tunneled_probe_rsp_ies(padapter, pxmitframe, pframe);2114break;2115#endif /* CONFIG_WFD */2116default:2117res = _FAIL;2118break;2119}21202121exit:2122return res;2123}21242125s32 rtw_make_tdls_wlanhdr(_adapter *padapter , u8 *hdr, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)2126{2127u16 *qc;2128struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr;2129struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2130struct qos_priv *pqospriv = &pmlmepriv->qospriv;2131struct sta_priv *pstapriv = &padapter->stapriv;2132struct sta_info *psta = NULL, *ptdls_sta = NULL;2133u8 tdls_seq = 0, baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };21342135sint res = _SUCCESS;2136u16 *fctrl = &pwlanhdr->frame_ctl;213721382139_rtw_memset(hdr, 0, WLANHDR_OFFSET);21402141set_frame_sub_type(fctrl, pattrib->subtype);21422143switch (ptxmgmt->action_code) {2144case TDLS_SETUP_REQUEST:2145case TDLS_SETUP_RESPONSE:2146case TDLS_SETUP_CONFIRM:2147case TDLS_PEER_TRAFFIC_INDICATION:2148case TDLS_PEER_PSM_REQUEST:2149case TUNNELED_PROBE_REQ:2150case TUNNELED_PROBE_RSP:2151case TDLS_DISCOVERY_REQUEST:2152SetToDs(fctrl);2153_rtw_memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);2154_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);2155_rtw_memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);2156break;2157case TDLS_CHANNEL_SWITCH_REQUEST:2158case TDLS_CHANNEL_SWITCH_RESPONSE:2159case TDLS_PEER_PSM_RESPONSE:2160case TDLS_PEER_TRAFFIC_RESPONSE:2161_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);2162_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);2163_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);2164tdls_seq = 1;2165break;2166case TDLS_TEARDOWN:2167if (ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_) {2168_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);2169_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);2170_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);2171tdls_seq = 1;2172} else {2173SetToDs(fctrl);2174_rtw_memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);2175_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);2176_rtw_memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);2177}2178break;2179}21802181if (pattrib->encrypt)2182SetPrivacy(fctrl);21832184if (ptxmgmt->action_code == TDLS_PEER_TRAFFIC_RESPONSE)2185SetPwrMgt(fctrl);21862187if (pqospriv->qos_option) {2188qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);2189if (pattrib->priority)2190SetPriority(qc, pattrib->priority);2191SetAckpolicy(qc, pattrib->ack_policy);2192}21932194psta = pattrib->psta;21952196/* 1. update seq_num per link by sta_info */2197/* 2. rewrite encrypt to _AES_, also rewrite iv_len, icv_len */2198if (tdls_seq == 1) {2199ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);2200if (ptdls_sta) {2201ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority]++;2202ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;2203pattrib->seqnum = ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority];2204SetSeqNum(hdr, pattrib->seqnum);22052206if (pattrib->encrypt) {2207pattrib->encrypt = _AES_;2208pattrib->iv_len = 8;2209pattrib->icv_len = 8;2210pattrib->bswenc = _FALSE;2211}2212pattrib->mac_id = ptdls_sta->cmn.mac_id;2213} else {2214res = _FAIL;2215goto exit;2216}2217} else if (psta) {2218psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;2219psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;2220pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];2221SetSeqNum(hdr, pattrib->seqnum);2222}222322242225exit:222622272228return res;2229}22302231s32 rtw_xmit_tdls_coalesce(_adapter *padapter, struct xmit_frame *pxmitframe, struct tdls_txmgmt *ptxmgmt)2232{2233s32 llc_sz;22342235u8 *pframe, *mem_start;22362237struct sta_info *psta;2238struct sta_priv *pstapriv = &padapter->stapriv;2239struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2240struct pkt_attrib *pattrib = &pxmitframe->attrib;2241u8 *pbuf_start;2242s32 bmcst = IS_MCAST(pattrib->ra);2243s32 res = _SUCCESS;224422452246if (pattrib->psta)2247psta = pattrib->psta;2248else {2249if (bmcst)2250psta = rtw_get_bcmc_stainfo(padapter);2251else2252psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);2253}22542255if (psta == NULL) {2256res = _FAIL;2257goto exit;2258}22592260if (pxmitframe->buf_addr == NULL) {2261res = _FAIL;2262goto exit;2263}22642265pbuf_start = pxmitframe->buf_addr;2266mem_start = pbuf_start + TXDESC_OFFSET;22672268if (rtw_make_tdls_wlanhdr(padapter, mem_start, pattrib, ptxmgmt) == _FAIL) {2269res = _FAIL;2270goto exit;2271}22722273pframe = mem_start;2274pframe += pattrib->hdrlen;22752276/* adding icv, if necessary... */2277if (pattrib->iv_len) {2278if (psta != NULL) {2279switch (pattrib->encrypt) {2280case _WEP40_:2281case _WEP104_:2282WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);2283break;2284case _TKIP_:2285if (bmcst)2286TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);2287else2288TKIP_IV(pattrib->iv, psta->dot11txpn, 0);2289break;2290case _AES_:2291if (bmcst)2292AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);2293else2294AES_IV(pattrib->iv, psta->dot11txpn, 0);2295break;2296}2297}22982299_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len);2300pframe += pattrib->iv_len;23012302}23032304llc_sz = rtw_put_snap(pframe, pattrib->ether_type);2305pframe += llc_sz;23062307/* pattrib->pktlen will be counted in rtw_build_tdls_ies */2308pattrib->pktlen = 0;23092310rtw_build_tdls_ies(padapter, pxmitframe, pframe, ptxmgmt);23112312if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {2313pframe += pattrib->pktlen;2314_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len);2315pframe += pattrib->icv_len;2316}23172318pattrib->nr_frags = 1;2319pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + llc_sz +2320((pattrib->bswenc) ? pattrib->icv_len : 0) + pattrib->pktlen;23212322if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {2323res = _FAIL;2324goto exit;2325}23262327xmitframe_swencrypt(padapter, pxmitframe);23282329update_attrib_vcs_info(padapter, pxmitframe);23302331exit:233223332334return res;2335}2336#endif /* CONFIG_TDLS */23372338/*2339* Calculate wlan 802.11 packet MAX size from pkt_attrib2340* This function doesn't consider fragment case2341*/2342u32 rtw_calculate_wlan_pkt_size_by_attribue(struct pkt_attrib *pattrib)2343{2344u32 len = 0;23452346len = pattrib->hdrlen /* WLAN Header */2347+ pattrib->iv_len /* IV */2348+ XATTRIB_GET_MCTRL_LEN(pattrib)2349+ SNAP_SIZE + sizeof(u16) /* LLC */2350+ pattrib->pktlen2351+ (pattrib->encrypt == _TKIP_ ? 8 : 0) /* MIC */2352+ (pattrib->bswenc ? pattrib->icv_len : 0) /* ICV */2353;23542355return len;2356}23572358#ifdef CONFIG_TX_AMSDU2359s32 check_amsdu(struct xmit_frame *pxmitframe)2360{2361struct pkt_attrib *pattrib;2362s32 ret = _TRUE;23632364if (!pxmitframe)2365ret = _FALSE;23662367pattrib = &pxmitframe->attrib;23682369if (IS_MCAST(pattrib->ra))2370ret = _FALSE;23712372if ((pattrib->ether_type == 0x888e) ||2373(pattrib->ether_type == 0x0806) ||2374(pattrib->ether_type == 0x88b4) ||2375(pattrib->dhcp_pkt == 1))2376ret = _FALSE;23772378if ((pattrib->encrypt == _WEP40_) ||2379(pattrib->encrypt == _WEP104_) ||2380(pattrib->encrypt == _TKIP_))2381ret = _FALSE;23822383if (!pattrib->qos_en)2384ret = _FALSE;23852386if (IS_AMSDU_AMPDU_NOT_VALID(pattrib))2387ret = _FALSE;23882389return ret;2390}23912392s32 check_amsdu_tx_support(_adapter *padapter)2393{2394struct dvobj_priv *pdvobjpriv;2395int tx_amsdu;2396int tx_amsdu_rate;2397int current_tx_rate;2398s32 ret = _FALSE;23992400pdvobjpriv = adapter_to_dvobj(padapter);2401tx_amsdu = padapter->tx_amsdu;2402tx_amsdu_rate = padapter->tx_amsdu_rate;2403current_tx_rate = pdvobjpriv->traffic_stat.cur_tx_tp;24042405if (tx_amsdu == 1)2406ret = _TRUE;2407else if (tx_amsdu == 2 && (tx_amsdu_rate == 0 || current_tx_rate > tx_amsdu_rate))2408ret = _TRUE;2409else2410ret = _FALSE;24112412return ret;2413}24142415s32 rtw_xmitframe_coalesce_amsdu(_adapter *padapter, struct xmit_frame *pxmitframe, struct xmit_frame *pxmitframe_queue)2416{24172418struct pkt_file pktfile;2419struct pkt_attrib *pattrib;2420_pkt *pkt;24212422struct pkt_file pktfile_queue;2423struct pkt_attrib *pattrib_queue;2424_pkt *pkt_queue;24252426s32 llc_sz, mem_sz;24272428s32 padding = 0;24292430u8 *pframe, *mem_start;2431u8 hw_hdr_offset;24322433u16* len;2434u8 *pbuf_start;2435s32 res = _SUCCESS;24362437if (pxmitframe->buf_addr == NULL) {2438RTW_INFO("==> %s buf_addr==NULL\n", __FUNCTION__);2439return _FAIL;2440}244124422443pbuf_start = pxmitframe->buf_addr;24442445#ifdef CONFIG_USB_TX_AGGREGATION2446hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);2447#else2448#ifdef CONFIG_TX_EARLY_MODE /* for SDIO && Tx Agg */2449hw_hdr_offset = TXDESC_OFFSET + EARLY_MODE_INFO_SIZE;2450#else2451hw_hdr_offset = TXDESC_OFFSET;2452#endif2453#endif24542455mem_start = pbuf_start + hw_hdr_offset; //for DMA24562457pattrib = &pxmitframe->attrib;24582459pattrib->amsdu = 1;24602461if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {2462RTW_INFO("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n");2463res = _FAIL;2464goto exit;2465}24662467llc_sz = 0;24682469pframe = mem_start;24702471//SetMFrag(mem_start);2472ClearMFrag(mem_start);24732474pframe += pattrib->hdrlen;24752476/* adding icv, if necessary... */2477if (pattrib->iv_len) {2478_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len); // queue or new?24792480RTW_DBG("rtw_xmitframe_coalesce: keyid=%d pattrib->iv[3]=%.2x pframe=%.2x %.2x %.2x %.2x\n",2481padapter->securitypriv.dot11PrivacyKeyIndex, pattrib->iv[3], *pframe, *(pframe + 1), *(pframe + 2), *(pframe + 3));24822483pframe += pattrib->iv_len;2484}24852486pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len;24872488if(pxmitframe_queue)2489{2490pattrib_queue = &pxmitframe_queue->attrib;2491pkt_queue = pxmitframe_queue->pkt;24922493_rtw_open_pktfile(pkt_queue, &pktfile_queue);2494_rtw_pktfile_read(&pktfile_queue, NULL, pattrib_queue->pkt_hdrlen);24952496#ifdef CONFIG_RTW_MESH2497if (MLME_IS_MESH(padapter)) {2498/* mDA(6), mSA(6), len(2), mctrl */2499_rtw_memcpy(pframe, pattrib_queue->mda, ETH_ALEN);2500pframe += ETH_ALEN;2501_rtw_memcpy(pframe, pattrib_queue->msa, ETH_ALEN);2502pframe += ETH_ALEN;2503len = (u16*)pframe;2504pframe += 2;2505rtw_mesh_tx_build_mctrl(padapter, pattrib_queue, pframe);2506pframe += XATTRIB_GET_MCTRL_LEN(pattrib_queue);2507} else2508#endif2509{2510/* 802.3 MAC Header DA(6) SA(6) Len(2)*/2511_rtw_memcpy(pframe, pattrib_queue->dst, ETH_ALEN);2512pframe += ETH_ALEN;2513_rtw_memcpy(pframe, pattrib_queue->src, ETH_ALEN);2514pframe += ETH_ALEN;2515len = (u16*)pframe;2516pframe += 2;2517}25182519llc_sz = rtw_put_snap(pframe, pattrib_queue->ether_type);2520pframe += llc_sz;25212522mem_sz = _rtw_pktfile_read(&pktfile_queue, pframe, pattrib_queue->pktlen);2523pframe += mem_sz;25242525*len = htons(XATTRIB_GET_MCTRL_LEN(pattrib_queue) + llc_sz + mem_sz);25262527//calc padding2528padding = 4 - ((ETH_HLEN + XATTRIB_GET_MCTRL_LEN(pattrib_queue) + llc_sz + mem_sz) & (4-1));2529if(padding == 4)2530padding = 0;25312532//_rtw_memset(pframe,0xaa, padding);2533pframe += padding;25342535pattrib->last_txcmdsz += ETH_HLEN + XATTRIB_GET_MCTRL_LEN(pattrib_queue) + llc_sz + mem_sz + padding ;2536}25372538//2nd mpdu25392540pkt = pxmitframe->pkt;2541_rtw_open_pktfile(pkt, &pktfile);2542_rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen);25432544#ifdef CONFIG_RTW_MESH2545if (MLME_IS_MESH(padapter)) {2546/* mDA(6), mSA(6), len(2), mctrl */2547_rtw_memcpy(pframe, pattrib->mda, ETH_ALEN);2548pframe += ETH_ALEN;2549_rtw_memcpy(pframe, pattrib->msa, ETH_ALEN);2550pframe += ETH_ALEN;2551len = (u16*)pframe;2552pframe += 2;2553rtw_mesh_tx_build_mctrl(padapter, pattrib, pframe);2554pframe += XATTRIB_GET_MCTRL_LEN(pattrib);2555} else2556#endif2557{2558/* 802.3 MAC Header DA(6) SA(6) Len(2) */2559_rtw_memcpy(pframe, pattrib->dst, ETH_ALEN);2560pframe += ETH_ALEN;2561_rtw_memcpy(pframe, pattrib->src, ETH_ALEN);2562pframe += ETH_ALEN;2563len = (u16*)pframe;2564pframe += 2;2565}25662567llc_sz = rtw_put_snap(pframe, pattrib->ether_type);2568pframe += llc_sz;25692570mem_sz = _rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen);25712572pframe += mem_sz;25732574*len = htons(XATTRIB_GET_MCTRL_LEN(pattrib) + llc_sz + mem_sz);25752576//the last ampdu has no padding2577padding = 0;25782579pattrib->nr_frags = 1;25802581pattrib->last_txcmdsz += ETH_HLEN + XATTRIB_GET_MCTRL_LEN(pattrib) + llc_sz + mem_sz + padding +2582((pattrib->bswenc) ? pattrib->icv_len : 0) ;25832584if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {2585_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len);2586pframe += pattrib->icv_len;2587}25882589if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {2590RTW_INFO("xmitframe_addmic(padapter, pxmitframe)==_FAIL\n");2591res = _FAIL;2592goto exit;2593}25942595xmitframe_swencrypt(padapter, pxmitframe);25962597update_attrib_vcs_info(padapter, pxmitframe);25982599exit:2600return res;2601}2602#endif /* CONFIG_TX_AMSDU */26032604/*26052606This sub-routine will perform all the following:260726081. remove 802.3 header.26092. create wlan_header, based on the info in pxmitframe26103. append sta's iv/ext-iv26114. append LLC26125. move frag chunk from pframe to pxmitframe->mem26136. apply sw-encrypt, if necessary.26142615*/2616s32 rtw_xmitframe_coalesce(_adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)2617{2618struct pkt_file pktfile;26192620s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;26212622SIZE_PTR addr;26232624u8 *pframe, *mem_start;2625u8 hw_hdr_offset;26262627/* struct sta_info *psta; */2628/* struct sta_priv *pstapriv = &padapter->stapriv; */2629/* struct mlme_priv *pmlmepriv = &padapter->mlmepriv; */2630struct xmit_priv *pxmitpriv = &padapter->xmitpriv;26312632struct pkt_attrib *pattrib = &pxmitframe->attrib;26332634u8 *pbuf_start;26352636s32 bmcst = IS_MCAST(pattrib->ra);2637s32 res = _SUCCESS;263826392640/*2641if (pattrib->psta)2642{2643psta = pattrib->psta;2644} else2645{2646RTW_INFO("%s, call rtw_get_stainfo()\n", __func__);2647psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);2648}26492650if(psta==NULL)2651{26522653RTW_INFO("%s, psta==NUL\n", __func__);2654return _FAIL;2655}265626572658if(!(psta->state &_FW_LINKED))2659{2660RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);2661return _FAIL;2662}2663*/2664if (pxmitframe->buf_addr == NULL) {2665RTW_INFO("==> %s buf_addr==NULL\n", __FUNCTION__);2666return _FAIL;2667}26682669pbuf_start = pxmitframe->buf_addr;26702671#ifdef CONFIG_USB_TX_AGGREGATION2672hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);2673#else2674#ifdef CONFIG_TX_EARLY_MODE /* for SDIO && Tx Agg */2675hw_hdr_offset = TXDESC_OFFSET + EARLY_MODE_INFO_SIZE;2676#else2677hw_hdr_offset = TXDESC_OFFSET;2678#endif2679#endif26802681mem_start = pbuf_start + hw_hdr_offset;26822683if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {2684RTW_INFO("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n");2685res = _FAIL;2686goto exit;2687}26882689_rtw_open_pktfile(pkt, &pktfile);2690_rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen);26912692frg_inx = 0;2693frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */26942695while (1) {2696llc_sz = 0;26972698mpdu_len = frg_len;26992700pframe = mem_start;27012702SetMFrag(mem_start);27032704pframe += pattrib->hdrlen;2705mpdu_len -= pattrib->hdrlen;27062707/* adding icv, if necessary... */2708if (pattrib->iv_len) {2709#if 02710/* if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) */2711/* psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv)); */2712/* else */2713/* psta = rtw_get_stainfo(pstapriv, pattrib->ra); */27142715if (psta != NULL) {2716switch (pattrib->encrypt) {2717case _WEP40_:2718case _WEP104_:2719WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);2720break;2721case _TKIP_:2722if (bmcst)2723TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);2724else2725TKIP_IV(pattrib->iv, psta->dot11txpn, 0);2726break;2727case _AES_:2728if (bmcst)2729AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);2730else2731AES_IV(pattrib->iv, psta->dot11txpn, 0);2732break;2733#ifdef CONFIG_WAPI_SUPPORT2734case _SMS4_:2735rtw_wapi_get_iv(padapter, pattrib->ra, pattrib->iv);2736break;2737#endif2738}2739}2740#endif2741_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len);274227432744pframe += pattrib->iv_len;27452746mpdu_len -= pattrib->iv_len;2747}27482749if (frg_inx == 0) {2750#ifdef CONFIG_RTW_MESH2751if (MLME_IS_MESH(padapter)) {2752rtw_mesh_tx_build_mctrl(padapter, pattrib, pframe);2753pframe += XATTRIB_GET_MCTRL_LEN(pattrib);2754mpdu_len -= XATTRIB_GET_MCTRL_LEN(pattrib);2755}2756#endif27572758llc_sz = rtw_put_snap(pframe, pattrib->ether_type);2759pframe += llc_sz;2760mpdu_len -= llc_sz;2761}27622763if ((pattrib->icv_len > 0) && (pattrib->bswenc))2764mpdu_len -= pattrib->icv_len;276527662767if (bmcst) {2768/* don't do fragment to broadcat/multicast packets */2769mem_sz = _rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen);2770} else2771mem_sz = _rtw_pktfile_read(&pktfile, pframe, mpdu_len);27722773pframe += mem_sz;27742775if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {2776_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len);2777pframe += pattrib->icv_len;2778}27792780frg_inx++;27812782if (bmcst || (rtw_endofpktfile(&pktfile) == _TRUE)) {2783pattrib->nr_frags = frg_inx;27842785pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len +2786((pattrib->nr_frags == 1) ? (XATTRIB_GET_MCTRL_LEN(pattrib) + llc_sz) : 0) +2787((pattrib->bswenc) ? pattrib->icv_len : 0) + mem_sz;27882789ClearMFrag(mem_start);27902791break;2792}27932794addr = (SIZE_PTR)(pframe);27952796mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset;2797_rtw_memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);27982799}28002801if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {2802RTW_INFO("xmitframe_addmic(padapter, pxmitframe)==_FAIL\n");2803res = _FAIL;2804goto exit;2805}28062807xmitframe_swencrypt(padapter, pxmitframe);28082809if (bmcst == _FALSE)2810update_attrib_vcs_info(padapter, pxmitframe);2811else2812pattrib->vcs_mode = NONE_VCS;28132814exit:281528162817return res;2818}28192820#if defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH)2821/*2822* CCMP encryption for unicast robust mgmt frame and broadcast group privicy action2823* BIP for broadcast robust mgmt frame2824*/2825s32 rtw_mgmt_xmitframe_coalesce(_adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)2826{2827#define DBG_MGMT_XMIT_COALESEC_DUMP 02828#define DBG_MGMT_XMIT_BIP_DUMP 02829#define DBG_MGMT_XMIT_ENC_DUMP 028302831struct pkt_file pktfile;2832s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;2833SIZE_PTR addr;2834u8 *pframe, *mem_start = NULL, *tmp_buf = NULL;2835u8 hw_hdr_offset, subtype ;2836u8 category = 0xFF;2837struct sta_info *psta = NULL;2838struct xmit_priv *pxmitpriv = &padapter->xmitpriv;2839struct pkt_attrib *pattrib = &pxmitframe->attrib;2840u8 *pbuf_start;2841s32 bmcst = IS_MCAST(pattrib->ra);2842s32 res = _FAIL;2843u8 *BIP_AAD = NULL;2844u8 *MGMT_body = NULL;28452846struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;2847struct mlme_priv *pmlmepriv = &padapter->mlmepriv;2848struct rtw_ieee80211_hdr *pwlanhdr;2849u8 MME[_MME_IE_LENGTH_];28502851_irqL irqL;2852u32 ori_len;2853union pn48 *pn = NULL;2854u8 kid;28552856if (pxmitframe->buf_addr == NULL) {2857RTW_WARN(FUNC_ADPT_FMT" pxmitframe->buf_addr\n"2858, FUNC_ADPT_ARG(padapter));2859return _FAIL;2860}28612862mem_start = pframe = (u8 *)(pxmitframe->buf_addr) + TXDESC_OFFSET;2863pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;2864subtype = get_frame_sub_type(pframe); /* bit(7)~bit(2) */28652866/* check if robust mgmt frame */2867if (subtype != WIFI_DEAUTH && subtype != WIFI_DISASSOC && subtype != WIFI_ACTION)2868return _SUCCESS;2869if (subtype == WIFI_ACTION) {2870category = *(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));2871if (CATEGORY_IS_NON_ROBUST(category))2872return _SUCCESS;2873}2874if (!bmcst) {2875if (pattrib->psta)2876psta = pattrib->psta;2877else2878pattrib->psta = psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);2879if (psta == NULL) {2880RTW_INFO(FUNC_ADPT_FMT" unicast sta == NULL\n", FUNC_ADPT_ARG(padapter));2881return _FAIL;2882}2883if (!(psta->flags & WLAN_STA_MFP)) {2884/* peer is not MFP capable, no need to encrypt */2885return _SUCCESS;2886}2887if (psta->bpairwise_key_installed != _TRUE) {2888RTW_INFO(FUNC_ADPT_FMT" PTK is not installed\n"2889, FUNC_ADPT_ARG(padapter));2890return _FAIL;2891}2892}28932894ori_len = BIP_AAD_SIZE + pattrib->pktlen;2895tmp_buf = BIP_AAD = rtw_zmalloc(ori_len);2896if (BIP_AAD == NULL)2897return _FAIL;28982899_enter_critical_bh(&padapter->security_key_mutex, &irqL);29002901if (bmcst) {2902if (subtype == WIFI_ACTION && CATEGORY_IS_GROUP_PRIVACY(category)) {2903/* broadcast group privacy action frame */2904#if DBG_MGMT_XMIT_COALESEC_DUMP2905RTW_INFO(FUNC_ADPT_FMT" broadcast gp action(%u)\n"2906, FUNC_ADPT_ARG(padapter), category);2907#endif29082909if (pattrib->psta)2910psta = pattrib->psta;2911else2912pattrib->psta = psta = rtw_get_bcmc_stainfo(padapter);2913if (psta == NULL) {2914RTW_INFO(FUNC_ADPT_FMT" broadcast sta == NULL\n"2915, FUNC_ADPT_ARG(padapter));2916goto xmitframe_coalesce_fail;2917}2918if (padapter->securitypriv.binstallGrpkey != _TRUE) {2919RTW_INFO(FUNC_ADPT_FMT" GTK is not installed\n"2920, FUNC_ADPT_ARG(padapter));2921goto xmitframe_coalesce_fail;2922}29232924pn = &psta->dot11txpn;2925kid = padapter->securitypriv.dot118021XGrpKeyid;2926} else {2927#ifdef CONFIG_IEEE80211W2928/* broadcast robust mgmt frame, using BIP */2929int frame_body_len;2930u8 mic[16];29312932/* IGTK key is not install ex: mesh MFP without IGTK */2933if (SEC_IS_BIP_KEY_INSTALLED(&padapter->securitypriv) != _TRUE)2934goto xmitframe_coalesce_success;29352936#if DBG_MGMT_XMIT_COALESEC_DUMP2937if (subtype == WIFI_DEAUTH)2938RTW_INFO(FUNC_ADPT_FMT" braodcast deauth\n", FUNC_ADPT_ARG(padapter));2939else if (subtype == WIFI_DISASSOC)2940RTW_INFO(FUNC_ADPT_FMT" braodcast disassoc\n", FUNC_ADPT_ARG(padapter));2941else if (subtype == WIFI_ACTION) {2942RTW_INFO(FUNC_ADPT_FMT" braodcast action(%u)\n"2943, FUNC_ADPT_ARG(padapter), category);2944}2945#endif29462947_rtw_memset(MME, 0, _MME_IE_LENGTH_);29482949MGMT_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);2950pframe += pattrib->pktlen;29512952/* octent 0 and 1 is key index ,BIP keyid is 4 or 5, LSB only need octent 0 */2953MME[0] = padapter->securitypriv.dot11wBIPKeyid;2954/* increase PN and apply to packet */2955padapter->securitypriv.dot11wBIPtxpn.val++;2956RTW_PUT_LE64(&MME[2], padapter->securitypriv.dot11wBIPtxpn.val);29572958/* add MME IE with MIC all zero, MME string doesn't include element id and length */2959pframe = rtw_set_ie(pframe, _MME_IE_ , 16 , MME, &(pattrib->pktlen));2960pattrib->last_txcmdsz = pattrib->pktlen;2961/* total frame length - header length */2962frame_body_len = pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr);29632964/* conscruct AAD, copy frame control field */2965_rtw_memcpy(BIP_AAD, &pwlanhdr->frame_ctl, 2);2966ClearRetry(BIP_AAD);2967ClearPwrMgt(BIP_AAD);2968ClearMData(BIP_AAD);2969/* conscruct AAD, copy address 1 to address 3 */2970_rtw_memcpy(BIP_AAD + 2, pwlanhdr->addr1, 18);2971/* copy management fram body */2972_rtw_memcpy(BIP_AAD + BIP_AAD_SIZE, MGMT_body, frame_body_len);29732974#if DBG_MGMT_XMIT_BIP_DUMP2975/* dump total packet include MME with zero MIC */2976{2977int i;2978printk("Total packet: ");2979for (i = 0; i < BIP_AAD_SIZE + frame_body_len; i++)2980printk(" %02x ", BIP_AAD[i]);2981printk("\n");2982}2983#endif29842985/* calculate mic */2986if (omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey2987, BIP_AAD, BIP_AAD_SIZE + frame_body_len, mic))2988goto xmitframe_coalesce_fail;29892990#if DBG_MGMT_XMIT_BIP_DUMP2991/* dump calculated mic result */2992{2993int i;2994printk("Calculated mic result: ");2995for (i = 0; i < 16; i++)2996printk(" %02x ", mic[i]);2997printk("\n");2998}2999#endif30003001/* copy right BIP mic value, total is 128bits, we use the 0~63 bits */3002_rtw_memcpy(pframe - 8, mic, 8);30033004#if DBG_MGMT_XMIT_BIP_DUMP3005/*dump all packet after mic ok */3006{3007int pp;3008printk("pattrib->pktlen = %d\n", pattrib->pktlen);3009for(pp=0;pp< pattrib->pktlen; pp++)3010printk(" %02x ", mem_start[pp]);3011printk("\n");3012}3013#endif30143015#endif /* CONFIG_IEEE80211W */30163017goto xmitframe_coalesce_success;3018}3019}3020else {3021/* unicast robust mgmt frame */3022#if DBG_MGMT_XMIT_COALESEC_DUMP3023if (subtype == WIFI_DEAUTH) {3024RTW_INFO(FUNC_ADPT_FMT" unicast deauth to "MAC_FMT"\n"3025, FUNC_ADPT_ARG(padapter), MAC_ARG(pattrib->ra));3026} else if (subtype == WIFI_DISASSOC) {3027RTW_INFO(FUNC_ADPT_FMT" unicast disassoc to "MAC_FMT"\n"3028, FUNC_ADPT_ARG(padapter), MAC_ARG(pattrib->ra));3029} else if (subtype == WIFI_ACTION) {3030RTW_INFO(FUNC_ADPT_FMT" unicast action(%u) to "MAC_FMT"\n"3031, FUNC_ADPT_ARG(padapter), category, MAC_ARG(pattrib->ra));3032}3033#endif30343035_rtw_memcpy(pattrib->dot118021x_UncstKey.skey, psta->dot118021x_UncstKey.skey, 16);30363037/* To use wrong key */3038if (pattrib->key_type == IEEE80211W_WRONG_KEY) {3039RTW_INFO("use wrong key\n");3040pattrib->dot118021x_UncstKey.skey[0] = 0xff;3041}30423043pn = &psta->dot11txpn;3044kid = 0;3045}30463047#if DBG_MGMT_XMIT_ENC_DUMP3048/* before encrypt dump the management packet content */3049{3050int i;3051printk("Management pkt: ");3052for(i=0; i<pattrib->pktlen; i++)3053printk(" %02x ", pframe[i]);3054printk("=======\n");3055}3056#endif30573058/* bakeup original management packet */3059_rtw_memcpy(tmp_buf, pframe, pattrib->pktlen);3060/* move to data portion */3061pframe += pattrib->hdrlen;30623063/* 802.11w encrypted management packet must be _AES_ */3064if (pattrib->key_type != IEEE80211W_NO_KEY) {3065pattrib->encrypt = _AES_;3066pattrib->bswenc = _TRUE;3067}30683069pattrib->iv_len = 8;3070/* it's MIC of AES */3071pattrib->icv_len = 8;30723073switch (pattrib->encrypt) {3074case _AES_:3075/* set AES IV header */3076AES_IV(pattrib->iv, (*pn), kid);3077break;3078default:3079goto xmitframe_coalesce_fail;3080}30813082/* insert iv header into management frame */3083_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len);3084pframe += pattrib->iv_len;3085/* copy mgmt data portion after CCMP header */3086_rtw_memcpy(pframe, tmp_buf + pattrib->hdrlen, pattrib->pktlen - pattrib->hdrlen);3087/* move pframe to end of mgmt pkt */3088pframe += pattrib->pktlen - pattrib->hdrlen;3089/* add 8 bytes CCMP IV header to length */3090pattrib->pktlen += pattrib->iv_len;30913092#if DBG_MGMT_XMIT_ENC_DUMP3093/* dump management packet include AES IV header */3094{3095int i;3096printk("Management pkt + IV: ");3097/* for(i=0; i<pattrib->pktlen; i++) */30983099printk("@@@@@@@@@@@@@\n");3100}3101#endif31023103if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {3104_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len);3105pframe += pattrib->icv_len;3106}3107/* add 8 bytes MIC */3108pattrib->pktlen += pattrib->icv_len;3109/* set final tx command size */3110pattrib->last_txcmdsz = pattrib->pktlen;31113112/* set protected bit must be beofre SW encrypt */3113SetPrivacy(mem_start);31143115#if DBG_MGMT_XMIT_ENC_DUMP3116/* dump management packet include AES header */3117{3118int i;3119printk("prepare to enc Management pkt + IV: ");3120for (i = 0; i < pattrib->pktlen; i++)3121printk(" %02x ", mem_start[i]);3122printk("@@@@@@@@@@@@@\n");3123}3124#endif31253126/* software encrypt */3127xmitframe_swencrypt(padapter, pxmitframe);31283129xmitframe_coalesce_success:3130_exit_critical_bh(&padapter->security_key_mutex, &irqL);3131rtw_mfree(BIP_AAD, ori_len);3132return _SUCCESS;31333134xmitframe_coalesce_fail:3135_exit_critical_bh(&padapter->security_key_mutex, &irqL);3136rtw_mfree(BIP_AAD, ori_len);31373138return _FAIL;3139}3140#endif /* defined(CONFIG_IEEE80211W) || defined(CONFIG_RTW_MESH) */31413142/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header3143* IEEE LLC/SNAP header contains 8 octets3144* First 3 octets comprise the LLC portion3145* SNAP portion, 5 octets, is divided into two fields:3146* Organizationally Unique Identifier(OUI), 3 octets,3147* type, defined by that organization, 2 octets.3148*/3149s32 rtw_put_snap(u8 *data, u16 h_proto)3150{3151struct ieee80211_snap_hdr *snap;3152u8 *oui;315331543155snap = (struct ieee80211_snap_hdr *)data;3156snap->dsap = 0xaa;3157snap->ssap = 0xaa;3158snap->ctrl = 0x03;31593160if (h_proto == 0x8137 || h_proto == 0x80f3)3161oui = P802_1H_OUI;3162else3163oui = RFC1042_OUI;31643165snap->oui[0] = oui[0];3166snap->oui[1] = oui[1];3167snap->oui[2] = oui[2];31683169*(u16 *)(data + SNAP_SIZE) = htons(h_proto);317031713172return SNAP_SIZE + sizeof(u16);3173}31743175void rtw_update_protection(_adapter *padapter, u8 *ie, uint ie_len)3176{31773178uint protection;3179u8 *perp;3180sint erp_len;3181struct xmit_priv *pxmitpriv = &padapter->xmitpriv;3182struct registry_priv *pregistrypriv = &padapter->registrypriv;318331843185switch (pxmitpriv->vcs_setting) {3186case DISABLE_VCS:3187pxmitpriv->vcs = NONE_VCS;3188break;31893190case ENABLE_VCS:3191break;31923193case AUTO_VCS:3194default:3195perp = rtw_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);3196if (perp == NULL)3197pxmitpriv->vcs = NONE_VCS;3198else {3199protection = (*(perp + 2)) & BIT(1);3200if (protection) {3201if (pregistrypriv->vcs_type == RTS_CTS)3202pxmitpriv->vcs = RTS_CTS;3203else3204pxmitpriv->vcs = CTS_TO_SELF;3205} else3206pxmitpriv->vcs = NONE_VCS;3207}32083209break;32103211}321232133214}32153216void rtw_count_tx_stats(PADAPTER padapter, struct xmit_frame *pxmitframe, int sz)3217{3218struct sta_info *psta = NULL;3219struct stainfo_stats *pstats = NULL;3220struct xmit_priv *pxmitpriv = &padapter->xmitpriv;3221struct mlme_priv *pmlmepriv = &padapter->mlmepriv;3222u8 pkt_num = 1;32233224if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {3225#if defined(CONFIG_USB_TX_AGGREGATION) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)3226pkt_num = pxmitframe->agg_num;3227#endif3228pmlmepriv->LinkDetectInfo.NumTxOkInPeriod += pkt_num;32293230pxmitpriv->tx_pkts += pkt_num;32313232pxmitpriv->tx_bytes += sz;32333234psta = pxmitframe->attrib.psta;3235if (psta) {3236pstats = &psta->sta_stats;32373238pstats->tx_pkts += pkt_num;32393240pstats->tx_bytes += sz;3241#if defined(CONFIG_CHECK_LEAVE_LPS) && defined(CONFIG_LPS_CHK_BY_TP)3242if (adapter_to_pwrctl(padapter)->lps_chk_by_tp)3243traffic_check_for_leave_lps_by_tp(padapter, _TRUE, psta);3244#endif /* CONFIG_LPS */3245}32463247#ifdef CONFIG_CHECK_LEAVE_LPS3248/* traffic_check_for_leave_lps(padapter, _TRUE); */3249#endif /* CONFIG_CHECK_LEAVE_LPS */32503251}3252}32533254static struct xmit_buf *__rtw_alloc_cmd_xmitbuf(struct xmit_priv *pxmitpriv,3255enum cmdbuf_type buf_type)3256{3257struct xmit_buf *pxmitbuf = NULL;325832593260pxmitbuf = &pxmitpriv->pcmd_xmitbuf[buf_type];3261if (pxmitbuf != NULL) {3262pxmitbuf->priv_data = NULL;32633264#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)3265pxmitbuf->len = 0;3266pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;3267pxmitbuf->agg_num = 0;3268pxmitbuf->pg_num = 0;3269#endif3270#ifdef CONFIG_PCI_HCI3271pxmitbuf->len = 0;3272#ifdef CONFIG_TRX_BD_ARCH3273/*pxmitbuf->buf_desc = NULL;*/3274#else3275pxmitbuf->desc = NULL;3276#endif3277#endif32783279if (pxmitbuf->sctx) {3280RTW_INFO("%s pxmitbuf->sctx is not NULL\n", __func__);3281rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);3282}3283} else3284RTW_INFO("%s fail, no xmitbuf available !!!\n", __func__);32853286return pxmitbuf;3287}32883289struct xmit_frame *__rtw_alloc_cmdxmitframe(struct xmit_priv *pxmitpriv,3290enum cmdbuf_type buf_type)3291{3292struct xmit_frame *pcmdframe;3293struct xmit_buf *pxmitbuf;32943295pcmdframe = rtw_alloc_xmitframe(pxmitpriv);3296if (pcmdframe == NULL) {3297RTW_INFO("%s, alloc xmitframe fail\n", __FUNCTION__);3298return NULL;3299}33003301pxmitbuf = __rtw_alloc_cmd_xmitbuf(pxmitpriv, buf_type);3302if (pxmitbuf == NULL) {3303RTW_INFO("%s, alloc xmitbuf fail\n", __FUNCTION__);3304rtw_free_xmitframe(pxmitpriv, pcmdframe);3305return NULL;3306}33073308pcmdframe->frame_tag = MGNT_FRAMETAG;33093310pcmdframe->pxmitbuf = pxmitbuf;33113312pcmdframe->buf_addr = pxmitbuf->pbuf;33133314/* initial memory to zero */3315_rtw_memset(pcmdframe->buf_addr, 0, MAX_CMDBUF_SZ);33163317pxmitbuf->priv_data = pcmdframe;33183319return pcmdframe;33203321}33223323struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)3324{3325_irqL irqL;3326struct xmit_buf *pxmitbuf = NULL;3327_list *plist, *phead;3328_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;332933303331_enter_critical(&pfree_queue->lock, &irqL);33323333if (_rtw_queue_empty(pfree_queue) == _TRUE)3334pxmitbuf = NULL;3335else {33363337phead = get_list_head(pfree_queue);33383339plist = get_next(phead);33403341pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);33423343rtw_list_delete(&(pxmitbuf->list));3344}33453346if (pxmitbuf != NULL) {3347pxmitpriv->free_xmit_extbuf_cnt--;3348#ifdef DBG_XMIT_BUF_EXT3349RTW_INFO("DBG_XMIT_BUF_EXT ALLOC no=%d, free_xmit_extbuf_cnt=%d\n", pxmitbuf->no, pxmitpriv->free_xmit_extbuf_cnt);3350#endif335133523353pxmitbuf->priv_data = NULL;33543355#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)3356pxmitbuf->len = 0;3357pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;3358pxmitbuf->agg_num = 1;3359#endif3360#ifdef CONFIG_PCI_HCI3361pxmitbuf->len = 0;3362#ifdef CONFIG_TRX_BD_ARCH3363/*pxmitbuf->buf_desc = NULL;*/3364#else3365pxmitbuf->desc = NULL;3366#endif3367#endif33683369if (pxmitbuf->sctx) {3370RTW_INFO("%s pxmitbuf->sctx is not NULL\n", __func__);3371rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);3372}33733374}33753376_exit_critical(&pfree_queue->lock, &irqL);337733783379return pxmitbuf;3380}33813382s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)3383{3384_irqL irqL;3385_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;338633873388if (pxmitbuf == NULL)3389return _FAIL;33903391_enter_critical(&pfree_queue->lock, &irqL);33923393rtw_list_delete(&pxmitbuf->list);33943395rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_queue));3396pxmitpriv->free_xmit_extbuf_cnt++;3397#ifdef DBG_XMIT_BUF_EXT3398RTW_INFO("DBG_XMIT_BUF_EXT FREE no=%d, free_xmit_extbuf_cnt=%d\n", pxmitbuf->no , pxmitpriv->free_xmit_extbuf_cnt);3399#endif34003401_exit_critical(&pfree_queue->lock, &irqL);340234033404return _SUCCESS;3405}34063407struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)3408{3409_irqL irqL;3410struct xmit_buf *pxmitbuf = NULL;3411_list *plist, *phead;3412_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;341334143415/* RTW_INFO("+rtw_alloc_xmitbuf\n"); */34163417_enter_critical(&pfree_xmitbuf_queue->lock, &irqL);34183419if (_rtw_queue_empty(pfree_xmitbuf_queue) == _TRUE)3420pxmitbuf = NULL;3421else {34223423phead = get_list_head(pfree_xmitbuf_queue);34243425plist = get_next(phead);34263427pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);34283429rtw_list_delete(&(pxmitbuf->list));3430}34313432if (pxmitbuf != NULL) {3433pxmitpriv->free_xmitbuf_cnt--;3434#ifdef DBG_XMIT_BUF3435RTW_INFO("DBG_XMIT_BUF ALLOC no=%d, free_xmitbuf_cnt=%d\n", pxmitbuf->no, pxmitpriv->free_xmitbuf_cnt);3436#endif3437/* RTW_INFO("alloc, free_xmitbuf_cnt=%d\n", pxmitpriv->free_xmitbuf_cnt); */34383439pxmitbuf->priv_data = NULL;34403441#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)3442pxmitbuf->len = 0;3443pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;3444pxmitbuf->agg_num = 0;3445pxmitbuf->pg_num = 0;3446#endif3447#ifdef CONFIG_PCI_HCI3448pxmitbuf->len = 0;3449#ifdef CONFIG_TRX_BD_ARCH3450/*pxmitbuf->buf_desc = NULL;*/3451#else3452pxmitbuf->desc = NULL;3453#endif3454#endif34553456if (pxmitbuf->sctx) {3457RTW_INFO("%s pxmitbuf->sctx is not NULL\n", __func__);3458rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);3459}3460}3461#ifdef DBG_XMIT_BUF3462else3463RTW_INFO("DBG_XMIT_BUF rtw_alloc_xmitbuf return NULL\n");3464#endif34653466_exit_critical(&pfree_xmitbuf_queue->lock, &irqL);346734683469return pxmitbuf;3470}34713472s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)3473{3474_irqL irqL;3475_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;347634773478/* RTW_INFO("+rtw_free_xmitbuf\n"); */34793480if (pxmitbuf == NULL)3481return _FAIL;34823483if (pxmitbuf->sctx) {3484RTW_INFO("%s pxmitbuf->sctx is not NULL\n", __func__);3485rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);3486}34873488if (pxmitbuf->buf_tag == XMITBUF_CMD) {3489} else if (pxmitbuf->buf_tag == XMITBUF_MGNT)3490rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf);3491else {3492_enter_critical(&pfree_xmitbuf_queue->lock, &irqL);34933494rtw_list_delete(&pxmitbuf->list);34953496rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));34973498pxmitpriv->free_xmitbuf_cnt++;3499/* RTW_INFO("FREE, free_xmitbuf_cnt=%d\n", pxmitpriv->free_xmitbuf_cnt); */3500#ifdef DBG_XMIT_BUF3501RTW_INFO("DBG_XMIT_BUF FREE no=%d, free_xmitbuf_cnt=%d\n", pxmitbuf->no , pxmitpriv->free_xmitbuf_cnt);3502#endif3503_exit_critical(&pfree_xmitbuf_queue->lock, &irqL);3504}350535063507return _SUCCESS;3508}35093510void rtw_init_xmitframe(struct xmit_frame *pxframe)3511{3512if (pxframe != NULL) { /* default value setting */3513pxframe->buf_addr = NULL;3514pxframe->pxmitbuf = NULL;35153516_rtw_memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));3517/* pxframe->attrib.psta = NULL; */35183519pxframe->frame_tag = DATA_FRAMETAG;35203521#ifdef CONFIG_USB_HCI3522pxframe->pkt = NULL;3523#ifdef USB_PACKET_OFFSET_SZ3524pxframe->pkt_offset = (PACKET_OFFSET_SZ / 8);3525#else3526pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */3527#endif35283529#ifdef CONFIG_USB_TX_AGGREGATION3530pxframe->agg_num = 1;3531#endif35323533#endif /* #ifdef CONFIG_USB_HCI */35343535#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)3536pxframe->pg_num = 1;3537pxframe->agg_num = 1;3538#endif35393540#ifdef CONFIG_XMIT_ACK3541pxframe->ack_report = 0;3542#endif35433544}3545}35463547/*3548Calling context:35491. OS_TXENTRY35502. RXENTRY (rx_thread or RX_ISR/RX_CallBack)35513552If we turn on USE_RXTHREAD, then, no need for critical section.3553Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...35543555Must be very very cautious...35563557*/3558struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* (_queue *pfree_xmit_queue) */3559{3560/*3561Please remember to use all the osdep_service api,3562and lock/unlock or _enter/_exit critical to protect3563pfree_xmit_queue3564*/35653566_irqL irqL;3567struct xmit_frame *pxframe = NULL;3568_list *plist, *phead;3569_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;357035713572_enter_critical_bh(&pfree_xmit_queue->lock, &irqL);35733574if (_rtw_queue_empty(pfree_xmit_queue) == _TRUE) {3575pxframe = NULL;3576} else {3577phead = get_list_head(pfree_xmit_queue);35783579plist = get_next(phead);35803581pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);35823583rtw_list_delete(&(pxframe->list));3584pxmitpriv->free_xmitframe_cnt--;3585}35863587_exit_critical_bh(&pfree_xmit_queue->lock, &irqL);35883589rtw_init_xmitframe(pxframe);359035913592return pxframe;3593}35943595struct xmit_frame *rtw_alloc_xmitframe_ext(struct xmit_priv *pxmitpriv)3596{3597_irqL irqL;3598struct xmit_frame *pxframe = NULL;3599_list *plist, *phead;3600_queue *queue = &pxmitpriv->free_xframe_ext_queue;360136023603_enter_critical_bh(&queue->lock, &irqL);36043605if (_rtw_queue_empty(queue) == _TRUE) {3606pxframe = NULL;3607} else {3608phead = get_list_head(queue);3609plist = get_next(phead);3610pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);36113612rtw_list_delete(&(pxframe->list));3613pxmitpriv->free_xframe_ext_cnt--;3614}36153616_exit_critical_bh(&queue->lock, &irqL);36173618rtw_init_xmitframe(pxframe);361936203621return pxframe;3622}36233624struct xmit_frame *rtw_alloc_xmitframe_once(struct xmit_priv *pxmitpriv)3625{3626struct xmit_frame *pxframe = NULL;3627u8 *alloc_addr;36283629alloc_addr = rtw_zmalloc(sizeof(struct xmit_frame) + 4);36303631if (alloc_addr == NULL)3632goto exit;36333634pxframe = (struct xmit_frame *)N_BYTE_ALIGMENT((SIZE_PTR)(alloc_addr), 4);3635pxframe->alloc_addr = alloc_addr;36363637pxframe->padapter = pxmitpriv->adapter;3638pxframe->frame_tag = NULL_FRAMETAG;36393640pxframe->pkt = NULL;36413642pxframe->buf_addr = NULL;3643pxframe->pxmitbuf = NULL;36443645rtw_init_xmitframe(pxframe);36463647RTW_INFO("################## %s ##################\n", __func__);36483649exit:3650return pxframe;3651}36523653s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)3654{3655_irqL irqL;3656_queue *queue = NULL;3657_adapter *padapter = pxmitpriv->adapter;3658_pkt *pndis_pkt = NULL;365936603661if (pxmitframe == NULL) {3662goto exit;3663}36643665if (pxmitframe->pkt) {3666pndis_pkt = pxmitframe->pkt;3667pxmitframe->pkt = NULL;3668}36693670if (pxmitframe->alloc_addr) {3671RTW_INFO("################## %s with alloc_addr ##################\n", __func__);3672rtw_mfree(pxmitframe->alloc_addr, sizeof(struct xmit_frame) + 4);3673goto check_pkt_complete;3674}36753676if (pxmitframe->ext_tag == 0)3677queue = &pxmitpriv->free_xmit_queue;3678else if (pxmitframe->ext_tag == 1)3679queue = &pxmitpriv->free_xframe_ext_queue;3680else3681rtw_warn_on(1);36823683_enter_critical_bh(&queue->lock, &irqL);36843685rtw_list_delete(&pxmitframe->list);3686rtw_list_insert_tail(&pxmitframe->list, get_list_head(queue));3687if (pxmitframe->ext_tag == 0) {3688pxmitpriv->free_xmitframe_cnt++;3689} else if (pxmitframe->ext_tag == 1) {3690pxmitpriv->free_xframe_ext_cnt++;3691} else {3692}36933694_exit_critical_bh(&queue->lock, &irqL);36953696check_pkt_complete:36973698if (pndis_pkt)3699rtw_os_pkt_complete(padapter, pndis_pkt);37003701exit:370237033704return _SUCCESS;3705}37063707void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, _queue *pframequeue)3708{3709_irqL irqL;3710_list *plist, *phead;3711struct xmit_frame *pxmitframe;371237133714_enter_critical_bh(&(pframequeue->lock), &irqL);37153716phead = get_list_head(pframequeue);3717plist = get_next(phead);37183719while (rtw_end_of_queue_search(phead, plist) == _FALSE) {37203721pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);37223723plist = get_next(plist);37243725rtw_free_xmitframe(pxmitpriv, pxmitframe);37263727}3728_exit_critical_bh(&(pframequeue->lock), &irqL);37293730}37313732s32 rtw_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)3733{3734DBG_COUNTER(padapter->tx_logs.core_tx_enqueue);3735if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL) {3736/* pxmitframe->pkt = NULL; */3737return _FAIL;3738}37393740return _SUCCESS;3741}37423743static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, struct tx_servq *ptxservq, _queue *pframe_queue)3744{3745_list *xmitframe_plist, *xmitframe_phead;3746struct xmit_frame *pxmitframe = NULL;37473748xmitframe_phead = get_list_head(pframe_queue);3749xmitframe_plist = get_next(xmitframe_phead);37503751while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {3752pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);37533754/* xmitframe_plist = get_next(xmitframe_plist); */37553756/*#ifdef RTK_DMP_PLATFORM3757#ifdef CONFIG_USB_TX_AGGREGATION3758if((ptxservq->qcnt>0) && (ptxservq->qcnt<=2))3759{3760pxmitframe = NULL;37613762tasklet_schedule(&pxmitpriv->xmit_tasklet);37633764break;3765}3766#endif3767#endif*/3768rtw_list_delete(&pxmitframe->list);37693770ptxservq->qcnt--;37713772/* rtw_list_insert_tail(&pxmitframe->list, &phwxmit->pending); */37733774/* ptxservq->qcnt--; */37753776break;37773778/* pxmitframe = NULL; */37793780}37813782return pxmitframe;3783}37843785static struct xmit_frame *get_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, struct tx_servq *ptxservq, _queue *pframe_queue)3786{3787_list *xmitframe_plist, *xmitframe_phead;3788struct xmit_frame *pxmitframe = NULL;37893790xmitframe_phead = get_list_head(pframe_queue);3791xmitframe_plist = get_next(xmitframe_phead);37923793while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {3794pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);3795break;3796}37973798return pxmitframe;3799}38003801struct xmit_frame *rtw_get_xframe(struct xmit_priv *pxmitpriv, int *num_frame)3802{3803_irqL irqL0;3804_list *sta_plist, *sta_phead;3805struct hw_xmit *phwxmit_i = pxmitpriv->hwxmits;3806sint entry = pxmitpriv->hwxmit_entry;38073808struct hw_xmit *phwxmit;3809struct tx_servq *ptxservq = NULL;3810_queue *pframe_queue = NULL;3811struct xmit_frame *pxmitframe = NULL;3812_adapter *padapter = pxmitpriv->adapter;3813struct registry_priv *pregpriv = &padapter->registrypriv;3814int i, inx[4];38153816inx[0] = 0;3817inx[1] = 1;3818inx[2] = 2;3819inx[3] = 3;38203821*num_frame = 0;38223823/*No amsdu when wifi_spec on*/3824if (pregpriv->wifi_spec == 1) {3825return NULL;3826}38273828_enter_critical_bh(&pxmitpriv->lock, &irqL0);38293830for (i = 0; i < entry; i++) {3831phwxmit = phwxmit_i + inx[i];38323833sta_phead = get_list_head(phwxmit->sta_queue);3834sta_plist = get_next(sta_phead);38353836while ((rtw_end_of_queue_search(sta_phead, sta_plist)) == _FALSE) {38373838ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);3839pframe_queue = &ptxservq->sta_pending;38403841if(ptxservq->qcnt)3842{3843*num_frame = ptxservq->qcnt;3844pxmitframe = get_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);3845goto exit;3846}3847sta_plist = get_next(sta_plist);3848}3849}38503851exit:38523853_exit_critical_bh(&pxmitpriv->lock, &irqL0);38543855return pxmitframe;3856}385738583859struct xmit_frame *rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, sint entry)3860{3861_irqL irqL0;3862_list *sta_plist, *sta_phead;3863struct hw_xmit *phwxmit;3864struct tx_servq *ptxservq = NULL;3865_queue *pframe_queue = NULL;3866struct xmit_frame *pxmitframe = NULL;3867_adapter *padapter = pxmitpriv->adapter;3868struct registry_priv *pregpriv = &padapter->registrypriv;3869int i, inx[4];38703871inx[0] = 0;3872inx[1] = 1;3873inx[2] = 2;3874inx[3] = 3;38753876if (pregpriv->wifi_spec == 1) {3877int j;3878#if 03879if (flags < XMIT_QUEUE_ENTRY) {3880/* priority exchange according to the completed xmitbuf flags. */3881inx[flags] = 0;3882inx[0] = flags;3883}3884#endif38853886#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_PCI_HCI)3887for (j = 0; j < 4; j++)3888inx[j] = pxmitpriv->wmm_para_seq[j];3889#endif3890}38913892_enter_critical_bh(&pxmitpriv->lock, &irqL0);38933894for (i = 0; i < entry; i++) {3895phwxmit = phwxmit_i + inx[i];38963897/* _enter_critical_ex(&phwxmit->sta_queue->lock, &irqL0); */38983899sta_phead = get_list_head(phwxmit->sta_queue);3900sta_plist = get_next(sta_phead);39013902while ((rtw_end_of_queue_search(sta_phead, sta_plist)) == _FALSE) {39033904ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);39053906pframe_queue = &ptxservq->sta_pending;39073908pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);39093910if (pxmitframe) {3911phwxmit->accnt--;39123913/* Remove sta node when there is no pending packets. */3914if (_rtw_queue_empty(pframe_queue)) /* must be done after get_next and before break */3915rtw_list_delete(&ptxservq->tx_pending);39163917/* _exit_critical_ex(&phwxmit->sta_queue->lock, &irqL0); */39183919goto exit;3920}39213922sta_plist = get_next(sta_plist);39233924}39253926/* _exit_critical_ex(&phwxmit->sta_queue->lock, &irqL0); */39273928}39293930exit:39313932_exit_critical_bh(&pxmitpriv->lock, &irqL0);39333934return pxmitframe;3935}39363937#if 13938struct tx_servq *rtw_get_sta_pending(_adapter *padapter, struct sta_info *psta, sint up, u8 *ac)3939{3940struct tx_servq *ptxservq = NULL;394139423943switch (up) {3944case 1:3945case 2:3946ptxservq = &(psta->sta_xmitpriv.bk_q);3947*(ac) = 3;3948break;39493950case 4:3951case 5:3952ptxservq = &(psta->sta_xmitpriv.vi_q);3953*(ac) = 1;3954break;39553956case 6:3957case 7:3958ptxservq = &(psta->sta_xmitpriv.vo_q);3959*(ac) = 0;3960break;39613962case 0:3963case 3:3964default:3965ptxservq = &(psta->sta_xmitpriv.be_q);3966*(ac) = 2;3967break;39683969}397039713972return ptxservq;3973}3974#else3975__inline static struct tx_servq *rtw_get_sta_pending3976(_adapter *padapter, _queue **ppstapending, struct sta_info *psta, sint up)3977{3978struct tx_servq *ptxservq;3979struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;398039813982#ifdef CONFIG_RTL871139833984if (IS_MCAST(psta->cmn.mac_addr)) {3985ptxservq = &(psta->sta_xmitpriv.be_q); /* we will use be_q to queue bc/mc frames in BCMC_stainfo */3986*ppstapending = &padapter->xmitpriv.bm_pending;3987} else3988#endif3989{3990switch (up) {3991case 1:3992case 2:3993ptxservq = &(psta->sta_xmitpriv.bk_q);3994*ppstapending = &padapter->xmitpriv.bk_pending;3995(phwxmits + 3)->accnt++;3996break;39973998case 4:3999case 5:4000ptxservq = &(psta->sta_xmitpriv.vi_q);4001*ppstapending = &padapter->xmitpriv.vi_pending;4002(phwxmits + 1)->accnt++;4003break;40044005case 6:4006case 7:4007ptxservq = &(psta->sta_xmitpriv.vo_q);4008*ppstapending = &padapter->xmitpriv.vo_pending;4009(phwxmits + 0)->accnt++;4010break;40114012case 0:4013case 3:4014default:4015ptxservq = &(psta->sta_xmitpriv.be_q);4016*ppstapending = &padapter->xmitpriv.be_pending;4017(phwxmits + 2)->accnt++;4018break;40194020}40214022}402340244025return ptxservq;4026}4027#endif40284029/*4030* Will enqueue pxmitframe to the proper queue,4031* and indicate it to xx_pending list.....4032*/4033s32 rtw_xmit_classifier(_adapter *padapter, struct xmit_frame *pxmitframe)4034{4035/* _irqL irqL0; */4036u8 ac_index;4037struct sta_info *psta;4038struct tx_servq *ptxservq;4039struct pkt_attrib *pattrib = &pxmitframe->attrib;4040struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;4041sint res = _SUCCESS;404240434044DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class);40454046/*4047if (pattrib->psta) {4048psta = pattrib->psta;4049} else {4050RTW_INFO("%s, call rtw_get_stainfo()\n", __func__);4051psta = rtw_get_stainfo(pstapriv, pattrib->ra);4052}4053*/40544055psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);4056if (pattrib->psta != psta) {4057DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_sta);4058RTW_INFO("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);4059return _FAIL;4060}40614062if (psta == NULL) {4063DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_nosta);4064res = _FAIL;4065RTW_INFO("rtw_xmit_classifier: psta == NULL\n");4066goto exit;4067}40684069if (!(psta->state & _FW_LINKED)) {4070DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_fwlink);4071RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);4072return _FAIL;4073}40744075ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));40764077/* _enter_critical(&pstapending->lock, &irqL0); */40784079if (rtw_is_list_empty(&ptxservq->tx_pending))4080rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));40814082/* _enter_critical(&ptxservq->sta_pending.lock, &irqL1); */40834084rtw_list_insert_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));4085ptxservq->qcnt++;4086phwxmits[ac_index].accnt++;40874088/* _exit_critical(&ptxservq->sta_pending.lock, &irqL1); */40894090/* _exit_critical(&pstapending->lock, &irqL0); */40914092exit:409340944095return res;4096}40974098void rtw_alloc_hwxmits(_adapter *padapter)4099{4100struct hw_xmit *hwxmits;4101struct xmit_priv *pxmitpriv = &padapter->xmitpriv;41024103pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;41044105pxmitpriv->hwxmits = NULL;41064107pxmitpriv->hwxmits = (struct hw_xmit *)rtw_zmalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry);41084109if (pxmitpriv->hwxmits == NULL) {4110RTW_INFO("alloc hwxmits fail!...\n");4111return;4112}41134114hwxmits = pxmitpriv->hwxmits;41154116if (pxmitpriv->hwxmit_entry == 5) {4117/* pxmitpriv->bmc_txqueue.head = 0; */4118/* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */4119hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;41204121/* pxmitpriv->vo_txqueue.head = 0; */4122/* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */4123hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;41244125/* pxmitpriv->vi_txqueue.head = 0; */4126/* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */4127hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;41284129/* pxmitpriv->bk_txqueue.head = 0; */4130/* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */4131hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;41324133/* pxmitpriv->be_txqueue.head = 0; */4134/* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */4135hwxmits[4] .sta_queue = &pxmitpriv->be_pending;41364137} else if (pxmitpriv->hwxmit_entry == 4) {41384139/* pxmitpriv->vo_txqueue.head = 0; */4140/* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */4141hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;41424143/* pxmitpriv->vi_txqueue.head = 0; */4144/* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */4145hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;41464147/* pxmitpriv->be_txqueue.head = 0; */4148/* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */4149hwxmits[2] .sta_queue = &pxmitpriv->be_pending;41504151/* pxmitpriv->bk_txqueue.head = 0; */4152/* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */4153hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;4154} else {415541564157}415841594160}41614162void rtw_free_hwxmits(_adapter *padapter)4163{4164struct hw_xmit *hwxmits;4165struct xmit_priv *pxmitpriv = &padapter->xmitpriv;41664167hwxmits = pxmitpriv->hwxmits;4168if (hwxmits)4169rtw_mfree((u8 *)hwxmits, (sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry));4170}41714172void rtw_init_hwxmits(struct hw_xmit *phwxmit, sint entry)4173{4174sint i;4175for (i = 0; i < entry; i++, phwxmit++) {4176/* _rtw_spinlock_init(&phwxmit->xmit_lock); */4177/* _rtw_init_listhead(&phwxmit->pending); */4178/* phwxmit->txcmdcnt = 0; */4179phwxmit->accnt = 0;4180}4181}41824183#ifdef CONFIG_BR_EXT4184int rtw_br_client_tx(_adapter *padapter, struct sk_buff **pskb)4185{4186struct sk_buff *skb = *pskb;4187_irqL irqL;4188/* if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) */4189{4190void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb);4191int res, is_vlan_tag = 0, i, do_nat25 = 1;4192unsigned short vlan_hdr = 0;4193void *br_port = NULL;41944195/* mac_clone_handle_frame(priv, skb); */41964197#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))4198br_port = padapter->pnetdev->br_port;4199#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */4200rcu_read_lock();4201br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);4202rcu_read_unlock();4203#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) */4204_enter_critical_bh(&padapter->br_ext_lock, &irqL);4205if (!(skb->data[0] & 1) &&4206br_port &&4207memcmp(skb->data + MACADDRLEN, padapter->br_mac, MACADDRLEN) &&4208*((unsigned short *)(skb->data + MACADDRLEN * 2)) != __constant_htons(ETH_P_8021Q) &&4209*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP) &&4210!memcmp(padapter->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN) && padapter->scdb_entry) {4211memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);4212padapter->scdb_entry->ageing_timer = jiffies;4213_exit_critical_bh(&padapter->br_ext_lock, &irqL);4214} else4215/* if (!priv->pmib->ethBrExtInfo.nat25_disable) */4216{4217/* if (priv->dev->br_port &&4218* !memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN)) { */4219#if 14220if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q)) {4221is_vlan_tag = 1;4222vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2));4223for (i = 0; i < 6; i++)4224*((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2));4225skb_pull(skb, 4);4226}4227/* if SA == br_mac && skb== IP => copy SIP to br_ip ?? why */4228if (!memcmp(skb->data + MACADDRLEN, padapter->br_mac, MACADDRLEN) &&4229(*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)))4230memcpy(padapter->br_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4);42314232if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_IP)) {4233if (memcmp(padapter->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN)) {4234void *scdb_findEntry(_adapter *priv, unsigned char *macAddr, unsigned char *ipAddr);42354236padapter->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(padapter,4237skb->data + MACADDRLEN, skb->data + WLAN_ETHHDR_LEN + 12);4238if (padapter->scdb_entry != NULL) {4239memcpy(padapter->scdb_mac, skb->data + MACADDRLEN, MACADDRLEN);4240memcpy(padapter->scdb_ip, skb->data + WLAN_ETHHDR_LEN + 12, 4);4241padapter->scdb_entry->ageing_timer = jiffies;4242do_nat25 = 0;4243}4244} else {4245if (padapter->scdb_entry) {4246padapter->scdb_entry->ageing_timer = jiffies;4247do_nat25 = 0;4248} else {4249memset(padapter->scdb_mac, 0, MACADDRLEN);4250memset(padapter->scdb_ip, 0, 4);4251}4252}4253}4254_exit_critical_bh(&padapter->br_ext_lock, &irqL);4255#endif /* 1 */4256if (do_nat25) {4257int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method);4258if (nat25_db_handle(padapter, skb, NAT25_CHECK) == 0) {4259struct sk_buff *newskb;42604261if (is_vlan_tag) {4262skb_push(skb, 4);4263for (i = 0; i < 6; i++)4264*((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2));4265*((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q);4266*((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr;4267}42684269newskb = rtw_skb_copy(skb);4270if (newskb == NULL) {4271/* priv->ext_stats.tx_drops++; */4272DEBUG_ERR("TX DROP: rtw_skb_copy fail!\n");4273/* goto stop_proc; */4274return -1;4275}4276rtw_skb_free(skb);42774278*pskb = skb = newskb;4279if (is_vlan_tag) {4280vlan_hdr = *((unsigned short *)(skb->data + MACADDRLEN * 2 + 2));4281for (i = 0; i < 6; i++)4282*((unsigned short *)(skb->data + MACADDRLEN * 2 + 2 - i * 2)) = *((unsigned short *)(skb->data + MACADDRLEN * 2 - 2 - i * 2));4283skb_pull(skb, 4);4284}4285}42864287if (skb_is_nonlinear(skb))4288DEBUG_ERR("%s(): skb_is_nonlinear!!\n", __FUNCTION__);428942904291#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))4292res = skb_linearize(skb, GFP_ATOMIC);4293#else /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */4294res = skb_linearize(skb);4295#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18)) */4296if (res < 0) {4297DEBUG_ERR("TX DROP: skb_linearize fail!\n");4298/* goto free_and_stop; */4299return -1;4300}43014302res = nat25_db_handle(padapter, skb, NAT25_INSERT);4303if (res < 0) {4304if (res == -2) {4305/* priv->ext_stats.tx_drops++; */4306DEBUG_ERR("TX DROP: nat25_db_handle fail!\n");4307/* goto free_and_stop; */4308return -1;43094310}4311/* we just print warning message and let it go */4312/* DEBUG_WARN("%s()-%d: nat25_db_handle INSERT Warning!\n", __FUNCTION__, __LINE__); */4313/* return -1; */ /* return -1 will cause system crash on 2011/08/30! */4314return 0;4315}4316}43174318memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);43194320dhcp_flag_bcast(padapter, skb);43214322if (is_vlan_tag) {4323skb_push(skb, 4);4324for (i = 0; i < 6; i++)4325*((unsigned short *)(skb->data + i * 2)) = *((unsigned short *)(skb->data + 4 + i * 2));4326*((unsigned short *)(skb->data + MACADDRLEN * 2)) = __constant_htons(ETH_P_8021Q);4327*((unsigned short *)(skb->data + MACADDRLEN * 2 + 2)) = vlan_hdr;4328}4329}4330#if 04331else {4332if (*((unsigned short *)(skb->data + MACADDRLEN * 2)) == __constant_htons(ETH_P_8021Q))4333is_vlan_tag = 1;43344335if (is_vlan_tag) {4336if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A_VALN(skb->data))4337memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);4338} else {4339if (ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A(skb->data))4340memcpy(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);4341}4342}4343#endif /* 0 */43444345/* check if SA is equal to our MAC */4346if (memcmp(skb->data + MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN)) {4347/* priv->ext_stats.tx_drops++; */4348DEBUG_ERR("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n",4349skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]);4350/* goto free_and_stop; */4351return -1;4352}4353}4354return 0;4355}4356#endif /* CONFIG_BR_EXT */43574358u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)4359{4360u32 addr;4361struct pkt_attrib *pattrib = &pxmitframe->attrib;43624363switch (pattrib->qsel) {4364case 0:4365case 3:4366addr = BE_QUEUE_INX;4367break;4368case 1:4369case 2:4370addr = BK_QUEUE_INX;4371break;4372case 4:4373case 5:4374addr = VI_QUEUE_INX;4375break;4376case 6:4377case 7:4378addr = VO_QUEUE_INX;4379break;4380case 0x10:4381addr = BCN_QUEUE_INX;4382break;4383case 0x11: /* BC/MC in PS (HIQ) */4384addr = HIGH_QUEUE_INX;4385break;4386case 0x13:4387addr = TXCMD_QUEUE_INX;4388break;4389case 0x12:4390default:4391addr = MGT_QUEUE_INX;4392break;43934394}43954396return addr;43974398}43994400static void do_queue_select(_adapter *padapter, struct pkt_attrib *pattrib)4401{4402u8 qsel;44034404qsel = pattrib->priority;44054406#ifdef CONFIG_MCC_MODE4407if (MCC_EN(padapter)) {4408/* Under MCC */4409if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {4410if (padapter->mcc_adapterpriv.role == MCC_ROLE_GO4411|| padapter->mcc_adapterpriv.role == MCC_ROLE_AP) {4412pattrib->qsel = QSLT_VO; /* AP interface VO queue */4413pattrib->priority = QSLT_VO;4414} else {4415pattrib->qsel = QSLT_BE; /* STA interface BE queue */4416pattrib->priority = QSLT_BE;4417}4418} else4419/* Not Under MCC */4420pattrib->qsel = qsel;4421} else4422/* Not enable MCC */4423pattrib->qsel = qsel;4424#else /* !CONFIG_MCC_MODE */4425pattrib->qsel = qsel;4426#endif /* CONFIG_MCC_MODE */44274428/* high priority packet */4429if (pattrib->hipriority_pkt) {4430pattrib->qsel = QSLT_VO;4431pattrib->priority = QSLT_VO;4432}4433}44344435/*4436* The main transmit(tx) entry4437*4438* Return4439* 1 enqueue4440* 0 success, hardware will handle this xmit frame(packet)4441* <0 fail4442*/4443#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))4444s32 rtw_monitor_xmit_entry(struct sk_buff *skb, struct net_device *ndev)4445{4446u16 frame_ctl;4447struct ieee80211_radiotap_header rtap_hdr;4448_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);4449struct pkt_file pktfile;4450struct rtw_ieee80211_hdr *pwlanhdr;4451struct pkt_attrib *pattrib;4452struct xmit_frame *pmgntframe;4453struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4454struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);4455unsigned char *pframe;4456u8 dummybuf[32];4457int len = skb->len, rtap_len;445844594460// rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, skb->truesize);44614462#ifdef CONFIG_MONITOR_MODE_XMIT4463int consume;4464#endif /* CONFIG_MONITOR_MODE_XMIT */4465if (likely(skb))4466rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, skb->truesize);44674468#ifndef CONFIG_CUSTOMER_ALIBABA_GENERAL4469if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))4470goto fail;44714472_rtw_open_pktfile((_pkt *)skb, &pktfile);4473_rtw_pktfile_read(&pktfile, (u8 *)(&rtap_hdr), sizeof(struct ieee80211_radiotap_header));4474rtap_len = ieee80211_get_radiotap_len((u8 *)(&rtap_hdr));4475if (unlikely(rtap_hdr.it_version))4476goto fail;44774478if (unlikely(skb->len < rtap_len))4479goto fail;44804481#ifdef CONFIG_MONITOR_MODE_XMIT4482len -= sizeof(struct ieee80211_radiotap_header);4483rtap_len -= sizeof(struct ieee80211_radiotap_header);44844485while(rtap_len) {4486consume = rtap_len > sizeof(dummybuf) ? sizeof(dummybuf) : rtap_len;4487_rtw_pktfile_read(&pktfile, dummybuf, consume);4488rtap_len -= consume;4489len -= consume;4490}4491#else /* CONFIG_MONITOR_MODE_XMIT */44924493if (rtap_len != 12) {4494RTW_INFO("radiotap len (should be 14): %d\n", rtap_len);4495goto fail;4496}4497_rtw_pktfile_read(&pktfile, dummybuf, rtap_len-sizeof(struct ieee80211_radiotap_header));4498len = len - rtap_len;4499#endif /* CONFIG_MONITOR_MODE_XMIT */4500#endif /* CONFIG_CUSTOMER_ALIBABA_GENERAL */4501pmgntframe = alloc_mgtxmitframe(pxmitpriv);4502if (pmgntframe == NULL) {4503rtw_udelay_os(500);4504goto fail;4505}45064507_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);4508pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;4509// _rtw_memcpy(pframe, (void *)checking, len);4510_rtw_pktfile_read(&pktfile, pframe, len);451145124513/* Check DATA/MGNT frames */4514pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;4515frame_ctl = le16_to_cpu(pwlanhdr->frame_ctl);4516if ((frame_ctl & RTW_IEEE80211_FCTL_FTYPE) == RTW_IEEE80211_FTYPE_DATA) {45174518pattrib = &pmgntframe->attrib;4519update_monitor_frame_attrib(padapter, pattrib);45204521if (is_broadcast_mac_addr(pwlanhdr->addr3) || is_broadcast_mac_addr(pwlanhdr->addr1))4522pattrib->rate = MGN_24M;45234524} else {45254526pattrib = &pmgntframe->attrib;4527update_mgntframe_attrib(padapter, pattrib);45284529}4530pattrib->retry_ctrl = _FALSE;4531pattrib->pktlen = len;4532pmlmeext->mgnt_seq = GetSequence(pwlanhdr);4533pattrib->seqnum = pmlmeext->mgnt_seq;4534pmlmeext->mgnt_seq++;4535pattrib->last_txcmdsz = pattrib->pktlen;45364537dump_mgntframe(padapter, pmgntframe);45384539fail:4540#ifdef CONFIG_MONITOR_MODE_XMIT4541rtw_endofpktfile(&pktfile);4542#endif /* CONFIG_MONITOR_MODE_XMIT */4543rtw_skb_free(skb);4544return 0;4545}4546#endif45474548/*4549*4550* Return _TRUE when frame has been put to queue, otherwise return _FALSE.4551*/4552static u8 xmit_enqueue(struct _ADAPTER *a, struct xmit_frame *frame)4553{4554struct sta_info *sta = NULL;4555struct pkt_attrib *attrib = NULL;4556_irqL irqL;4557_list *head;4558u8 ret = _TRUE;455945604561attrib = &frame->attrib;4562sta = attrib->psta;4563if (!sta)4564return _FALSE;45654566_enter_critical_bh(&sta->tx_queue.lock, &irqL);45674568head = get_list_head(&sta->tx_queue);45694570if ((rtw_is_list_empty(head) == _TRUE) && (!sta->tx_q_enable)) {4571ret = _FALSE;4572goto exit;4573}45744575rtw_list_insert_tail(&frame->list, head);4576RTW_INFO(FUNC_ADPT_FMT ": en-queue tx pkt for macid=%d\n",4577FUNC_ADPT_ARG(a), sta->cmn.mac_id);45784579exit:4580_exit_critical_bh(&sta->tx_queue.lock, &irqL);45814582return ret;4583}45844585static void xmit_dequeue(struct sta_info *sta)4586{4587struct _ADAPTER *a;4588_irqL irqL;4589_list *head, *list;4590struct xmit_frame *frame;459145924593a = sta->padapter;45944595_enter_critical_bh(&sta->tx_queue.lock, &irqL);45964597head = get_list_head(&sta->tx_queue);45984599do {4600if (rtw_is_list_empty(head) == _TRUE)4601break;46024603list = get_next(head);4604rtw_list_delete(list);4605frame = LIST_CONTAINOR(list, struct xmit_frame, list);4606RTW_INFO(FUNC_ADPT_FMT ": de-queue tx frame of macid=%d\n",4607FUNC_ADPT_ARG(a), sta->cmn.mac_id);46084609rtw_hal_xmit(a, frame);4610} while (1);46114612_exit_critical_bh(&sta->tx_queue.lock, &irqL);4613}46144615void rtw_xmit_dequeue_callback(_workitem *work)4616{4617struct sta_info *sta;461846194620sta = container_of(work, struct sta_info, tx_q_work);4621xmit_dequeue(sta);4622}46234624void rtw_xmit_queue_set(struct sta_info *sta)4625{4626_irqL irqL;46274628_enter_critical_bh(&sta->tx_queue.lock, &irqL);46294630if (sta->tx_q_enable) {4631RTW_WARN(FUNC_ADPT_FMT ": duplicated set!\n",4632FUNC_ADPT_ARG(sta->padapter));4633goto exit;4634}4635sta->tx_q_enable = 1;4636RTW_INFO(FUNC_ADPT_FMT ": enable queue TX for macid=%d\n",4637FUNC_ADPT_ARG(sta->padapter), sta->cmn.mac_id);46384639exit:4640_exit_critical_bh(&sta->tx_queue.lock, &irqL);4641}46424643void rtw_xmit_queue_clear(struct sta_info *sta)4644{4645_irqL irqL;46464647_enter_critical_bh(&sta->tx_queue.lock, &irqL);46484649if (!sta->tx_q_enable) {4650RTW_WARN(FUNC_ADPT_FMT ": tx queue for macid=%d "4651"not be enabled!\n",4652FUNC_ADPT_ARG(sta->padapter), sta->cmn.mac_id);4653goto exit;4654}46554656sta->tx_q_enable = 0;4657RTW_INFO(FUNC_ADPT_FMT ": disable queue TX for macid=%d\n",4658FUNC_ADPT_ARG(sta->padapter), sta->cmn.mac_id);46594660_set_workitem(&sta->tx_q_work);46614662exit:4663_exit_critical_bh(&sta->tx_queue.lock, &irqL);4664}46654666/*4667* The main transmit(tx) entry post handle4668*4669* Return4670* 1 enqueue4671* 0 success, hardware will handle this xmit frame(packet)4672* <0 fail4673*/4674s32 rtw_xmit_posthandle(_adapter *padapter, struct xmit_frame *pxmitframe, _pkt *pkt)4675{4676#ifdef CONFIG_AP_MODE4677_irqL irqL0;4678#endif4679struct xmit_priv *pxmitpriv = &padapter->xmitpriv;4680s32 res;46814682res = update_attrib(padapter, pkt, &pxmitframe->attrib);46834684#ifdef CONFIG_MCC_MODE4685/* record data kernel TX to driver to check MCC concurrent TX */4686rtw_hal_mcc_calc_tx_bytes_from_kernel(padapter, pxmitframe->attrib.pktlen);4687#endif /* CONFIG_MCC_MODE */46884689#ifdef CONFIG_WAPI_SUPPORT4690if (pxmitframe->attrib.ether_type != 0x88B4) {4691if (rtw_wapi_drop_for_key_absent(padapter, pxmitframe->attrib.ra)) {4692WAPI_TRACE(WAPI_RX, "drop for key absend when tx\n");4693res = _FAIL;4694}4695}4696#endif4697if (res == _FAIL) {4698/*RTW_INFO("%s-"ADPT_FMT" update attrib fail\n", __func__, ADPT_ARG(padapter));*/4699#ifdef DBG_TX_DROP_FRAME4700RTW_INFO("DBG_TX_DROP_FRAME %s update attrib fail\n", __FUNCTION__);4701#endif4702rtw_free_xmitframe(pxmitpriv, pxmitframe);4703return -1;4704}4705pxmitframe->pkt = pkt;47064707rtw_led_tx_control(padapter, pxmitframe->attrib.dst);47084709do_queue_select(padapter, &pxmitframe->attrib);47104711#ifdef CONFIG_AP_MODE4712_enter_critical_bh(&pxmitpriv->lock, &irqL0);4713if (xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe) == _TRUE) {4714_exit_critical_bh(&pxmitpriv->lock, &irqL0);4715DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue);4716return 1;4717}4718_exit_critical_bh(&pxmitpriv->lock, &irqL0);4719#endif47204721if (xmit_enqueue(padapter, pxmitframe) == _TRUE)4722return 1;47234724/* pre_xmitframe */4725if (rtw_hal_xmit(padapter, pxmitframe) == _FALSE)4726return 1;47274728return 0;4729}47304731/*4732* The main transmit(tx) entry4733*4734* Return4735* 1 enqueue4736* 0 success, hardware will handle this xmit frame(packet)4737* <0 fail4738*/4739s32 rtw_xmit(_adapter *padapter, _pkt **ppkt)4740{4741static systime start = 0;4742static u32 drop_cnt = 0;4743struct xmit_priv *pxmitpriv = &padapter->xmitpriv;4744struct xmit_frame *pxmitframe = NULL;4745s32 res;47464747DBG_COUNTER(padapter->tx_logs.core_tx);47484749if (IS_CH_WAITING(adapter_to_rfctl(padapter)))4750return -1;47514752if (rtw_linked_check(padapter) == _FALSE)4753return -1;47544755if (start == 0)4756start = rtw_get_current_time();47574758pxmitframe = rtw_alloc_xmitframe(pxmitpriv);47594760if (rtw_get_passing_time_ms(start) > 2000) {4761if (drop_cnt)4762RTW_INFO("DBG_TX_DROP_FRAME %s no more pxmitframe, drop_cnt:%u\n", __FUNCTION__, drop_cnt);4763start = rtw_get_current_time();4764drop_cnt = 0;4765}47664767if (pxmitframe == NULL) {4768drop_cnt++;4769/*RTW_INFO("%s-"ADPT_FMT" no more xmitframe\n", __func__, ADPT_ARG(padapter));*/4770DBG_COUNTER(padapter->tx_logs.core_tx_err_pxmitframe);4771return -1;4772}47734774#ifdef CONFIG_BR_EXT4775if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) == _TRUE) {4776void *br_port = NULL;47774778#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))4779br_port = padapter->pnetdev->br_port;4780#else4781rcu_read_lock();4782br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);4783rcu_read_unlock();4784#endif47854786if (br_port) {4787res = rtw_br_client_tx(padapter, ppkt);4788if (res == -1) {4789rtw_free_xmitframe(pxmitpriv, pxmitframe);4790DBG_COUNTER(padapter->tx_logs.core_tx_err_brtx);4791return -1;4792}4793}4794}4795#endif /* CONFIG_BR_EXT */47964797#ifdef CONFIG_RTW_MESH4798if (MLME_IS_MESH(padapter)) {4799_list b2u_list;48004801res = rtw_mesh_addr_resolve(padapter, pxmitframe, *ppkt, &b2u_list);4802if (res == RTW_RA_RESOLVING)4803return 1;4804if (res == _FAIL)4805return -1;48064807#if CONFIG_RTW_MESH_DATA_BMC_TO_UC4808if (!rtw_is_list_empty(&b2u_list)) {4809_list *list = get_next(&b2u_list);4810struct xmit_frame *b2uframe;48114812while ((rtw_end_of_queue_search(&b2u_list, list)) == _FALSE) {4813b2uframe = LIST_CONTAINOR(list, struct xmit_frame, list);4814list = get_next(list);4815rtw_list_delete(&b2uframe->list);48164817b2uframe->pkt = rtw_os_pkt_copy(*ppkt);4818if (!b2uframe->pkt) {4819if (res == RTW_BMC_NO_NEED)4820res = _SUCCESS;4821rtw_free_xmitframe(pxmitpriv, b2uframe);4822continue;4823}48244825rtw_xmit_posthandle(padapter, b2uframe, b2uframe->pkt);4826}4827}4828#endif /* CONFIG_RTW_MESH_DATA_BMC_TO_UC */48294830if (res == RTW_BMC_NO_NEED) {4831rtw_free_xmitframe(&padapter->xmitpriv, pxmitframe);4832return 0;4833}4834}4835#endif /* CONFIG_RTW_MESH */48364837pxmitframe->pkt = NULL; /* let rtw_xmit_posthandle not to free pkt inside */4838res = rtw_xmit_posthandle(padapter, pxmitframe, *ppkt);48394840return res;4841}48424843#ifdef CONFIG_TDLS4844sint xmitframe_enqueue_for_tdls_sleeping_sta(_adapter *padapter, struct xmit_frame *pxmitframe)4845{4846sint ret = _FALSE;48474848_irqL irqL;4849struct sta_info *ptdls_sta = NULL;4850struct sta_priv *pstapriv = &padapter->stapriv;4851struct pkt_attrib *pattrib = &pxmitframe->attrib;4852struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);4853int i;48544855ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);4856if (ptdls_sta == NULL)4857return ret;4858else if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {48594860if (pattrib->triggered == 1) {4861ret = _TRUE;4862return ret;4863}48644865_enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);48664867if (ptdls_sta->state & WIFI_SLEEP_STATE) {4868rtw_list_delete(&pxmitframe->list);48694870/* _enter_critical_bh(&psta->sleep_q.lock, &irqL); */48714872rtw_list_insert_tail(&pxmitframe->list, get_list_head(&ptdls_sta->sleep_q));48734874ptdls_sta->sleepq_len++;4875ptdls_sta->sleepq_ac_len++;48764877/* indicate 4-AC queue bit in TDLS peer traffic indication */4878switch (pattrib->priority) {4879case 1:4880case 2:4881ptdls_sta->uapsd_bk |= BIT(1);4882break;4883case 4:4884case 5:4885ptdls_sta->uapsd_vi |= BIT(1);4886break;4887case 6:4888case 7:4889ptdls_sta->uapsd_vo |= BIT(1);4890break;4891case 0:4892case 3:4893default:4894ptdls_sta->uapsd_be |= BIT(1);4895break;4896}48974898/* Transmit TDLS PTI via AP */4899if (ptdls_sta->sleepq_len == 1)4900rtw_tdls_cmd(padapter, ptdls_sta->cmn.mac_addr, TDLS_ISSUE_PTI);49014902ret = _TRUE;4903}49044905_exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);4906}49074908return ret;49094910}4911#endif /* CONFIG_TDLS */49124913#define RTW_HIQ_FILTER_ALLOW_ALL 04914#define RTW_HIQ_FILTER_ALLOW_SPECIAL 14915#define RTW_HIQ_FILTER_DENY_ALL 249164917inline bool xmitframe_hiq_filter(struct xmit_frame *xmitframe)4918{4919bool allow = _FALSE;4920_adapter *adapter = xmitframe->padapter;4921struct registry_priv *registry = &adapter->registrypriv;49224923if (adapter->registrypriv.wifi_spec == 1)4924allow = _TRUE;4925else if (registry->hiq_filter == RTW_HIQ_FILTER_ALLOW_SPECIAL) {49264927struct pkt_attrib *attrib = &xmitframe->attrib;49284929if (attrib->ether_type == 0x08064930|| attrib->ether_type == 0x888e4931#ifdef CONFIG_WAPI_SUPPORT4932|| attrib->ether_type == 0x88B44933#endif4934|| attrib->dhcp_pkt4935) {4936if (0)4937RTW_INFO(FUNC_ADPT_FMT" ether_type:0x%04x%s\n", FUNC_ADPT_ARG(xmitframe->padapter)4938, attrib->ether_type, attrib->dhcp_pkt ? " DHCP" : "");4939allow = _TRUE;4940}4941} else if (registry->hiq_filter == RTW_HIQ_FILTER_ALLOW_ALL)4942allow = _TRUE;4943else if (registry->hiq_filter == RTW_HIQ_FILTER_DENY_ALL)4944allow = _FALSE;4945else4946rtw_warn_on(1);49474948return allow;4949}49504951#if defined(CONFIG_AP_MODE) || defined(CONFIG_TDLS)49524953sint xmitframe_enqueue_for_sleeping_sta(_adapter *padapter, struct xmit_frame *pxmitframe)4954{4955_irqL irqL;4956sint ret = _FALSE;4957struct sta_info *psta = NULL;4958struct sta_priv *pstapriv = &padapter->stapriv;4959struct pkt_attrib *pattrib = &pxmitframe->attrib;4960sint bmcst = IS_MCAST(pattrib->ra);4961bool update_tim = _FALSE;4962#ifdef CONFIG_TDLS49634964if (padapter->tdlsinfo.link_established == _TRUE)4965ret = xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pxmitframe);4966#endif /* CONFIG_TDLS */49674968if (!MLME_IS_AP(padapter) && !MLME_IS_MESH(padapter)) {4969DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_fwstate);4970return ret;4971}4972/*4973if(pattrib->psta)4974{4975psta = pattrib->psta;4976}4977else4978{4979RTW_INFO("%s, call rtw_get_stainfo()\n", __func__);4980psta=rtw_get_stainfo(pstapriv, pattrib->ra);4981}4982*/4983psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);4984if (pattrib->psta != psta) {4985DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_sta);4986RTW_INFO("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);4987return _FALSE;4988}49894990if (psta == NULL) {4991DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_nosta);4992RTW_INFO("%s, psta==NUL\n", __func__);4993return _FALSE;4994}49954996if (!(psta->state & _FW_LINKED)) {4997DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_link);4998RTW_INFO("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);4999return _FALSE;5000}50015002if (pattrib->triggered == 1) {5003DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_trigger);5004/* RTW_INFO("directly xmit pspoll_triggered packet\n"); */50055006/* pattrib->triggered=0; */5007if (bmcst && xmitframe_hiq_filter(pxmitframe) == _TRUE)5008pattrib->qsel = QSLT_HIGH;/* HIQ */50095010return ret;5011}501250135014if (bmcst) {5015_enter_critical_bh(&psta->sleep_q.lock, &irqL);50165017if (rtw_tim_map_anyone_be_set(padapter, pstapriv->sta_dz_bitmap)) { /* if anyone sta is in ps mode */5018/* pattrib->qsel = QSLT_HIGH; */ /* HIQ */50195020rtw_list_delete(&pxmitframe->list);50215022/*_enter_critical_bh(&psta->sleep_q.lock, &irqL);*/50235024rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));50255026psta->sleepq_len++;50275028if (!(rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)))5029update_tim = _TRUE;50305031rtw_tim_map_set(padapter, pstapriv->tim_bitmap, 0);5032rtw_tim_map_set(padapter, pstapriv->sta_dz_bitmap, 0);50335034/* RTW_INFO("enqueue, sq_len=%d\n", psta->sleepq_len); */5035/* RTW_INFO_DUMP("enqueue, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */5036if (update_tim == _TRUE) {5037if (is_broadcast_mac_addr(pattrib->ra))5038_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "buffer BC");5039else5040_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "buffer MC");5041} else5042chk_bmc_sleepq_cmd(padapter);50435044/*_exit_critical_bh(&psta->sleep_q.lock, &irqL);*/50455046ret = _TRUE;50475048DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_mcast);5049}50505051_exit_critical_bh(&psta->sleep_q.lock, &irqL);50525053return ret;50545055}505650575058_enter_critical_bh(&psta->sleep_q.lock, &irqL);50595060if (psta->state & WIFI_SLEEP_STATE) {5061u8 wmmps_ac = 0;50625063if (rtw_tim_map_is_set(padapter, pstapriv->sta_dz_bitmap, psta->cmn.aid)) {5064rtw_list_delete(&pxmitframe->list);50655066/* _enter_critical_bh(&psta->sleep_q.lock, &irqL); */50675068rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));50695070psta->sleepq_len++;50715072switch (pattrib->priority) {5073case 1:5074case 2:5075wmmps_ac = psta->uapsd_bk & BIT(0);5076break;5077case 4:5078case 5:5079wmmps_ac = psta->uapsd_vi & BIT(0);5080break;5081case 6:5082case 7:5083wmmps_ac = psta->uapsd_vo & BIT(0);5084break;5085case 0:5086case 3:5087default:5088wmmps_ac = psta->uapsd_be & BIT(0);5089break;5090}50915092if (wmmps_ac)5093psta->sleepq_ac_len++;50945095if (((psta->has_legacy_ac) && (!wmmps_ac)) || ((!psta->has_legacy_ac) && (wmmps_ac))) {5096if (!(rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid)))5097update_tim = _TRUE;50985099rtw_tim_map_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid);51005101/* RTW_INFO("enqueue, sq_len=%d\n", psta->sleepq_len); */5102/* RTW_INFO_DUMP("enqueue, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */51035104if (update_tim == _TRUE) {5105/* RTW_INFO("sleepq_len==1, update BCNTIM\n"); */5106/* upate BCN for TIM IE */5107_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "buffer UC");5108}5109}51105111/* _exit_critical_bh(&psta->sleep_q.lock, &irqL); */51125113/* if(psta->sleepq_len > (NR_XMITFRAME>>3)) */5114/* { */5115/* wakeup_sta_to_xmit(padapter, psta); */5116/* } */51175118ret = _TRUE;51195120DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_ucast);5121}51225123}51245125_exit_critical_bh(&psta->sleep_q.lock, &irqL);51265127return ret;51285129}51305131static void dequeue_xmitframes_to_sleeping_queue(_adapter *padapter, struct sta_info *psta, _queue *pframequeue)5132{5133sint ret;5134_list *plist, *phead;5135u8 ac_index;5136struct tx_servq *ptxservq;5137struct pkt_attrib *pattrib;5138struct xmit_frame *pxmitframe;5139struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;51405141phead = get_list_head(pframequeue);5142plist = get_next(phead);51435144while (rtw_end_of_queue_search(phead, plist) == _FALSE) {5145pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);51465147plist = get_next(plist);51485149pattrib = &pxmitframe->attrib;51505151pattrib->triggered = 0;51525153ret = xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe);51545155if (_TRUE == ret) {5156ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));51575158ptxservq->qcnt--;5159phwxmits[ac_index].accnt--;5160} else {5161/* RTW_INFO("xmitframe_enqueue_for_sleeping_sta return _FALSE\n"); */5162}51635164}51655166}51675168void stop_sta_xmit(_adapter *padapter, struct sta_info *psta)5169{5170_irqL irqL0;5171struct sta_info *psta_bmc;5172struct sta_xmit_priv *pstaxmitpriv;5173struct sta_priv *pstapriv = &padapter->stapriv;5174struct xmit_priv *pxmitpriv = &padapter->xmitpriv;51755176pstaxmitpriv = &psta->sta_xmitpriv;51775178/* for BC/MC Frames */5179psta_bmc = rtw_get_bcmc_stainfo(padapter);518051815182_enter_critical_bh(&pxmitpriv->lock, &irqL0);51835184psta->state |= WIFI_SLEEP_STATE;51855186#ifdef CONFIG_TDLS5187if (!(psta->tdls_sta_state & TDLS_LINKED_STATE))5188#endif /* CONFIG_TDLS */5189rtw_tim_map_set(padapter, pstapriv->sta_dz_bitmap, psta->cmn.aid);51905191dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);5192rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));5193dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);5194rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));5195dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending);5196rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));5197dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending);5198rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));51995200#ifdef CONFIG_TDLS5201if (!(psta->tdls_sta_state & TDLS_LINKED_STATE) && (psta_bmc != NULL)) {5202#endif /* CONFIG_TDLS */52035204/* for BC/MC Frames */5205pstaxmitpriv = &psta_bmc->sta_xmitpriv;5206dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->vo_q.sta_pending);5207rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));5208dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->vi_q.sta_pending);5209rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));5210dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->be_q.sta_pending);5211rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));5212dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->bk_q.sta_pending);5213rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));52145215#ifdef CONFIG_TDLS5216}5217#endif /* CONFIG_TDLS */5218_exit_critical_bh(&pxmitpriv->lock, &irqL0);521952205221}52225223void wakeup_sta_to_xmit(_adapter *padapter, struct sta_info *psta)5224{5225_irqL irqL;5226u8 update_mask = 0, wmmps_ac = 0;5227struct sta_info *psta_bmc;5228_list *xmitframe_plist, *xmitframe_phead;5229struct xmit_frame *pxmitframe = NULL;5230struct sta_priv *pstapriv = &padapter->stapriv;5231struct xmit_priv *pxmitpriv = &padapter->xmitpriv;52325233psta_bmc = rtw_get_bcmc_stainfo(padapter);523452355236/* _enter_critical_bh(&psta->sleep_q.lock, &irqL); */5237_enter_critical_bh(&pxmitpriv->lock, &irqL);52385239xmitframe_phead = get_list_head(&psta->sleep_q);5240xmitframe_plist = get_next(xmitframe_phead);52415242while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {5243pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);52445245xmitframe_plist = get_next(xmitframe_plist);52465247rtw_list_delete(&pxmitframe->list);52485249switch (pxmitframe->attrib.priority) {5250case 1:5251case 2:5252wmmps_ac = psta->uapsd_bk & BIT(1);5253break;5254case 4:5255case 5:5256wmmps_ac = psta->uapsd_vi & BIT(1);5257break;5258case 6:5259case 7:5260wmmps_ac = psta->uapsd_vo & BIT(1);5261break;5262case 0:5263case 3:5264default:5265wmmps_ac = psta->uapsd_be & BIT(1);5266break;5267}52685269psta->sleepq_len--;5270if (psta->sleepq_len > 0)5271pxmitframe->attrib.mdata = 1;5272else5273pxmitframe->attrib.mdata = 0;52745275if (wmmps_ac) {5276psta->sleepq_ac_len--;5277if (psta->sleepq_ac_len > 0) {5278pxmitframe->attrib.mdata = 1;5279pxmitframe->attrib.eosp = 0;5280} else {5281pxmitframe->attrib.mdata = 0;5282pxmitframe->attrib.eosp = 1;5283}5284}52855286pxmitframe->attrib.triggered = 1;52875288/*5289_exit_critical_bh(&psta->sleep_q.lock, &irqL);5290if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)5291{5292rtw_os_xmit_complete(padapter, pxmitframe);5293}5294_enter_critical_bh(&psta->sleep_q.lock, &irqL);5295*/5296rtw_hal_xmitframe_enqueue(padapter, pxmitframe);529752985299}53005301if (psta->sleepq_len == 0) {5302#ifdef CONFIG_TDLS5303if (psta->tdls_sta_state & TDLS_LINKED_STATE) {5304if (psta->state & WIFI_SLEEP_STATE)5305psta->state ^= WIFI_SLEEP_STATE;53065307_exit_critical_bh(&pxmitpriv->lock, &irqL);5308return;5309}5310#endif /* CONFIG_TDLS */53115312if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, psta->cmn.aid)) {5313/* RTW_INFO("wakeup to xmit, qlen==0\n"); */5314/* RTW_INFO_DUMP("update_BCNTIM, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */5315/* upate BCN for TIM IE */5316/* update_BCNTIM(padapter); */5317update_mask = BIT(0);5318}53195320rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid);53215322if (psta->state & WIFI_SLEEP_STATE)5323psta->state ^= WIFI_SLEEP_STATE;53245325if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {5326RTW_INFO("%s alive check\n", __func__);5327psta->expire_to = pstapriv->expire_to;5328psta->state ^= WIFI_STA_ALIVE_CHK_STATE;5329}53305331rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, psta->cmn.aid);5332}53335334/* for BC/MC Frames */5335if (!psta_bmc)5336goto _exit;53375338if (!(rtw_tim_map_anyone_be_set_exclude_aid0(padapter, pstapriv->sta_dz_bitmap))) { /* no any sta in ps mode */5339xmitframe_phead = get_list_head(&psta_bmc->sleep_q);5340xmitframe_plist = get_next(xmitframe_phead);53415342while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {5343pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);53445345xmitframe_plist = get_next(xmitframe_plist);53465347rtw_list_delete(&pxmitframe->list);53485349psta_bmc->sleepq_len--;5350if (psta_bmc->sleepq_len > 0)5351pxmitframe->attrib.mdata = 1;5352else5353pxmitframe->attrib.mdata = 0;535453555356pxmitframe->attrib.triggered = 1;5357/*5358_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);5359if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)5360{5361rtw_os_xmit_complete(padapter, pxmitframe);5362}5363_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);53645365*/5366rtw_hal_xmitframe_enqueue(padapter, pxmitframe);53675368}53695370if (psta_bmc->sleepq_len == 0) {5371if (rtw_tim_map_is_set(padapter, pstapriv->tim_bitmap, 0)) {5372/* RTW_INFO("wakeup to xmit, qlen==0\n"); */5373/* RTW_INFO_DUMP("update_BCNTIM, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */5374/* upate BCN for TIM IE */5375/* update_BCNTIM(padapter); */5376update_mask |= BIT(1);5377}5378rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, 0);5379rtw_tim_map_clear(padapter, pstapriv->sta_dz_bitmap, 0);5380}53815382}53835384_exit:53855386/* _exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL); */5387_exit_critical_bh(&pxmitpriv->lock, &irqL);53885389if (update_mask) {5390/* update_BCNTIM(padapter); */5391if ((update_mask & (BIT(0) | BIT(1))) == (BIT(0) | BIT(1)))5392_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "clear UC&BMC");5393else if ((update_mask & BIT(1)) == BIT(1))5394_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "clear BMC");5395else5396_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0, "clear UC");5397}53985399}54005401void xmit_delivery_enabled_frames(_adapter *padapter, struct sta_info *psta)5402{5403_irqL irqL;5404u8 wmmps_ac = 0;5405_list *xmitframe_plist, *xmitframe_phead;5406struct xmit_frame *pxmitframe = NULL;5407struct sta_priv *pstapriv = &padapter->stapriv;5408struct xmit_priv *pxmitpriv = &padapter->xmitpriv;540954105411/* _enter_critical_bh(&psta->sleep_q.lock, &irqL); */5412_enter_critical_bh(&pxmitpriv->lock, &irqL);54135414xmitframe_phead = get_list_head(&psta->sleep_q);5415xmitframe_plist = get_next(xmitframe_phead);54165417while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {5418pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);54195420xmitframe_plist = get_next(xmitframe_plist);54215422switch (pxmitframe->attrib.priority) {5423case 1:5424case 2:5425wmmps_ac = psta->uapsd_bk & BIT(1);5426break;5427case 4:5428case 5:5429wmmps_ac = psta->uapsd_vi & BIT(1);5430break;5431case 6:5432case 7:5433wmmps_ac = psta->uapsd_vo & BIT(1);5434break;5435case 0:5436case 3:5437default:5438wmmps_ac = psta->uapsd_be & BIT(1);5439break;5440}54415442if (!wmmps_ac)5443continue;54445445rtw_list_delete(&pxmitframe->list);54465447psta->sleepq_len--;5448psta->sleepq_ac_len--;54495450if (psta->sleepq_ac_len > 0) {5451pxmitframe->attrib.mdata = 1;5452pxmitframe->attrib.eosp = 0;5453} else {5454pxmitframe->attrib.mdata = 0;5455pxmitframe->attrib.eosp = 1;5456}54575458pxmitframe->attrib.triggered = 1;5459rtw_hal_xmitframe_enqueue(padapter, pxmitframe);54605461if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) {5462#ifdef CONFIG_TDLS5463if (psta->tdls_sta_state & TDLS_LINKED_STATE) {5464/* _exit_critical_bh(&psta->sleep_q.lock, &irqL); */5465goto exit;5466}5467#endif /* CONFIG_TDLS */5468rtw_tim_map_clear(padapter, pstapriv->tim_bitmap, psta->cmn.aid);54695470/* RTW_INFO("wakeup to xmit, qlen==0\n"); */5471/* RTW_INFO_DUMP("update_BCNTIM, tim=", pstapriv->tim_bitmap, pstapriv->aid_bmp_len); */5472/* upate BCN for TIM IE */5473/* update_BCNTIM(padapter); */5474update_beacon(padapter, _TIM_IE_, NULL, _TRUE, 0);5475/* update_mask = BIT(0); */5476}54775478}54795480#ifdef CONFIG_TDLS5481exit:5482#endif5483/* _exit_critical_bh(&psta->sleep_q.lock, &irqL); */5484_exit_critical_bh(&pxmitpriv->lock, &irqL);54855486return;5487}54885489#endif /* defined(CONFIG_AP_MODE) || defined(CONFIG_TDLS) */54905491#ifdef CONFIG_XMIT_THREAD_MODE5492void enqueue_pending_xmitbuf(5493struct xmit_priv *pxmitpriv,5494struct xmit_buf *pxmitbuf)5495{5496_irqL irql;5497_queue *pqueue;5498_adapter *pri_adapter = pxmitpriv->adapter;54995500pqueue = &pxmitpriv->pending_xmitbuf_queue;55015502_enter_critical_bh(&pqueue->lock, &irql);5503rtw_list_delete(&pxmitbuf->list);5504rtw_list_insert_tail(&pxmitbuf->list, get_list_head(pqueue));5505_exit_critical_bh(&pqueue->lock, &irql);55065507#if defined(CONFIG_SDIO_HCI) && defined(CONFIG_CONCURRENT_MODE)5508pri_adapter = GET_PRIMARY_ADAPTER(pri_adapter);5509#endif /*SDIO_HCI + CONCURRENT*/5510_rtw_up_sema(&(pri_adapter->xmitpriv.xmit_sema));5511}55125513void enqueue_pending_xmitbuf_to_head(5514struct xmit_priv *pxmitpriv,5515struct xmit_buf *pxmitbuf)5516{5517_irqL irql;5518_queue *pqueue = &pxmitpriv->pending_xmitbuf_queue;55195520_enter_critical_bh(&pqueue->lock, &irql);5521rtw_list_delete(&pxmitbuf->list);5522rtw_list_insert_head(&pxmitbuf->list, get_list_head(pqueue));5523_exit_critical_bh(&pqueue->lock, &irql);5524}55255526struct xmit_buf *dequeue_pending_xmitbuf(5527struct xmit_priv *pxmitpriv)5528{5529_irqL irql;5530struct xmit_buf *pxmitbuf;5531_queue *pqueue;553255335534pxmitbuf = NULL;5535pqueue = &pxmitpriv->pending_xmitbuf_queue;55365537_enter_critical_bh(&pqueue->lock, &irql);55385539if (_rtw_queue_empty(pqueue) == _FALSE) {5540_list *plist, *phead;55415542phead = get_list_head(pqueue);5543plist = get_next(phead);5544pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);5545rtw_list_delete(&pxmitbuf->list);5546}55475548_exit_critical_bh(&pqueue->lock, &irql);55495550return pxmitbuf;5551}55525553static struct xmit_buf *dequeue_pending_xmitbuf_ext(5554struct xmit_priv *pxmitpriv)5555{5556_irqL irql;5557struct xmit_buf *pxmitbuf;5558_queue *pqueue;55595560pxmitbuf = NULL;5561pqueue = &pxmitpriv->pending_xmitbuf_queue;55625563_enter_critical_bh(&pqueue->lock, &irql);55645565if (_rtw_queue_empty(pqueue) == _FALSE) {5566_list *plist, *phead;55675568phead = get_list_head(pqueue);5569plist = phead;5570do {5571plist = get_next(plist);5572if (plist == phead)5573break;55745575pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);55765577if (pxmitbuf->buf_tag == XMITBUF_MGNT) {5578rtw_list_delete(&pxmitbuf->list);5579break;5580}5581pxmitbuf = NULL;5582} while (1);5583}55845585_exit_critical_bh(&pqueue->lock, &irql);55865587return pxmitbuf;5588}55895590struct xmit_buf *select_and_dequeue_pending_xmitbuf(_adapter *padapter)5591{5592struct xmit_priv *pxmitpriv = &padapter->xmitpriv;5593struct xmit_buf *pxmitbuf = NULL;55945595if (_TRUE == rtw_is_xmit_blocked(padapter))5596return pxmitbuf;55975598pxmitbuf = dequeue_pending_xmitbuf_ext(pxmitpriv);5599if (pxmitbuf == NULL && rtw_xmit_ac_blocked(padapter) != _TRUE)5600pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);56015602return pxmitbuf;5603}56045605sint check_pending_xmitbuf(5606struct xmit_priv *pxmitpriv)5607{5608_irqL irql;5609_queue *pqueue;5610sint ret = _FALSE;56115612pqueue = &pxmitpriv->pending_xmitbuf_queue;56135614_enter_critical_bh(&pqueue->lock, &irql);56155616if (_rtw_queue_empty(pqueue) == _FALSE)5617ret = _TRUE;56185619_exit_critical_bh(&pqueue->lock, &irql);56205621return ret;5622}56235624thread_return rtw_xmit_thread(thread_context context)5625{5626s32 err;5627PADAPTER padapter;5628#ifdef RTW_XMIT_THREAD_HIGH_PRIORITY5629#ifdef PLATFORM_LINUX5630struct sched_param param = { .sched_priority = 1 };56315632sched_setscheduler(current, SCHED_FIFO, ¶m);5633#endif /* PLATFORM_LINUX */5634#endif /* RTW_XMIT_THREAD_HIGH_PRIORITY */56355636err = _SUCCESS;5637padapter = (PADAPTER)context;56385639thread_enter("RTW_XMIT_THREAD");56405641do {5642err = rtw_hal_xmit_thread_handler(padapter);5643flush_signals_thread();5644} while (_SUCCESS == err);56455646RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(padapter));56475648rtw_thread_wait_stop();56495650return 0;5651}5652#endif56535654#ifdef DBG_XMIT_BLOCK5655void dump_xmit_block(void *sel, _adapter *padapter)5656{5657struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);56585659RTW_PRINT_SEL(sel, "[XMIT-BLOCK] xmit_block :0x%02x\n", dvobj->xmit_block);5660if (dvobj->xmit_block & XMIT_BLOCK_REDLMEM)5661RTW_PRINT_SEL(sel, "Reason:%s\n", "XMIT_BLOCK_REDLMEM");5662if (dvobj->xmit_block & XMIT_BLOCK_SUSPEND)5663RTW_PRINT_SEL(sel, "Reason:%s\n", "XMIT_BLOCK_SUSPEND");5664if (dvobj->xmit_block == XMIT_BLOCK_NONE)5665RTW_PRINT_SEL(sel, "Reason:%s\n", "XMIT_BLOCK_NONE");5666}5667void dump_xmit_block_info(void *sel, const char *fun_name, _adapter *padapter)5668{5669struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);56705671RTW_INFO("\n"ADPT_FMT" call %s\n", ADPT_ARG(padapter), fun_name);5672dump_xmit_block(sel, padapter);5673}5674#define DBG_XMIT_BLOCK_DUMP(adapter) dump_xmit_block_info(RTW_DBGDUMP, __func__, adapter)5675#endif56765677void rtw_set_xmit_block(_adapter *padapter, enum XMIT_BLOCK_REASON reason)5678{5679_irqL irqL;5680struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);56815682_enter_critical_bh(&dvobj->xmit_block_lock, &irqL);5683dvobj->xmit_block |= reason;5684_exit_critical_bh(&dvobj->xmit_block_lock, &irqL);56855686#ifdef DBG_XMIT_BLOCK5687DBG_XMIT_BLOCK_DUMP(padapter);5688#endif5689}56905691void rtw_clr_xmit_block(_adapter *padapter, enum XMIT_BLOCK_REASON reason)5692{5693_irqL irqL;5694struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);56955696_enter_critical_bh(&dvobj->xmit_block_lock, &irqL);5697dvobj->xmit_block &= ~reason;5698_exit_critical_bh(&dvobj->xmit_block_lock, &irqL);56995700#ifdef DBG_XMIT_BLOCK5701DBG_XMIT_BLOCK_DUMP(padapter);5702#endif5703}5704bool rtw_is_xmit_blocked(_adapter *padapter)5705{5706struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);57075708#ifdef DBG_XMIT_BLOCK5709DBG_XMIT_BLOCK_DUMP(padapter);5710#endif5711return ((dvobj->xmit_block) ? _TRUE : _FALSE);5712}57135714bool rtw_xmit_ac_blocked(_adapter *adapter)5715{5716struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);5717struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);5718_adapter *iface;5719struct mlme_ext_priv *mlmeext;5720bool blocked = _FALSE;5721int i;5722#ifdef DBG_CONFIG_ERROR_DETECT5723#ifdef DBG_CONFIG_ERROR_RESET5724#ifdef CONFIG_USB_HCI5725if (rtw_hal_sreset_inprogress(adapter) == _TRUE) {5726blocked = _TRUE;5727goto exit;5728}5729#endif/* #ifdef CONFIG_USB_HCI */5730#endif/* #ifdef DBG_CONFIG_ERROR_RESET */5731#endif/* #ifdef DBG_CONFIG_ERROR_DETECT */57325733if (rfctl->offch_state != OFFCHS_NONE5734#ifdef CONFIG_DFS5735|| IS_RADAR_DETECTED(rfctl) || rfctl->csa_ch5736#endif5737) {5738blocked = _TRUE;5739goto exit;5740}57415742for (i = 0; i < dvobj->iface_nums; i++) {5743iface = dvobj->padapters[i];5744mlmeext = &iface->mlmeextpriv;57455746/* check scan state */5747if (mlmeext_scan_state(mlmeext) != SCAN_DISABLE5748&& mlmeext_scan_state(mlmeext) != SCAN_BACK_OP5749) {5750blocked = _TRUE;5751goto exit;5752}57535754if (mlmeext_scan_state(mlmeext) == SCAN_BACK_OP5755&& !mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_TX_RESUME)5756) {5757blocked = _TRUE;5758goto exit;5759}5760}57615762#ifdef CONFIG_MCC_MODE5763if (MCC_EN(adapter)) {5764if (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {5765if (MCC_STOP(adapter)) {5766blocked = _TRUE;5767goto exit;5768}5769}5770}5771#endif /* CONFIG_MCC_MODE */57725773exit:5774return blocked;5775}57765777#ifdef CONFIG_TX_AMSDU5778void rtw_amsdu_vo_timeout_handler(void *FunctionContext)5779{5780_adapter *adapter = (_adapter *)FunctionContext;57815782adapter->xmitpriv.amsdu_vo_timeout = RTW_AMSDU_TIMER_TIMEOUT;57835784tasklet_hi_schedule(&adapter->xmitpriv.xmit_tasklet);5785}57865787void rtw_amsdu_vi_timeout_handler(void *FunctionContext)5788{5789_adapter *adapter = (_adapter *)FunctionContext;57905791adapter->xmitpriv.amsdu_vi_timeout = RTW_AMSDU_TIMER_TIMEOUT;57925793tasklet_hi_schedule(&adapter->xmitpriv.xmit_tasklet);5794}57955796void rtw_amsdu_be_timeout_handler(void *FunctionContext)5797{5798_adapter *adapter = (_adapter *)FunctionContext;57995800adapter->xmitpriv.amsdu_be_timeout = RTW_AMSDU_TIMER_TIMEOUT;58015802if (printk_ratelimit())5803RTW_INFO("%s Timeout!\n",__FUNCTION__);58045805tasklet_hi_schedule(&adapter->xmitpriv.xmit_tasklet);5806}58075808void rtw_amsdu_bk_timeout_handler(void *FunctionContext)5809{5810_adapter *adapter = (_adapter *)FunctionContext;58115812adapter->xmitpriv.amsdu_bk_timeout = RTW_AMSDU_TIMER_TIMEOUT;58135814tasklet_hi_schedule(&adapter->xmitpriv.xmit_tasklet);5815}58165817u8 rtw_amsdu_get_timer_status(_adapter *padapter, u8 priority)5818{5819struct xmit_priv *pxmitpriv = &padapter->xmitpriv;58205821u8 status = RTW_AMSDU_TIMER_UNSET;58225823switch(priority)5824{5825case 1:5826case 2:5827status = pxmitpriv->amsdu_bk_timeout;5828break;5829case 4:5830case 5:5831status = pxmitpriv->amsdu_vi_timeout;5832break;5833case 6:5834case 7:5835status = pxmitpriv->amsdu_vo_timeout;5836break;5837case 0:5838case 3:5839default:5840status = pxmitpriv->amsdu_be_timeout;5841break;5842}5843return status;5844}58455846void rtw_amsdu_set_timer_status(_adapter *padapter, u8 priority, u8 status)5847{5848struct xmit_priv *pxmitpriv = &padapter->xmitpriv;58495850switch(priority)5851{5852case 1:5853case 2:5854pxmitpriv->amsdu_bk_timeout = status;5855break;5856case 4:5857case 5:5858pxmitpriv->amsdu_vi_timeout = status;5859break;5860case 6:5861case 7:5862pxmitpriv->amsdu_vo_timeout = status;5863break;5864case 0:5865case 3:5866default:5867pxmitpriv->amsdu_be_timeout = status;5868break;5869}5870}58715872void rtw_amsdu_set_timer(_adapter *padapter, u8 priority)5873{5874struct xmit_priv *pxmitpriv = &padapter->xmitpriv;58755876_timer* amsdu_timer = NULL;58775878switch(priority)5879{5880case 1:5881case 2:5882amsdu_timer = &pxmitpriv->amsdu_bk_timer;5883break;5884case 4:5885case 5:5886amsdu_timer = &pxmitpriv->amsdu_vi_timer;5887break;5888case 6:5889case 7:5890amsdu_timer = &pxmitpriv->amsdu_vo_timer;5891break;5892case 0:5893case 3:5894default:5895amsdu_timer = &pxmitpriv->amsdu_be_timer;5896break;5897}5898_set_timer(amsdu_timer, 1);5899}59005901void rtw_amsdu_cancel_timer(_adapter *padapter, u8 priority)5902{5903struct xmit_priv *pxmitpriv = &padapter->xmitpriv;5904_timer* amsdu_timer = NULL;59055906switch(priority)5907{5908case 1:5909case 2:5910amsdu_timer = &pxmitpriv->amsdu_bk_timer;5911break;5912case 4:5913case 5:5914amsdu_timer = &pxmitpriv->amsdu_vi_timer;5915break;5916case 6:5917case 7:5918amsdu_timer = &pxmitpriv->amsdu_vo_timer;5919break;5920case 0:5921case 3:5922default:5923amsdu_timer = &pxmitpriv->amsdu_be_timer;5924break;5925}5926_cancel_timer_ex(amsdu_timer);5927}5928#endif /* CONFIG_TX_AMSDU */59295930#ifdef DBG_TXBD_DESC_DUMP5931static struct rtw_tx_desc_backup tx_backup[HW_QUEUE_ENTRY][TX_BAK_FRMAE_CNT];5932static u8 backup_idx[HW_QUEUE_ENTRY];59335934void rtw_tx_desc_backup(_adapter *padapter, struct xmit_frame *pxmitframe, u8 desc_size, u8 hwq)5935{5936u32 tmp32;5937u8 *pxmit_buf;59385939if (rtw_get_hw_init_completed(padapter) == _FALSE)5940return;59415942pxmit_buf = pxmitframe->pxmitbuf->pbuf;59435944_rtw_memcpy(tx_backup[hwq][backup_idx[hwq]].tx_bak_desc, pxmit_buf, desc_size);5945_rtw_memcpy(tx_backup[hwq][backup_idx[hwq]].tx_bak_data_hdr, pxmit_buf+desc_size, TX_BAK_DATA_LEN);59465947tmp32 = rtw_read32(padapter, get_txbd_rw_reg(hwq));59485949tx_backup[hwq][backup_idx[hwq]].tx_bak_rp = (tmp32>>16)&0xfff;5950tx_backup[hwq][backup_idx[hwq]].tx_bak_wp = tmp32&0xfff;59515952tx_backup[hwq][backup_idx[hwq]].tx_desc_size = desc_size;59535954backup_idx[hwq] = (backup_idx[hwq] + 1) % TX_BAK_FRMAE_CNT;5955}59565957void rtw_tx_desc_backup_reset(void)5958{5959int i, j;59605961for (i = 0; i < HW_QUEUE_ENTRY; i++) {5962for (j = 0; j < TX_BAK_FRMAE_CNT; j++)5963_rtw_memset(&tx_backup[i][j], 0, sizeof(struct rtw_tx_desc_backup));59645965backup_idx[i] = 0;5966}5967}59685969u8 rtw_get_tx_desc_backup(_adapter *padapter, u8 hwq, struct rtw_tx_desc_backup **pbak)5970{5971*pbak = &tx_backup[hwq][0];59725973return backup_idx[hwq];5974}5975#endif59765977#ifdef CONFIG_PCI_TX_POLLING5978void rtw_tx_poll_init(_adapter *padapter)5979{5980struct xmit_priv *pxmitpriv = &padapter->xmitpriv;5981_timer* timer = &pxmitpriv->tx_poll_timer;59825983if (!is_primary_adapter(padapter))5984return;59855986if (timer->function != NULL) {5987RTW_INFO("tx polling timer has been init.\n");5988return;5989}59905991rtw_init_timer(timer, padapter, rtw_tx_poll_timeout_handler, padapter);5992rtw_tx_poll_timer_set(padapter, 1);5993RTW_INFO("Tx poll timer init!\n");5994}59955996void rtw_tx_poll_timeout_handler(void *FunctionContext)5997{5998_adapter *adapter = (_adapter *)FunctionContext;59996000rtw_tx_poll_timer_set(adapter, 1);60016002if (adapter->hal_func.tx_poll_handler)6003adapter->hal_func.tx_poll_handler(adapter);6004else6005RTW_WARN("hal ops: tx_poll_handler is NULL\n");6006}60076008void rtw_tx_poll_timer_set(_adapter *padapter, u32 delay)6009{6010struct xmit_priv *pxmitpriv = &padapter->xmitpriv;6011_timer* timer = NULL;60126013timer = &pxmitpriv->tx_poll_timer;6014_set_timer(timer, delay);6015}60166017void rtw_tx_poll_timer_cancel(_adapter *padapter)6018{6019struct xmit_priv *pxmitpriv = &padapter->xmitpriv;6020_timer* timer = NULL;60216022if (!is_primary_adapter(padapter))6023return;60246025timer = &pxmitpriv->tx_poll_timer;6026_cancel_timer_ex(timer);6027timer->function = NULL;6028RTW_INFO("Tx poll timer cancel !\n");6029}6030#endif /* CONFIG_PCI_TX_POLLING */60316032void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms)6033{6034sctx->timeout_ms = timeout_ms;6035sctx->submit_time = rtw_get_current_time();6036#ifdef PLATFORM_LINUX /* TODO: add condition wating interface for other os */6037init_completion(&sctx->done);6038#endif6039sctx->status = RTW_SCTX_SUBMITTED;6040}60416042int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg)6043{6044int ret = _FAIL;6045unsigned long expire;6046int status = 0;60476048#ifdef PLATFORM_LINUX6049expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : MAX_SCHEDULE_TIMEOUT;6050if (!wait_for_completion_timeout(&sctx->done, expire)) {6051/* timeout, do something?? */6052status = RTW_SCTX_DONE_TIMEOUT;6053RTW_INFO("%s timeout: %s\n", __func__, msg);6054} else6055status = sctx->status;6056#endif60576058if (status == RTW_SCTX_DONE_SUCCESS)6059ret = _SUCCESS;60606061return ret;6062}60636064bool rtw_sctx_chk_waring_status(int status)6065{6066switch (status) {6067case RTW_SCTX_DONE_UNKNOWN:6068case RTW_SCTX_DONE_BUF_ALLOC:6069case RTW_SCTX_DONE_BUF_FREE:60706071case RTW_SCTX_DONE_DRV_STOP:6072case RTW_SCTX_DONE_DEV_REMOVE:6073return _TRUE;6074default:6075return _FALSE;6076}6077}60786079void rtw_sctx_done_err(struct submit_ctx **sctx, int status)6080{6081if (*sctx) {6082if (rtw_sctx_chk_waring_status(status))6083RTW_INFO("%s status:%d\n", __func__, status);6084(*sctx)->status = status;6085#ifdef PLATFORM_LINUX6086complete(&((*sctx)->done));6087#endif6088*sctx = NULL;6089}6090}60916092void rtw_sctx_done(struct submit_ctx **sctx)6093{6094rtw_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);6095}60966097#ifdef CONFIG_XMIT_ACK6098int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms)6099{6100struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;61016102pack_tx_ops->submit_time = rtw_get_current_time();6103pack_tx_ops->timeout_ms = timeout_ms;6104pack_tx_ops->status = RTW_SCTX_SUBMITTED;61056106return rtw_sctx_wait(pack_tx_ops, __func__);6107}61086109void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status)6110{6111struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;61126113if (pxmitpriv->ack_tx)6114rtw_sctx_done_err(&pack_tx_ops, status);6115else6116RTW_INFO("%s ack_tx not set\n", __func__);6117}6118#endif /* CONFIG_XMIT_ACK */611961206121