blob: cdd27c47f8fd44716dda1b40df1a3b5c555d290b [file] [log] [blame]
Larry Finger5e93f352014-03-28 21:37:38 -05001/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 ******************************************************************************/
15#define _RTW_XMIT_C_
16
17#include <osdep_service.h>
18#include <drv_types.h>
19#include <wifi.h>
20#include <osdep_intf.h>
21#include <linux/ip.h>
22#include <usb_ops.h>
Jes Sorensen638443d2014-05-16 10:04:18 +020023#include <rtl8723a_xmit.h>
Larry Finger5e93f352014-03-28 21:37:38 -050024
25static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
26static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
27
28static void _init_txservq(struct tx_servq *ptxservq)
29{
30
31 INIT_LIST_HEAD(&ptxservq->tx_pending);
32 _rtw_init_queue23a(&ptxservq->sta_pending);
33 ptxservq->qcnt = 0;
34
35}
36
37void _rtw_init_sta_xmit_priv23a(struct sta_xmit_priv *psta_xmitpriv)
38{
39
40 spin_lock_init(&psta_xmitpriv->lock);
41
42 /* for (i = 0 ; i < MAX_NUMBLKS; i++) */
43 /* _init_txservq(&psta_xmitpriv->blk_q[i]); */
44
45 _init_txservq(&psta_xmitpriv->be_q);
46 _init_txservq(&psta_xmitpriv->bk_q);
47 _init_txservq(&psta_xmitpriv->vi_q);
48 _init_txservq(&psta_xmitpriv->vo_q);
49 INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
50 INIT_LIST_HEAD(&psta_xmitpriv->apsd);
51
52}
53
Jes Sorensen269746a2014-05-09 15:03:54 +020054int _rtw_init_xmit_priv23a(struct xmit_priv *pxmitpriv,
55 struct rtw_adapter *padapter)
Larry Finger5e93f352014-03-28 21:37:38 -050056{
57 int i;
58 struct xmit_buf *pxmitbuf;
59 struct xmit_frame *pxframe;
Jes Sorensen269746a2014-05-09 15:03:54 +020060 int res = _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -050061 u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
62 u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
63
Larry Finger5e93f352014-03-28 21:37:38 -050064 spin_lock_init(&pxmitpriv->lock);
65 spin_lock_init(&pxmitpriv->lock_sctx);
66 sema_init(&pxmitpriv->xmit_sema, 0);
67 sema_init(&pxmitpriv->terminate_xmitthread_sema, 0);
68
Larry Finger5e93f352014-03-28 21:37:38 -050069 pxmitpriv->adapter = padapter;
70
71 _rtw_init_queue23a(&pxmitpriv->be_pending);
72 _rtw_init_queue23a(&pxmitpriv->bk_pending);
73 _rtw_init_queue23a(&pxmitpriv->vi_pending);
74 _rtw_init_queue23a(&pxmitpriv->vo_pending);
75 _rtw_init_queue23a(&pxmitpriv->bm_pending);
76
77 _rtw_init_queue23a(&pxmitpriv->free_xmit_queue);
78
Larry Finger5e93f352014-03-28 21:37:38 -050079 for (i = 0; i < NR_XMITFRAME; i++) {
Jes Sorensen251ccc22014-05-09 15:03:52 +020080 pxframe = (struct xmit_frame *)
81 kzalloc(sizeof(struct xmit_frame), GFP_KERNEL);
82 if (!pxframe)
83 break;
Larry Finger5e93f352014-03-28 21:37:38 -050084 INIT_LIST_HEAD(&pxframe->list);
85
86 pxframe->padapter = padapter;
87 pxframe->frame_tag = NULL_FRAMETAG;
88
Larry Finger5e93f352014-03-28 21:37:38 -050089 list_add_tail(&pxframe->list,
90 &pxmitpriv->free_xmit_queue.queue);
Larry Finger5e93f352014-03-28 21:37:38 -050091 }
92
Jes Sorensen251ccc22014-05-09 15:03:52 +020093 pxmitpriv->free_xmitframe_cnt = i;
Larry Finger5e93f352014-03-28 21:37:38 -050094
95 pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
96
97 /* init xmit_buf */
98 _rtw_init_queue23a(&pxmitpriv->free_xmitbuf_queue);
99 INIT_LIST_HEAD(&pxmitpriv->xmitbuf_list);
100 _rtw_init_queue23a(&pxmitpriv->pending_xmitbuf_queue);
101
102 for (i = 0; i < NR_XMITBUFF; i++) {
103 pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL);
104 if (!pxmitbuf)
105 goto fail;
106 INIT_LIST_HEAD(&pxmitbuf->list);
107 INIT_LIST_HEAD(&pxmitbuf->list2);
108
109 pxmitbuf->padapter = padapter;
110
111 /* Tx buf allocation may fail sometimes, so sleep and retry. */
112 res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf,
113 (MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ));
114 if (res == _FAIL) {
115 goto fail;
116 }
117
118 list_add_tail(&pxmitbuf->list,
119 &pxmitpriv->free_xmitbuf_queue.queue);
120 list_add_tail(&pxmitbuf->list2,
121 &pxmitpriv->xmitbuf_list);
122 }
123
124 pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
125
126 /* init xframe_ext queue, the same count as extbuf */
127 _rtw_init_queue23a(&pxmitpriv->free_xframe_ext_queue);
128
Larry Finger5e93f352014-03-28 21:37:38 -0500129 for (i = 0; i < num_xmit_extbuf; i++) {
Jes Sorensen3a350582014-05-09 15:03:53 +0200130 pxframe = (struct xmit_frame *)
131 kzalloc(sizeof(struct xmit_frame), GFP_KERNEL);
132 if (!pxframe)
133 break;
Larry Finger5e93f352014-03-28 21:37:38 -0500134 INIT_LIST_HEAD(&pxframe->list);
135
136 pxframe->padapter = padapter;
137 pxframe->frame_tag = NULL_FRAMETAG;
138
139 pxframe->pkt = NULL;
140
141 pxframe->buf_addr = NULL;
142 pxframe->pxmitbuf = NULL;
143
144 pxframe->ext_tag = 1;
145
146 list_add_tail(&pxframe->list,
147 &pxmitpriv->free_xframe_ext_queue.queue);
Larry Finger5e93f352014-03-28 21:37:38 -0500148 }
Jes Sorensen3a350582014-05-09 15:03:53 +0200149 pxmitpriv->free_xframe_ext_cnt = i;
Larry Finger5e93f352014-03-28 21:37:38 -0500150
151 /* Init xmit extension buff */
152 _rtw_init_queue23a(&pxmitpriv->free_xmit_extbuf_queue);
153 INIT_LIST_HEAD(&pxmitpriv->xmitextbuf_list);
154
155 for (i = 0; i < num_xmit_extbuf; i++) {
156 pxmitbuf = kzalloc(sizeof(struct xmit_buf), GFP_KERNEL);
157 if (!pxmitbuf)
158 goto fail;
159 INIT_LIST_HEAD(&pxmitbuf->list);
160 INIT_LIST_HEAD(&pxmitbuf->list2);
161
162 pxmitbuf->padapter = padapter;
163
164 /* Tx buf allocation may fail sometimes, so sleep and retry. */
165 res = rtw_os_xmit_resource_alloc23a(padapter, pxmitbuf,
166 max_xmit_extbuf_size + XMITBUF_ALIGN_SZ);
167 if (res == _FAIL) {
168 goto exit;
169 }
170
171 list_add_tail(&pxmitbuf->list,
172 &pxmitpriv->free_xmit_extbuf_queue.queue);
173 list_add_tail(&pxmitbuf->list2,
174 &pxmitpriv->xmitextbuf_list);
175 }
176
177 pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
178
179 rtw_alloc_hwxmits23a(padapter);
180 rtw_init_hwxmits23a(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
181
182 for (i = 0; i < 4; i ++)
183 pxmitpriv->wmm_para_seq[i] = i;
184
185 pxmitpriv->txirp_cnt = 1;
186
187 sema_init(&pxmitpriv->tx_retevt, 0);
188
189 /* per AC pending irp */
190 pxmitpriv->beq_cnt = 0;
191 pxmitpriv->bkq_cnt = 0;
192 pxmitpriv->viq_cnt = 0;
193 pxmitpriv->voq_cnt = 0;
194
195 pxmitpriv->ack_tx = false;
196 mutex_init(&pxmitpriv->ack_tx_mutex);
197 rtw_sctx_init23a(&pxmitpriv->ack_tx_ops, 0);
Jes Sorensenb3d139a2014-05-16 10:04:17 +0200198 tasklet_init(&padapter->xmitpriv.xmit_tasklet,
199 (void(*)(unsigned long))rtl8723au_xmit_tasklet,
200 (unsigned long)padapter);
Larry Finger5e93f352014-03-28 21:37:38 -0500201
202exit:
203
204 return res;
205fail:
206 goto exit;
207}
208
209void _rtw_free_xmit_priv23a (struct xmit_priv *pxmitpriv)
210{
211 struct rtw_adapter *padapter = pxmitpriv->adapter;
Jes Sorensen251ccc22014-05-09 15:03:52 +0200212 struct xmit_frame *pxframe;
Larry Finger5e93f352014-03-28 21:37:38 -0500213 struct xmit_buf *pxmitbuf;
214 struct list_head *plist, *ptmp;
Larry Finger5e93f352014-03-28 21:37:38 -0500215
Jes Sorensen251ccc22014-05-09 15:03:52 +0200216 list_for_each_safe(plist, ptmp, &pxmitpriv->free_xmit_queue.queue) {
217 pxframe = container_of(plist, struct xmit_frame, list);
218 list_del_init(&pxframe->list);
219 rtw_os_xmit_complete23a(padapter, pxframe);
220 kfree(pxframe);
Larry Finger5e93f352014-03-28 21:37:38 -0500221 }
222
223 list_for_each_safe(plist, ptmp, &pxmitpriv->xmitbuf_list) {
224 pxmitbuf = container_of(plist, struct xmit_buf, list2);
225 list_del_init(&pxmitbuf->list2);
226 rtw_os_xmit_resource_free23a(padapter, pxmitbuf);
227 kfree(pxmitbuf);
228 }
229
Larry Finger5e93f352014-03-28 21:37:38 -0500230 /* free xframe_ext queue, the same count as extbuf */
Jes Sorensen3a350582014-05-09 15:03:53 +0200231 list_for_each_safe(plist, ptmp,
232 &pxmitpriv->free_xframe_ext_queue.queue) {
233 pxframe = container_of(plist, struct xmit_frame, list);
234 list_del_init(&pxframe->list);
235 rtw_os_xmit_complete23a(padapter, pxframe);
236 kfree(pxframe);
Larry Finger5e93f352014-03-28 21:37:38 -0500237 }
Larry Finger5e93f352014-03-28 21:37:38 -0500238
239 /* free xmit extension buff */
240 list_for_each_safe(plist, ptmp, &pxmitpriv->xmitextbuf_list) {
241 pxmitbuf = container_of(plist, struct xmit_buf, list2);
242 list_del_init(&pxmitbuf->list2);
243 rtw_os_xmit_resource_free23a(padapter, pxmitbuf);
244 kfree(pxmitbuf);
245 }
246
247 rtw_free_hwxmits23a(padapter);
248 mutex_destroy(&pxmitpriv->ack_tx_mutex);
249}
250
251static void update_attrib_vcs_info(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
252{
253 u32 sz;
254 struct pkt_attrib *pattrib = &pxmitframe->attrib;
255 struct sta_info *psta = pattrib->psta;
256 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
257 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
258
259 if (pattrib->psta) {
260 psta = pattrib->psta;
261 } else {
262 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
263 psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
264 }
265
266 if (psta == NULL) {
267 DBG_8723A("%s, psta == NUL\n", __func__);
268 return;
269 }
270
271 if (!(psta->state &_FW_LINKED)) {
272 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
273 return;
274 }
275
276 if (pattrib->nr_frags != 1)
277 sz = padapter->xmitpriv.frag_len;
278 else /* no frag */
279 sz = pattrib->last_txcmdsz;
280
281 /* (1) RTS_Threshold is compared to the MPDU, not MSDU. */
282 /* (2) If there are more than one frag in this MSDU, only the first frag uses protection frame. */
283 /* Other fragments are protected by previous fragment. */
284 /* So we only need to check the length of first fragment. */
285 if (pmlmeext->cur_wireless_mode < WIRELESS_11_24N || padapter->registrypriv.wifi_spec) {
286 if (sz > padapter->registrypriv.rts_thresh) {
287 pattrib->vcs_mode = RTS_CTS;
288 } else {
289 if (psta->rtsen)
290 pattrib->vcs_mode = RTS_CTS;
291 else if (psta->cts2self)
292 pattrib->vcs_mode = CTS_TO_SELF;
293 else
294 pattrib->vcs_mode = NONE_VCS;
295 }
296 } else {
297 while (true) {
298 /* IOT action */
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200299 if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS &&
300 pattrib->ampdu_en &&
301 padapter->securitypriv.dot11PrivacyAlgrthm ==
302 WLAN_CIPHER_SUITE_CCMP) {
Larry Finger5e93f352014-03-28 21:37:38 -0500303 pattrib->vcs_mode = CTS_TO_SELF;
304 break;
305 }
306
307 /* check ERP protection */
308 if (psta->rtsen || psta->cts2self) {
309 if (psta->rtsen)
310 pattrib->vcs_mode = RTS_CTS;
311 else if (psta->cts2self)
312 pattrib->vcs_mode = CTS_TO_SELF;
313
314 break;
315 }
316
317 /* check HT op mode */
318 if (pattrib->ht_en) {
319 u8 HTOpMode = pmlmeinfo->HT_protection;
320 if ((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) ||
321 (!pmlmeext->cur_bwmode && HTOpMode == 3)) {
322 pattrib->vcs_mode = RTS_CTS;
323 break;
324 }
325 }
326
327 /* check rts */
328 if (sz > padapter->registrypriv.rts_thresh) {
329 pattrib->vcs_mode = RTS_CTS;
330 break;
331 }
332
333 /* to do list: check MIMO power save condition. */
334
335 /* check AMPDU aggregation for TXOP */
336 if (pattrib->ampdu_en) {
337 pattrib->vcs_mode = RTS_CTS;
338 break;
339 }
340
341 pattrib->vcs_mode = NONE_VCS;
342 break;
343 }
344 }
345}
346
347static void update_attrib_phy_info(struct pkt_attrib *pattrib, struct sta_info *psta)
348{
349 /*if (psta->rtsen)
350 pattrib->vcs_mode = RTS_CTS;
351 else if (psta->cts2self)
352 pattrib->vcs_mode = CTS_TO_SELF;
353 else
354 pattrib->vcs_mode = NONE_VCS;*/
355
356 pattrib->mdata = 0;
357 pattrib->eosp = 0;
358 pattrib->triggered = 0;
359
360 /* qos_en, ht_en, init rate, , bw, ch_offset, sgi */
361 pattrib->qos_en = psta->qos_option;
362
363 pattrib->raid = psta->raid;
364 pattrib->ht_en = psta->htpriv.ht_option;
365 pattrib->bwmode = psta->htpriv.bwmode;
366 pattrib->ch_offset = psta->htpriv.ch_offset;
367 pattrib->sgi = psta->htpriv.sgi;
368 pattrib->ampdu_en = false;
369
370 pattrib->retry_ctrl = false;
371}
372
373u8 qos_acm23a(u8 acm_mask, u8 priority)
374{
375 u8 change_priority = priority;
376
377 switch (priority) {
378 case 0:
379 case 3:
380 if (acm_mask & BIT(1))
381 change_priority = 1;
382 break;
383 case 1:
384 case 2:
385 break;
386 case 4:
387 case 5:
388 if (acm_mask & BIT(2))
389 change_priority = 0;
390 break;
391 case 6:
392 case 7:
393 if (acm_mask & BIT(3))
394 change_priority = 5;
395 break;
396 default:
397 DBG_8723A("qos_acm23a(): invalid pattrib->priority: %d!!!\n",
398 priority);
Jes Sorensen78558482014-05-09 15:04:19 +0200399 change_priority = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500400 break;
401 }
402
403 return change_priority;
404}
405
Jes Sorensene59cb422014-04-09 23:21:10 +0200406static void set_qos(struct sk_buff *skb, struct pkt_attrib *pattrib)
Larry Finger5e93f352014-03-28 21:37:38 -0500407{
Jes Sorensene59cb422014-04-09 23:21:10 +0200408 u8 *pframe = skb->data;
409 struct iphdr *ip_hdr;
Jes Sorensenc06209d2014-05-09 15:04:18 +0200410 u8 UserPriority = 0;
Larry Finger5e93f352014-03-28 21:37:38 -0500411
Larry Finger5e93f352014-03-28 21:37:38 -0500412 /* get UserPriority from IP hdr */
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200413 if (pattrib->ether_type == ETH_P_IP) {
Jes Sorensene59cb422014-04-09 23:21:10 +0200414 ip_hdr = (struct iphdr *)(pframe + ETH_HLEN);
415 UserPriority = ip_hdr->tos >> 5;
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200416 } else if (pattrib->ether_type == ETH_P_PAE) {
Larry Finger5e93f352014-03-28 21:37:38 -0500417 /* "When priority processing of data frames is supported, */
418 /* a STA's SME should send EAPOL-Key frames at the highest
419 priority." */
420 UserPriority = 7;
421 }
422
423 pattrib->priority = UserPriority;
424 pattrib->hdrlen = sizeof(struct ieee80211_qos_hdr);
Jes Sorensenb2f72ca2014-05-21 09:38:09 +0200425 pattrib->type = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_DATA;
Larry Finger5e93f352014-03-28 21:37:38 -0500426}
427
Jes Sorensen8fd873d2014-05-16 10:04:40 +0200428static int update_attrib(struct rtw_adapter *padapter,
Jes Sorensene59cb422014-04-09 23:21:10 +0200429 struct sk_buff *skb, struct pkt_attrib *pattrib)
Larry Finger5e93f352014-03-28 21:37:38 -0500430{
Larry Finger5e93f352014-03-28 21:37:38 -0500431 struct sta_info *psta = NULL;
Larry Finger5e93f352014-03-28 21:37:38 -0500432 int bmcast;
433 struct sta_priv *pstapriv = &padapter->stapriv;
434 struct security_priv *psecuritypriv = &padapter->securitypriv;
435 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500436 int res = _SUCCESS;
Jes Sorensene59cb422014-04-09 23:21:10 +0200437 struct ethhdr *ehdr = (struct ethhdr *) skb->data;
Larry Finger5e93f352014-03-28 21:37:38 -0500438
Jes Sorensene59cb422014-04-09 23:21:10 +0200439 pattrib->ether_type = ntohs(ehdr->h_proto);
Larry Finger5e93f352014-03-28 21:37:38 -0500440
Jes Sorensene59cb422014-04-09 23:21:10 +0200441 ether_addr_copy(pattrib->dst, ehdr->h_dest);
442 ether_addr_copy(pattrib->src, ehdr->h_source);
Larry Finger5e93f352014-03-28 21:37:38 -0500443
444 pattrib->pctrl = 0;
445
Jes Sorensenf2f97032014-05-25 22:43:04 +0200446 if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
447 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
Jes Sorensene59cb422014-04-09 23:21:10 +0200448 ether_addr_copy(pattrib->ra, pattrib->dst);
449 ether_addr_copy(pattrib->ta, pattrib->src);
Jes Sorensenf2f97032014-05-25 22:43:04 +0200450 } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
Jes Sorensene59cb422014-04-09 23:21:10 +0200451 ether_addr_copy(pattrib->ra, get_bssid(pmlmepriv));
452 ether_addr_copy(pattrib->ta, pattrib->src);
Jes Sorensenf2f97032014-05-25 22:43:04 +0200453 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Jes Sorensene59cb422014-04-09 23:21:10 +0200454 ether_addr_copy(pattrib->ra, pattrib->dst);
455 ether_addr_copy(pattrib->ta, get_bssid(pmlmepriv));
Larry Finger5e93f352014-03-28 21:37:38 -0500456 }
457
Jes Sorensene59cb422014-04-09 23:21:10 +0200458 pattrib->pktlen = skb->len - ETH_HLEN;
Larry Finger5e93f352014-03-28 21:37:38 -0500459
460 if (pattrib->ether_type == ETH_P_IP) {
461 /* The following is for DHCP and ARP packet, we use cck1M
462 to tx these packets and let LPS awake some time */
463 /* to prevent DHCP protocol fail */
Larry Finger5e93f352014-03-28 21:37:38 -0500464 pattrib->dhcp_pkt = 0;
Jes Sorensene59cb422014-04-09 23:21:10 +0200465 /* MINIMUM_DHCP_PACKET_SIZE) { */
466 if (pattrib->pktlen > 282 + 24) {
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200467 if (pattrib->ether_type == ETH_P_IP) {/* IP header */
Jes Sorensene59cb422014-04-09 23:21:10 +0200468 u8 *pframe = skb->data;
469 pframe += ETH_HLEN;
470
471 if ((pframe[21] == 68 && pframe[23] == 67) ||
472 (pframe[21] == 67 && pframe[23] == 68)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500473 /* 68 : UDP BOOTP client */
474 /* 67 : UDP BOOTP server */
475 RT_TRACE(_module_rtl871x_xmit_c_,
476 _drv_err_,
477 ("======================"
478 "update_attrib: get DHCP "
479 "Packet\n"));
480 pattrib->dhcp_pkt = 1;
481 }
482 }
483 }
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200484 } else if (pattrib->ether_type == ETH_P_PAE) {
Larry Finger5e93f352014-03-28 21:37:38 -0500485 DBG_8723A_LEVEL(_drv_always_, "send eapol packet\n");
486 }
487
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200488 if ((pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500489 rtw_set_scan_deny(padapter, 3000);
490 }
491
492 /* If EAPOL , ARP , OR DHCP packet, driver must be in active mode. */
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200493 if ((pattrib->ether_type == ETH_P_ARP) ||
494 (pattrib->ether_type == ETH_P_PAE) || (pattrib->dhcp_pkt == 1)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500495 rtw_lps_ctrl_wk_cmd23a(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
496 }
497
498 bmcast = is_multicast_ether_addr(pattrib->ra);
499
500 /* get sta_info */
501 if (bmcast) {
502 psta = rtw_get_bcmc_stainfo23a(padapter);
503 } else {
504 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
505 if (psta == NULL) { /* if we cannot get psta => drrp the pkt */
506 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
507 ("\nupdate_attrib => get sta_info fail, ra:"
508 MAC_FMT"\n", MAC_ARG(pattrib->ra)));
509 res = _FAIL;
510 goto exit;
Jes Sorensenf2f97032014-05-25 22:43:04 +0200511 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) &&
Larry Finger5e93f352014-03-28 21:37:38 -0500512 (!(psta->state & _FW_LINKED))) {
513 res = _FAIL;
514 goto exit;
515 }
516 }
517
518 if (psta) {
519 pattrib->mac_id = psta->mac_id;
520 /* DBG_8723A("%s ==> mac_id(%d)\n", __func__, pattrib->mac_id); */
521 pattrib->psta = psta;
522 } else {
523 /* if we cannot get psta => drop the pkt */
524 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
525 ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT
526 "\n", MAC_ARG(pattrib->ra)));
527 res = _FAIL;
528 goto exit;
529 }
530
531 pattrib->ack_policy = 0;
532 /* get ether_hdr_len */
533
534 /* pattrib->ether_type == 0x8100) ? (14 + 4): 14; vlan tag */
535 pattrib->pkt_hdrlen = ETH_HLEN;
536
537 pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
Jes Sorensenb2f72ca2014-05-21 09:38:09 +0200538 pattrib->type = IEEE80211_FTYPE_DATA;
Larry Finger5e93f352014-03-28 21:37:38 -0500539 pattrib->priority = 0;
540
541 if (check_fwstate(pmlmepriv, WIFI_AP_STATE | WIFI_ADHOC_STATE |
542 WIFI_ADHOC_MASTER_STATE)) {
543 if (psta->qos_option)
Jes Sorensene59cb422014-04-09 23:21:10 +0200544 set_qos(skb, pattrib);
Larry Finger5e93f352014-03-28 21:37:38 -0500545 } else {
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +0200546 if (pmlmepriv->qos_option) {
Jes Sorensene59cb422014-04-09 23:21:10 +0200547 set_qos(skb, pattrib);
Larry Finger5e93f352014-03-28 21:37:38 -0500548
549 if (pmlmepriv->acm_mask != 0) {
550 pattrib->priority = qos_acm23a(pmlmepriv->acm_mask,
551 pattrib->priority);
552 }
553 }
554 }
555
556 if (psta->ieee8021x_blocked == true) {
557 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
558 ("\n psta->ieee8021x_blocked == true\n"));
559
560 pattrib->encrypt = 0;
561
Jes Sorensen3483b8a2014-04-09 23:21:09 +0200562 if ((pattrib->ether_type != ETH_P_PAE) &&
Larry Finger5e93f352014-03-28 21:37:38 -0500563 (check_fwstate(pmlmepriv, WIFI_MP_STATE) == false)) {
564 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
565 ("\npsta->ieee8021x_blocked == true, "
566 "pattrib->ether_type(%.4x) != 0x888e\n",
567 pattrib->ether_type));
568 res = _FAIL;
569 goto exit;
570 }
571 } else {
572 GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
573
574 switch (psecuritypriv->dot11AuthAlgrthm) {
575 case dot11AuthAlgrthm_Open:
576 case dot11AuthAlgrthm_Shared:
577 case dot11AuthAlgrthm_Auto:
578 pattrib->key_idx =
579 (u8)psecuritypriv->dot11PrivacyKeyIndex;
580 break;
581 case dot11AuthAlgrthm_8021X:
582 if (bmcast)
583 pattrib->key_idx =
584 (u8)psecuritypriv->dot118021XGrpKeyid;
585 else
586 pattrib->key_idx = 0;
587 break;
588 default:
589 pattrib->key_idx = 0;
590 break;
591 }
592
593 }
594
595 switch (pattrib->encrypt) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200596 case WLAN_CIPHER_SUITE_WEP40:
597 case WLAN_CIPHER_SUITE_WEP104:
Jes Sorensen06e17e32014-05-25 22:43:02 +0200598 pattrib->iv_len = IEEE80211_WEP_IV_LEN;
599 pattrib->icv_len = IEEE80211_WEP_ICV_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -0500600 break;
601
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200602 case WLAN_CIPHER_SUITE_TKIP:
Jes Sorensen06e17e32014-05-25 22:43:02 +0200603 pattrib->iv_len = IEEE80211_TKIP_IV_LEN;
604 pattrib->icv_len = IEEE80211_TKIP_ICV_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -0500605
Jes Sorensen9216c512014-05-21 09:37:29 +0200606 if (!padapter->securitypriv.busetkipkey) {
Larry Finger5e93f352014-03-28 21:37:38 -0500607 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
608 ("\npadapter->securitypriv.busetkip"
Jes Sorensen9216c512014-05-21 09:37:29 +0200609 "key(%d) == false drop packet\n",
Larry Finger5e93f352014-03-28 21:37:38 -0500610 padapter->securitypriv.busetkipkey));
611 res = _FAIL;
612 goto exit;
613 }
614
615 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200616 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -0500617 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200618 ("pattrib->encrypt =%d (WLAN_CIPHER_SUITE_CCMP)\n",
619 pattrib->encrypt));
Jes Sorensen06e17e32014-05-25 22:43:02 +0200620 pattrib->iv_len = IEEE80211_CCMP_HDR_LEN;
621 pattrib->icv_len = IEEE80211_CCMP_MIC_LEN;
Larry Finger5e93f352014-03-28 21:37:38 -0500622 break;
623
624 default:
625 pattrib->iv_len = 0;
626 pattrib->icv_len = 0;
627 break;
628 }
629
630 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
631 ("update_attrib: encrypt =%d\n", pattrib->encrypt));
632
Jes Sorensen9216c512014-05-21 09:37:29 +0200633 if (pattrib->encrypt && !psecuritypriv->hw_decrypted) {
Larry Finger5e93f352014-03-28 21:37:38 -0500634 pattrib->bswenc = true;
635 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
636 ("update_attrib: encrypt =%d bswenc = true\n",
637 pattrib->encrypt));
638 } else {
639 pattrib->bswenc = false;
640 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
641 ("update_attrib: bswenc = false\n"));
642 }
643 update_attrib_phy_info(pattrib, psta);
644
645exit:
646
647 return res;
648}
649
Jes Sorensen8fd873d2014-05-16 10:04:40 +0200650static int xmitframe_addmic(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -0500651 struct xmit_frame *pxmitframe) {
652 struct mic_data micdata;
653 struct sta_info *stainfo;
654 struct pkt_attrib *pattrib = &pxmitframe->attrib;
655 struct security_priv *psecuritypriv = &padapter->securitypriv;
656 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
657 int curfragnum, length;
658 u8 *pframe, *payload, mic[8];
659 u8 priority[4]= {0x0, 0x0, 0x0, 0x0};
660 u8 hw_hdr_offset = 0;
661 int bmcst = is_multicast_ether_addr(pattrib->ra);
662
663 if (pattrib->psta) {
664 stainfo = pattrib->psta;
665 } else {
666 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
667 stainfo = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
668 }
669
670 if (!stainfo) {
671 DBG_8723A("%s, psta == NUL\n", __func__);
672 return _FAIL;
673 }
674
675 if (!(stainfo->state &_FW_LINKED)) {
676 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
677 __func__, stainfo->state);
678 return _FAIL;
679 }
680
681 hw_hdr_offset = TXDESC_OFFSET;
682
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200683 if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) {
Larry Finger5e93f352014-03-28 21:37:38 -0500684 /* encode mic code */
685 if (stainfo) {
686 u8 null_key[16]={0x0, 0x0, 0x0, 0x0,
687 0x0, 0x0, 0x0, 0x0,
688 0x0, 0x0, 0x0, 0x0,
689 0x0, 0x0, 0x0, 0x0};
690
691 pframe = pxmitframe->buf_addr + hw_hdr_offset;
692
693 if (bmcst) {
694 if (!memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)) {
695 return _FAIL;
696 }
697 /* start to calculate the mic code */
698 rtw_secmicsetkey23a(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
699 } else {
700 if (!memcmp(&stainfo->dot11tkiptxmickey.skey[0],
701 null_key, 16)) {
702 return _FAIL;
703 }
704 /* start to calculate the mic code */
705 rtw_secmicsetkey23a(&micdata, &stainfo->dot11tkiptxmickey.skey[0]);
706 }
707
708 if (pframe[1] & 1) { /* ToDS == 1 */
709 /* DA */
710 rtw_secmicappend23a(&micdata, &pframe[16], 6);
711 if (pframe[1] & 2) /* From Ds == 1 */
712 rtw_secmicappend23a(&micdata,
713 &pframe[24], 6);
714 else
715 rtw_secmicappend23a(&micdata,
716 &pframe[10], 6);
717 } else { /* ToDS == 0 */
718 /* DA */
719 rtw_secmicappend23a(&micdata, &pframe[4], 6);
720 if (pframe[1] & 2) /* From Ds == 1 */
721 rtw_secmicappend23a(&micdata,
722 &pframe[16], 6);
723 else
724 rtw_secmicappend23a(&micdata,
725 &pframe[10], 6);
726 }
727
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +0200728 /* if (pmlmepriv->qos_option == 1) */
Larry Finger5e93f352014-03-28 21:37:38 -0500729 if (pattrib->qos_en)
730 priority[0] = (u8)pxmitframe->attrib.priority;
731
732 rtw_secmicappend23a(&micdata, &priority[0], 4);
733
734 payload = pframe;
735
736 for (curfragnum = 0; curfragnum < pattrib->nr_frags;
737 curfragnum++) {
Larry Fingerc17416e2014-03-28 21:37:42 -0500738 payload = PTR_ALIGN(payload, 4);
Larry Finger5e93f352014-03-28 21:37:38 -0500739 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
740 ("=== curfragnum =%d, pframe = 0x%.2x, "
741 "0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x"
742 "%.2x, 0x%.2x, 0x%.2x,!!!\n",
743 curfragnum, *payload, *(payload + 1),
744 *(payload + 2), *(payload + 3),
745 *(payload + 4), *(payload + 5),
746 *(payload + 6), *(payload + 7)));
747
748 payload = payload + pattrib->hdrlen +
749 pattrib->iv_len;
750 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
751 ("curfragnum =%d pattrib->hdrlen =%d "
752 "pattrib->iv_len =%d", curfragnum,
753 pattrib->hdrlen, pattrib->iv_len));
754 if ((curfragnum + 1) == pattrib->nr_frags) {
755 length = pattrib->last_txcmdsz -
756 pattrib->hdrlen -
757 pattrib->iv_len -
758 ((pattrib->bswenc) ?
759 pattrib->icv_len : 0);
760 rtw_secmicappend23a(&micdata, payload,
761 length);
762 payload = payload + length;
763 } else {
764 length = pxmitpriv->frag_len -
765 pattrib->hdrlen -
766 pattrib->iv_len -
767 ((pattrib->bswenc) ?
768 pattrib->icv_len : 0);
769 rtw_secmicappend23a(&micdata, payload,
770 length);
771 payload = payload + length +
772 pattrib->icv_len;
773 RT_TRACE(_module_rtl871x_xmit_c_,
774 _drv_err_,
775 ("curfragnum =%d length =%d "
776 "pattrib->icv_len =%d",
777 curfragnum, length,
778 pattrib->icv_len));
779 }
780 }
781 rtw_secgetmic23a(&micdata, &mic[0]);
782 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
783 ("xmitframe_addmic: before add mic code!!\n"));
784 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
785 ("xmitframe_addmic: pattrib->last_txcmdsz ="
786 "%d!!!\n", pattrib->last_txcmdsz));
787 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
788 ("xmitframe_addmic: mic[0]= 0x%.2x , mic[1]="
789 "0x%.2x , mic[2]= 0x%.2x , mic[3]= 0x%.2x\n"
790 "mic[4]= 0x%.2x , mic[5]= 0x%.2x , mic[6]= 0x%.2x "
791 ", mic[7]= 0x%.2x !!!!\n", mic[0], mic[1],
792 mic[2], mic[3], mic[4], mic[5], mic[6],
793 mic[7]));
794 /* add mic code and add the mic code length
795 in last_txcmdsz */
796
797 memcpy(payload, &mic[0], 8);
798 pattrib->last_txcmdsz += 8;
799
800 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
801 ("\n ======== last pkt ========\n"));
802 payload = payload - pattrib->last_txcmdsz + 8;
803 for (curfragnum = 0; curfragnum < pattrib->last_txcmdsz;
804 curfragnum = curfragnum + 8)
805 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
806 (" %.2x, %.2x, %.2x, %.2x, %.2x, "
807 " %.2x, %.2x, %.2x ",
808 *(payload + curfragnum),
809 *(payload + curfragnum + 1),
810 *(payload + curfragnum + 2),
811 *(payload + curfragnum + 3),
812 *(payload + curfragnum + 4),
813 *(payload + curfragnum + 5),
814 *(payload + curfragnum + 6),
815 *(payload + curfragnum + 7)));
816 } else {
817 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
818 ("xmitframe_addmic: rtw_get_stainfo23a =="
819 "NULL!!!\n"));
820 }
821 }
822
823 return _SUCCESS;
824}
825
Jes Sorensen8fd873d2014-05-16 10:04:40 +0200826static int xmitframe_swencrypt(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -0500827 struct xmit_frame *pxmitframe)
828{
829 struct pkt_attrib *pattrib = &pxmitframe->attrib;
830
831 /* if ((psecuritypriv->sw_encrypt)||(pattrib->bswenc)) */
832 if (pattrib->bswenc) {
833 /* DBG_8723A("start xmitframe_swencrypt\n"); */
834 RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_,
835 ("### xmitframe_swencrypt\n"));
836 switch (pattrib->encrypt) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200837 case WLAN_CIPHER_SUITE_WEP40:
838 case WLAN_CIPHER_SUITE_WEP104:
Larry Finger5e93f352014-03-28 21:37:38 -0500839 rtw_wep_encrypt23a(padapter, pxmitframe);
840 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200841 case WLAN_CIPHER_SUITE_TKIP:
Larry Finger5e93f352014-03-28 21:37:38 -0500842 rtw_tkip_encrypt23a(padapter, pxmitframe);
843 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +0200844 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -0500845 rtw_aes_encrypt23a(padapter, pxmitframe);
846 break;
847 default:
848 break;
849 }
850
851 } else {
852 RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
853 ("### xmitframe_hwencrypt\n"));
854 }
855
856 return _SUCCESS;
857}
858
Jes Sorensen39ef8912014-05-21 09:37:58 +0200859static int rtw_make_wlanhdr(struct rtw_adapter *padapter, u8 *hdr,
860 struct pkt_attrib *pattrib)
Larry Finger5e93f352014-03-28 21:37:38 -0500861{
Larry Finger5e93f352014-03-28 21:37:38 -0500862 struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
Jes Sorensene5b2a422014-05-21 09:38:05 +0200863 struct ieee80211_qos_hdr *qoshdr;
Larry Finger5e93f352014-03-28 21:37:38 -0500864 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
Larry Finger5e93f352014-03-28 21:37:38 -0500865 u8 qos_option = false;
866 int res = _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -0500867
868 struct sta_info *psta;
869
870 int bmcst = is_multicast_ether_addr(pattrib->ra);
871
872 if (pattrib->psta) {
873 psta = pattrib->psta;
874 } else {
875 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
876 if (bmcst) {
877 psta = rtw_get_bcmc_stainfo23a(padapter);
878 } else {
879 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
880 }
881 }
882
883 if (psta == NULL) {
884 DBG_8723A("%s, psta == NUL\n", __func__);
885 return _FAIL;
886 }
887
888 if (!(psta->state &_FW_LINKED)) {
889 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
890 return _FAIL;
891 }
892
893 memset(hdr, 0, WLANHDR_OFFSET);
894
Jes Sorensenb2f72ca2014-05-21 09:38:09 +0200895 pwlanhdr->frame_control = cpu_to_le16(pattrib->type);
Larry Finger5e93f352014-03-28 21:37:38 -0500896
Jes Sorensenb2f72ca2014-05-21 09:38:09 +0200897 if (pattrib->type & IEEE80211_FTYPE_DATA) {
Jes Sorensenf2f97032014-05-25 22:43:04 +0200898 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500899 /* to_ds = 1, fr_ds = 0; */
900 /* Data transfer to AP */
Jes Sorensenc26e9572014-05-21 09:38:17 +0200901 pwlanhdr->frame_control |=
902 cpu_to_le16(IEEE80211_FCTL_TODS);
Jes Sorensen04e57762014-05-25 22:43:03 +0200903 ether_addr_copy(pwlanhdr->addr1, get_bssid(pmlmepriv));
904 ether_addr_copy(pwlanhdr->addr2, pattrib->src);
905 ether_addr_copy(pwlanhdr->addr3, pattrib->dst);
Larry Finger5e93f352014-03-28 21:37:38 -0500906
Jes Sorensenbd8ad4a2014-05-09 15:03:21 +0200907 if (pmlmepriv->qos_option)
Larry Finger5e93f352014-03-28 21:37:38 -0500908 qos_option = true;
909
Jes Sorensenf2f97032014-05-25 22:43:04 +0200910 } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
Larry Finger5e93f352014-03-28 21:37:38 -0500911 /* to_ds = 0, fr_ds = 1; */
Jes Sorensenc26e9572014-05-21 09:38:17 +0200912 pwlanhdr->frame_control |=
913 cpu_to_le16(IEEE80211_FCTL_FROMDS);
Jes Sorensen04e57762014-05-25 22:43:03 +0200914 ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
915 ether_addr_copy(pwlanhdr->addr2, get_bssid(pmlmepriv));
916 ether_addr_copy(pwlanhdr->addr3, pattrib->src);
Larry Finger5e93f352014-03-28 21:37:38 -0500917
918 if (psta->qos_option)
919 qos_option = true;
Jes Sorensenf2f97032014-05-25 22:43:04 +0200920 } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
921 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
Jes Sorensen04e57762014-05-25 22:43:03 +0200922 ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
923 ether_addr_copy(pwlanhdr->addr2, pattrib->src);
924 ether_addr_copy(pwlanhdr->addr3, get_bssid(pmlmepriv));
Larry Finger5e93f352014-03-28 21:37:38 -0500925
926 if (psta->qos_option)
927 qos_option = true;
928 }
929 else {
930 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
931 res = _FAIL;
932 goto exit;
933 }
934 if (pattrib->mdata)
Jes Sorensenc6716e12014-05-21 09:38:02 +0200935 pwlanhdr->frame_control |=
936 cpu_to_le16(IEEE80211_FCTL_MOREDATA);
Larry Finger5e93f352014-03-28 21:37:38 -0500937 if (pattrib->encrypt)
Jes Sorensenc6716e12014-05-21 09:38:02 +0200938 pwlanhdr->frame_control |=
939 cpu_to_le16(IEEE80211_FCTL_PROTECTED);
Larry Finger5e93f352014-03-28 21:37:38 -0500940 if (qos_option) {
Jes Sorensene5b2a422014-05-21 09:38:05 +0200941 qoshdr = (struct ieee80211_qos_hdr *)hdr;
942
943 qoshdr->qos_ctrl = cpu_to_le16(
944 pattrib->priority & IEEE80211_QOS_CTL_TID_MASK);
945
946 qoshdr->qos_ctrl |= cpu_to_le16(
947 (pattrib->ack_policy << 5) &
948 IEEE80211_QOS_CTL_ACK_POLICY_MASK);
949
950 if (pattrib->eosp)
951 qoshdr->qos_ctrl |=
952 cpu_to_le16(IEEE80211_QOS_CTL_EOSP);
Larry Finger5e93f352014-03-28 21:37:38 -0500953 }
954 /* TODO: fill HT Control Field */
955
956 /* Update Seq Num will be handled by f/w */
957 if (psta) {
958 psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
959 psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
960 pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
Jes Sorensen670ce682014-05-21 09:37:57 +0200961 /* We dont need to worry about frag bits here */
962 pwlanhdr->seq_ctrl = cpu_to_le16(IEEE80211_SN_TO_SEQ(
963 pattrib->seqnum));
Larry Finger5e93f352014-03-28 21:37:38 -0500964 /* check if enable ampdu */
965 if (pattrib->ht_en && psta->htpriv.ampdu_enable) {
Jes Sorensen072fc842014-05-09 15:04:14 +0200966 if (pattrib->priority >= 16)
967 printk(KERN_WARNING "%s: Invalid "
968 "pattrib->priority %i\n",
969 __func__, pattrib->priority);
970 if (psta->htpriv.agg_enable_bitmap &
971 BIT(pattrib->priority))
972 pattrib->ampdu_en = true;
Larry Finger5e93f352014-03-28 21:37:38 -0500973 }
974 /* re-check if enable ampdu by BA_starting_seqctrl */
975 if (pattrib->ampdu_en) {
976 u16 tx_seq;
977
978 tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];
979
980 /* check BA_starting_seqctrl */
981 if (SN_LESS(pattrib->seqnum, tx_seq)) {
982 /* DBG_8723A("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq); */
983 pattrib->ampdu_en = false;/* AGG BK */
984 } else if (SN_EQUAL(pattrib->seqnum, tx_seq)) {
985 psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff;
986 pattrib->ampdu_en = true;/* AGG EN */
987 } else {
988 /* DBG_8723A("tx ampdu over run\n"); */
989 psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff;
990 pattrib->ampdu_en = true;/* AGG EN */
991 }
992 }
993 }
994 }
995exit:
996 return res;
997}
998
999s32 rtw_txframes_pending23a(struct rtw_adapter *padapter)
1000{
1001 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1002
Jes Sorensen794ff052014-05-09 15:03:59 +02001003 return (!list_empty(&pxmitpriv->be_pending.queue)) ||
1004 (!list_empty(&pxmitpriv->bk_pending.queue)) ||
1005 (!list_empty(&pxmitpriv->vi_pending.queue)) ||
1006 (!list_empty(&pxmitpriv->vo_pending.queue));
Larry Finger5e93f352014-03-28 21:37:38 -05001007}
1008
1009s32 rtw_txframes_sta_ac_pending23a(struct rtw_adapter *padapter,
1010 struct pkt_attrib *pattrib)
1011{
1012 struct sta_info *psta;
1013 struct tx_servq *ptxservq;
1014 int priority = pattrib->priority;
1015
1016 if (pattrib->psta) {
1017 psta = pattrib->psta;
1018 } else {
1019 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1020 psta = rtw_get_stainfo23a(&padapter->stapriv, &pattrib->ra[0]);
1021 }
1022 if (psta == NULL) {
1023 DBG_8723A("%s, psta == NUL\n", __func__);
1024 return 0;
1025 }
1026 if (!(psta->state &_FW_LINKED)) {
1027 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1028 psta->state);
1029 return 0;
1030 }
1031 switch (priority) {
1032 case 1:
1033 case 2:
1034 ptxservq = &psta->sta_xmitpriv.bk_q;
1035 break;
1036 case 4:
1037 case 5:
1038 ptxservq = &psta->sta_xmitpriv.vi_q;
1039 break;
1040 case 6:
1041 case 7:
1042 ptxservq = &psta->sta_xmitpriv.vo_q;
1043 break;
1044 case 0:
1045 case 3:
1046 default:
1047 ptxservq = &psta->sta_xmitpriv.be_q;
1048 break;
1049 }
1050 return ptxservq->qcnt;
1051}
1052
1053/*
1054 * Calculate wlan 802.11 packet MAX size from pkt_attrib
1055 * This function doesn't consider fragment case
1056 */
1057u32 rtw_calculate_wlan_pkt_size_by_attribue23a(struct pkt_attrib *pattrib)
1058{
1059 u32 len = 0;
1060
1061 len = pattrib->hdrlen + pattrib->iv_len; /* WLAN Header and IV */
1062 len += SNAP_SIZE + sizeof(u16); /* LLC */
1063 len += pattrib->pktlen;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001064 if (pattrib->encrypt == WLAN_CIPHER_SUITE_TKIP) len += 8; /* MIC */
Larry Finger5e93f352014-03-28 21:37:38 -05001065 len += ((pattrib->bswenc) ? pattrib->icv_len : 0); /* ICV */
1066
1067 return len;
1068}
1069
1070/*
1071
1072This sub-routine will perform all the following:
1073
10741. remove 802.3 header.
10752. create wlan_header, based on the info in pxmitframe
10763. append sta's iv/ext-iv
10774. append LLC
10785. move frag chunk from pframe to pxmitframe->mem
10796. apply sw-encrypt, if necessary.
1080
1081*/
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001082int rtw_xmitframe_coalesce23a(struct rtw_adapter *padapter, struct sk_buff *skb,
Larry Finger5e93f352014-03-28 21:37:38 -05001083 struct xmit_frame *pxmitframe)
1084{
Jes Sorensen69a0f972014-04-09 23:21:11 +02001085 struct sta_info *psta;
1086 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1087 struct pkt_attrib *pattrib = &pxmitframe->attrib;
Jes Sorensen8e3ddad2014-05-21 09:37:44 +02001088 struct ieee80211_hdr *hdr;
Larry Finger5e93f352014-03-28 21:37:38 -05001089 s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
Larry Finger5e93f352014-03-28 21:37:38 -05001090 u8 *pframe, *mem_start;
1091 u8 hw_hdr_offset;
1092 u8 *pbuf_start;
Jes Sorensen3e689a92014-04-09 23:21:12 +02001093 u8 *pdata = skb->data;
1094 int data_len = skb->len;
Larry Finger5e93f352014-03-28 21:37:38 -05001095 s32 bmcst = is_multicast_ether_addr(pattrib->ra);
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001096 int res = _SUCCESS;
Larry Finger5e93f352014-03-28 21:37:38 -05001097
Jes Sorensen69a0f972014-04-09 23:21:11 +02001098 if (pattrib->psta)
Larry Finger5e93f352014-03-28 21:37:38 -05001099 psta = pattrib->psta;
Jes Sorensen69a0f972014-04-09 23:21:11 +02001100 else {
Larry Finger5e93f352014-03-28 21:37:38 -05001101 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1102 psta = rtw_get_stainfo23a(&padapter->stapriv, pattrib->ra);
1103 }
1104
Jes Sorensen69a0f972014-04-09 23:21:11 +02001105 if (!psta) {
Larry Finger5e93f352014-03-28 21:37:38 -05001106 DBG_8723A("%s, psta == NUL\n", __func__);
1107 return _FAIL;
1108 }
1109
1110 if (!(psta->state &_FW_LINKED)) {
Jes Sorensen69a0f972014-04-09 23:21:11 +02001111 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n",
1112 __func__, psta->state);
Larry Finger5e93f352014-03-28 21:37:38 -05001113 return _FAIL;
1114 }
1115
Jes Sorensen69a0f972014-04-09 23:21:11 +02001116 if (!pxmitframe->buf_addr) {
Larry Finger5e93f352014-03-28 21:37:38 -05001117 DBG_8723A("==> %s buf_addr == NULL\n", __func__);
1118 return _FAIL;
1119 }
1120
1121 pbuf_start = pxmitframe->buf_addr;
1122
1123 hw_hdr_offset = TXDESC_OFFSET;
1124
Jes Sorensen69a0f972014-04-09 23:21:11 +02001125 mem_start = pbuf_start + hw_hdr_offset;
Larry Finger5e93f352014-03-28 21:37:38 -05001126
Jes Sorensen39ef8912014-05-21 09:37:58 +02001127 if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {
Larry Finger5e93f352014-03-28 21:37:38 -05001128 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
Jes Sorensen39ef8912014-05-21 09:37:58 +02001129 ("%s: rtw_make_wlanhdr fail; drop pkt\n", __func__));
Larry Finger5e93f352014-03-28 21:37:38 -05001130 res = _FAIL;
1131 goto exit;
1132 }
1133
Jes Sorensen3e689a92014-04-09 23:21:12 +02001134 pdata += pattrib->pkt_hdrlen;
1135 data_len -= pattrib->pkt_hdrlen;
Larry Finger5e93f352014-03-28 21:37:38 -05001136
1137 frg_inx = 0;
1138 frg_len = pxmitpriv->frag_len - 4;/* 2346-4 = 2342 */
1139
1140 while (1) {
1141 llc_sz = 0;
1142
1143 mpdu_len = frg_len;
1144
1145 pframe = mem_start;
Jes Sorensen8e3ddad2014-05-21 09:37:44 +02001146 hdr = (struct ieee80211_hdr *)mem_start;
Larry Finger5e93f352014-03-28 21:37:38 -05001147
1148 pframe += pattrib->hdrlen;
1149 mpdu_len -= pattrib->hdrlen;
1150
1151 /* adding icv, if necessary... */
1152 if (pattrib->iv_len) {
Jes Sorensen69a0f972014-04-09 23:21:11 +02001153 if (psta) {
Larry Finger5e93f352014-03-28 21:37:38 -05001154 switch (pattrib->encrypt) {
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001155 case WLAN_CIPHER_SUITE_WEP40:
1156 case WLAN_CIPHER_SUITE_WEP104:
Jes Sorensen69a0f972014-04-09 23:21:11 +02001157 WEP_IV(pattrib->iv, psta->dot11txpn,
1158 pattrib->key_idx);
Larry Finger5e93f352014-03-28 21:37:38 -05001159 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001160 case WLAN_CIPHER_SUITE_TKIP:
Larry Finger5e93f352014-03-28 21:37:38 -05001161 if (bmcst)
Jes Sorensen69a0f972014-04-09 23:21:11 +02001162 TKIP_IV(pattrib->iv,
1163 psta->dot11txpn,
1164 pattrib->key_idx);
Larry Finger5e93f352014-03-28 21:37:38 -05001165 else
Jes Sorensen69a0f972014-04-09 23:21:11 +02001166 TKIP_IV(pattrib->iv,
1167 psta->dot11txpn, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05001168 break;
Jes Sorensen9e3d6df2014-05-21 09:37:34 +02001169 case WLAN_CIPHER_SUITE_CCMP:
Larry Finger5e93f352014-03-28 21:37:38 -05001170 if (bmcst)
Jes Sorensen69a0f972014-04-09 23:21:11 +02001171 AES_IV(pattrib->iv,
1172 psta->dot11txpn,
1173 pattrib->key_idx);
Larry Finger5e93f352014-03-28 21:37:38 -05001174 else
Jes Sorensen69a0f972014-04-09 23:21:11 +02001175 AES_IV(pattrib->iv,
1176 psta->dot11txpn, 0);
Larry Finger5e93f352014-03-28 21:37:38 -05001177 break;
1178 }
1179 }
1180
1181 memcpy(pframe, pattrib->iv, pattrib->iv_len);
1182
1183 RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
1184 ("rtw_xmiaframe_coalesce23a: keyid =%d pattrib"
1185 "->iv[3]=%.2x pframe =%.2x %.2x %.2x %.2x\n",
1186 padapter->securitypriv.dot11PrivacyKeyIndex,
1187 pattrib->iv[3], *pframe, *(pframe+1),
1188 *(pframe+2), *(pframe+3)));
1189 pframe += pattrib->iv_len;
1190 mpdu_len -= pattrib->iv_len;
1191 }
1192 if (frg_inx == 0) {
1193 llc_sz = rtw_put_snap23a(pframe, pattrib->ether_type);
1194 pframe += llc_sz;
1195 mpdu_len -= llc_sz;
1196 }
1197
Jes Sorensen69a0f972014-04-09 23:21:11 +02001198 if (pattrib->icv_len > 0 && pattrib->bswenc)
Larry Finger5e93f352014-03-28 21:37:38 -05001199 mpdu_len -= pattrib->icv_len;
1200
Jes Sorensen3e689a92014-04-09 23:21:12 +02001201 if (bmcst)
Larry Finger5e93f352014-03-28 21:37:38 -05001202 /* don't do fragment to broadcat/multicast packets */
Jes Sorensen3e689a92014-04-09 23:21:12 +02001203 mem_sz = min_t(s32, data_len, pattrib->pktlen);
1204 else
1205 mem_sz = min_t(s32, data_len, mpdu_len);
1206
1207 memcpy(pframe, pdata, mem_sz);
1208
Larry Finger5e93f352014-03-28 21:37:38 -05001209 pframe += mem_sz;
Jes Sorensen3e689a92014-04-09 23:21:12 +02001210 pdata += mem_sz;
1211 data_len -= mem_sz;
Larry Finger5e93f352014-03-28 21:37:38 -05001212
1213 if ((pattrib->icv_len >0) && (pattrib->bswenc)) {
1214 memcpy(pframe, pattrib->icv, pattrib->icv_len);
1215 pframe += pattrib->icv_len;
1216 }
1217
1218 frg_inx++;
1219
Jes Sorensen3e689a92014-04-09 23:21:12 +02001220 if (bmcst || data_len <= 0) {
Larry Finger5e93f352014-03-28 21:37:38 -05001221 pattrib->nr_frags = frg_inx;
1222
1223 pattrib->last_txcmdsz = pattrib->hdrlen +
1224 pattrib->iv_len +
1225 ((pattrib->nr_frags == 1) ?
1226 llc_sz : 0) +
1227 ((pattrib->bswenc) ?
1228 pattrib->icv_len : 0) + mem_sz;
Jes Sorensen8e3ddad2014-05-21 09:37:44 +02001229 hdr->frame_control &=
1230 ~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
Larry Finger5e93f352014-03-28 21:37:38 -05001231
1232 break;
1233 } else {
Jes Sorensen69a0f972014-04-09 23:21:11 +02001234 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1235 ("%s: There're still something in packet!\n",
1236 __func__));
Larry Finger5e93f352014-03-28 21:37:38 -05001237 }
Jes Sorensen8e3ddad2014-05-21 09:37:44 +02001238 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS);
Larry Finger5e93f352014-03-28 21:37:38 -05001239
Larry Fingerc17416e2014-03-28 21:37:42 -05001240 mem_start = PTR_ALIGN(pframe, 4) + hw_hdr_offset;
Larry Finger5e93f352014-03-28 21:37:38 -05001241 memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);
Larry Finger5e93f352014-03-28 21:37:38 -05001242 }
1243
1244 if (xmitframe_addmic(padapter, pxmitframe) == _FAIL) {
Jes Sorensen69a0f972014-04-09 23:21:11 +02001245 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1246 ("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n"));
Larry Finger5e93f352014-03-28 21:37:38 -05001247 DBG_8723A("xmitframe_addmic(padapter, pxmitframe) == _FAIL\n");
1248 res = _FAIL;
1249 goto exit;
1250 }
1251
1252 xmitframe_swencrypt(padapter, pxmitframe);
1253
1254 if (bmcst == false)
1255 update_attrib_vcs_info(padapter, pxmitframe);
1256 else
1257 pattrib->vcs_mode = NONE_VCS;
1258
1259exit:
1260 return res;
1261}
1262
1263/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
1264 * IEEE LLC/SNAP header contains 8 octets
1265 * First 3 octets comprise the LLC portion
1266 * SNAP portion, 5 octets, is divided into two fields:
1267 * Organizationally Unique Identifier(OUI), 3 octets,
1268 * type, defined by that organization, 2 octets.
1269 */
1270s32 rtw_put_snap23a(u8 *data, u16 h_proto)
1271{
1272 struct ieee80211_snap_hdr *snap;
1273 u8 *oui;
1274
1275 snap = (struct ieee80211_snap_hdr *)data;
1276 snap->dsap = 0xaa;
1277 snap->ssap = 0xaa;
1278 snap->ctrl = 0x03;
1279
1280 if (h_proto == 0x8137 || h_proto == 0x80f3)
1281 oui = P802_1H_OUI;
1282 else
1283 oui = RFC1042_OUI;
1284 snap->oui[0] = oui[0];
1285 snap->oui[1] = oui[1];
1286 snap->oui[2] = oui[2];
1287 *(u16 *)(data + SNAP_SIZE) = htons(h_proto);
1288 return SNAP_SIZE + sizeof(u16);
1289}
1290
1291void rtw_update_protection23a(struct rtw_adapter *padapter, u8 *ie, uint ie_len)
1292{
Jes Sorensen4bf954b2014-04-15 19:43:54 +02001293 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1294 struct registry_priv *pregistrypriv = &padapter->registrypriv;
1295 uint protection;
1296 const u8 *p;
Larry Finger5e93f352014-03-28 21:37:38 -05001297
1298 switch (pxmitpriv->vcs_setting) {
1299 case DISABLE_VCS:
1300 pxmitpriv->vcs = NONE_VCS;
1301 break;
1302 case ENABLE_VCS:
1303 break;
1304 case AUTO_VCS:
1305 default:
Jes Sorensen4bf954b2014-04-15 19:43:54 +02001306 p = cfg80211_find_ie(WLAN_EID_ERP_INFO, ie, ie_len);
1307 if (!p)
Larry Finger5e93f352014-03-28 21:37:38 -05001308 pxmitpriv->vcs = NONE_VCS;
Jes Sorensen4bf954b2014-04-15 19:43:54 +02001309 else {
1310 protection = (*(p + 2)) & BIT(1);
Larry Finger5e93f352014-03-28 21:37:38 -05001311 if (protection) {
1312 if (pregistrypriv->vcs_type == RTS_CTS)
1313 pxmitpriv->vcs = RTS_CTS;
1314 else
1315 pxmitpriv->vcs = CTS_TO_SELF;
1316 } else {
1317 pxmitpriv->vcs = NONE_VCS;
1318 }
1319 }
1320 break;
1321 }
1322}
1323
1324void rtw_count_tx_stats23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe, int sz)
1325{
1326 struct sta_info *psta = NULL;
1327 struct stainfo_stats *pstats = NULL;
1328 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1329 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1330
1331 if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
1332 pxmitpriv->tx_bytes += sz;
1333 pmlmepriv->LinkDetectInfo.NumTxOkInPeriod++;
1334
1335 psta = pxmitframe->attrib.psta;
1336 if (psta) {
1337 pstats = &psta->sta_stats;
1338 pstats->tx_pkts++;
1339 pstats->tx_bytes += sz;
1340 }
1341 }
1342}
1343
1344struct xmit_buf *rtw_alloc_xmitbuf23a_ext(struct xmit_priv *pxmitpriv)
1345{
1346 unsigned long irqL;
1347 struct xmit_buf *pxmitbuf = NULL;
1348 struct list_head *phead;
1349 struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
1350
1351 spin_lock_irqsave(&pfree_queue->lock, irqL);
1352
1353 phead = get_list_head(pfree_queue);
1354
1355 if (!list_empty(phead)) {
1356 pxmitbuf = list_first_entry(phead, struct xmit_buf, list);
1357
1358 list_del_init(&pxmitbuf->list);
1359
1360 pxmitpriv->free_xmit_extbuf_cnt--;
1361 pxmitbuf->priv_data = NULL;
1362 pxmitbuf->ext_tag = true;
1363
1364 if (pxmitbuf->sctx) {
1365 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1366 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
1367 }
1368 }
1369
1370 spin_unlock_irqrestore(&pfree_queue->lock, irqL);
1371
1372 return pxmitbuf;
1373}
1374
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001375int rtw_free_xmitbuf_ext23a(struct xmit_priv *pxmitpriv,
1376 struct xmit_buf *pxmitbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001377{
1378 unsigned long irqL;
1379 struct rtw_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
1380
1381 if (pxmitbuf == NULL)
1382 return _FAIL;
1383
1384 spin_lock_irqsave(&pfree_queue->lock, irqL);
1385
1386 list_del_init(&pxmitbuf->list);
1387
1388 list_add_tail(&pxmitbuf->list, get_list_head(pfree_queue));
1389 pxmitpriv->free_xmit_extbuf_cnt++;
1390
1391 spin_unlock_irqrestore(&pfree_queue->lock, irqL);
1392
1393 return _SUCCESS;
1394}
1395
1396struct xmit_buf *rtw_alloc_xmitbuf23a(struct xmit_priv *pxmitpriv)
1397{
1398 unsigned long irqL;
1399 struct xmit_buf *pxmitbuf = NULL;
1400 struct list_head *phead;
1401 struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
1402
1403 /* DBG_8723A("+rtw_alloc_xmitbuf23a\n"); */
1404
1405 spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
1406
1407 phead = get_list_head(pfree_xmitbuf_queue);
1408
1409 if (!list_empty(phead)) {
1410 pxmitbuf = list_first_entry(phead, struct xmit_buf, list);
1411
1412 list_del_init(&pxmitbuf->list);
1413
1414 pxmitpriv->free_xmitbuf_cnt--;
1415 pxmitbuf->priv_data = NULL;
1416 pxmitbuf->ext_tag = false;
1417 pxmitbuf->flags = XMIT_VO_QUEUE;
1418
1419 if (pxmitbuf->sctx) {
1420 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1421 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
1422 }
1423 }
1424
1425 spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
1426
1427 return pxmitbuf;
1428}
1429
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001430int rtw_free_xmitbuf23a(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
Larry Finger5e93f352014-03-28 21:37:38 -05001431{
1432 unsigned long irqL;
1433 struct rtw_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
1434
1435 /* DBG_8723A("+rtw_free_xmitbuf23a\n"); */
1436
1437 if (pxmitbuf == NULL)
1438 return _FAIL;
1439
1440 if (pxmitbuf->sctx) {
1441 DBG_8723A("%s pxmitbuf->sctx is not NULL\n", __func__);
1442 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
1443 }
1444
1445 if (pxmitbuf->ext_tag) {
1446 rtw_free_xmitbuf_ext23a(pxmitpriv, pxmitbuf);
1447 } else {
1448 spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
1449
1450 list_del_init(&pxmitbuf->list);
1451
1452 list_add_tail(&pxmitbuf->list,
1453 get_list_head(pfree_xmitbuf_queue));
1454
1455 pxmitpriv->free_xmitbuf_cnt++;
1456 spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
1457 }
1458
1459 return _SUCCESS;
1460}
1461
1462static void rtw_init_xmitframe(struct xmit_frame *pxframe)
1463{
1464 if (pxframe != NULL) {
1465 /* default value setting */
1466 pxframe->buf_addr = NULL;
1467 pxframe->pxmitbuf = NULL;
1468
1469 memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
1470 /* pxframe->attrib.psta = NULL; */
1471
1472 pxframe->frame_tag = DATA_FRAMETAG;
1473
1474 pxframe->pkt = NULL;
1475 pxframe->pkt_offset = 1;/* default use pkt_offset to fill tx desc */
1476
1477 pxframe->ack_report = 0;
1478 }
1479}
1480
1481/*
1482Calling context:
14831. OS_TXENTRY
14842. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
1485
1486If we turn on USE_RXTHREAD, then, no need for critical section.
1487Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
1488
1489Must be very very cautious...
1490
1491*/
Jes Sorensen6042cbf2014-05-09 15:03:51 +02001492static struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)
Larry Finger5e93f352014-03-28 21:37:38 -05001493{
Larry Finger5e93f352014-03-28 21:37:38 -05001494 struct xmit_frame *pxframe = NULL;
1495 struct list_head *plist, *phead;
1496 struct rtw_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
1497
1498 spin_lock_bh(&pfree_xmit_queue->lock);
1499
Jes Sorensen794ff052014-05-09 15:03:59 +02001500 if (list_empty(&pfree_xmit_queue->queue)) {
Jes Sorensen6042cbf2014-05-09 15:03:51 +02001501 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
1502 ("rtw_alloc_xmitframe:%d\n",
1503 pxmitpriv->free_xmitframe_cnt));
Larry Finger5e93f352014-03-28 21:37:38 -05001504 pxframe = NULL;
1505 } else {
1506 phead = get_list_head(pfree_xmit_queue);
1507
1508 plist = phead->next;
1509
1510 pxframe = container_of(plist, struct xmit_frame, list);
1511
1512 list_del_init(&pxframe->list);
1513 pxmitpriv->free_xmitframe_cnt--;
Jes Sorensen6042cbf2014-05-09 15:03:51 +02001514 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
1515 ("rtw_alloc_xmitframe():free_xmitframe_cnt =%d\n",
1516 pxmitpriv->free_xmitframe_cnt));
Larry Finger5e93f352014-03-28 21:37:38 -05001517 }
1518
1519 spin_unlock_bh(&pfree_xmit_queue->lock);
1520
1521 rtw_init_xmitframe(pxframe);
1522
1523 return pxframe;
1524}
1525
1526struct xmit_frame *rtw_alloc_xmitframe23a_ext(struct xmit_priv *pxmitpriv)
1527{
1528 struct xmit_frame *pxframe = NULL;
1529 struct list_head *plist, *phead;
1530 struct rtw_queue *queue = &pxmitpriv->free_xframe_ext_queue;
1531
1532 spin_lock_bh(&queue->lock);
1533
Jes Sorensen794ff052014-05-09 15:03:59 +02001534 if (list_empty(&queue->queue)) {
Larry Finger5e93f352014-03-28 21:37:38 -05001535 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext:%d\n", pxmitpriv->free_xframe_ext_cnt));
1536 pxframe = NULL;
1537 } else {
1538 phead = get_list_head(queue);
1539 plist = phead->next;
1540 pxframe = container_of(plist, struct xmit_frame, list);
1541
1542 list_del_init(&pxframe->list);
1543 pxmitpriv->free_xframe_ext_cnt--;
1544 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe23a_ext():free_xmitframe_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
1545 }
1546
1547 spin_unlock_bh(&queue->lock);
1548
1549 rtw_init_xmitframe(pxframe);
1550
1551 return pxframe;
1552}
1553
1554s32 rtw_free_xmitframe23a(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)
1555{
1556 struct rtw_queue *queue = NULL;
1557 struct rtw_adapter *padapter = pxmitpriv->adapter;
1558 struct sk_buff *pndis_pkt = NULL;
1559
1560 if (pxmitframe == NULL) {
1561 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("====== rtw_free_xmitframe23a():pxmitframe == NULL!!!!!!!!!!\n"));
1562 goto exit;
1563 }
1564
1565 if (pxmitframe->pkt) {
1566 pndis_pkt = pxmitframe->pkt;
1567 pxmitframe->pkt = NULL;
1568 }
1569
1570 if (pxmitframe->ext_tag == 0)
1571 queue = &pxmitpriv->free_xmit_queue;
1572 else if (pxmitframe->ext_tag == 1)
1573 queue = &pxmitpriv->free_xframe_ext_queue;
1574
1575 if (!queue)
1576 goto check_pkt_complete;
1577 spin_lock_bh(&queue->lock);
1578
1579 list_del_init(&pxmitframe->list);
1580 list_add_tail(&pxmitframe->list, get_list_head(queue));
1581 if (pxmitframe->ext_tag == 0) {
1582 pxmitpriv->free_xmitframe_cnt++;
1583 RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xmitframe_cnt =%d\n", pxmitpriv->free_xmitframe_cnt));
1584 } else if (pxmitframe->ext_tag == 1) {
1585 pxmitpriv->free_xframe_ext_cnt++;
1586 RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe23a():free_xframe_ext_cnt =%d\n", pxmitpriv->free_xframe_ext_cnt));
1587 }
1588
1589 spin_unlock_bh(&queue->lock);
1590
1591check_pkt_complete:
1592
1593 if (pndis_pkt)
1594 rtw_os_pkt_complete23a(padapter, pndis_pkt);
1595
1596exit:
1597
1598 return _SUCCESS;
1599}
1600
1601void rtw_free_xmitframe_queue23a(struct xmit_priv *pxmitpriv,
1602 struct rtw_queue *pframequeue)
1603{
1604 struct list_head *plist, *phead, *ptmp;
1605 struct xmit_frame *pxmitframe;
1606
1607 spin_lock_bh(&pframequeue->lock);
1608
1609 phead = get_list_head(pframequeue);
1610
1611 list_for_each_safe(plist, ptmp, phead) {
1612 pxmitframe = container_of(plist, struct xmit_frame, list);
1613
1614 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
1615 }
1616 spin_unlock_bh(&pframequeue->lock);
1617
1618}
1619
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001620int rtw_xmitframe_enqueue23a(struct rtw_adapter *padapter,
Larry Finger5e93f352014-03-28 21:37:38 -05001621 struct xmit_frame *pxmitframe)
1622{
1623 if (rtw_xmit23a_classifier(padapter, pxmitframe) == _FAIL) {
1624 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1625 ("rtw_xmitframe_enqueue23a: drop xmit pkt for "
1626 "classifier fail\n"));
1627 return _FAIL;
1628 }
1629
1630 return _SUCCESS;
1631}
1632
1633static struct xmit_frame *
1634dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit,
1635 struct tx_servq *ptxservq, struct rtw_queue *pframe_queue)
1636{
1637 struct list_head *phead;
1638 struct xmit_frame *pxmitframe = NULL;
1639
1640 phead = get_list_head(pframe_queue);
1641
1642 if (!list_empty(phead)) {
1643 pxmitframe = list_first_entry(phead, struct xmit_frame, list);
1644 list_del_init(&pxmitframe->list);
1645 ptxservq->qcnt--;
1646 }
1647 return pxmitframe;
1648}
1649
1650struct xmit_frame *
1651rtw_dequeue_xframe23a(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i,
1652 int entry)
1653{
1654 struct list_head *sta_plist, *sta_phead, *ptmp;
1655 struct hw_xmit *phwxmit;
1656 struct tx_servq *ptxservq = NULL;
1657 struct rtw_queue *pframe_queue = NULL;
1658 struct xmit_frame *pxmitframe = NULL;
1659 struct rtw_adapter *padapter = pxmitpriv->adapter;
1660 struct registry_priv *pregpriv = &padapter->registrypriv;
1661 int i, inx[4];
1662
1663 inx[0] = 0;
1664 inx[1] = 1;
1665 inx[2] = 2;
1666 inx[3] = 3;
1667 if (pregpriv->wifi_spec == 1) {
1668 int j;
1669
1670 for (j = 0; j < 4; j++)
1671 inx[j] = pxmitpriv->wmm_para_seq[j];
1672 }
1673
1674 spin_lock_bh(&pxmitpriv->lock);
1675
1676 for (i = 0; i < entry; i++) {
1677 phwxmit = phwxmit_i + inx[i];
1678
1679 sta_phead = get_list_head(phwxmit->sta_queue);
1680
1681 list_for_each_safe(sta_plist, ptmp, sta_phead) {
1682 ptxservq = container_of(sta_plist, struct tx_servq,
1683 tx_pending);
1684
1685 pframe_queue = &ptxservq->sta_pending;
1686
1687 pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);
1688
1689 if (pxmitframe) {
1690 phwxmit->accnt--;
1691
1692 /* Remove sta node when there is no pending packets. */
Jes Sorensen794ff052014-05-09 15:03:59 +02001693 /* must be done after get_next and
1694 before break */
1695 if (list_empty(&pframe_queue->queue))
Larry Finger5e93f352014-03-28 21:37:38 -05001696 list_del_init(&ptxservq->tx_pending);
1697 goto exit;
1698 }
1699 }
1700 }
1701exit:
1702 spin_unlock_bh(&pxmitpriv->lock);
1703 return pxmitframe;
1704}
1705
1706struct tx_servq *rtw_get_sta_pending23a(struct rtw_adapter *padapter, struct sta_info *psta, int up, u8 *ac)
1707{
1708 struct tx_servq *ptxservq = NULL;
1709
1710 switch (up) {
1711 case 1:
1712 case 2:
1713 ptxservq = &psta->sta_xmitpriv.bk_q;
1714 *(ac) = 3;
1715 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BK\n"));
1716 break;
1717 case 4:
1718 case 5:
1719 ptxservq = &psta->sta_xmitpriv.vi_q;
1720 *(ac) = 1;
1721 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VI\n"));
1722 break;
1723 case 6:
1724 case 7:
1725 ptxservq = &psta->sta_xmitpriv.vo_q;
1726 *(ac) = 0;
1727 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : VO\n"));
1728 break;
1729 case 0:
1730 case 3:
1731 default:
1732 ptxservq = &psta->sta_xmitpriv.be_q;
1733 *(ac) = 2;
1734 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_get_sta_pending23a : BE\n"));
1735 break;
1736 }
1737 return ptxservq;
1738}
1739
1740/*
1741 * Will enqueue pxmitframe to the proper queue,
1742 * and indicate it to xx_pending list.....
1743 */
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001744int rtw_xmit23a_classifier(struct rtw_adapter *padapter,
1745 struct xmit_frame *pxmitframe)
Larry Finger5e93f352014-03-28 21:37:38 -05001746{
1747 struct sta_info *psta;
1748 struct tx_servq *ptxservq;
1749 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1750 struct sta_priv *pstapriv = &padapter->stapriv;
1751 struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
1752 u8 ac_index;
1753 int res = _SUCCESS;
1754
1755 if (pattrib->psta) {
1756 psta = pattrib->psta;
1757 } else {
1758 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1759 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
1760 }
1761 if (psta == NULL) {
1762 res = _FAIL;
1763 DBG_8723A("rtw_xmit23a_classifier: psta == NULL\n");
1764 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
1765 ("rtw_xmit23a_classifier: psta == NULL\n"));
1766 goto exit;
1767 }
1768 if (!(psta->state & _FW_LINKED)) {
1769 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1770 psta->state);
1771 return _FAIL;
1772 }
1773 ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority,
1774 (u8 *)(&ac_index));
1775
1776 if (list_empty(&ptxservq->tx_pending)) {
1777 list_add_tail(&ptxservq->tx_pending,
1778 get_list_head(phwxmits[ac_index].sta_queue));
1779 }
1780
1781 list_add_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
1782 ptxservq->qcnt++;
1783 phwxmits[ac_index].accnt++;
1784exit:
1785 return res;
1786}
1787
1788void rtw_alloc_hwxmits23a(struct rtw_adapter *padapter)
1789{
1790 struct hw_xmit *hwxmits;
1791 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1792 int size;
1793
1794 pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
1795
1796 size = sizeof(struct hw_xmit) * (pxmitpriv->hwxmit_entry + 1);
1797 pxmitpriv->hwxmits = kzalloc(size, GFP_KERNEL);
1798
1799 hwxmits = pxmitpriv->hwxmits;
1800
1801 if (pxmitpriv->hwxmit_entry == 5) {
1802 /* pxmitpriv->bmc_txqueue.head = 0; */
1803 /* hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue; */
1804 hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
1805
1806 /* pxmitpriv->vo_txqueue.head = 0; */
1807 /* hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue; */
1808 hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
1809
1810 /* pxmitpriv->vi_txqueue.head = 0; */
1811 /* hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue; */
1812 hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
1813
1814 /* pxmitpriv->bk_txqueue.head = 0; */
1815 /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
1816 hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
1817
1818 /* pxmitpriv->be_txqueue.head = 0; */
1819 /* hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue; */
1820 hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
1821
1822 } else if (pxmitpriv->hwxmit_entry == 4) {
1823
1824 /* pxmitpriv->vo_txqueue.head = 0; */
1825 /* hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue; */
1826 hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
1827
1828 /* pxmitpriv->vi_txqueue.head = 0; */
1829 /* hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue; */
1830 hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
1831
1832 /* pxmitpriv->be_txqueue.head = 0; */
1833 /* hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue; */
1834 hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
1835
1836 /* pxmitpriv->bk_txqueue.head = 0; */
1837 /* hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue; */
1838 hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
1839 } else {
1840
1841 }
1842}
1843
1844void rtw_free_hwxmits23a(struct rtw_adapter *padapter)
1845{
1846 struct hw_xmit *hwxmits;
1847 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1848
1849 hwxmits = pxmitpriv->hwxmits;
1850 kfree(hwxmits);
1851}
1852
1853void rtw_init_hwxmits23a(struct hw_xmit *phwxmit, int entry)
1854{
1855 int i;
1856
1857 for (i = 0; i < entry; i++, phwxmit++)
1858 phwxmit->accnt = 0;
1859}
1860
1861u32 rtw_get_ff_hwaddr23a(struct xmit_frame *pxmitframe)
1862{
1863 u32 addr;
1864 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1865
1866 switch (pattrib->qsel) {
1867 case 0:
1868 case 3:
1869 addr = BE_QUEUE_INX;
1870 break;
1871 case 1:
1872 case 2:
1873 addr = BK_QUEUE_INX;
1874 break;
1875 case 4:
1876 case 5:
1877 addr = VI_QUEUE_INX;
1878 break;
1879 case 6:
1880 case 7:
1881 addr = VO_QUEUE_INX;
1882 break;
1883 case 0x10:
1884 addr = BCN_QUEUE_INX;
1885 break;
1886 case 0x11:/* BC/MC in PS (HIQ) */
1887 addr = HIGH_QUEUE_INX;
1888 break;
1889 case 0x12:
1890 default:
1891 addr = MGT_QUEUE_INX;
1892 break;
1893 }
1894
1895 return addr;
1896}
1897
1898static void do_queue_select(struct rtw_adapter *padapter, struct pkt_attrib *pattrib)
1899{
1900 u8 qsel;
1901
1902 qsel = pattrib->priority;
1903 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
1904 ("### do_queue_select priority =%d , qsel = %d\n",
1905 pattrib->priority, qsel));
1906
1907 pattrib->qsel = qsel;
1908}
1909
1910/*
1911 * The main transmit(tx) entry
1912 *
1913 * Return
1914 * 1 enqueue
1915 * 0 success, hardware will handle this xmit frame(packet)
1916 * <0 fail
1917 */
1918int rtw_xmit23a(struct rtw_adapter *padapter, struct sk_buff *skb)
1919{
1920 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1921 struct xmit_frame *pxmitframe = NULL;
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001922 int res;
Larry Finger5e93f352014-03-28 21:37:38 -05001923
Jes Sorensen6042cbf2014-05-09 15:03:51 +02001924 pxmitframe = rtw_alloc_xmitframe(pxmitpriv);
Larry Finger5e93f352014-03-28 21:37:38 -05001925
1926 if (pxmitframe == NULL) {
1927 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
1928 ("rtw_xmit23a: no more pxmitframe\n"));
1929 return -1;
1930 }
1931
1932 res = update_attrib(padapter, skb, &pxmitframe->attrib);
1933
1934 if (res == _FAIL) {
1935 RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit23a: update attrib fail\n"));
1936 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
1937 return -1;
1938 }
1939 pxmitframe->pkt = skb;
1940
1941 rtw_led_control(padapter, LED_CTL_TX);
1942
1943 do_queue_select(padapter, &pxmitframe->attrib);
1944
1945#ifdef CONFIG_8723AU_AP_MODE
1946 spin_lock_bh(&pxmitpriv->lock);
1947 if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
1948 spin_unlock_bh(&pxmitpriv->lock);
1949 return 1;
1950 }
1951 spin_unlock_bh(&pxmitpriv->lock);
1952#endif
1953
Jes Sorensen638443d2014-05-16 10:04:18 +02001954 if (rtl8723au_hal_xmit(padapter, pxmitframe) == false)
Larry Finger5e93f352014-03-28 21:37:38 -05001955 return 1;
1956
1957 return 0;
1958}
1959
1960#if defined(CONFIG_8723AU_AP_MODE)
1961
1962int xmitframe_enqueue_for_sleeping_sta23a(struct rtw_adapter *padapter, struct xmit_frame *pxmitframe)
1963{
1964 int ret = false;
1965 struct sta_info *psta = NULL;
1966 struct sta_priv *pstapriv = &padapter->stapriv;
1967 struct pkt_attrib *pattrib = &pxmitframe->attrib;
1968 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1969 int bmcst = is_multicast_ether_addr(pattrib->ra);
1970
1971 if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == false)
Jes Sorensen8fd873d2014-05-16 10:04:40 +02001972 return ret;
Larry Finger5e93f352014-03-28 21:37:38 -05001973
1974 if (pattrib->psta) {
1975 psta = pattrib->psta;
1976 } else {
1977 DBG_8723A("%s, call rtw_get_stainfo23a()\n", __func__);
1978 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
1979 }
1980
1981 if (psta == NULL) {
1982 DBG_8723A("%s, psta == NUL\n", __func__);
1983 return false;
1984 }
1985
1986 if (!(psta->state & _FW_LINKED)) {
1987 DBG_8723A("%s, psta->state(0x%x) != _FW_LINKED\n", __func__,
1988 psta->state);
1989 return false;
1990 }
1991
1992 if (pattrib->triggered == 1) {
1993 if (bmcst)
1994 pattrib->qsel = 0x11;/* HIQ */
1995 return ret;
1996 }
1997
1998 if (bmcst) {
1999 spin_lock_bh(&psta->sleep_q.lock);
2000
2001 if (pstapriv->sta_dz_bitmap) {
2002 /* if anyone sta is in ps mode */
2003 list_del_init(&pxmitframe->list);
2004
2005 /* spin_lock_bh(&psta->sleep_q.lock); */
2006
2007 list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
2008
2009 psta->sleepq_len++;
2010
2011 pstapriv->tim_bitmap |= BIT(0);/* */
2012 pstapriv->sta_dz_bitmap |= BIT(0);
2013
2014 /* DBG_8723A("enqueue, sq_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
2015
Jes Sorensen3455f1f2014-04-15 19:43:31 +02002016 /* tx bc/mc packets after upate bcn */
2017 update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
Larry Finger5e93f352014-03-28 21:37:38 -05002018
2019 /* spin_unlock_bh(&psta->sleep_q.lock); */
2020
2021 ret = true;
2022
2023 }
2024
2025 spin_unlock_bh(&psta->sleep_q.lock);
2026
2027 return ret;
2028
2029 }
2030
2031 spin_lock_bh(&psta->sleep_q.lock);
2032
2033 if (psta->state&WIFI_SLEEP_STATE) {
2034 u8 wmmps_ac = 0;
2035
2036 if (pstapriv->sta_dz_bitmap & CHKBIT(psta->aid)) {
2037 list_del_init(&pxmitframe->list);
2038
2039 /* spin_lock_bh(&psta->sleep_q.lock); */
2040
2041 list_add_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
2042
2043 psta->sleepq_len++;
2044
2045 switch (pattrib->priority) {
2046 case 1:
2047 case 2:
2048 wmmps_ac = psta->uapsd_bk & BIT(0);
2049 break;
2050 case 4:
2051 case 5:
2052 wmmps_ac = psta->uapsd_vi & BIT(0);
2053 break;
2054 case 6:
2055 case 7:
2056 wmmps_ac = psta->uapsd_vo & BIT(0);
2057 break;
2058 case 0:
2059 case 3:
2060 default:
2061 wmmps_ac = psta->uapsd_be & BIT(0);
2062 break;
2063 }
2064
2065 if (wmmps_ac)
2066 psta->sleepq_ac_len++;
2067
2068 if (((psta->has_legacy_ac) && (!wmmps_ac)) ||
2069 ((!psta->has_legacy_ac) && (wmmps_ac))) {
2070 pstapriv->tim_bitmap |= CHKBIT(psta->aid);
2071
2072 if (psta->sleepq_len == 1) {
2073 /* upate BCN for TIM IE */
Jes Sorensen3455f1f2014-04-15 19:43:31 +02002074 update_beacon23a(padapter, WLAN_EID_TIM,
2075 NULL, false);
Larry Finger5e93f352014-03-28 21:37:38 -05002076 }
2077 }
2078
2079 /* spin_unlock_bh(&psta->sleep_q.lock); */
2080
2081 /* if (psta->sleepq_len > (NR_XMITFRAME>>3)) */
2082 /* */
2083 /* wakeup_sta_to_xmit23a(padapter, psta); */
2084 /* */
2085
2086 ret = true;
2087
2088 }
2089
2090 }
2091
2092 spin_unlock_bh(&psta->sleep_q.lock);
2093
2094 return ret;
2095}
2096
2097static void
2098dequeue_xmitframes_to_sleeping_queue(struct rtw_adapter *padapter,
2099 struct sta_info *psta,
2100 struct rtw_queue *pframequeue)
2101{
2102 int ret;
2103 struct list_head *plist, *phead, *ptmp;
2104 u8 ac_index;
2105 struct tx_servq *ptxservq;
2106 struct pkt_attrib *pattrib;
2107 struct xmit_frame *pxmitframe;
2108 struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
2109
2110 phead = get_list_head(pframequeue);
2111
2112 list_for_each_safe(plist, ptmp, phead) {
2113 pxmitframe = container_of(plist, struct xmit_frame, list);
2114
2115 ret = xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe);
2116
2117 if (ret == true) {
2118 pattrib = &pxmitframe->attrib;
2119
2120 ptxservq = rtw_get_sta_pending23a(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
2121
2122 ptxservq->qcnt--;
2123 phwxmits[ac_index].accnt--;
2124 } else {
2125 /* DBG_8723A("xmitframe_enqueue_for_sleeping_sta23a return false\n"); */
2126 }
2127 }
2128}
2129
2130void stop_sta_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
2131{
2132 struct sta_info *psta_bmc;
2133 struct sta_xmit_priv *pstaxmitpriv;
2134 struct sta_priv *pstapriv = &padapter->stapriv;
2135 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2136
2137 pstaxmitpriv = &psta->sta_xmitpriv;
2138
2139 /* for BC/MC Frames */
2140 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
2141
2142 spin_lock_bh(&pxmitpriv->lock);
2143
2144 psta->state |= WIFI_SLEEP_STATE;
2145
2146 pstapriv->sta_dz_bitmap |= CHKBIT(psta->aid);
2147
2148 dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
2149 list_del_init(&pstaxmitpriv->vo_q.tx_pending);
2150
2151 dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
2152 list_del_init(&pstaxmitpriv->vi_q.tx_pending);
2153
2154 dequeue_xmitframes_to_sleeping_queue(padapter, psta,
2155 &pstaxmitpriv->be_q.sta_pending);
2156 list_del_init(&pstaxmitpriv->be_q.tx_pending);
2157
2158 dequeue_xmitframes_to_sleeping_queue(padapter, psta,
2159 &pstaxmitpriv->bk_q.sta_pending);
2160 list_del_init(&pstaxmitpriv->bk_q.tx_pending);
2161
2162 /* for BC/MC Frames */
2163 pstaxmitpriv = &psta_bmc->sta_xmitpriv;
2164 dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc,
2165 &pstaxmitpriv->be_q.sta_pending);
2166 list_del_init(&pstaxmitpriv->be_q.tx_pending);
2167
2168 spin_unlock_bh(&pxmitpriv->lock);
2169}
2170
2171void wakeup_sta_to_xmit23a(struct rtw_adapter *padapter, struct sta_info *psta)
2172{
2173 u8 update_mask = 0, wmmps_ac = 0;
2174 struct sta_info *psta_bmc;
2175 struct list_head *plist, *phead, *ptmp;
2176 struct xmit_frame *pxmitframe = NULL;
2177 struct sta_priv *pstapriv = &padapter->stapriv;
2178 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2179
2180 spin_lock_bh(&pxmitpriv->lock);
2181
2182 phead = get_list_head(&psta->sleep_q);
2183
2184 list_for_each_safe(plist, ptmp, phead) {
2185 pxmitframe = container_of(plist, struct xmit_frame, list);
2186 list_del_init(&pxmitframe->list);
2187
2188 switch (pxmitframe->attrib.priority) {
2189 case 1:
2190 case 2:
2191 wmmps_ac = psta->uapsd_bk & BIT(1);
2192 break;
2193 case 4:
2194 case 5:
2195 wmmps_ac = psta->uapsd_vi & BIT(1);
2196 break;
2197 case 6:
2198 case 7:
2199 wmmps_ac = psta->uapsd_vo & BIT(1);
2200 break;
2201 case 0:
2202 case 3:
2203 default:
2204 wmmps_ac = psta->uapsd_be & BIT(1);
2205 break;
2206 }
2207
2208 psta->sleepq_len--;
2209 if (psta->sleepq_len > 0)
2210 pxmitframe->attrib.mdata = 1;
2211 else
2212 pxmitframe->attrib.mdata = 0;
2213
2214 if (wmmps_ac) {
2215 psta->sleepq_ac_len--;
2216 if (psta->sleepq_ac_len > 0) {
2217 pxmitframe->attrib.mdata = 1;
2218 pxmitframe->attrib.eosp = 0;
2219 } else {
2220 pxmitframe->attrib.mdata = 0;
2221 pxmitframe->attrib.eosp = 1;
2222 }
2223 }
2224
2225 pxmitframe->attrib.triggered = 1;
Jes Sorensen638443d2014-05-16 10:04:18 +02002226 rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe);
Larry Finger5e93f352014-03-28 21:37:38 -05002227 }
2228
2229 if (psta->sleepq_len == 0) {
2230 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
2231
2232 /* upate BCN for TIM IE */
2233 update_mask = BIT(0);
2234
2235 if (psta->state&WIFI_SLEEP_STATE)
2236 psta->state ^= WIFI_SLEEP_STATE;
2237
2238 if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
2239 psta->expire_to = pstapriv->expire_to;
2240 psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
2241 }
2242
2243 pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
2244 }
2245
2246 /* spin_unlock_bh(&psta->sleep_q.lock); */
2247 spin_unlock_bh(&pxmitpriv->lock);
2248
2249 /* for BC/MC Frames */
2250 psta_bmc = rtw_get_bcmc_stainfo23a(padapter);
2251 if (!psta_bmc)
2252 return;
2253
2254 if ((pstapriv->sta_dz_bitmap&0xfffe) == 0x0) {
2255 /* no any sta in ps mode */
2256 spin_lock_bh(&pxmitpriv->lock);
2257
2258 phead = get_list_head(&psta_bmc->sleep_q);
2259
2260 list_for_each_safe(plist, ptmp, phead) {
2261 pxmitframe = container_of(plist, struct xmit_frame,
2262 list);
2263
2264 list_del_init(&pxmitframe->list);
2265
2266 psta_bmc->sleepq_len--;
2267 if (psta_bmc->sleepq_len > 0)
2268 pxmitframe->attrib.mdata = 1;
2269 else
2270 pxmitframe->attrib.mdata = 0;
2271
2272 pxmitframe->attrib.triggered = 1;
Jes Sorensen638443d2014-05-16 10:04:18 +02002273 rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe);
Larry Finger5e93f352014-03-28 21:37:38 -05002274 }
2275 if (psta_bmc->sleepq_len == 0) {
2276 pstapriv->tim_bitmap &= ~BIT(0);
2277 pstapriv->sta_dz_bitmap &= ~BIT(0);
2278
2279 /* upate BCN for TIM IE */
2280 /* update_BCNTIM(padapter); */
2281 update_mask |= BIT(1);
2282 }
2283
2284 /* spin_unlock_bh(&psta_bmc->sleep_q.lock); */
2285 spin_unlock_bh(&pxmitpriv->lock);
2286 }
2287
2288 if (update_mask)
Jes Sorensen3455f1f2014-04-15 19:43:31 +02002289 update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
Larry Finger5e93f352014-03-28 21:37:38 -05002290}
2291
2292void xmit_delivery_enabled_frames23a(struct rtw_adapter *padapter,
2293 struct sta_info *psta)
2294{
2295 u8 wmmps_ac = 0;
2296 struct list_head *plist, *phead, *ptmp;
2297 struct xmit_frame *pxmitframe;
2298 struct sta_priv *pstapriv = &padapter->stapriv;
2299 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
2300
2301 /* spin_lock_bh(&psta->sleep_q.lock); */
2302 spin_lock_bh(&pxmitpriv->lock);
2303
2304 phead = get_list_head(&psta->sleep_q);
2305
2306 list_for_each_safe(plist, ptmp, phead) {
2307 pxmitframe = container_of(plist, struct xmit_frame, list);
2308
2309 switch (pxmitframe->attrib.priority) {
2310 case 1:
2311 case 2:
2312 wmmps_ac = psta->uapsd_bk & BIT(1);
2313 break;
2314 case 4:
2315 case 5:
2316 wmmps_ac = psta->uapsd_vi & BIT(1);
2317 break;
2318 case 6:
2319 case 7:
2320 wmmps_ac = psta->uapsd_vo & BIT(1);
2321 break;
2322 case 0:
2323 case 3:
2324 default:
2325 wmmps_ac = psta->uapsd_be & BIT(1);
2326 break;
2327 }
2328
2329 if (!wmmps_ac)
2330 continue;
2331
2332 list_del_init(&pxmitframe->list);
2333
2334 psta->sleepq_len--;
2335 psta->sleepq_ac_len--;
2336
2337 if (psta->sleepq_ac_len > 0) {
2338 pxmitframe->attrib.mdata = 1;
2339 pxmitframe->attrib.eosp = 0;
2340 } else {
2341 pxmitframe->attrib.mdata = 0;
2342 pxmitframe->attrib.eosp = 1;
2343 }
2344
2345 pxmitframe->attrib.triggered = 1;
2346
Jes Sorensen638443d2014-05-16 10:04:18 +02002347 rtl8723au_hal_xmitframe_enqueue(padapter, pxmitframe);
Larry Finger5e93f352014-03-28 21:37:38 -05002348
2349 if ((psta->sleepq_ac_len == 0) && (!psta->has_legacy_ac) &&
2350 (wmmps_ac)) {
2351 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
2352
2353 /* upate BCN for TIM IE */
Jes Sorensen3455f1f2014-04-15 19:43:31 +02002354 update_beacon23a(padapter, WLAN_EID_TIM, NULL, false);
Larry Finger5e93f352014-03-28 21:37:38 -05002355 }
2356 }
2357 spin_unlock_bh(&pxmitpriv->lock);
2358}
2359
2360#endif
2361
2362void rtw_sctx_init23a(struct submit_ctx *sctx, int timeout_ms)
2363{
2364 sctx->timeout_ms = timeout_ms;
2365 init_completion(&sctx->done);
2366 sctx->status = RTW_SCTX_SUBMITTED;
2367}
2368
2369int rtw_sctx_wait23a(struct submit_ctx *sctx)
2370{
2371 int ret = _FAIL;
2372 unsigned long expire;
2373 int status = 0;
2374
2375 expire = sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) :
2376 MAX_SCHEDULE_TIMEOUT;
2377 if (!wait_for_completion_timeout(&sctx->done, expire)) {
2378 /* timeout, do something?? */
2379 status = RTW_SCTX_DONE_TIMEOUT;
2380 DBG_8723A("%s timeout\n", __func__);
2381 } else {
2382 status = sctx->status;
2383 }
2384
2385 if (status == RTW_SCTX_DONE_SUCCESS)
2386 ret = _SUCCESS;
2387
2388 return ret;
2389}
2390
2391static bool rtw_sctx_chk_waring_status(int status)
2392{
2393 switch (status) {
2394 case RTW_SCTX_DONE_UNKNOWN:
2395 case RTW_SCTX_DONE_BUF_ALLOC:
2396 case RTW_SCTX_DONE_BUF_FREE:
2397 case RTW_SCTX_DONE_DRV_STOP:
2398 case RTW_SCTX_DONE_DEV_REMOVE:
2399 return true;
2400 default:
2401 return false;
2402 }
2403}
2404
2405void rtw23a_sctx_done_err(struct submit_ctx **sctx, int status)
2406{
2407 if (*sctx) {
2408 if (rtw_sctx_chk_waring_status(status))
2409 DBG_8723A("%s status:%d\n", __func__, status);
2410 (*sctx)->status = status;
2411 complete(&(*sctx)->done);
2412 *sctx = NULL;
2413 }
2414}
2415
2416void rtw_sctx_done23a(struct submit_ctx **sctx)
2417{
2418 rtw23a_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
2419}
2420
2421int rtw_ack_tx_wait23a(struct xmit_priv *pxmitpriv, u32 timeout_ms)
2422{
2423 struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
2424
2425 pack_tx_ops->timeout_ms = timeout_ms;
2426 pack_tx_ops->status = RTW_SCTX_SUBMITTED;
2427
2428 return rtw_sctx_wait23a(pack_tx_ops);
2429}
2430
2431void rtw_ack_tx_done23a(struct xmit_priv *pxmitpriv, int status)
2432{
2433 struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
2434
2435 if (pxmitpriv->ack_tx)
2436 rtw23a_sctx_done_err(&pack_tx_ops, status);
2437 else
2438 DBG_8723A("%s ack_tx not set\n", __func__);
2439}