1 /******************************************************************************
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 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20
21 #define _RTL8723BU_XMIT_C_
22
23 #include <rtl8723b_hal.h>
24
25
rtl8723bu_init_xmit_priv(_adapter * padapter)26 s32 rtl8723bu_init_xmit_priv(_adapter *padapter)
27 {
28 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
29
30 #ifdef PLATFORM_LINUX
31 tasklet_init(&pxmitpriv->xmit_tasklet,
32 (void(*)(unsigned long))rtl8723bu_xmit_tasklet,
33 (unsigned long)padapter);
34 #endif
35 return _SUCCESS;
36 }
37
rtl8723bu_free_xmit_priv(_adapter * padapter)38 void rtl8723bu_free_xmit_priv(_adapter *padapter)
39 {
40 }
41
_dbg_dump_tx_info(_adapter * padapter,int frame_tag,struct tx_desc * ptxdesc)42 void _dbg_dump_tx_info(_adapter *padapter,int frame_tag,struct tx_desc *ptxdesc)
43 {
44 u8 bDumpTxPkt;
45 u8 bDumpTxDesc = _FALSE;
46 rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DUMP_TXPKT, &(bDumpTxPkt));
47
48 if(bDumpTxPkt ==1){//dump txdesc for data frame
49 DBG_871X("dump tx_desc for data frame\n");
50 if((frame_tag&0x0f) == DATA_FRAMETAG){
51 bDumpTxDesc = _TRUE;
52 }
53 }
54 else if(bDumpTxPkt ==2){//dump txdesc for mgnt frame
55 DBG_871X("dump tx_desc for mgnt frame\n");
56 if((frame_tag&0x0f) == MGNT_FRAMETAG){
57 bDumpTxDesc = _TRUE;
58 }
59 }
60 else if(bDumpTxPkt ==3){//dump early info
61 }
62
63 if(bDumpTxDesc){
64 // ptxdesc->txdw4 = cpu_to_le32(0x00001006);//RTS Rate=24M
65 // ptxdesc->txdw6 = 0x6666f800;
66 DBG_8192C("=====================================\n");
67 DBG_8192C("txdw0(0x%08x)\n",ptxdesc->txdw0);
68 DBG_8192C("txdw1(0x%08x)\n",ptxdesc->txdw1);
69 DBG_8192C("txdw2(0x%08x)\n",ptxdesc->txdw2);
70 DBG_8192C("txdw3(0x%08x)\n",ptxdesc->txdw3);
71 DBG_8192C("txdw4(0x%08x)\n",ptxdesc->txdw4);
72 DBG_8192C("txdw5(0x%08x)\n",ptxdesc->txdw5);
73 DBG_8192C("txdw6(0x%08x)\n",ptxdesc->txdw6);
74 DBG_8192C("txdw7(0x%08x)\n",ptxdesc->txdw7);
75 DBG_8192C("=====================================\n");
76 }
77
78 }
79
urb_zero_packet_chk(_adapter * padapter,int sz)80 int urb_zero_packet_chk(_adapter *padapter, int sz)
81 {
82 u8 blnSetTxDescOffset;
83 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
84 blnSetTxDescOffset = (((sz + TXDESC_SIZE) % pHalData->UsbBulkOutSize) ==0)?1:0;
85
86 return blnSetTxDescOffset;
87 }
fill_txdesc_sectype(struct pkt_attrib * pattrib,struct tx_desc * ptxdesc)88 void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
89 {
90 if ((pattrib->encrypt > 0) && !pattrib->bswenc)
91 {
92 switch (pattrib->encrypt)
93 {
94 //SEC_TYPE
95 case _WEP40_:
96 case _WEP104_:
97 ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
98 break;
99 case _TKIP_:
100 case _TKIP_WTMIC_:
101 //ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000);
102 ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
103 break;
104 case _AES_:
105 ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000);
106 break;
107 case _NO_PRIVACY_:
108 default:
109 break;
110
111 }
112
113 }
114
115 }
116
fill_txdesc_vcs(struct pkt_attrib * pattrib,u32 * pdw)117 void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw)
118 {
119 //DBG_8192C("cvs_mode=%d\n", pattrib->vcs_mode);
120
121 switch(pattrib->vcs_mode)
122 {
123 case RTS_CTS:
124 *pdw |= cpu_to_le32(BIT(12));
125 break;
126 case CTS_TO_SELF:
127 *pdw |= cpu_to_le32(BIT(11));
128 break;
129 case NONE_VCS:
130 default:
131 break;
132 }
133
134 if(pattrib->vcs_mode) {
135 *pdw |= cpu_to_le32(BIT(13));
136
137 // Set RTS BW
138 if(pattrib->ht_en)
139 {
140 *pdw |= (pattrib->bwmode&CHANNEL_WIDTH_40)? cpu_to_le32(BIT(27)):0;
141
142 if(pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
143 *pdw |= cpu_to_le32((0x01<<28)&0x30000000);
144 else if(pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
145 *pdw |= cpu_to_le32((0x02<<28)&0x30000000);
146 else if(pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
147 *pdw |= 0;
148 else
149 *pdw |= cpu_to_le32((0x03<<28)&0x30000000);
150 }
151 }
152 }
153
fill_txdesc_phy(struct pkt_attrib * pattrib,u32 * pdw)154 void fill_txdesc_phy(struct pkt_attrib *pattrib, u32 *pdw)
155 {
156 //DBG_8192C("bwmode=%d, ch_off=%d\n", pattrib->bwmode, pattrib->ch_offset);
157
158 if(pattrib->ht_en)
159 {
160 *pdw |= (pattrib->bwmode&CHANNEL_WIDTH_40)? cpu_to_le32(BIT(25)):0;
161
162 if(pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
163 *pdw |= cpu_to_le32((0x01<<20)&0x003f0000);
164 else if(pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
165 *pdw |= cpu_to_le32((0x02<<20)&0x003f0000);
166 else if(pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
167 *pdw |= 0;
168 else
169 *pdw |= cpu_to_le32((0x03<<20)&0x003f0000);
170 }
171 }
172
update_txdesc(struct xmit_frame * pxmitframe,u8 * pmem,s32 sz,u8 bagg_pkt)173 static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
174 {
175 int pull=0;
176
177
178 _adapter *padapter = pxmitframe->padapter;
179 struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
180 #if 0
181 uint qsel;
182 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
183 struct pkt_attrib *pattrib = &pxmitframe->attrib;
184 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
185
186 struct ht_priv *phtpriv = &pmlmepriv->htpriv;
187 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
188 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
189 sint bmcst = IS_MCAST(pattrib->ra);
190 #ifdef CONFIG_P2P
191 struct wifidirect_info* pwdinfo = &padapter->wdinfo;
192 #endif //CONFIG_P2P
193 #endif
194 #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX
195 if ((PACKET_OFFSET_SZ != 0)
196 && (_FALSE == bagg_pkt)
197 && (urb_zero_packet_chk(padapter, sz) == 0)) {
198 ptxdesc = (struct tx_desc *)(pmem + PACKET_OFFSET_SZ);
199 pull = 1;
200 pxmitframe->pkt_offset --;
201 }
202 #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
203
204 _rtw_memset(ptxdesc, 0, sizeof(struct tx_desc));
205
206 rtl8723b_update_txdesc(pxmitframe, (u8 *)ptxdesc);
207 _dbg_dump_tx_info(padapter,pxmitframe->frame_tag,ptxdesc);
208 return pull;
209
210 }
211
212 #ifdef CONFIG_XMIT_THREAD_MODE
213 /*
214 * Description
215 * Transmit xmitbuf to hardware tx fifo
216 *
217 * Return
218 * _SUCCESS ok
219 * _FAIL something error
220 */
rtl8723bu_xmit_buf_handler(PADAPTER padapter)221 s32 rtl8723bu_xmit_buf_handler(PADAPTER padapter)
222 {
223 //PHAL_DATA_TYPE phal;
224 struct xmit_priv *pxmitpriv;
225 struct xmit_buf *pxmitbuf;
226 s32 ret;
227
228
229 //phal = GET_HAL_DATA(padapter);
230 pxmitpriv = &padapter->xmitpriv;
231
232 ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
233 if (_FAIL == ret) {
234 RT_TRACE(_module_hal_xmit_c_, _drv_emerg_,
235 ("%s: down SdioXmitBufSema fail!\n", __FUNCTION__));
236 return _FAIL;
237 }
238
239 if (RTW_CANNOT_RUN(padapter)) {
240 RT_TRACE(_module_hal_xmit_c_, _drv_notice_
241 , ("%s: bDriverStopped(%s) bSurpriseRemoved(%s)!\n"
242 , __func__
243 , rtw_is_drv_stopped(padapter)?"True":"False"
244 , rtw_is_surprise_removed(padapter)?"True":"False"));
245 return _FAIL;
246 }
247
248 if(check_pending_xmitbuf(pxmitpriv) == _FALSE)
249 return _SUCCESS;
250
251 #ifdef CONFIG_LPS_LCLK
252 ret = rtw_register_tx_alive(padapter);
253 if (ret != _SUCCESS) {
254 RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
255 ("%s: wait to leave LPS_LCLK\n", __FUNCTION__));
256 return _SUCCESS;
257 }
258 #endif
259
260 do {
261 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
262 if (pxmitbuf == NULL) break;
263
264 rtw_write_port(padapter, pxmitbuf->ff_hwaddr, pxmitbuf->len, (unsigned char*)pxmitbuf);
265
266 } while (1);
267
268 #ifdef CONFIG_LPS_LCLK
269 rtw_unregister_tx_alive(padapter);
270 #endif
271
272 return _SUCCESS;
273 }
274 #endif
275
276
rtw_dump_xframe(_adapter * padapter,struct xmit_frame * pxmitframe)277 static s32 rtw_dump_xframe(_adapter *padapter, struct xmit_frame *pxmitframe)
278 {
279 s32 ret = _SUCCESS;
280 s32 inner_ret = _SUCCESS;
281 int t, sz, w_sz, pull=0;
282 u8 *mem_addr;
283 u32 ff_hwaddr;
284 struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
285 struct pkt_attrib *pattrib = &pxmitframe->attrib;
286 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
287 struct security_priv *psecuritypriv = &padapter->securitypriv;
288
289 if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
290 (pxmitframe->attrib.ether_type != 0x0806) &&
291 (pxmitframe->attrib.ether_type != 0x888e) &&
292 (pxmitframe->attrib.dhcp_pkt != 1))
293 {
294 rtw_issue_addbareq_cmd(padapter, pxmitframe);
295 }
296
297 mem_addr = pxmitframe->buf_addr;
298
299 RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_dump_xframe()\n"));
300
301 for (t = 0; t < pattrib->nr_frags; t++)
302 {
303 if (inner_ret != _SUCCESS && ret == _SUCCESS)
304 ret = _FAIL;
305
306 if (t != (pattrib->nr_frags - 1))
307 {
308 RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("pattrib->nr_frags=%d\n", pattrib->nr_frags));
309
310 sz = pxmitpriv->frag_len;
311 sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);
312 }
313 else //no frag
314 {
315 sz = pattrib->last_txcmdsz;
316 }
317
318 pull = update_txdesc(pxmitframe, mem_addr, sz, _FALSE);
319 // rtl8723b_update_txdesc(pxmitframe, mem_addr+PACKET_OFFSET_SZ);
320
321 if(pull)
322 {
323 mem_addr += PACKET_OFFSET_SZ; //pull txdesc head
324
325 //pxmitbuf ->pbuf = mem_addr;
326 pxmitframe->buf_addr = mem_addr;
327
328 w_sz = sz + TXDESC_SIZE;
329 }
330 else
331 {
332 w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
333 }
334
335 ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
336 #ifdef CONFIG_XMIT_THREAD_MODE
337 pxmitbuf->len = w_sz;
338 pxmitbuf->ff_hwaddr = ff_hwaddr;
339 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
340 #else
341 inner_ret = rtw_write_port(padapter, ff_hwaddr, w_sz, (unsigned char*)pxmitbuf);
342 #endif
343 rtw_count_tx_stats(padapter, pxmitframe, sz);
344
345
346 RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_write_port, w_sz=%d\n", w_sz));
347 //DBG_8192C("rtw_write_port, w_sz=%d, sz=%d, txdesc_sz=%d, tid=%d\n", w_sz, sz, w_sz-sz, pattrib->priority);
348
349 mem_addr += w_sz;
350
351 mem_addr = (u8 *)RND4(((SIZE_PTR)(mem_addr)));
352
353 }
354
355 rtw_free_xmitframe(pxmitpriv, pxmitframe);
356
357 if (ret != _SUCCESS)
358 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
359
360 return ret;
361 }
362
363 #ifdef CONFIG_USB_TX_AGGREGATION
xmitframe_need_length(struct xmit_frame * pxmitframe)364 static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
365 {
366 struct pkt_attrib *pattrib = &pxmitframe->attrib;
367
368 u32 len = 0;
369
370 // no consider fragement
371 len = pattrib->hdrlen + pattrib->iv_len +
372 SNAP_SIZE + sizeof(u16) +
373 pattrib->pktlen +
374 ((pattrib->bswenc) ? pattrib->icv_len : 0);
375
376 if(pattrib->encrypt ==_TKIP_)
377 len += 8;
378
379 return len;
380 }
381
382 #define IDEA_CONDITION 1 // check all packets before enqueue
rtl8723bu_xmitframe_complete(_adapter * padapter,struct xmit_priv * pxmitpriv,struct xmit_buf * pxmitbuf)383 s32 rtl8723bu_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
384 {
385 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
386 struct xmit_frame *pxmitframe = NULL;
387 struct xmit_frame *pfirstframe = NULL;
388
389 // aggregate variable
390 struct hw_xmit *phwxmit;
391 struct sta_info *psta = NULL;
392 struct tx_servq *ptxservq = NULL;
393
394 _irqL irqL;
395 _list *xmitframe_plist = NULL, *xmitframe_phead = NULL;
396
397 u32 pbuf; // next pkt address
398 u32 pbuf_tail; // last pkt tail
399 u32 len; // packet length, except TXDESC_SIZE and PKT_OFFSET
400
401 u32 bulkSize = pHalData->UsbBulkOutSize;
402 u8 descCount;
403 u32 bulkPtr;
404
405 // dump frame variable
406 u32 ff_hwaddr;
407
408 _list *sta_plist, *sta_phead;
409 u8 single_sta_in_queue = _FALSE;
410
411 #ifndef IDEA_CONDITION
412 int res = _SUCCESS;
413 #endif
414
415 RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n"));
416
417
418 // check xmitbuffer is ok
419 if (pxmitbuf == NULL) {
420 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
421 if (pxmitbuf == NULL) return _FALSE;
422 }
423
424
425 //3 1. pick up first frame
426 do {
427 rtw_free_xmitframe(pxmitpriv, pxmitframe);
428
429 pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
430 if (pxmitframe == NULL) {
431 // no more xmit frame, release xmit buffer
432 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
433 return _FALSE;
434 }
435
436
437 #ifndef IDEA_CONDITION
438 if (pxmitframe->frame_tag != DATA_FRAMETAG) {
439 RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_,
440 ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n",
441 pxmitframe->frame_tag, DATA_FRAMETAG));
442 // rtw_free_xmitframe(pxmitpriv, pxmitframe);
443 continue;
444 }
445
446 // TID 0~15
447 if ((pxmitframe->attrib.priority < 0) ||
448 (pxmitframe->attrib.priority > 15)) {
449 RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_,
450 ("xmitframe_complete: TID(%d) should be 0~15!\n",
451 pxmitframe->attrib.priority));
452 // rtw_free_xmitframe(pxmitpriv, pxmitframe);
453 continue;
454 }
455 #endif
456
457 pxmitframe->pxmitbuf = pxmitbuf;
458 pxmitframe->buf_addr = pxmitbuf->pbuf;
459 pxmitbuf->priv_data = pxmitframe;
460
461 /* pxmitframe->agg_num = 1; */ /* alloc xmitframe should assign to 1. */
462 /* pxmitframe->pkt_offset = 1; */ /* first frame of aggregation, reserve offset */
463 pxmitframe->pkt_offset = (PACKET_OFFSET_SZ/8);
464
465 if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) {
466 DBG_871X("%s coalesce 1st xmitframe failed\n", __func__);
467 continue;
468 }
469
470
471 // always return ndis_packet after rtw_xmitframe_coalesce
472 rtw_os_xmit_complete(padapter, pxmitframe);
473
474 break;
475 } while (1);
476
477 //3 2. aggregate same priority and same DA(AP or STA) frames
478 pfirstframe = pxmitframe;
479 len = xmitframe_need_length(pfirstframe) + TXDESC_OFFSET;
480 pbuf_tail = len;
481 pbuf = _RND8(pbuf_tail);
482
483 // check pkt amount in one bluk
484 descCount = 0;
485 bulkPtr = bulkSize;
486 if (pbuf < bulkPtr)
487 descCount++;
488 else {
489 descCount = 0;
490 bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize; // round to next bulkSize
491 }
492
493 // dequeue same priority packet from station tx queue
494 psta = pfirstframe->attrib.psta;
495 switch (pfirstframe->attrib.priority) {
496 case 1:
497 case 2:
498 ptxservq = &(psta->sta_xmitpriv.bk_q);
499 phwxmit = pxmitpriv->hwxmits + 3;
500 break;
501
502 case 4:
503 case 5:
504 ptxservq = &(psta->sta_xmitpriv.vi_q);
505 phwxmit = pxmitpriv->hwxmits + 1;
506 break;
507
508 case 6:
509 case 7:
510 ptxservq = &(psta->sta_xmitpriv.vo_q);
511 phwxmit = pxmitpriv->hwxmits;
512 break;
513
514 case 0:
515 case 3:
516 default:
517 ptxservq = &(psta->sta_xmitpriv.be_q);
518 phwxmit = pxmitpriv->hwxmits + 2;
519 break;
520 }
521
522 _enter_critical_bh(&pxmitpriv->lock, &irqL);
523
524 sta_phead = get_list_head(phwxmit->sta_queue);
525 sta_plist = get_next(sta_phead);
526 single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist));
527
528 xmitframe_phead = get_list_head(&ptxservq->sta_pending);
529 xmitframe_plist = get_next(xmitframe_phead);
530 while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE)
531 {
532 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
533 xmitframe_plist = get_next(xmitframe_plist);
534
535 if(_FAIL == rtw_hal_busagg_qsel_check(padapter,pfirstframe->attrib.qsel,pxmitframe->attrib.qsel))
536 break;
537
538 len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE; // no offset
539 if (pbuf + len > MAX_XMITBUF_SZ) break;
540
541 rtw_list_delete(&pxmitframe->list);
542 ptxservq->qcnt--;
543 phwxmit->accnt--;
544
545 #ifndef IDEA_CONDITION
546 // suppose only data frames would be in queue
547 if (pxmitframe->frame_tag != DATA_FRAMETAG) {
548 RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_,
549 ("xmitframe_complete: frame tag(%d) is not DATA_FRAMETAG(%d)!\n",
550 pxmitframe->frame_tag, DATA_FRAMETAG));
551 rtw_free_xmitframe(pxmitpriv, pxmitframe);
552 continue;
553 }
554
555 // TID 0~15
556 if ((pxmitframe->attrib.priority < 0) ||
557 (pxmitframe->attrib.priority > 15)) {
558 RT_TRACE(_module_rtl8192c_xmit_c_, _drv_err_,
559 ("xmitframe_complete: TID(%d) should be 0~15!\n",
560 pxmitframe->attrib.priority));
561 rtw_free_xmitframe(pxmitpriv, pxmitframe);
562 continue;
563 }
564 #endif
565
566 // pxmitframe->pxmitbuf = pxmitbuf;
567 pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf;
568
569 pxmitframe->agg_num = 0; // not first frame of aggregation
570 pxmitframe->pkt_offset = 0; // not first frame of aggregation, no need to reserve offset
571
572 if (rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe) == _FALSE) {
573 DBG_871X("%s coalesce failed \n",__FUNCTION__);
574 rtw_free_xmitframe(pxmitpriv, pxmitframe);
575 continue;
576 }
577
578
579 // always return ndis_packet after rtw_xmitframe_coalesce
580 rtw_os_xmit_complete(padapter, pxmitframe);
581
582 // (len - TXDESC_SIZE) == pxmitframe->attrib.last_txcmdsz
583 update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, _TRUE);
584
585 // don't need xmitframe any more
586 rtw_free_xmitframe(pxmitpriv, pxmitframe);
587
588 // handle pointer and stop condition
589 pbuf_tail = pbuf + len;
590 pbuf = _RND8(pbuf_tail);
591
592 pfirstframe->agg_num++;
593 if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)
594 break;
595
596 if (pbuf < bulkPtr) {
597 descCount++;
598 if (descCount == pHalData->UsbTxAggDescNum)
599 break;
600 } else {
601 descCount = 0;
602 bulkPtr = ((pbuf / bulkSize) + 1) * bulkSize;
603 }
604 }
605 if (_rtw_queue_empty(&ptxservq->sta_pending) == _TRUE)
606 rtw_list_delete(&ptxservq->tx_pending);
607 else if (single_sta_in_queue == _FALSE) {
608 /* Re-arrange the order of stations in this ac queue to balance the service for these stations */
609 rtw_list_delete(&ptxservq->tx_pending);
610 rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue));
611 }
612
613 _exit_critical_bh(&pxmitpriv->lock, &irqL);
614
615 if ((pfirstframe->attrib.ether_type != 0x0806) &&
616 (pfirstframe->attrib.ether_type != 0x888e) &&
617 (pfirstframe->attrib.dhcp_pkt != 1))
618 {
619 rtw_issue_addbareq_cmd(padapter, pfirstframe);
620 }
621
622 #ifndef CONFIG_USE_USB_BUFFER_ALLOC_TX
623 //3 3. update first frame txdesc
624 if ((PACKET_OFFSET_SZ != 0)
625 && (pbuf_tail % bulkSize) == 0) {
626 // remove pkt_offset
627 pbuf_tail -= PACKET_OFFSET_SZ;
628 pfirstframe->buf_addr += PACKET_OFFSET_SZ;
629 pfirstframe->pkt_offset = 0;
630 }
631 #endif // CONFIG_USE_USB_BUFFER_ALLOC_TX
632 update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, _TRUE);
633
634 //3 4. write xmit buffer to USB FIFO
635 ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
636
637 // xmit address == ((xmit_frame*)pxmitbuf->priv_data)->buf_addr
638 rtw_write_port(padapter, ff_hwaddr, pbuf_tail, (u8*)pxmitbuf);
639
640
641 //3 5. update statisitc
642 pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
643 if (pfirstframe->pkt_offset == 1) pbuf_tail -= PACKET_OFFSET_SZ;
644
645 rtw_count_tx_stats(padapter, pfirstframe, pbuf_tail);
646
647 rtw_free_xmitframe(pxmitpriv, pfirstframe);
648
649 return _TRUE;
650 }
651
652 #else
653
rtl8723bu_xmitframe_complete(_adapter * padapter,struct xmit_priv * pxmitpriv,struct xmit_buf * pxmitbuf)654 s32 rtl8723bu_xmitframe_complete(_adapter *padapter, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
655 {
656
657 struct hw_xmit *phwxmits;
658 sint hwentry;
659 struct xmit_frame *pxmitframe=NULL;
660 int res=_SUCCESS, xcnt = 0;
661
662 phwxmits = pxmitpriv->hwxmits;
663 hwentry = pxmitpriv->hwxmit_entry;
664
665 RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("xmitframe_complete()\n"));
666
667 if(pxmitbuf==NULL)
668 {
669 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
670 if(!pxmitbuf)
671 {
672 return _FALSE;
673 }
674 }
675
676
677 do
678 {
679 pxmitframe = rtw_dequeue_xframe(pxmitpriv, phwxmits, hwentry);
680
681 if(pxmitframe)
682 {
683 pxmitframe->pxmitbuf = pxmitbuf;
684
685 pxmitframe->buf_addr = pxmitbuf->pbuf;
686
687 pxmitbuf->priv_data = pxmitframe;
688
689 if((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG)
690 {
691 if(pxmitframe->attrib.priority<=15)//TID0~15
692 {
693 res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
694 }
695
696 rtw_os_xmit_complete(padapter, pxmitframe);//always return ndis_packet after rtw_xmitframe_coalesce
697 }
698
699
700 RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("xmitframe_complete(): rtw_dump_xframe\n"));
701
702
703 if(res == _SUCCESS)
704 {
705 rtw_dump_xframe(padapter, pxmitframe);
706 }
707 else
708 {
709 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
710 rtw_free_xmitframe(pxmitpriv, pxmitframe);
711 }
712
713 xcnt++;
714
715 }
716 else
717 {
718 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
719 return _FALSE;
720 }
721
722 break;
723
724 }while(0/*xcnt < (NR_XMITFRAME >> 3)*/);
725
726 return _TRUE;
727
728 }
729 #endif
730
731
732
xmitframe_direct(_adapter * padapter,struct xmit_frame * pxmitframe)733 static s32 xmitframe_direct(_adapter *padapter, struct xmit_frame *pxmitframe)
734 {
735 s32 res = _SUCCESS;
736
737
738 res = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
739 if (res == _SUCCESS) {
740 rtw_dump_xframe(padapter, pxmitframe);
741 }
742
743 return res;
744 }
745
746 /*
747 * Return
748 * _TRUE dump packet directly
749 * _FALSE enqueue packet
750 */
pre_xmitframe(_adapter * padapter,struct xmit_frame * pxmitframe)751 static s32 pre_xmitframe(_adapter *padapter, struct xmit_frame *pxmitframe)
752 {
753 _irqL irqL;
754 s32 res;
755 struct xmit_buf *pxmitbuf = NULL;
756 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
757 struct pkt_attrib *pattrib = &pxmitframe->attrib;
758 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
759 u8 lg_sta_num;
760
761 _enter_critical_bh(&pxmitpriv->lock, &irqL);
762
763 if (rtw_txframes_sta_ac_pending(padapter, pattrib) > 0)
764 goto enqueue;
765
766 if (rtw_xmit_ac_blocked(padapter) == _TRUE)
767 goto enqueue;
768
769 rtw_dev_iface_status(padapter, NULL, NULL , &lg_sta_num, NULL, NULL);
770 if (lg_sta_num)
771 goto enqueue;
772
773 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
774 if (pxmitbuf == NULL)
775 goto enqueue;
776
777 _exit_critical_bh(&pxmitpriv->lock, &irqL);
778
779 pxmitframe->pxmitbuf = pxmitbuf;
780 pxmitframe->buf_addr = pxmitbuf->pbuf;
781 pxmitbuf->priv_data = pxmitframe;
782
783 if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) {
784 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
785 rtw_free_xmitframe(pxmitpriv, pxmitframe);
786 }
787
788 return _TRUE;
789
790 enqueue:
791 res = rtw_xmitframe_enqueue(padapter, pxmitframe);
792 _exit_critical_bh(&pxmitpriv->lock, &irqL);
793
794 if (res != _SUCCESS) {
795 RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n"));
796 rtw_free_xmitframe(pxmitpriv, pxmitframe);
797
798 pxmitpriv->tx_drop++;
799 return _TRUE;
800 }
801
802 return _FALSE;
803 }
804
rtl8723bu_mgnt_xmit(_adapter * padapter,struct xmit_frame * pmgntframe)805 s32 rtl8723bu_mgnt_xmit(_adapter *padapter, struct xmit_frame *pmgntframe)
806 {
807 return rtw_dump_xframe(padapter, pmgntframe);
808 }
809
810 /*
811 * Return
812 * _TRUE dump packet directly ok
813 * _FALSE temporary can't transmit packets to hardware
814 */
rtl8723bu_hal_xmit(_adapter * padapter,struct xmit_frame * pxmitframe)815 s32 rtl8723bu_hal_xmit(_adapter *padapter, struct xmit_frame *pxmitframe)
816 {
817 return pre_xmitframe(padapter, pxmitframe);
818 }
819
rtl8723bu_hal_xmitframe_enqueue(_adapter * padapter,struct xmit_frame * pxmitframe)820 s32 rtl8723bu_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
821 {
822 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
823 s32 err;
824
825 if ((err=rtw_xmitframe_enqueue(padapter, pxmitframe)) != _SUCCESS)
826 {
827 rtw_free_xmitframe(pxmitpriv, pxmitframe);
828
829 pxmitpriv->tx_drop++;
830 }
831 else
832 {
833 #ifdef PLATFORM_LINUX
834 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
835 #endif
836 }
837
838 return err;
839
840 }
841
842
843 #ifdef CONFIG_HOSTAPD_MLME
844
rtl8723bu_hostap_mgnt_xmit_cb(struct urb * urb)845 static void rtl8723bu_hostap_mgnt_xmit_cb(struct urb *urb)
846 {
847 #ifdef PLATFORM_LINUX
848 struct sk_buff *skb = (struct sk_buff *)urb->context;
849
850 //DBG_8192C("%s\n", __FUNCTION__);
851
852 rtw_skb_free(skb);
853 #endif
854 }
855
rtl8723bu_hostap_mgnt_xmit_entry(_adapter * padapter,_pkt * pkt)856 s32 rtl8723bu_hostap_mgnt_xmit_entry(_adapter *padapter, _pkt *pkt)
857 {
858 #ifdef PLATFORM_LINUX
859 u16 fc;
860 int rc, len, pipe;
861 unsigned int bmcst, tid, qsel;
862 struct sk_buff *skb, *pxmit_skb;
863 struct urb *urb;
864 unsigned char *pxmitbuf;
865 struct tx_desc *ptxdesc;
866 struct ieee80211_hdr *tx_hdr;
867 struct hostapd_priv *phostapdpriv = padapter->phostapdpriv;
868 struct net_device *pnetdev = padapter->pnetdev;
869 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
870 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
871
872
873 //DBG_8192C("%s\n", __FUNCTION__);
874
875 skb = pkt;
876
877 len = skb->len;
878 tx_hdr = (struct ieee80211_hdr *)(skb->data);
879 fc = le16_to_cpu(tx_hdr->frame_ctl);
880 bmcst = IS_MCAST(tx_hdr->addr1);
881
882 if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_MGMT)
883 goto _exit;
884
885 pxmit_skb = rtw_skb_alloc(len + TXDESC_SIZE);
886
887 if(!pxmit_skb)
888 goto _exit;
889
890 pxmitbuf = pxmit_skb->data;
891
892 urb = usb_alloc_urb(0, GFP_ATOMIC);
893 if (!urb) {
894 goto _exit;
895 }
896
897 // ----- fill tx desc -----
898 ptxdesc = (struct tx_desc *)pxmitbuf;
899 _rtw_memset(ptxdesc, 0, sizeof(*ptxdesc));
900
901 //offset 0
902 ptxdesc->txdw0 |= cpu_to_le32(len&0x0000ffff);
903 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);//default = 32 bytes for TX Desc
904 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
905
906 if(bmcst)
907 {
908 ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
909 }
910
911 //offset 4
912 ptxdesc->txdw1 |= cpu_to_le32(0x00);//MAC_ID
913
914 ptxdesc->txdw1 |= cpu_to_le32((0x12<<QSEL_SHT)&0x00001f00);
915
916 ptxdesc->txdw1 |= cpu_to_le32((0x06<< 16) & 0x000f0000);//b mode
917
918 //offset 8
919
920 //offset 12
921 ptxdesc->txdw3 |= cpu_to_le32((le16_to_cpu(tx_hdr->seq_ctl)<<16)&0xffff0000);
922
923 //offset 16
924 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));//driver uses rate
925
926 //offset 20
927
928
929 //HW append seq
930 ptxdesc->txdw4 |= cpu_to_le32(BIT(7)); // Hw set sequence number
931 ptxdesc->txdw3 |= cpu_to_le32((8 <<28)); //set bit3 to 1. Suugested by TimChen. 2009.12.29.
932
933
934 rtl8723b_cal_txdesc_chksum(ptxdesc);
935 // ----- end of fill tx desc -----
936
937 //
938 skb_put(pxmit_skb, len + TXDESC_SIZE);
939 pxmitbuf = pxmitbuf + TXDESC_SIZE;
940 _rtw_memcpy(pxmitbuf, skb->data, len);
941
942 //DBG_8192C("mgnt_xmit, len=%x\n", pxmit_skb->len);
943
944
945 // ----- prepare urb for submit -----
946
947 //translate DMA FIFO addr to pipehandle
948 //pipe = ffaddr2pipehdl(pdvobj, MGT_QUEUE_INX);
949 pipe = usb_sndbulkpipe(pdvobj->pusbdev, pHalData->Queue2EPNum[(u8)MGT_QUEUE_INX]&0x0f);
950
951 usb_fill_bulk_urb(urb, pdvobj->pusbdev, pipe,
952 pxmit_skb->data, pxmit_skb->len, rtl8723bu_hostap_mgnt_xmit_cb, pxmit_skb);
953
954 urb->transfer_flags |= URB_ZERO_PACKET;
955 usb_anchor_urb(urb, &phostapdpriv->anchored);
956 rc = usb_submit_urb(urb, GFP_ATOMIC);
957 if (rc < 0) {
958 usb_unanchor_urb(urb);
959 kfree_skb(skb);
960 }
961 usb_free_urb(urb);
962
963
964 _exit:
965
966 rtw_skb_free(skb);
967
968 #endif
969
970 return 0;
971
972 }
973 #endif
974
975