diff options
Diffstat (limited to 'drivers/staging/rtl8723au/core/rtw_xmit.c')
-rw-r--r-- | drivers/staging/rtl8723au/core/rtw_xmit.c | 2341 |
1 files changed, 0 insertions, 2341 deletions
diff --git a/drivers/staging/rtl8723au/core/rtw_xmit.c b/drivers/staging/rtl8723au/core/rtw_xmit.c deleted file mode 100644 index 3de40cfa5f3b..000000000000 --- a/drivers/staging/rtl8723au/core/rtw_xmit.c +++ /dev/null @@ -1,2341 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - ******************************************************************************/ -#define _RTW_XMIT_C_ - -#include <osdep_service.h> -#include <drv_types.h> -#include <wifi.h> -#include <osdep_intf.h> -#include <linux/ip.h> -#include <usb_ops.h> -#include <rtl8723a_xmit.h> - -static void _init_txservq(struct tx_servq *ptxservq) -{ - - INIT_LIST_HEAD(&ptxservq->tx_pending); - _rtw_init_queue23a(&ptxservq->sta_pending); - ptxservq->qcnt = 0; - -} - -void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv) -{ - - spin_lock_init(&psta_xmitpriv->lock); - - /* for (i = 0 ; i < MAX_NUMBLKS; i++) */ - /* _init_txservq(&psta_xmitpriv->blk_q[i]); */ - - _init_txservq(&psta_xmitpriv->be_q); - _init_txservq(&psta_xmitpriv->bk_q); - _init_txservq(&psta_xmitpriv->vi_q); - _init_txservq(&psta_xmitpriv->vo_q); - INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz); - INIT_LIST_HEAD(&psta_xmitpriv->apsd); - -} - -int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv, - struct rtw_adapter *padapter) -{ - int i; - struct xmit_buf *pxmitbuf; - struct xmit_frame *pxframe; - int res = _SUCCESS; - u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ; - u32 num_xmit_extbuf = NR_XMIT_EXTBUFF; - - spin_lock_init(&pxmitpriv->lock); - spin_lock_init(&pxmitpriv->lock_sctx); - sema_init(&pxmitpriv->xmit_sema, 0); - sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); - - pxmitpriv->adapter = padapter; - - _rtw_init_queue23a(&pxmitpriv->be_pending); - _rtw_init_queue23a(&pxmitpriv->bk_pending); - _rtw_init_queue23a(&pxmitpriv->vi_pending); - _rtw_init_queue23a(&pxmitpriv->vo_pending); - _rtw_init_queue23a(&pxmitpriv->bm_pending); - - _rtw_init_queue23a(&pxmitpriv->free_xmit_queue); - - for (i = 0; i < NR_XMITFRAME; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xmit_queue.queue); - } - - pxmitpriv->free_xmitframe_cnt = i; - - pxmitpriv->frag_len = MAX_FRAG_THRESHOLD; - - /* init xmit_buf */ - _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list); - _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue); - - for (i = 0; i < NR_XMITBUFF; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { - goto fail; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmitbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitbuf_list); - } - - pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF; - - /* init xframe_ext queue, the same count as extbuf */ - _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxframe = kzalloc(sizeof(struct xmit_frame), GFP_KERNEL); - if (!pxframe) - break; - INIT_LIST_HEAD(&pxframe->list); - - pxframe->padapter = padapter; - pxframe->frame_tag = NULL_FRAMETAG; - - pxframe->pkt = NULL; - - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - pxframe->ext_tag = 1; - - list_add_tail(&pxframe->list, - &pxmitpriv->free_xframe_ext_queue.queue); - } - pxmitpriv->free_xframe_ext_cnt = i; - - /* Init xmit extension buff */ - _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue); - INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list); - - for (i = 0; i < num_xmit_extbuf; i++) { - pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL); - if (!pxmitbuf) - goto fail; - INIT_LIST_HEAD(&pxmitbuf->list); - INIT_LIST_HEAD(&pxmitbuf->list2); - - pxmitbuf->padapter = padapter; - - /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf, - max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); - if (res == _FAIL) { - goto exit; - } - - list_add_tail(&pxmitbuf->list, - &pxmitpriv->free_xmit_extbuf_queue.queue); - list_add_tail(&pxmitbuf->list2, - &pxmitpriv->xmitextbuf_list); - } - - pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; - - rtw_alloc_hwxmits23a(padapter); - rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); - - for (i = 0; i < 4; i ++) - pxmitpriv->wmm_para_seq[i] = i; - - sema_init(&pxmitpriv->tx_retevt, 0); - - pxmitpriv->ack_tx = false; - mutex_init(&pxmitpriv->ack_tx_mutex); - rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0); - tasklet_init(&padapter->xmitpriv.xmit_tasklet, - (void(*)(unsigned long))rtl8723au_xmit_tasklet, - (unsigned long)padapter); - -exit: - - return res; -fail: - goto exit; -} - -void _rtw_free_xmit_priv23a(struct xmit_priv *pxmitpriv) -{ - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct xmit_frame *pxframe, *ptmp; - struct xmit_buf *pxmitbuf, *ptmp2; - - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xmit_queue.queue, list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - /* free xframe_ext queue, the same count as extbuf */ - list_for_each_entry_safe(pxframe, ptmp, - &pxmitpriv->free_xframe_ext_queue.queue, - list) { - list_del_init(&pxframe->list); - rtw_os_xmit_complete23a(padapter, pxframe); - kfree(pxframe); - } - - /* free xmit extension buff */ - list_for_each_entry_safe(pxmitbuf, ptmp2, - &pxmitpriv->xmitextbuf_list, list2) { - list_del_init(&pxmitbuf->list2); - rtw_os_xmit_resource_free23a(padapter, pxmitbuf); - kfree(pxmitbuf); - } - - rtw_free_hwxmits23a(padapter); - mutex_destroy(&pxmitpriv->ack_tx_mutex); -} - -static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - u32 sz; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_info *psta = pattrib->psta; - struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv; - struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return; - } - - if (pattrib->nr_frags != 1) - sz = padapter->xmitpriv.frag_len; - else /* no frag */ - sz = pattrib->last_txcmdsz; - - /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */ - /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */ - /* Other fragments are protected by previous fragment. */ - /* So we only need to check the length of first fragment. */ - if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) { - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - } else { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS; - } - } else { - while (true) { - /* IOT action */ - if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS && - pattrib->ampdu_en && - padapter->securitypriv.dot11PrivacyAlgrthm == - WLAN_CIPHER_SUITE_CCMP) { - pattrib->vcs_mode = CTS_TO_SELF; - break; - } - - /* check ERP protection */ - if (psta->rtsen || psta->cts2self) { - if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - - break; - } - - /* check HT op mode */ - if (pattrib->ht_en) { - u8 HTOpMode = pmlmeinfo->HT_protection; - - if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) || - (!pmlmeext->cur_bwmode && HTOpMode == 3)) { - pattrib->vcs_mode = RTS_CTS; - break; - } - } - - /* check rts */ - if (sz > padapter->registrypriv.rts_thresh) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - /* to do list: check MIMO power save condition. */ - - /* check AMPDU aggregation for TXOP */ - if (pattrib->ampdu_en) { - pattrib->vcs_mode = RTS_CTS; - break; - } - - pattrib->vcs_mode = NONE_VCS; - break; - } - } -} - -static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta) -{ - /*if (psta->rtsen) - pattrib->vcs_mode = RTS_CTS; - else if (psta->cts2self) - pattrib->vcs_mode = CTS_TO_SELF; - else - pattrib->vcs_mode = NONE_VCS;*/ - - pattrib->mdata = 0; - pattrib->eosp = 0; - pattrib->triggered = 0; - - /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */ - pattrib->qos_en = psta->qos_option; - - pattrib->raid = psta->raid; - pattrib->ht_en = psta->htpriv.ht_option; - pattrib->bwmode = psta->htpriv.bwmode; - pattrib->ch_offset = psta->htpriv.ch_offset; - pattrib->sgi = psta->htpriv.sgi; - pattrib->ampdu_en = false; - - pattrib->retry_ctrl = false; -} - -u8 qos_acm23a(u8 acm_mask, u8 priority) -{ - u8 change_priority = priority; - - switch (priority) { - case 0: - case 3: - if (acm_mask & BIT(1)) - change_priority = 1; - break; - case 1: - case 2: - break; - case 4: - case 5: - if (acm_mask & BIT(2)) - change_priority = 0; - break; - case 6: - case 7: - if (acm_mask & BIT(3)) - change_priority = 5; - break; - default: - DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n", - priority); - change_priority = 0; - break; - } - - return change_priority; -} - -static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - u8 *pframe = skb->data; - struct iphdr *ip_hdr; - u8 UserPriority = 0; - - /* get UserPriority from IP hdr */ - if (pattrib->ether_type == ETH_P_IP) { - ip_hdr = (struct iphdr *)(pframe + ETH_HLEN); - UserPriority = ip_hdr->tos >> 5; - } else if (pattrib->ether_type == ETH_P_PAE) { - /* "When priority processing of data frames is supported, */ - /* a STA's SME should send EAPOL-Key frames at the highest - priority." */ - UserPriority = 7; - } - - pattrib->priority = UserPriority; - pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr); - pattrib->type = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA; -} - -static int update_attrib(struct rtw_adapter *padapter, - struct sk_buff *skb, struct pkt_attrib *pattrib) -{ - struct sta_info *psta = NULL; - int bmcast; - struct sta_priv *pstapriv = &padapter->stapriv; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int res = _SUCCESS; - struct ethhdr *ehdr = (struct ethhdr *) skb->data; - - pattrib->ether_type = ntohs(ehdr->h_proto); - - ether_addr_copy(pattrib->dst, ehdr->h_dest); - ether_addr_copy(pattrib->src, ehdr->h_source); - - pattrib->pctrl = 0; - - if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - ether_addr_copy(pattrib->ra, get_bssid(pmlmepriv)); - ether_addr_copy(pattrib->ta, pattrib->src); - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - ether_addr_copy(pattrib->ra, pattrib->dst); - ether_addr_copy(pattrib->ta, get_bssid(pmlmepriv)); - } - - pattrib->pktlen = skb->len - ETH_HLEN; - - if (pattrib->ether_type == ETH_P_IP) { - /* The following is for DHCP and ARP packet, we use cck1M - to tx these packets and let LPS awake some time */ - /* to prevent DHCP protocol fail */ - pattrib->dhcp_pkt = 0; - /* MINIMUM_DHCP_PACKET_SIZE) { */ - if (pattrib->pktlen > 282 + 24) { - if (pattrib->ether_type == ETH_P_IP) {/* IP header */ - u8 *pframe = skb->data; - - pframe += ETH_HLEN; - - if ((pframe[21] == 68 && pframe[23] == 67) || - (pframe[21] == 67 && pframe[23] == 68)) { - /* 68 : UDP BOOTP client */ - /* 67 : UDP BOOTP server */ - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "======================update_attrib: get DHCP Packet\n"); - pattrib->dhcp_pkt = 1; - } - } - } - } else if (pattrib->ether_type == ETH_P_PAE) { - DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n"); - } - - if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_set_scan_deny(padapter, 3000); - } - - /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */ - if ((pattrib->ether_type == ETH_P_ARP) || - (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) { - rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1); - } - - bmcast = is_multicast_ether_addr(pattrib->ra); - - /* get sta_info */ - if (bmcast) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - if (psta == NULL) { /* if we cannot get psta => drrp the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && - (!(psta->state & _FW_LINKED))) { - res = _FAIL; - goto exit; - } - } - - if (psta) { - pattrib->mac_id = psta->mac_id; - /* DBG_8723A("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */ - pattrib->psta = psta; - } else { - /* if we cannot get psta => drop the pkt */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "update_attrib => get sta_info fail, ra:%pM\n", - pattrib->ra); - res = _FAIL; - goto exit; - } - - pattrib->ack_policy = 0; - /* get ether_hdr_len */ - - /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ - pattrib->pkt_hdrlen = ETH_HLEN; - - pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr); - pattrib->type = IEEE80211_FTYPE_DATA; - pattrib->priority = 0; - - if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | - WIFI_ADHOC_MASTER_STATE)) { - if (psta->qos_option) - set_qos(skb, pattrib); - } else { - if (pmlmepriv->qos_option) { - set_qos(skb, pattrib); - - if (pmlmepriv->acm_mask != 0) { - pattrib->priority = qos_acm23a(pmlmepriv->acm_mask, - pattrib->priority); - } - } - } - - if (psta->ieee8021x_blocked == true) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true\n"); - - pattrib->encrypt = 0; - - if ((pattrib->ether_type != ETH_P_PAE) && - !check_fwstate(pmlmepriv, WIFI_MP_STATE)) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "psta->ieee8021x_blocked == true, pattrib->ether_type(%.4x) != 0x888e\n", - pattrib->ether_type); - res = _FAIL; - goto exit; - } - } else { - GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast); - - switch (psecuritypriv->dot11AuthAlgrthm) { - case dot11AuthAlgrthm_Open: - case dot11AuthAlgrthm_Shared: - case dot11AuthAlgrthm_Auto: - pattrib->key_idx = - (u8)psecuritypriv->dot11PrivacyKeyIndex; - break; - case dot11AuthAlgrthm_8021X: - if (bmcast) - pattrib->key_idx = - (u8)psecuritypriv->dot118021XGrpKeyid; - else - pattrib->key_idx = 0; - break; - default: - pattrib->key_idx = 0; - break; - } - - } - - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pattrib->iv_len = IEEE80211_WEP_IV_LEN; - pattrib->icv_len = IEEE80211_WEP_ICV_LEN; - break; - - case WLAN_CIPHER_SUITE_TKIP: - pattrib->iv_len = IEEE80211_TKIP_IV_LEN; - pattrib->icv_len = IEEE80211_TKIP_ICV_LEN; - - if (!padapter->securitypriv.busetkipkey) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "padapter->securitypriv.busetkipkey(%d) == false drop packet\n", - padapter->securitypriv.busetkipkey); - res = _FAIL; - goto exit; - } - - break; - case WLAN_CIPHER_SUITE_CCMP: - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n", - pattrib->encrypt); - pattrib->iv_len = IEEE80211_CCMP_HDR_LEN; - pattrib->icv_len = IEEE80211_CCMP_MIC_LEN; - break; - - default: - pattrib->iv_len = 0; - pattrib->icv_len = 0; - break; - } - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: encrypt =%d\n", pattrib->encrypt); - - if (pattrib->encrypt && !psecuritypriv->hw_decrypted) { - pattrib->bswenc = true; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "update_attrib: encrypt =%d bswenc = true\n", - pattrib->encrypt); - } else { - pattrib->bswenc = false; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "update_attrib: bswenc = false\n"); - } - update_attrib_phy_info(pattrib, psta); - -exit: - - return res; -} - -static int xmitframe_addmic(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) { - struct mic_data micdata; - struct sta_info *stainfo; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct security_priv *psecuritypriv = &padapter->securitypriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int curfragnum, length; - u8 *pframe, *payload, mic[8]; - u8 priority[4]= {0x0, 0x0, 0x0, 0x0}; - u8 hw_hdr_offset = 0; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - stainfo = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - - if (!stainfo) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(stainfo->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, stainfo->state); - return _FAIL; - } - - hw_hdr_offset = TXDESC_OFFSET; - - if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) { - /* encode mic code */ - if (stainfo) { - u8 null_key[16]={0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0}; - - pframe = pxmitframe->buf_addr + hw_hdr_offset; - - if (bmcst) { - if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey); - } else { - if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0], - null_key, 16)) { - return _FAIL; - } - /* start to calculate the mic code */ - rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]); - } - - if (pframe[1] & 1) { /* ToDS == 1 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[16], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[24], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } else { /* ToDS == 0 */ - /* DA */ - rtw_secmicappend23a(&micdata, &pframe[4], 6); - if (pframe[1] & 2) /* From Ds == 1 */ - rtw_secmicappend23a(&micdata, - &pframe[16], 6); - else - rtw_secmicappend23a(&micdata, - &pframe[10], 6); - } - - /* if (pmlmepriv->qos_option == 1) */ - if (pattrib->qos_en) - priority[0] = (u8)pxmitframe->attrib.priority; - - rtw_secmicappend23a(&micdata, &priority[0], 4); - - payload = pframe; - - for (curfragnum = 0; curfragnum < pattrib->nr_frags; - curfragnum++) { - payload = PTR_ALIGN(payload, 4); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "=== curfragnum =%d, pframe = 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n", - curfragnum, *payload, *(payload + 1), - *(payload + 2), *(payload + 3), - *(payload + 4), *(payload + 5), - *(payload + 6), *(payload + 7)); - - payload = payload + pattrib->hdrlen + - pattrib->iv_len; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "curfragnum =%d pattrib->hdrlen =%d pattrib->iv_len =%d\n", - curfragnum, - pattrib->hdrlen, pattrib->iv_len); - if ((curfragnum + 1) == pattrib->nr_frags) { - length = pattrib->last_txcmdsz - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length; - } else { - length = pxmitpriv->frag_len - - pattrib->hdrlen - - pattrib->iv_len - - ((pattrib->bswenc) ? - pattrib->icv_len : 0); - rtw_secmicappend23a(&micdata, payload, - length); - payload = payload + length + - pattrib->icv_len; - RT_TRACE(_module_rtl871x_xmit_c_, - _drv_err_, - "curfragnum =%d length =%d pattrib->icv_len =%d\n", - curfragnum, length, - pattrib->icv_len); - } - } - rtw_secgetmic23a(&micdata, &mic[0]); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: before add mic code!!\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: pattrib->last_txcmdsz =%d!!!\n", - pattrib->last_txcmdsz); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: mic[0]= 0x%.2x , mic[1]=0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\nmic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x , mic[7]= 0x%.2x !!!!\n", - mic[0], mic[1], mic[2], mic[3], - mic[4], mic[5], mic[6], mic[7]); - /* add mic code and add the mic code length - in last_txcmdsz */ - - memcpy(payload, &mic[0], 8); - pattrib->last_txcmdsz += 8; - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "======== last pkt ========\n"); - payload = payload - pattrib->last_txcmdsz + 8; - for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz; - curfragnum = curfragnum + 8) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "%.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x, %.2x\n", - *(payload + curfragnum), - *(payload + curfragnum + 1), - *(payload + curfragnum + 2), - *(payload + curfragnum + 3), - *(payload + curfragnum + 4), - *(payload + curfragnum + 5), - *(payload + curfragnum + 6), - *(payload + curfragnum + 7)); - } - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic: rtw_get_stainfo23a ==NULL!!!\n"); - } - } - - return _SUCCESS; -} - -static int xmitframe_swencrypt(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */ - if (pattrib->bswenc) { - /* DBG_8723A("start xmitframe_swencrypt\n"); */ - RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, - "### xmitframe_swencrypt\n"); - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - rtw_wep_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_TKIP: - rtw_tkip_encrypt23a(padapter, pxmitframe); - break; - case WLAN_CIPHER_SUITE_CCMP: - rtw_aes_encrypt23a(padapter, pxmitframe); - break; - default: - break; - } - - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "### xmitframe_hwencrypt\n"); - } - - return _SUCCESS; -} - -static int rtw_make_wlanhdr(struct rtw_adapter *padapter, u8 *hdr, - struct pkt_attrib *pattrib) -{ - struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; - struct ieee80211_qos_hdr *qoshdr; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - u8 qos_option = false; - int res = _SUCCESS; - - struct sta_info *psta; - - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - if (bmcst) { - psta = rtw_get_bcmc_stainfo23a(padapter); - } else { - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state); - return _FAIL; - } - - memset(hdr, 0, WLANHDR_OFFSET); - - pwlanhdr->frame_control = cpu_to_le16(pattrib->type); - - if (pattrib->type & IEEE80211_FTYPE_DATA) { - if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { - /* to_ds = 1, fr_ds = 0; */ - /* Data transfer to AP */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_TODS); - ether_addr_copy(pwlanhdr->addr1, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, pattrib->dst); - - if (pmlmepriv->qos_option) - qos_option = true; - - } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) { - /* to_ds = 0, fr_ds = 1; */ - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_FROMDS); - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, get_bssid(pmlmepriv)); - ether_addr_copy(pwlanhdr->addr3, pattrib->src); - - if (psta->qos_option) - qos_option = true; - } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || - check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) { - ether_addr_copy(pwlanhdr->addr1, pattrib->dst); - ether_addr_copy(pwlanhdr->addr2, pattrib->src); - ether_addr_copy(pwlanhdr->addr3, get_bssid(pmlmepriv)); - - if (psta->qos_option) - qos_option = true; - } - else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "fw_state:%x is not allowed to xmit frame\n", - get_fwstate(pmlmepriv)); - res = _FAIL; - goto exit; - } - if (pattrib->mdata) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - if (pattrib->encrypt) - pwlanhdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - if (qos_option) { - qoshdr = (struct ieee80211_qos_hdr *)hdr; - - qoshdr->qos_ctrl = cpu_to_le16( - pattrib->priority & IEEE80211_QOS_CTL_TID_MASK); - - qoshdr->qos_ctrl |= cpu_to_le16( - (pattrib->ack_policy << 5) & - IEEE80211_QOS_CTL_ACK_POLICY_MASK); - - if (pattrib->eosp) - qoshdr->qos_ctrl |= - cpu_to_le16(IEEE80211_QOS_CTL_EOSP); - } - /* TODO: fill HT Control Field */ - - /* Update Seq Num will be handled by f/w */ - if (psta) { - psta->sta_xmitpriv.txseq_tid[pattrib->priority]++; - psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF; - pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority]; - /* We dont need to worry about frag bits here */ - pwlanhdr->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ( - pattrib->seqnum)); - /* check if enable ampdu */ - if (pattrib->ht_en && psta->htpriv.ampdu_enable) { - if (pattrib->priority >= 16) - printk(KERN_WARNING "%s: Invalid " - "pattrib->priority %i\n", - __func__, pattrib->priority); - if (psta->htpriv.agg_enable_bitmap & - BIT(pattrib->priority)) - pattrib->ampdu_en = true; - } - /* re-check if enable ampdu by BA_starting_seqctrl */ - if (pattrib->ampdu_en) { - u16 tx_seq; - - tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f]; - - /* check BA_starting_seqctrl */ - if (SN_LESS(pattrib->seqnum, tx_seq)) { - /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */ - pattrib->ampdu_en = false;/* AGG BK */ - } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) { - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } else { - /* DBG_8723A("tx ampdu over run\n"); */ - psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff; - pattrib->ampdu_en = true;/* AGG EN */ - } - } - } - } -exit: - return res; -} - -s32 rtw_txframes_pending23a(struct rtw_adapter *padapter) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - return (!list_empty(&pxmitpriv->be_pending.queue)) || - (!list_empty(&pxmitpriv->bk_pending.queue)) || - (!list_empty(&pxmitpriv->vi_pending.queue)) || - (!list_empty(&pxmitpriv->vo_pending.queue)); -} - -s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter, - struct pkt_attrib *pattrib) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - int priority = pattrib->priority; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]); - } - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return 0; - } - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return 0; - } - switch (priority) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - break; - } - return ptxservq->qcnt; -} - -/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header - * IEEE LLC/SNAP header contains 8 octets - * First 3 octets comprise the LLC portion - * SNAP portion, 5 octets, is divided into two fields: - * Organizationally Unique Identifier(OUI), 3 octets, - * type, defined by that organization, 2 octets. - */ -static int rtw_put_snap(u8 *data, u16 h_proto) -{ - if (h_proto == ETH_P_IPX || h_proto == ETH_P_AARP) - ether_addr_copy(data, bridge_tunnel_header); - else - ether_addr_copy(data, rfc1042_header); - - data += ETH_ALEN; - put_unaligned_be16(h_proto, data); - return ETH_ALEN + sizeof(u16); -} - -/* - -This sub-routine will perform all the following: - -1. remove 802.3 header. -2. create wlan_header, based on the info in pxmitframe -3. append sta's iv/ext-iv -4. append LLC -5. move frag chunk from pframe to pxmitframe->mem -6. apply sw-encrypt, if necessary. - -*/ -int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct ieee80211_hdr *hdr; - s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; - u8 *pframe, *mem_start; - u8 hw_hdr_offset; - u8 *pbuf_start; - u8 *pdata = skb->data; - int data_len = skb->len; - s32 bmcst = is_multicast_ether_addr(pattrib->ra); - int res = _SUCCESS; - - if (pattrib->psta) - psta = pattrib->psta; - else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra); - } - - if (!psta) { - DBG_8723A("%s, psta == NUL\n", __func__); - return _FAIL; - } - - if (!(psta->state &_FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", - __func__, psta->state); - return _FAIL; - } - - if (!pxmitframe->buf_addr) { - DBG_8723A("==> %s buf_addr == NULL\n", __func__); - return _FAIL; - } - - pbuf_start = pxmitframe->buf_addr; - - hw_hdr_offset = TXDESC_OFFSET; - - mem_start = pbuf_start + hw_hdr_offset; - - if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: rtw_make_wlanhdr fail; drop pkt\n", __func__); - res = _FAIL; - goto exit; - } - - pdata += pattrib->pkt_hdrlen; - data_len -= pattrib->pkt_hdrlen; - - frg_inx = 0; - frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ - - while (1) { - llc_sz = 0; - - mpdu_len = frg_len; - - pframe = mem_start; - hdr = (struct ieee80211_hdr *)mem_start; - - pframe += pattrib->hdrlen; - mpdu_len -= pattrib->hdrlen; - - /* adding icv, if necessary... */ - if (pattrib->iv_len) { - if (psta) { - switch (pattrib->encrypt) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - WEP_IV(pattrib->iv, psta->dot11txpn, - pattrib->key_idx); - break; - case WLAN_CIPHER_SUITE_TKIP: - if (bmcst) - TKIP_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - TKIP_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - case WLAN_CIPHER_SUITE_CCMP: - if (bmcst) - AES_IV(pattrib->iv, - psta->dot11txpn, - pattrib->key_idx); - else - AES_IV(pattrib->iv, - psta->dot11txpn, 0); - break; - } - } - - memcpy(pframe, pattrib->iv, pattrib->iv_len); - - RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_, - "rtw_xmiaframe_coalesce23a: keyid =%d pattrib->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n", - padapter->securitypriv.dot11PrivacyKeyIndex, - pattrib->iv[3], *pframe, *(pframe+1), - *(pframe+2), *(pframe+3)); - pframe += pattrib->iv_len; - mpdu_len -= pattrib->iv_len; - } - if (frg_inx == 0) { - llc_sz = rtw_put_snap(pframe, pattrib->ether_type); - pframe += llc_sz; - mpdu_len -= llc_sz; - } - - if (pattrib->icv_len > 0 && pattrib->bswenc) - mpdu_len -= pattrib->icv_len; - - if (bmcst) - /* don't do fragment to broadcast/multicast packets */ - mem_sz = min_t(s32, data_len, pattrib->pktlen); - else - mem_sz = min_t(s32, data_len, mpdu_len); - - memcpy(pframe, pdata, mem_sz); - - pframe += mem_sz; - pdata += mem_sz; - data_len -= mem_sz; - - if ((pattrib->icv_len >0) && (pattrib->bswenc)) { - memcpy(pframe, pattrib->icv, pattrib->icv_len); - pframe += pattrib->icv_len; - } - - frg_inx++; - - if (bmcst || data_len <= 0) { - pattrib->nr_frags = frg_inx; - - pattrib->last_txcmdsz = pattrib->hdrlen + - pattrib->iv_len + - ((pattrib->nr_frags == 1) ? - llc_sz : 0) + - ((pattrib->bswenc) ? - pattrib->icv_len : 0) + mem_sz; - hdr->frame_control &= - ~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - break; - } else { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "%s: There're still something in packet!\n", - __func__); - } - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); - - mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset; - memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen); - } - - if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); - res = _FAIL; - goto exit; - } - - xmitframe_swencrypt(padapter, pxmitframe); - - if (bmcst == false) - update_attrib_vcs_info(padapter, pxmitframe); - else - pattrib->vcs_mode = NONE_VCS; - -exit: - return res; -} - -void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct registry_priv *pregistrypriv = &padapter->registrypriv; - uint protection; - const u8 *p; - - switch (pregistrypriv->vrtl_carrier_sense) { - case DISABLE_VCS: - pxmitpriv->vcs = NONE_VCS; - break; - case ENABLE_VCS: - break; - case AUTO_VCS: - default: - p = cfg80211_find_ie(WLAN_EID_ERP_INFO, ie, ie_len); - if (!p) - pxmitpriv->vcs = NONE_VCS; - else { - protection = (*(p + 2)) & BIT(1); - if (protection) { - if (pregistrypriv->vcs_type == RTS_CTS) - pxmitpriv->vcs = RTS_CTS; - else - pxmitpriv->vcs = CTS_TO_SELF; - } else { - pxmitpriv->vcs = NONE_VCS; - } - } - break; - } -} - -void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz) -{ - struct sta_info *psta = NULL; - struct stainfo_stats *pstats = NULL; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - - if (pxmitframe->frame_tag == DATA_FRAMETAG) { - pxmitpriv->tx_bytes += sz; - pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++; - - psta = pxmitframe->attrib.psta; - if (psta) { - pstats = &psta->sta_stats; - pstats->tx_pkts++; - pstats->tx_bytes += sz; - } - } -} - -struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - phead = get_list_head(pfree_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmit_extbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = true; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv, - struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue; - - if (pxmitbuf == NULL) - return _FAIL; - - spin_lock_irqsave(&pfree_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue)); - pxmitpriv->free_xmit_extbuf_cnt++; - - spin_unlock_irqrestore(&pfree_queue->lock, irqL); - - return _SUCCESS; -} - -struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv) -{ - unsigned long irqL; - struct xmit_buf *pxmitbuf = NULL; - struct list_head *phead; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */ - - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - phead = get_list_head(pfree_xmitbuf_queue); - - if (!list_empty(phead)) { - pxmitbuf = list_first_entry(phead, struct xmit_buf, list); - - list_del_init(&pxmitbuf->list); - - pxmitpriv->free_xmitbuf_cnt--; - pxmitbuf->priv_data = NULL; - pxmitbuf->ext_tag = false; - pxmitbuf->flags = XMIT_VO_QUEUE; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } - } - - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - - return pxmitbuf; -} - -int rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) -{ - unsigned long irqL; - struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; - - /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */ - - if (pxmitbuf == NULL) - return _FAIL; - - if (pxmitbuf->sctx) { - DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__); - rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - } - - if (pxmitbuf->ext_tag) { - rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf); - } else { - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL); - - list_del_init(&pxmitbuf->list); - - list_add_tail(&pxmitbuf->list, - get_list_head(pfree_xmitbuf_queue)); - - pxmitpriv->free_xmitbuf_cnt++; - spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL); - } - - return _SUCCESS; -} - -static void rtw_init_xmitframe(struct xmit_frame *pxframe) -{ - if (pxframe != NULL) { - /* default value setting */ - pxframe->buf_addr = NULL; - pxframe->pxmitbuf = NULL; - - memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib)); - /* pxframe->attrib.psta = NULL; */ - - pxframe->frame_tag = DATA_FRAMETAG; - - pxframe->pkt = NULL; - pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */ - - pxframe->ack_report = 0; - } -} - -/* -Calling context: -1. OS_TXENTRY -2. RXENTRY (rx_thread or RX_ISR/RX_CallBack) - -If we turn on USE_RXTHREAD, then, no need for critical section. -Otherwise, we must use _enter/_exit critical to protect free_xmit_queue... - -Must be very very cautious... - -*/ -static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue; - - spin_lock_bh(&pfree_xmit_queue->lock); - - pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe:%d\n", - pxmitpriv->free_xmitframe_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xmitframe_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } - - spin_unlock_bh(&pfree_xmit_queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv) -{ - struct xmit_frame *pxframe; - struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue; - - spin_lock_bh(&queue->lock); - - pxframe = list_first_entry_or_null(&queue->queue, - struct xmit_frame, list); - if (!pxframe) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext:%d\n", - pxmitpriv->free_xframe_ext_cnt); - } else { - list_del_init(&pxframe->list); - pxmitpriv->free_xframe_ext_cnt--; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - - rtw_init_xmitframe(pxframe); - - return pxframe; -} - -s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe) -{ - struct rtw_queue *queue = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct sk_buff *pndis_pkt = NULL; - - if (pxmitframe == NULL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"); - goto exit; - } - - if (pxmitframe->pkt) { - pndis_pkt = pxmitframe->pkt; - pxmitframe->pkt = NULL; - } - - if (pxmitframe->ext_tag == 0) - queue = &pxmitpriv->free_xmit_queue; - else if (pxmitframe->ext_tag == 1) - queue = &pxmitpriv->free_xframe_ext_queue; - - if (!queue) - goto check_pkt_complete; - spin_lock_bh(&queue->lock); - - list_del_init(&pxmitframe->list); - list_add_tail(&pxmitframe->list, get_list_head(queue)); - if (pxmitframe->ext_tag == 0) { - pxmitpriv->free_xmitframe_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", - pxmitpriv->free_xmitframe_cnt); - } else if (pxmitframe->ext_tag == 1) { - pxmitpriv->free_xframe_ext_cnt++; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, - "rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", - pxmitpriv->free_xframe_ext_cnt); - } - - spin_unlock_bh(&queue->lock); - -check_pkt_complete: - - if (pndis_pkt) - rtw_os_pkt_complete23a(padapter, pndis_pkt); - -exit: - - return _SUCCESS; -} - -void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv, - struct rtw_queue *pframequeue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - - spin_lock_bh(&pframequeue->lock); - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - spin_unlock_bh(&pframequeue->lock); - -} - -int rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) { - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmitframe_enqueue23a: drop xmit pkt for classifier fail\n"); - return _FAIL; - } - - return _SUCCESS; -} - -static struct xmit_frame * -dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, - struct tx_servq *ptxservq, struct rtw_queue *pframe_queue) -{ - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL; - - phead = get_list_head(pframe_queue); - - if (!list_empty(phead)) { - pxmitframe = list_first_entry(phead, struct xmit_frame, list); - list_del_init(&pxmitframe->list); - ptxservq->qcnt--; - } - return pxmitframe; -} - -struct xmit_frame * -rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, - int entry) -{ - struct list_head *sta_phead; - struct hw_xmit *phwxmit; - struct tx_servq *ptxservq = NULL, *ptmp; - struct rtw_queue *pframe_queue = NULL; - struct xmit_frame *pxmitframe = NULL; - struct rtw_adapter *padapter = pxmitpriv->adapter; - struct registry_priv *pregpriv = &padapter->registrypriv; - int i, inx[4]; - - inx[0] = 0; - inx[1] = 1; - inx[2] = 2; - inx[3] = 3; - if (pregpriv->wifi_spec == 1) { - int j; - - for (j = 0; j < 4; j++) - inx[j] = pxmitpriv->wmm_para_seq[j]; - } - - spin_lock_bh(&pxmitpriv->lock); - - for (i = 0; i < entry; i++) { - phwxmit = phwxmit_i + inx[i]; - - sta_phead = get_list_head(phwxmit->sta_queue); - list_for_each_entry_safe(ptxservq, ptmp, sta_phead, - tx_pending) { - pframe_queue = &ptxservq->sta_pending; - - pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue); - - if (pxmitframe) { - phwxmit->accnt--; - - /* Remove sta node when there is no pending packets. */ - /* must be done after get_next and - before break */ - if (list_empty(&pframe_queue->queue)) - list_del_init(&ptxservq->tx_pending); - goto exit; - } - } - } -exit: - spin_unlock_bh(&pxmitpriv->lock); - return pxmitframe; -} - -struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac) -{ - struct tx_servq *ptxservq = NULL; - - switch (up) { - case 1: - case 2: - ptxservq = &psta->sta_xmitpriv.bk_q; - *(ac) = 3; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BK\n"); - break; - case 4: - case 5: - ptxservq = &psta->sta_xmitpriv.vi_q; - *(ac) = 1; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VI\n"); - break; - case 6: - case 7: - ptxservq = &psta->sta_xmitpriv.vo_q; - *(ac) = 0; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : VO\n"); - break; - case 0: - case 3: - default: - ptxservq = &psta->sta_xmitpriv.be_q; - *(ac) = 2; - RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, - "rtw_get_sta_pending23a : BE\n"); - break; - } - return ptxservq; -} - -/* - * Will enqueue pxmitframe to the proper queue, - * and indicate it to xx_pending list..... - */ -int rtw_xmit23a_classifier(struct rtw_adapter *padapter, - struct xmit_frame *pxmitframe) -{ - struct sta_info *psta; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct sta_priv *pstapriv = &padapter->stapriv; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - u8 ac_index; - int res = _SUCCESS; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - if (psta == NULL) { - res = _FAIL; - DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n"); - RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, - "rtw_xmit23a_classifier: psta == NULL\n"); - goto exit; - } - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return _FAIL; - } - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, - (u8 *)(&ac_index)); - - if (list_empty(&ptxservq->tx_pending)) { - list_add_tail(&ptxservq->tx_pending, - get_list_head(phwxmits[ac_index].sta_queue)); - } - - list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending)); - ptxservq->qcnt++; - phwxmits[ac_index].accnt++; -exit: - return res; -} - -void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - int size; - - pxmitpriv->hwxmit_entry = HWXMIT_ENTRY; - - size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1); - pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL); - - hwxmits = pxmitpriv->hwxmits; - - if (pxmitpriv->hwxmit_entry == 5) { - /* pxmitpriv->bmc_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->bm_pending; - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[4] .sta_queue = &pxmitpriv->be_pending; - - } else if (pxmitpriv->hwxmit_entry == 4) { - - /* pxmitpriv->vo_txqueue.head = 0; */ - /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */ - hwxmits[0] .sta_queue = &pxmitpriv->vo_pending; - - /* pxmitpriv->vi_txqueue.head = 0; */ - /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */ - hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; - - /* pxmitpriv->be_txqueue.head = 0; */ - /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */ - hwxmits[2] .sta_queue = &pxmitpriv->be_pending; - - /* pxmitpriv->bk_txqueue.head = 0; */ - /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */ - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - } else { - - } -} - -void rtw_free_hwxmits23a(struct rtw_adapter *padapter) -{ - struct hw_xmit *hwxmits; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - hwxmits = pxmitpriv->hwxmits; - kfree(hwxmits); -} - -void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry) -{ - int i; - - for (i = 0; i < entry; i++, phwxmit++) - phwxmit->accnt = 0; -} - -u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe) -{ - u32 addr; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - - switch (pattrib->qsel) { - case 0: - case 3: - addr = BE_QUEUE_INX; - break; - case 1: - case 2: - addr = BK_QUEUE_INX; - break; - case 4: - case 5: - addr = VI_QUEUE_INX; - break; - case 6: - case 7: - addr = VO_QUEUE_INX; - break; - case 0x10: - addr = BCN_QUEUE_INX; - break; - case 0x11:/* BC/MC in PS (HIQ) */ - addr = HIGH_QUEUE_INX; - break; - case 0x12: - default: - addr = MGT_QUEUE_INX; - break; - } - - return addr; -} - -/* - * The main transmit(tx) entry - * - * Return - * 1 enqueue - * 0 success, hardware will handle this xmit frame(packet) - * <0 fail - */ -int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb) -{ - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - struct xmit_frame *pxmitframe = NULL; - int res; - - pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - - if (pxmitframe == NULL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: no more pxmitframe\n"); - return -1; - } - - res = update_attrib(padapter, skb, &pxmitframe->attrib); - - if (res == _FAIL) { - RT_TRACE(_module_xmit_osdep_c_, _drv_err_, - "rtw_xmit23a: update attrib fail\n"); - rtw_free_xmitframe23a(pxmitpriv, pxmitframe); - return -1; - } - pxmitframe->pkt = skb; - - pxmitframe->attrib.qsel = pxmitframe->attrib.priority; - -#ifdef CONFIG_8723AU_AP_MODE - spin_lock_bh(&pxmitpriv->lock); - if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) { - spin_unlock_bh(&pxmitpriv->lock); - return 1; - } - spin_unlock_bh(&pxmitpriv->lock); -#endif - - if (rtl8723au_hal_xmit(padapter, pxmitframe) == false) - return 1; - - return 0; -} - -#if defined(CONFIG_8723AU_AP_MODE) - -int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe) -{ - int ret = false; - struct sta_info *psta = NULL; - struct sta_priv *pstapriv = &padapter->stapriv; - struct pkt_attrib *pattrib = &pxmitframe->attrib; - struct mlme_priv *pmlmepriv = &padapter->mlmepriv; - int bmcst = is_multicast_ether_addr(pattrib->ra); - - if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return ret; - - if (pattrib->psta) { - psta = pattrib->psta; - } else { - DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__); - psta = rtw_get_stainfo23a(pstapriv, pattrib->ra); - } - - if (psta == NULL) { - DBG_8723A("%s, psta == NUL\n", __func__); - return false; - } - - if (!(psta->state & _FW_LINKED)) { - DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, - psta->state); - return false; - } - - if (pattrib->triggered == 1) { - if (bmcst) - pattrib->qsel = 0x11;/* HIQ */ - return ret; - } - - if (bmcst) { - spin_lock_bh(&psta->sleep_q.lock); - - if (pstapriv->sta_dz_bitmap) { - /* if anyone sta is in ps mode */ - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - pstapriv->tim_bitmap |= BIT(0);/* */ - pstapriv->sta_dz_bitmap |= BIT(0); - - /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */ - - /* tx bc/mc packets after update bcn */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - ret = true; - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; - - } - - spin_lock_bh(&psta->sleep_q.lock); - - if (psta->state&WIFI_SLEEP_STATE) { - u8 wmmps_ac = 0; - - if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) { - list_del_init(&pxmitframe->list); - - /* spin_lock_bh(&psta->sleep_q.lock); */ - - list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q)); - - psta->sleepq_len++; - - switch (pattrib->priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(0); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(0); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(0); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(0); - break; - } - - if (wmmps_ac) - psta->sleepq_ac_len++; - - if (((psta->has_legacy_ac) && (!wmmps_ac)) || - ((!psta->has_legacy_ac) && (wmmps_ac))) { - pstapriv->tim_bitmap |= CHKBIT(psta->aid); - - if (psta->sleepq_len == 1) { - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, - NULL, false); - } - } - - /* spin_unlock_bh(&psta->sleep_q.lock); */ - - /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */ - /* */ - /* wakeup_sta_to_xmit23a(padapter, psta); */ - /* */ - - ret = true; - - } - - } - - spin_unlock_bh(&psta->sleep_q.lock); - - return ret; -} - -static void -dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter, - struct sta_info *psta, - struct rtw_queue *pframequeue) -{ - int ret; - struct list_head *phead; - u8 ac_index; - struct tx_servq *ptxservq; - struct pkt_attrib *pattrib; - struct xmit_frame *pxmitframe, *ptmp; - struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; - - phead = get_list_head(pframequeue); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe); - - if (ret == true) { - pattrib = &pxmitframe->attrib; - - ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index)); - - ptxservq->qcnt--; - phwxmits[ac_index].accnt--; - } else { - /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */ - } - } -} - -void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - struct sta_info *psta_bmc; - struct sta_xmit_priv *pstaxmitpriv; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - pstaxmitpriv = &psta->sta_xmitpriv; - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - - spin_lock_bh(&pxmitpriv->lock); - - psta->state |= WIFI_SLEEP_STATE; - - pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending); - list_del_init(&pstaxmitpriv->vo_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending); - list_del_init(&pstaxmitpriv->vi_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - dequeue_xmitframes_to_sleeping_queue(padapter, psta, - &pstaxmitpriv->bk_q.sta_pending); - list_del_init(&pstaxmitpriv->bk_q.tx_pending); - - /* for BC/MC Frames */ - pstaxmitpriv = &psta_bmc->sta_xmitpriv; - dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, - &pstaxmitpriv->be_q.sta_pending); - list_del_init(&pstaxmitpriv->be_q.tx_pending); - - spin_unlock_bh(&pxmitpriv->lock); -} - -void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta) -{ - u8 update_mask = 0, wmmps_ac = 0; - struct sta_info *psta_bmc; - struct list_head *phead; - struct xmit_frame *pxmitframe = NULL, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - psta->sleepq_len--; - if (psta->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - if (wmmps_ac) { - psta->sleepq_ac_len--; - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - } - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - - if (psta->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_mask = BIT(0); - - if (psta->state&WIFI_SLEEP_STATE) - psta->state ^= WIFI_SLEEP_STATE; - - if (psta->state & WIFI_STA_ALIVE_CHK_STATE) { - psta->expire_to = pstapriv->expire_to; - psta->state ^= WIFI_STA_ALIVE_CHK_STATE; - } - - pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); - } - /* spin_unlock_bh(&psta->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - - /* for BC/MC Frames */ - psta_bmc = rtw_get_bcmc_stainfo23a(padapter); - if (!psta_bmc) - return; - - if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) { - /* no any sta in ps mode */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta_bmc->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - list_del_init(&pxmitframe->list); - - psta_bmc->sleepq_len--; - if (psta_bmc->sleepq_len > 0) - pxmitframe->attrib.mdata = 1; - else - pxmitframe->attrib.mdata = 0; - - pxmitframe->attrib.triggered = 1; - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - } - if (psta_bmc->sleepq_len == 0) { - pstapriv->tim_bitmap &= ~BIT(0); - pstapriv->sta_dz_bitmap &= ~BIT(0); - - /* update BCN for TIM IE */ - /* update_BCNTIM(padapter); */ - update_mask |= BIT(1); - } - /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */ - spin_unlock_bh(&pxmitpriv->lock); - } - - if (update_mask) - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); -} - -void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter, - struct sta_info *psta) -{ - u8 wmmps_ac = 0; - struct list_head *phead; - struct xmit_frame *pxmitframe, *ptmp; - struct sta_priv *pstapriv = &padapter->stapriv; - struct xmit_priv *pxmitpriv = &padapter->xmitpriv; - - /* spin_lock_bh(&psta->sleep_q.lock); */ - spin_lock_bh(&pxmitpriv->lock); - phead = get_list_head(&psta->sleep_q); - list_for_each_entry_safe(pxmitframe, ptmp, phead, list) { - switch (pxmitframe->attrib.priority) { - case 1: - case 2: - wmmps_ac = psta->uapsd_bk & BIT(1); - break; - case 4: - case 5: - wmmps_ac = psta->uapsd_vi & BIT(1); - break; - case 6: - case 7: - wmmps_ac = psta->uapsd_vo & BIT(1); - break; - case 0: - case 3: - default: - wmmps_ac = psta->uapsd_be & BIT(1); - break; - } - - if (!wmmps_ac) - continue; - - list_del_init(&pxmitframe->list); - - psta->sleepq_len--; - psta->sleepq_ac_len--; - - if (psta->sleepq_ac_len > 0) { - pxmitframe->attrib.mdata = 1; - pxmitframe->attrib.eosp = 0; - } else { - pxmitframe->attrib.mdata = 0; - pxmitframe->attrib.eosp = 1; - } - - pxmitframe->attrib.triggered = 1; - - rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe); - - if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && - (wmmps_ac)) { - pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); - - /* update BCN for TIM IE */ - update_beacon23a(padapter, WLAN_EID_TIM, NULL, false); - } - } - spin_unlock_bh(&pxmitpriv->lock); -} - -#endif - -void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms) -{ - sctx->timeout_ms = timeout_ms; - init_completion(&sctx->done); - sctx->status = RTW_SCTX_SUBMITTED; -} - -int rtw_sctx_wait23a(struct submit_ctx *sctx) -{ - int ret = _FAIL; - unsigned long expire; - int status = 0; - - expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : - MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&sctx->done, expire)) { - /* timeout, do something?? */ - status = RTW_SCTX_DONE_TIMEOUT; - DBG_8723A("%s timeout\n", __func__); - } else { - status = sctx->status; - } - - if (status == RTW_SCTX_DONE_SUCCESS) - ret = _SUCCESS; - - return ret; -} - -static bool rtw_sctx_chk_waring_status(int status) -{ - switch (status) { - case RTW_SCTX_DONE_UNKNOWN: - case RTW_SCTX_DONE_BUF_ALLOC: - case RTW_SCTX_DONE_BUF_FREE: - case RTW_SCTX_DONE_DRV_STOP: - case RTW_SCTX_DONE_DEV_REMOVE: - return true; - default: - return false; - } -} - -void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status) -{ - if (*sctx) { - if (rtw_sctx_chk_waring_status(status)) - DBG_8723A("%s status:%d\n", __func__, status); - (*sctx)->status = status; - complete(&(*sctx)->done); - *sctx = NULL; - } -} - -int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms) -{ - struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops; - - pack_tx_ops->timeout_ms = timeout_ms; - pack_tx_ops->status = RTW_SCTX_SUBMITTED; - - return rtw_sctx_wait23a(pack_tx_ops); -} - |