diff options
Diffstat (limited to 'drivers/staging/r8188eu/core/rtw_xmit.c')
-rw-r--r-- | drivers/staging/r8188eu/core/rtw_xmit.c | 518 |
1 files changed, 328 insertions, 190 deletions
diff --git a/drivers/staging/r8188eu/core/rtw_xmit.c b/drivers/staging/r8188eu/core/rtw_xmit.c index 0c033a077bf9..873d2c5c3634 100644 --- a/drivers/staging/r8188eu/core/rtw_xmit.c +++ b/drivers/staging/r8188eu/core/rtw_xmit.c @@ -16,16 +16,13 @@ static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; static void _init_txservq(struct tx_servq *ptxservq) { - INIT_LIST_HEAD(&ptxservq->tx_pending); rtw_init_queue(&ptxservq->sta_pending); ptxservq->qcnt = 0; - } void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) { - memset((unsigned char *)psta_xmitpriv, 0, sizeof(struct sta_xmit_priv)); spin_lock_init(&psta_xmitpriv->lock); _init_txservq(&psta_xmitpriv->be_q); @@ -34,7 +31,32 @@ void _rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv) _init_txservq(&psta_xmitpriv->vo_q); INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz); INIT_LIST_HEAD(&psta_xmitpriv->apsd); +} + +static int rtw_xmit_resource_alloc(struct adapter *padapter, struct xmit_buf *pxmitbuf, + u32 alloc_sz) +{ + pxmitbuf->pallocated_buf = kzalloc(alloc_sz, GFP_KERNEL); + if (!pxmitbuf->pallocated_buf) + return _FAIL; + + pxmitbuf->pbuf = (u8 *)ALIGN((size_t)(pxmitbuf->pallocated_buf), XMITBUF_ALIGN_SZ); + pxmitbuf->dma_transfer_addr = 0; + + pxmitbuf->pxmit_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!pxmitbuf->pxmit_urb) { + kfree(pxmitbuf->pallocated_buf); + return _FAIL; + } + return _SUCCESS; +} + +static void rtw_xmit_resource_free(struct adapter *padapter, struct xmit_buf *pxmitbuf, + u32 free_sz) +{ + usb_free_urb(pxmitbuf->pxmit_urb); + kfree(pxmitbuf->pallocated_buf); } s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) @@ -52,8 +74,8 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) sema_init(&pxmitpriv->terminate_xmitthread_sema, 0); /* - Please insert all the queue initializaiton using rtw_init_queue below - */ + * Please insert all the queue initializaiton using rtw_init_queue below + */ pxmitpriv->adapter = padapter; @@ -66,10 +88,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) rtw_init_queue(&pxmitpriv->free_xmit_queue); /* - Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME, - and initialize free_xmit_frame below. - Please also apply free_txobj to link_up all the xmit_frames... - */ + * Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME, + * and initialize free_xmit_frame below. + * Please also apply free_txobj to link_up all the xmit_frames... + */ pxmitpriv->pallocated_frame_buf = vzalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4); @@ -78,7 +100,7 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) res = _FAIL; goto exit; } - pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_frame_buf), 4); + pxmitpriv->pxmit_frame_buf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_frame_buf), 4); /* pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 - */ /* ((size_t) (pxmitpriv->pallocated_frame_buf) &3); */ @@ -112,10 +134,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) if (!pxmitpriv->pallocated_xmitbuf) { res = _FAIL; - goto exit; + goto free_frame_buf; } - pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmitbuf), 4); + pxmitpriv->pxmitbuf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_xmitbuf), 4); /* pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 - */ /* ((size_t) (pxmitpriv->pallocated_xmitbuf) &3); */ @@ -129,13 +151,12 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitbuf->ext_tag = false; /* Tx buf allocation may fail sometimes, so sleep and retry. */ - res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + res = rtw_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); if (res == _FAIL) { msleep(10); - res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); - if (res == _FAIL) { - goto exit; - } + res = rtw_xmit_resource_alloc(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + if (res == _FAIL) + goto free_xmitbuf; } pxmitbuf->flags = XMIT_VO_QUEUE; @@ -153,10 +174,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) if (!pxmitpriv->pallocated_xmit_extbuf) { res = _FAIL; - goto exit; + goto free_xmitbuf; } - pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4); + pxmitpriv->pxmit_extbuf = (u8 *)ALIGN((size_t)(pxmitpriv->pallocated_xmit_extbuf), 4); pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; @@ -167,10 +188,10 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitbuf->padapter = padapter; pxmitbuf->ext_tag = true; - res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); + res = rtw_xmit_resource_alloc(padapter, pxmitbuf, max_xmit_extbuf_size + XMITBUF_ALIGN_SZ); if (res == _FAIL) { res = _FAIL; - goto exit; + goto free_xmit_extbuf; } list_add_tail(&pxmitbuf->list, &pxmitpriv->free_xmit_extbuf_queue.queue); @@ -179,7 +200,11 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf; - rtw_alloc_hwxmits(padapter); + if (rtw_alloc_hwxmits(padapter)) { + res = _FAIL; + goto free_xmit_extbuf; + } + rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry); for (i = 0; i < 4; i++) @@ -201,11 +226,54 @@ s32 _rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, struct adapter *padapter) rtl8188eu_init_xmit_priv(padapter); -exit: + return _SUCCESS; +free_xmit_extbuf: + pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; + while (i--) { + rtw_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); + pxmitbuf++; + } + vfree(pxmitpriv->pallocated_xmit_extbuf); + i = NR_XMITBUFF; +free_xmitbuf: + pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf; + while (i--) { + rtw_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + pxmitbuf++; + } + vfree(pxmitpriv->pallocated_xmitbuf); +free_frame_buf: + vfree(pxmitpriv->pallocated_frame_buf); +exit: return res; } +static void rtw_pkt_complete(struct adapter *padapter, struct sk_buff *pkt) +{ + u16 queue; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + + queue = skb_get_queue_mapping(pkt); + if (padapter->registrypriv.wifi_spec) { + if (__netif_subqueue_stopped(padapter->pnetdev, queue) && + (pxmitpriv->hwxmits[queue].accnt < WMM_XMIT_THRESHOLD)) + netif_wake_subqueue(padapter->pnetdev, queue); + } else { + if (__netif_subqueue_stopped(padapter->pnetdev, queue)) + netif_wake_subqueue(padapter->pnetdev, queue); + } + + dev_kfree_skb_any(pkt); +} + +void rtw_xmit_complete(struct adapter *padapter, struct xmit_frame *pxframe) +{ + if (pxframe->pkt) + rtw_pkt_complete(padapter, pxframe->pkt); + pxframe->pkt = NULL; +} + void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) { int i; @@ -219,13 +287,13 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) return; for (i = 0; i < NR_XMITFRAME; i++) { - rtw_os_xmit_complete(padapter, pxmitframe); + rtw_xmit_complete(padapter, pxmitframe); pxmitframe++; } for (i = 0; i < NR_XMITBUFF; i++) { - rtw_os_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); + rtw_xmit_resource_free(padapter, pxmitbuf, (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ)); pxmitbuf++; } @@ -235,7 +303,7 @@ void _rtw_free_xmit_priv(struct xmit_priv *pxmitpriv) pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf; for (i = 0; i < num_xmit_extbuf; i++) { - rtw_os_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); + rtw_xmit_resource_free(padapter, pxmitbuf, (max_xmit_extbuf_size + XMITBUF_ALIGN_SZ)); pxmitbuf++; } @@ -296,6 +364,7 @@ static void update_attrib_vcs_info(struct adapter *padapter, struct xmit_frame * /* 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; @@ -372,25 +441,65 @@ u8 qos_acm(u8 acm_mask, u8 priority) change_priority = 5; break; default: - DBG_88E("qos_acm(): invalid pattrib->priority: %d!!!\n", priority); break; } return change_priority; } +static void rtw_open_pktfile(struct sk_buff *pktptr, struct pkt_file *pfile) +{ + if (!pktptr) { + pr_err("8188eu: pktptr is NULL\n"); + return; + } + if (!pfile) { + pr_err("8188eu: pfile is NULL\n"); + return; + } + pfile->pkt = pktptr; + pfile->cur_addr = pktptr->data; + pfile->buf_start = pktptr->data; + pfile->pkt_len = pktptr->len; + pfile->buf_len = pktptr->len; + + pfile->cur_buffer = pfile->buf_start; +} + +static uint rtw_remainder_len(struct pkt_file *pfile) +{ + return pfile->buf_len - ((size_t)(pfile->cur_addr) - + (size_t)(pfile->buf_start)); +} + +static uint rtw_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen) +{ + uint len; + + len = rtw_remainder_len(pfile); + len = (rlen > len) ? len : rlen; + + if (rmem) + skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len, rmem, len); + + pfile->cur_addr += len; + pfile->pkt_len -= len; + + return len; +} + static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) { struct ethhdr etherhdr; struct iphdr ip_hdr; s32 user_prio = 0; - _rtw_open_pktfile(ppktfile->pkt, ppktfile); - _rtw_pktfile_read(ppktfile, (unsigned char *)ðerhdr, ETH_HLEN); + rtw_open_pktfile(ppktfile->pkt, ppktfile); + rtw_pktfile_read(ppktfile, (unsigned char *)ðerhdr, ETH_HLEN); /* get user_prio from IP hdr */ if (pattrib->ether_type == 0x0800) { - _rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr)); + rtw_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr)); /* user_prio = (ntohs(ip_hdr.tos) >> 5) & 0x3; */ user_prio = ip_hdr.tos >> 5; } else if (pattrib->ether_type == 0x888e) { @@ -401,7 +510,7 @@ static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib) pattrib->priority = user_prio; pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN; - pattrib->subtype = WIFI_QOS_DATA_TYPE; + pattrib->subtype = IEEE80211_STYPE_QOS_DATA | IEEE80211_FTYPE_DATA; } static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct pkt_attrib *pattrib) @@ -419,8 +528,8 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p - _rtw_open_pktfile(pkt, &pktfile); - _rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN); + rtw_open_pktfile(pkt, &pktfile); + rtw_pktfile_read(&pktfile, (u8 *)ðerhdr, ETH_HLEN); pattrib->ether_type = ntohs(etherhdr.h_proto); @@ -443,30 +552,24 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->pktlen = pktfile.pkt_len; - if (ETH_P_IP == pattrib->ether_type) { + 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 */ u8 tmp[24]; - _rtw_pktfile_read(&pktfile, &tmp[0], 24); + + rtw_pktfile_read(&pktfile, &tmp[0], 24); pattrib->dhcp_pkt = 0; if (pktfile.pkt_len > 282) {/* MINIMUM_DHCP_PACKET_SIZE) { */ - if (ETH_P_IP == pattrib->ether_type) {/* IP header */ - if (((tmp[21] == 68) && (tmp[23] == 67)) || - ((tmp[21] == 67) && (tmp[23] == 68))) { - /* 68 : UDP BOOTP client */ - /* 67 : UDP BOOTP server */ - /* Use low rate to send DHCP packet. */ - pattrib->dhcp_pkt = 1; - } + if (((tmp[21] == 68) && (tmp[23] == 67)) || + ((tmp[21] == 67) && (tmp[23] == 68))) { + /* 68 : UDP BOOTP client */ + /* 67 : UDP BOOTP server */ + /* Use low rate to send DHCP packet. */ + pattrib->dhcp_pkt = 1; } } - } else if (0x888e == pattrib->ether_type) { - DBG_88E_LEVEL(_drv_info_, "send eapol packet\n"); } - if ((pattrib->ether_type == 0x888e) || (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 == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1)) rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1); @@ -489,7 +592,6 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p if (psta) { pattrib->mac_id = psta->mac_id; - /* DBG_88E("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */ pattrib->psta = psta; } else { /* if we cannot get psta => drop the pkt */ @@ -502,7 +604,7 @@ static s32 update_attrib(struct adapter *padapter, struct sk_buff *pkt, struct p pattrib->pkt_hdrlen = ETH_HLEN;/* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */ pattrib->hdrlen = WLAN_HDR_A3_LEN; - pattrib->subtype = WIFI_DATA_TYPE; + pattrib->subtype = IEEE80211_FTYPE_DATA; pattrib->priority = 0; if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE)) { @@ -630,7 +732,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr if (pframe[1] & 2) /* From Ds == 1 */ rtw_secmicappend(&micdata, &pframe[24], 6); else - rtw_secmicappend(&micdata, &pframe[10], 6); + rtw_secmicappend(&micdata, &pframe[10], 6); } else { /* ToDS == 0 */ rtw_secmicappend(&micdata, &pframe[4], 6); /* DA */ if (pframe[1] & 2) /* From Ds == 1 */ @@ -647,7 +749,7 @@ static s32 xmitframe_addmic(struct adapter *padapter, struct xmit_frame *pxmitfr payload = pframe; for (curfragnum = 0; curfragnum < pattrib->nr_frags; curfragnum++) { - payload = (u8 *)RND4((size_t)(payload)); + payload = PTR_ALIGN(payload, 4); payload = payload + pattrib->hdrlen + pattrib->iv_len; if ((curfragnum + 1) == pattrib->nr_frags) { @@ -701,31 +803,28 @@ s32 rtw_make_wlanhdr(struct adapter *padapter, u8 *hdr, struct pkt_attrib *pattr { u16 *qc; - struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr; + struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr; struct mlme_priv *pmlmepriv = &padapter->mlmepriv; struct qos_priv *pqospriv = &pmlmepriv->qospriv; u8 qos_option = false; int res = _SUCCESS; - __le16 *fctrl = &pwlanhdr->frame_ctl; + __le16 *fctrl = &pwlanhdr->frame_control; struct sta_info *psta; - if (pattrib->psta) { + if (pattrib->psta) psta = pattrib->psta; - } else { - if (is_multicast_ether_addr(pattrib->ra)) { - psta = rtw_get_bcmc_stainfo(padapter); - } else { - psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); - } - } + else if (is_multicast_ether_addr(pattrib->ra)) + psta = rtw_get_bcmc_stainfo(padapter); + else + psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra); memset(hdr, 0, WLANHDR_OFFSET); SetFrameSubType(fctrl, pattrib->subtype); - if (pattrib->subtype & WIFI_DATA_TYPE) { + if (pattrib->subtype & IEEE80211_FTYPE_DATA) { if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) { /* to_ds = 1, fr_ds = 0; */ /* Data transfer to AP */ @@ -861,22 +960,19 @@ s32 rtw_txframes_sta_ac_pending(struct adapter *padapter, struct pkt_attrib *pat } /* - -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. - -*/ + * 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. + */ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct xmit_frame *pxmitframe) { struct pkt_file pktfile; s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz; - size_t addr; u8 *pframe, *mem_start; u8 hw_hdr_offset; struct sta_info *psta; @@ -894,10 +990,8 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct if (!psta) return _FAIL; - if (!pxmitframe->buf_addr) { - DBG_88E("==> %s buf_addr == NULL\n", __func__); + if (!pxmitframe->buf_addr) return _FAIL; - } pbuf_start = pxmitframe->buf_addr; @@ -906,13 +1000,12 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct mem_start = pbuf_start + hw_hdr_offset; if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) { - DBG_88E("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n"); res = _FAIL; goto exit; } - _rtw_open_pktfile(pkt, &pktfile); - _rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen); + rtw_open_pktfile(pkt, &pktfile); + rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen); frg_inx = 0; frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */ @@ -965,15 +1058,14 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct mpdu_len -= llc_sz; } - if ((pattrib->icv_len > 0) && (pattrib->bswenc)) { + if ((pattrib->icv_len > 0) && (pattrib->bswenc)) mpdu_len -= pattrib->icv_len; - } if (bmcst) { - /* don't do fragment to broadcat/multicast packets */ - mem_sz = _rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen); + /* don't do fragment to broadcast/multicast packets */ + mem_sz = rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen); } else { - mem_sz = _rtw_pktfile_read(&pktfile, pframe, mpdu_len); + mem_sz = rtw_pktfile_read(&pktfile, pframe, mpdu_len); } pframe += mem_sz; @@ -985,7 +1077,7 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct frg_inx++; - if (bmcst || rtw_endofpktfile(&pktfile)) { + if (bmcst || pktfile.pkt_len == 0) { pattrib->nr_frags = frg_inx; pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags == 1) ? llc_sz : 0) + @@ -996,14 +1088,11 @@ s32 rtw_xmitframe_coalesce(struct adapter *padapter, struct sk_buff *pkt, struct break; } - addr = (size_t)(pframe); - - mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset; + 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) { - DBG_88E("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"); res = _FAIL; goto exit; } @@ -1083,7 +1172,6 @@ void rtw_update_protection(struct adapter *padapter, u8 *ie, uint ie_len) } break; } - } void rtw_count_tx_stats(struct adapter *padapter, struct xmit_frame *pxmitframe, int sz) @@ -1133,10 +1221,8 @@ struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv) pxmitbuf->priv_data = NULL; /* pxmitbuf->ext_tag = true; */ - if (pxmitbuf->sctx) { - DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); + if (pxmitbuf->sctx) rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } } spin_unlock_irqrestore(&pfree_queue->lock, flags); @@ -1171,8 +1257,6 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue; unsigned long flags; - /* DBG_88E("+rtw_alloc_xmitbuf\n"); */ - spin_lock_irqsave(&pfree_xmitbuf_queue->lock, flags); if (list_empty(&pfree_xmitbuf_queue->queue)) { @@ -1190,10 +1274,8 @@ struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv) if (pxmitbuf) { pxmitpriv->free_xmitbuf_cnt--; pxmitbuf->priv_data = NULL; - if (pxmitbuf->sctx) { - DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); + if (pxmitbuf->sctx) rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC); - } } spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, flags); @@ -1208,10 +1290,8 @@ s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) if (!pxmitbuf) return _FAIL; - if (pxmitbuf->sctx) { - DBG_88E("%s pxmitbuf->sctx is not NULL\n", __func__); + if (pxmitbuf->sctx) rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE); - } if (pxmitbuf->ext_tag) { rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf); @@ -1230,24 +1310,22 @@ s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf) } /* -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... - -*/ - + * 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... + */ struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)/* _queue *pfree_xmit_queue) */ { /* - Please remember to use all the osdep_service api, - and lock/unlock or _enter/_exit critical to protect - pfree_xmit_queue - */ + * Please remember to use all the osdep_service api, + * and lock/unlock or _enter/_exit critical to protect + * pfree_xmit_queue + */ struct xmit_frame *pxframe = NULL; struct list_head *plist, *phead; @@ -1315,7 +1393,7 @@ s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitfram spin_unlock_bh(&pfree_xmit_queue->lock); if (pndis_pkt) - rtw_os_pkt_complete(padapter, pndis_pkt); + rtw_pkt_complete(padapter, pndis_pkt); exit: @@ -1340,7 +1418,6 @@ void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, struct __queue *pfram rtw_free_xmitframe(pxmitpriv, pxmitframe); } spin_unlock_bh(&pframequeue->lock); - } s32 rtw_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe) @@ -1471,15 +1548,13 @@ s32 rtw_xmit_classifier(struct adapter *padapter, struct xmit_frame *pxmitframe) struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits; int res = _SUCCESS; - if (pattrib->psta) { + if (pattrib->psta) psta = pattrib->psta; - } else { + else psta = rtw_get_stainfo(pstapriv, pattrib->ra); - } if (!psta) { res = _FAIL; - DBG_88E("rtw_xmit_classifier: psta == NULL\n"); goto exit; } @@ -1496,7 +1571,7 @@ exit: return res; } -void rtw_alloc_hwxmits(struct adapter *padapter) +int rtw_alloc_hwxmits(struct adapter *padapter) { struct hw_xmit *hwxmits; struct xmit_priv *pxmitpriv = &padapter->xmitpriv; @@ -1504,22 +1579,17 @@ void rtw_alloc_hwxmits(struct adapter *padapter) pxmitpriv->hwxmit_entry = HWXMIT_ENTRY; pxmitpriv->hwxmits = kzalloc(sizeof(struct hw_xmit) * pxmitpriv->hwxmit_entry, GFP_KERNEL); + if (!pxmitpriv->hwxmits) + return -ENOMEM; hwxmits = pxmitpriv->hwxmits; - if (pxmitpriv->hwxmit_entry == 5) { - hwxmits[0] .sta_queue = &pxmitpriv->bm_pending; - hwxmits[1] .sta_queue = &pxmitpriv->vo_pending; - hwxmits[2] .sta_queue = &pxmitpriv->vi_pending; - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - hwxmits[4] .sta_queue = &pxmitpriv->be_pending; - } else if (pxmitpriv->hwxmit_entry == 4) { - hwxmits[0] .sta_queue = &pxmitpriv->vo_pending; - hwxmits[1] .sta_queue = &pxmitpriv->vi_pending; - hwxmits[2] .sta_queue = &pxmitpriv->be_pending; - hwxmits[3] .sta_queue = &pxmitpriv->bk_pending; - } else { - } + hwxmits[0].sta_queue = &pxmitpriv->vo_pending; + hwxmits[1].sta_queue = &pxmitpriv->vi_pending; + hwxmits[2].sta_queue = &pxmitpriv->be_pending; + hwxmits[3].sta_queue = &pxmitpriv->bk_pending; + + return 0; } void rtw_free_hwxmits(struct adapter *padapter) @@ -1537,7 +1607,6 @@ void rtw_init_hwxmits(struct hw_xmit *phwxmit, int entry) for (i = 0; i < entry; i++, phwxmit++) phwxmit->accnt = 0; - } static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb) @@ -1605,10 +1674,8 @@ static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb) } newskb = skb_copy(skb, GFP_ATOMIC); - if (!newskb) { - DEBUG_ERR("TX DROP: skb_copy fail!\n"); + if (!newskb) return -1; - } dev_kfree_skb_any(skb); *pskb = skb = newskb; @@ -1620,21 +1687,15 @@ static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb) } } - if (skb_is_nonlinear(skb)) - DEBUG_ERR("%s(): skb_is_nonlinear!!\n", __func__); - res = skb_linearize(skb); - if (res < 0) { - DEBUG_ERR("TX DROP: skb_linearize fail!\n"); - return -1; - } + if (res < 0) + return -1; res = nat25_db_handle(padapter, skb, NAT25_INSERT); if (res < 0) { - if (res == -2) { - DEBUG_ERR("TX DROP: nat25_db_handle fail!\n"); + if (res == -2) return -1; - } + return 0; } } @@ -1653,11 +1714,9 @@ static int rtw_br_client_tx(struct adapter *padapter, struct sk_buff **pskb) } /* check if SA is equal to our MAC */ - if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(padapter), ETH_ALEN)) { - DEBUG_ERR("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n", - skb->data[6], skb->data[7], skb->data[8], skb->data[9], skb->data[10], skb->data[11]); + if (memcmp(skb->data + ETH_ALEN, GET_MY_HWADDR(padapter), ETH_ALEN)) return -1; - } + return 0; } @@ -1724,10 +1783,8 @@ s32 rtw_xmit(struct adapter *padapter, struct sk_buff **ppkt) s32 res; pxmitframe = rtw_alloc_xmitframe(pxmitpriv); - if (!pxmitframe) { - DBG_88E("DBG_TX_DROP_FRAME %s no more pxmitframe\n", __func__); + if (!pxmitframe) return -1; - } rcu_read_lock(); br_port = rcu_dereference(padapter->pnetdev->rx_handler_data); @@ -1776,7 +1833,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra bool bmcst = is_multicast_ether_addr(pattrib->ra); if (!check_fwstate(pmlmepriv, WIFI_AP_STATE)) - return ret; + return ret; if (pattrib->psta) psta = pattrib->psta; @@ -1804,8 +1861,8 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra pstapriv->tim_bitmap |= BIT(0);/* */ pstapriv->sta_dz_bitmap |= BIT(0); - - update_beacon(padapter, _TIM_IE_, NULL, false);/* tx bc/mc packets after upate bcn */ + /* tx bc/mc packets after update bcn */ + update_beacon(padapter, _TIM_IE_, NULL, false); ret = true; } @@ -1855,7 +1912,7 @@ int xmitframe_enqueue_for_sleeping_sta(struct adapter *padapter, struct xmit_fra pstapriv->tim_bitmap |= BIT(psta->aid); if (psta->sleepq_len == 1) { - /* upate BCN for TIM IE */ + /* update BCN for TIM IE */ update_beacon(padapter, _TIM_IE_, NULL, false); } } @@ -1995,7 +2052,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) spin_unlock_bh(&psta->sleep_q.lock); if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_os_xmit_complete(padapter, pxmitframe); + rtw_xmit_complete(padapter, pxmitframe); spin_lock_bh(&psta->sleep_q.lock); } @@ -2045,7 +2102,7 @@ void wakeup_sta_to_xmit(struct adapter *padapter, struct sta_info *psta) spin_unlock_bh(&psta_bmc->sleep_q.lock); if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_os_xmit_complete(padapter, pxmitframe); + rtw_xmit_complete(padapter, pxmitframe); spin_lock_bh(&psta_bmc->sleep_q.lock); } @@ -2119,12 +2176,12 @@ void xmit_delivery_enabled_frames(struct adapter *padapter, struct sta_info *pst pxmitframe->attrib.triggered = 1; if (rtl8188eu_hal_xmit(padapter, pxmitframe)) - rtw_os_xmit_complete(padapter, pxmitframe); + rtw_xmit_complete(padapter, pxmitframe); if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) && (wmmps_ac)) { pstapriv->tim_bitmap &= ~BIT(psta->aid); - /* upate BCN for TIM IE */ + /* update BCN for TIM IE */ update_beacon(padapter, _TIM_IE_, NULL, false); } } @@ -2147,13 +2204,11 @@ int rtw_sctx_wait(struct submit_ctx *sctx) int status = 0; expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : MAX_SCHEDULE_TIMEOUT; - if (!wait_for_completion_timeout(&sctx->done, expire)) { + if (!wait_for_completion_timeout(&sctx->done, expire)) /* timeout, do something?? */ status = RTW_SCTX_DONE_TIMEOUT; - DBG_88E("%s timeout\n", __func__); - } else { + else status = sctx->status; - } if (status == RTW_SCTX_DONE_SUCCESS) ret = _SUCCESS; @@ -2161,26 +2216,9 @@ int rtw_sctx_wait(struct submit_ctx *sctx) 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 rtw_sctx_done_err(struct submit_ctx **sctx, int status) { if (*sctx) { - if (rtw_sctx_chk_waring_status(status)) - DBG_88E("%s status:%d\n", __func__, status); (*sctx)->status = status; complete(&((*sctx)->done)); *sctx = NULL; @@ -2204,6 +2242,106 @@ void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status) if (pxmitpriv->ack_tx) rtw_sctx_done_err(&pack_tx_ops, status); - else - DBG_88E("%s ack_tx not set\n", __func__); +} + +static void rtw_check_xmit_resource(struct adapter *padapter, struct sk_buff *pkt) +{ + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + u16 queue; + + queue = skb_get_queue_mapping(pkt); + if (padapter->registrypriv.wifi_spec) { + /* No free space for Tx, tx_worker is too slow */ + if (pxmitpriv->hwxmits[queue].accnt > WMM_XMIT_THRESHOLD) + netif_stop_subqueue(padapter->pnetdev, queue); + } else { + if (pxmitpriv->free_xmitframe_cnt <= 4) { + if (!netif_tx_queue_stopped(netdev_get_tx_queue(padapter->pnetdev, queue))) + netif_stop_subqueue(padapter->pnetdev, queue); + } + } +} + +static int rtw_mlcst2unicst(struct adapter *padapter, struct sk_buff *skb) +{ + struct sta_priv *pstapriv = &padapter->stapriv; + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct list_head *phead, *plist; + struct sk_buff *newskb; + struct sta_info *psta = NULL; + s32 res; + + spin_lock_bh(&pstapriv->asoc_list_lock); + phead = &pstapriv->asoc_list; + plist = phead->next; + + /* free sta asoc_queue */ + while (phead != plist) { + psta = container_of(plist, struct sta_info, asoc_list); + + plist = plist->next; + + /* avoid come from STA1 and send back STA1 */ + if (!memcmp(psta->hwaddr, &skb->data[6], 6)) + continue; + + newskb = skb_copy(skb, GFP_ATOMIC); + + if (newskb) { + memcpy(newskb->data, psta->hwaddr, 6); + res = rtw_xmit(padapter, &newskb); + if (res < 0) { + pxmitpriv->tx_drop++; + dev_kfree_skb_any(newskb); + } else { + pxmitpriv->tx_pkts++; + } + } else { + pxmitpriv->tx_drop++; + + spin_unlock_bh(&pstapriv->asoc_list_lock); + return false; /* Caller shall tx this multicast frame via normal way. */ + } + } + + spin_unlock_bh(&pstapriv->asoc_list_lock); + dev_kfree_skb_any(skb); + return true; +} + +netdev_tx_t rtw_xmit_entry(struct sk_buff *pkt, struct net_device *pnetdev) +{ + struct adapter *padapter = (struct adapter *)rtw_netdev_priv(pnetdev); + struct xmit_priv *pxmitpriv = &padapter->xmitpriv; + struct mlme_priv *pmlmepriv = &padapter->mlmepriv; + s32 res = 0; + + if (!rtw_if_up(padapter)) + goto drop_packet; + + rtw_check_xmit_resource(padapter, pkt); + + if (!rtw_mc2u_disable && check_fwstate(pmlmepriv, WIFI_AP_STATE) && + (IP_MCAST_MAC(pkt->data) || ICMPV6_MCAST_MAC(pkt->data)) && + (padapter->registrypriv.wifi_spec == 0)) { + if (pxmitpriv->free_xmitframe_cnt > (NR_XMITFRAME / 4)) { + res = rtw_mlcst2unicst(padapter, pkt); + if (res) + goto exit; + } + } + + res = rtw_xmit(padapter, &pkt); + if (res < 0) + goto drop_packet; + + pxmitpriv->tx_pkts++; + goto exit; + +drop_packet: + pxmitpriv->tx_drop++; + dev_kfree_skb_any(pkt); + +exit: + return NETDEV_TX_OK; } |