1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#define _RTL8188E_XMIT_C_
21#include <osdep_service.h>
22#include <drv_types.h>
23#include <wifi.h>
24#include <osdep_intf.h>
25#include <usb_ops.h>
26#include <rtl8188e_hal.h>
27
28s32 rtl8188eu_init_xmit_priv(struct adapter *adapt)
29{
30 struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
31
32 tasklet_init(&pxmitpriv->xmit_tasklet,
33 (void(*)(unsigned long))rtl8188eu_xmit_tasklet,
34 (unsigned long)adapt);
35 return _SUCCESS;
36}
37
38void rtl8188eu_free_xmit_priv(struct adapter *adapt)
39{
40}
41
42static u8 urb_zero_packet_chk(struct adapter *adapt, int sz)
43{
44 u8 set_tx_desc_offset;
45 struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
46 set_tx_desc_offset = (((sz + TXDESC_SIZE) % haldata->UsbBulkOutSize) == 0) ? 1 : 0;
47
48 return set_tx_desc_offset;
49}
50
51static void rtl8188eu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
52{
53 u16 *usptr = (u16 *)ptxdesc;
54 u32 count = 16;
55 u32 index;
56 u16 checksum = 0;
57
58
59 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
60
61 for (index = 0; index < count; index++)
62 checksum = checksum ^ le16_to_cpu(*(__le16 *)(usptr + index));
63 ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff & checksum);
64}
65
66
67
68
69void rtl8188e_fill_fake_txdesc(struct adapter *adapt, u8 *desc, u32 BufferLen, u8 ispspoll, u8 is_btqosnull)
70{
71 struct tx_desc *ptxdesc;
72
73
74 ptxdesc = (struct tx_desc *)desc;
75 _rtw_memset(desc, 0, TXDESC_SIZE);
76
77
78 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
79
80 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);
81
82 ptxdesc->txdw0 |= cpu_to_le32(BufferLen&0x0000ffff);
83
84
85 ptxdesc->txdw1 |= cpu_to_le32((QSLT_MGNT<<QSEL_SHT)&0x00001f00);
86
87
88 if (ispspoll) {
89 ptxdesc->txdw1 |= cpu_to_le32(NAVUSEHDR);
90 } else {
91 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
92 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
93 }
94
95 if (is_btqosnull)
96 ptxdesc->txdw2 |= cpu_to_le32(BIT(23));
97
98
99 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));
100
101
102
103 rtl8188eu_cal_txdesc_chksum(ptxdesc);
104}
105
106static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
107{
108 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
109 switch (pattrib->encrypt) {
110
111 case _WEP40_:
112 case _WEP104_:
113 ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
114 ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
115 break;
116 case _TKIP_:
117 case _TKIP_WTMIC_:
118 ptxdesc->txdw1 |= cpu_to_le32((0x01<<SEC_TYPE_SHT)&0x00c00000);
119 ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
120 break;
121 case _AES_:
122 ptxdesc->txdw1 |= cpu_to_le32((0x03<<SEC_TYPE_SHT)&0x00c00000);
123 ptxdesc->txdw2 |= cpu_to_le32(0x7 << AMPDU_DENSITY_SHT);
124 break;
125 case _NO_PRIVACY_:
126 default:
127 break;
128 }
129 }
130}
131
132static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
133{
134 switch (pattrib->vcs_mode) {
135 case RTS_CTS:
136 *pdw |= cpu_to_le32(RTS_EN);
137 break;
138 case CTS_TO_SELF:
139 *pdw |= cpu_to_le32(CTS_2_SELF);
140 break;
141 case NONE_VCS:
142 default:
143 break;
144 }
145 if (pattrib->vcs_mode) {
146 *pdw |= cpu_to_le32(HW_RTS_EN);
147
148 if (pattrib->ht_en) {
149 *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
150
151 if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
152 *pdw |= cpu_to_le32((0x01 << 28) & 0x30000000);
153 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
154 *pdw |= cpu_to_le32((0x02 << 28) & 0x30000000);
155 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
156 *pdw |= 0;
157 else
158 *pdw |= cpu_to_le32((0x03 << 28) & 0x30000000);
159 }
160 }
161}
162
163static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
164{
165 if (pattrib->ht_en) {
166 *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
167
168 if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
169 *pdw |= cpu_to_le32((0x01 << DATA_SC_SHT) & 0x003f0000);
170 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
171 *pdw |= cpu_to_le32((0x02 << DATA_SC_SHT) & 0x003f0000);
172 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
173 *pdw |= 0;
174 else
175 *pdw |= cpu_to_le32((0x03 << DATA_SC_SHT) & 0x003f0000);
176 }
177}
178
179static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
180{
181 int pull = 0;
182 uint qsel;
183 u8 data_rate, pwr_status, offset;
184 struct adapter *adapt = pxmitframe->padapter;
185 struct pkt_attrib *pattrib = &pxmitframe->attrib;
186 struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
187 struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
188 struct mlme_ext_priv *pmlmeext = &adapt->mlmeextpriv;
189 struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
190 int bmcst = IS_MCAST(pattrib->ra);
191
192 if (adapt->registrypriv.mp_mode == 0) {
193 if ((!bagg_pkt) && (urb_zero_packet_chk(adapt, sz) == 0)) {
194 ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
195 pull = 1;
196 }
197 }
198
199 _rtw_memset(ptxdesc, 0, sizeof(struct tx_desc));
200
201
202 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
203 ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);
204
205 offset = TXDESC_SIZE + OFFSET_SZ;
206
207 ptxdesc->txdw0 |= cpu_to_le32(((offset) << OFFSET_SHT) & 0x00ff0000);
208
209 if (bmcst)
210 ptxdesc->txdw0 |= cpu_to_le32(BMC);
211
212 if (adapt->registrypriv.mp_mode == 0) {
213 if (!bagg_pkt) {
214 if ((pull) && (pxmitframe->pkt_offset > 0))
215 pxmitframe->pkt_offset = pxmitframe->pkt_offset - 1;
216 }
217 }
218
219
220 if (pxmitframe->pkt_offset > 0)
221 ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
222
223
224 ptxdesc->txdw4 |= cpu_to_le32(USERATE);
225
226 if ((pxmitframe->frame_tag & 0x0f) == DATA_FRAMETAG) {
227
228 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3F);
229
230 qsel = (uint)(pattrib->qsel & 0x0000001f);
231 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
232
233 ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000);
234
235 fill_txdesc_sectype(pattrib, ptxdesc);
236
237 if (pattrib->ampdu_en) {
238 ptxdesc->txdw2 |= cpu_to_le32(AGG_EN);
239 ptxdesc->txdw6 = cpu_to_le32(0x6666f800);
240 } else {
241 ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);
242 }
243
244
245
246
247 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 0x0FFF0000);
248
249
250 if (pattrib->qos_en)
251 ptxdesc->txdw4 |= cpu_to_le32(QOS);
252
253
254 if (pxmitframe->agg_num > 1)
255 ptxdesc->txdw5 |= cpu_to_le32((pxmitframe->agg_num << USB_TXAGG_NUM_SHT) & 0xFF000000);
256
257 if ((pattrib->ether_type != 0x888e) &&
258 (pattrib->ether_type != 0x0806) &&
259 (pattrib->ether_type != 0x88b4) &&
260 (pattrib->dhcp_pkt != 1)) {
261
262
263 fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
264 fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
265
266 ptxdesc->txdw4 |= cpu_to_le32(0x00000008);
267 ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);
268
269 if (pattrib->ht_en) {
270 if (ODM_RA_GetShortGI_8188E(&haldata->odmpriv, pattrib->mac_id))
271 ptxdesc->txdw5 |= cpu_to_le32(SGI);
272 }
273 data_rate = ODM_RA_GetDecisionRate_8188E(&haldata->odmpriv, pattrib->mac_id);
274 ptxdesc->txdw5 |= cpu_to_le32(data_rate & 0x3F);
275 pwr_status = ODM_RA_GetHwPwrStatus_8188E(&haldata->odmpriv, pattrib->mac_id);
276 ptxdesc->txdw4 |= cpu_to_le32((pwr_status & 0x7) << PWR_STATUS_SHT);
277 } else {
278
279
280
281 ptxdesc->txdw2 |= cpu_to_le32(AGG_BK);
282 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
283 ptxdesc->txdw4 |= cpu_to_le32(BIT(24));
284 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
285 }
286 } else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
287
288 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id & 0x3f);
289
290 qsel = (uint)(pattrib->qsel&0x0000001f);
291 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
292
293 ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000f0000);
294
295
296
297 if (pxmitframe->ack_report)
298 ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
299
300
301 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0FFF0000);
302
303
304 ptxdesc->txdw5 |= cpu_to_le32(RTY_LMT_EN);
305 if (pattrib->retry_ctrl)
306 ptxdesc->txdw5 |= cpu_to_le32(0x00180000);
307 else
308 ptxdesc->txdw5 |= cpu_to_le32(0x00300000);
309
310 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
311 } else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
312 DBG_88E("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
313 } else if (((pxmitframe->frame_tag&0x0f) == MP_FRAMETAG) &&
314 (adapt->registrypriv.mp_mode == 1)) {
315 fill_txdesc_for_mp(adapt, ptxdesc);
316 } else {
317 DBG_88E("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
318
319
320 ptxdesc->txdw1 |= cpu_to_le32((4) & 0x3f);
321
322 ptxdesc->txdw1 |= cpu_to_le32((6 << RATE_ID_SHT) & 0x000f0000);
323
324
325
326
327 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<SEQ_SHT)&0x0fff0000);
328
329
330 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate(pmlmeext->tx_rate));
331 }
332
333
334
335
336
337
338
339
340
341 if (!pattrib->qos_en) {
342 ptxdesc->txdw3 |= cpu_to_le32(EN_HWSEQ);
343 ptxdesc->txdw4 |= cpu_to_le32(HW_SSN);
344 }
345
346 ODM_SetTxAntByTxInfo_88E(&haldata->odmpriv, pmem, pattrib->mac_id);
347
348 rtl8188eu_cal_txdesc_chksum(ptxdesc);
349 _dbg_dump_tx_info(adapt, pxmitframe->frame_tag, ptxdesc);
350 return pull;
351}
352
353
354static s32 rtw_dump_xframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
355{
356 s32 ret = _SUCCESS;
357 s32 inner_ret = _SUCCESS;
358 int t, sz, w_sz, pull = 0;
359 u8 *mem_addr;
360 u32 ff_hwaddr;
361 struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
362 struct pkt_attrib *pattrib = &pxmitframe->attrib;
363 struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
364 struct security_priv *psecuritypriv = &adapt->securitypriv;
365 if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
366 (pxmitframe->attrib.ether_type != 0x0806) &&
367 (pxmitframe->attrib.ether_type != 0x888e) &&
368 (pxmitframe->attrib.ether_type != 0x88b4) &&
369 (pxmitframe->attrib.dhcp_pkt != 1))
370 rtw_issue_addbareq_cmd(adapt, pxmitframe);
371 mem_addr = pxmitframe->buf_addr;
372
373 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
374
375 for (t = 0; t < pattrib->nr_frags; t++) {
376 if (inner_ret != _SUCCESS && ret == _SUCCESS)
377 ret = _FAIL;
378
379 if (t != (pattrib->nr_frags - 1)) {
380 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("pattrib->nr_frags=%d\n", pattrib->nr_frags));
381
382 sz = pxmitpriv->frag_len;
383 sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : pattrib->icv_len);
384 } else {
385
386 sz = pattrib->last_txcmdsz;
387 }
388
389 pull = update_txdesc(pxmitframe, mem_addr, sz, false);
390
391 if (pull) {
392 mem_addr += PACKET_OFFSET_SZ;
393 pxmitframe->buf_addr = mem_addr;
394 w_sz = sz + TXDESC_SIZE;
395 } else {
396 w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
397 }
398 ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
399
400 inner_ret = rtw_write_port(adapt, ff_hwaddr, w_sz, (unsigned char *)pxmitbuf);
401
402 rtw_count_tx_stats(adapt, pxmitframe, sz);
403
404 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_write_port, w_sz=%d\n", w_sz));
405
406 mem_addr += w_sz;
407
408 mem_addr = (u8 *)RND4(((size_t)(mem_addr)));
409 }
410
411 rtw_free_xmitframe(pxmitpriv, pxmitframe);
412
413 if (ret != _SUCCESS)
414 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
415
416 return ret;
417}
418
419static u32 xmitframe_need_length(struct xmit_frame *pxmitframe)
420{
421 struct pkt_attrib *pattrib = &pxmitframe->attrib;
422
423 u32 len = 0;
424
425
426 len = pattrib->hdrlen + pattrib->iv_len +
427 SNAP_SIZE + sizeof(u16) +
428 pattrib->pktlen +
429 ((pattrib->bswenc) ? pattrib->icv_len : 0);
430
431 if (pattrib->encrypt == _TKIP_)
432 len += 8;
433
434 return len;
435}
436
437s32 rtl8188eu_xmitframe_complete(struct adapter *adapt, struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
438{
439 struct hal_data_8188e *haldata = GET_HAL_DATA(adapt);
440 struct xmit_frame *pxmitframe = NULL;
441 struct xmit_frame *pfirstframe = NULL;
442
443
444 struct hw_xmit *phwxmit;
445 struct sta_info *psta = NULL;
446 struct tx_servq *ptxservq = NULL;
447
448 struct list_head *xmitframe_plist = NULL, *xmitframe_phead = NULL;
449
450 u32 pbuf;
451 u32 pbuf_tail;
452 u32 len;
453
454 u32 bulksize = haldata->UsbBulkOutSize;
455 u8 desc_cnt;
456 u32 bulkptr;
457
458
459 u32 ff_hwaddr;
460
461 RT_TRACE(_module_rtl8192c_xmit_c_, _drv_info_, ("+xmitframe_complete\n"));
462
463
464 if (pxmitbuf == NULL) {
465 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
466 if (pxmitbuf == NULL)
467 return false;
468 }
469
470
471 do {
472 rtw_free_xmitframe(pxmitpriv, pxmitframe);
473
474 pxmitframe = rtw_dequeue_xframe(pxmitpriv, pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
475 if (pxmitframe == NULL) {
476
477 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
478 return false;
479 }
480
481 pxmitframe->pxmitbuf = pxmitbuf;
482 pxmitframe->buf_addr = pxmitbuf->pbuf;
483 pxmitbuf->priv_data = pxmitframe;
484
485 pxmitframe->agg_num = 1;
486 pxmitframe->pkt_offset = 1;
487
488 rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
489
490
491 rtw_os_xmit_complete(adapt, pxmitframe);
492
493 break;
494 } while (1);
495
496
497 pfirstframe = pxmitframe;
498 len = xmitframe_need_length(pfirstframe) + TXDESC_SIZE + (pfirstframe->pkt_offset*PACKET_OFFSET_SZ);
499 pbuf_tail = len;
500 pbuf = _RND8(pbuf_tail);
501
502
503 desc_cnt = 0;
504 bulkptr = bulksize;
505 if (pbuf < bulkptr) {
506 desc_cnt++;
507 } else {
508 desc_cnt = 0;
509 bulkptr = ((pbuf / bulksize) + 1) * bulksize;
510 }
511
512
513 psta = pfirstframe->attrib.psta;
514 switch (pfirstframe->attrib.priority) {
515 case 1:
516 case 2:
517 ptxservq = &(psta->sta_xmitpriv.bk_q);
518 phwxmit = pxmitpriv->hwxmits + 3;
519 break;
520 case 4:
521 case 5:
522 ptxservq = &(psta->sta_xmitpriv.vi_q);
523 phwxmit = pxmitpriv->hwxmits + 1;
524 break;
525 case 6:
526 case 7:
527 ptxservq = &(psta->sta_xmitpriv.vo_q);
528 phwxmit = pxmitpriv->hwxmits;
529 break;
530 case 0:
531 case 3:
532 default:
533 ptxservq = &(psta->sta_xmitpriv.be_q);
534 phwxmit = pxmitpriv->hwxmits + 2;
535 break;
536 }
537 spin_lock_bh(&pxmitpriv->lock);
538
539 xmitframe_phead = get_list_head(&ptxservq->sta_pending);
540 xmitframe_plist = get_next(xmitframe_phead);
541
542 while (!rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
543 pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
544 xmitframe_plist = get_next(xmitframe_plist);
545
546 pxmitframe->agg_num = 0;
547 pxmitframe->pkt_offset = 0;
548
549 len = xmitframe_need_length(pxmitframe) + TXDESC_SIZE + (pxmitframe->pkt_offset*PACKET_OFFSET_SZ);
550
551 if (_RND8(pbuf + len) > MAX_XMITBUF_SZ) {
552 pxmitframe->agg_num = 1;
553 pxmitframe->pkt_offset = 1;
554 break;
555 }
556 rtw_list_delete(&pxmitframe->list);
557 ptxservq->qcnt--;
558 phwxmit->accnt--;
559
560 pxmitframe->buf_addr = pxmitbuf->pbuf + pbuf;
561
562 rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
563
564 rtw_os_xmit_complete(adapt, pxmitframe);
565
566
567 update_txdesc(pxmitframe, pxmitframe->buf_addr, pxmitframe->attrib.last_txcmdsz, true);
568
569
570 rtw_free_xmitframe(pxmitpriv, pxmitframe);
571
572
573 pbuf_tail = pbuf + len;
574 pbuf = _RND8(pbuf_tail);
575
576 pfirstframe->agg_num++;
577 if (MAX_TX_AGG_PACKET_NUMBER == pfirstframe->agg_num)
578 break;
579
580 if (pbuf < bulkptr) {
581 desc_cnt++;
582 if (desc_cnt == haldata->UsbTxAggDescNum)
583 break;
584 } else {
585 desc_cnt = 0;
586 bulkptr = ((pbuf / bulksize) + 1) * bulksize;
587 }
588 }
589
590 if (_rtw_queue_empty(&ptxservq->sta_pending) == true)
591 rtw_list_delete(&ptxservq->tx_pending);
592
593 spin_unlock_bh(&pxmitpriv->lock);
594 if ((pfirstframe->attrib.ether_type != 0x0806) &&
595 (pfirstframe->attrib.ether_type != 0x888e) &&
596 (pfirstframe->attrib.ether_type != 0x88b4) &&
597 (pfirstframe->attrib.dhcp_pkt != 1))
598 rtw_issue_addbareq_cmd(adapt, pfirstframe);
599
600 if ((pbuf_tail % bulksize) == 0) {
601
602 pbuf_tail -= PACKET_OFFSET_SZ;
603 pfirstframe->buf_addr += PACKET_OFFSET_SZ;
604 pfirstframe->pkt_offset--;
605 }
606
607 update_txdesc(pfirstframe, pfirstframe->buf_addr, pfirstframe->attrib.last_txcmdsz, true);
608
609
610 ff_hwaddr = rtw_get_ff_hwaddr(pfirstframe);
611 rtw_write_port(adapt, ff_hwaddr, pbuf_tail, (u8 *)pxmitbuf);
612
613
614 pbuf_tail -= (pfirstframe->agg_num * TXDESC_SIZE);
615 pbuf_tail -= (pfirstframe->pkt_offset * PACKET_OFFSET_SZ);
616
617 rtw_count_tx_stats(adapt, pfirstframe, pbuf_tail);
618
619 rtw_free_xmitframe(pxmitpriv, pfirstframe);
620
621 return true;
622}
623
624static s32 xmitframe_direct(struct adapter *adapt, struct xmit_frame *pxmitframe)
625{
626 s32 res = _SUCCESS;
627
628 res = rtw_xmitframe_coalesce(adapt, pxmitframe->pkt, pxmitframe);
629 if (res == _SUCCESS)
630 rtw_dump_xframe(adapt, pxmitframe);
631 else
632 DBG_88E("==> %s xmitframe_coalsece failed\n", __func__);
633 return res;
634}
635
636
637
638
639
640
641static s32 pre_xmitframe(struct adapter *adapt, struct xmit_frame *pxmitframe)
642{
643 s32 res;
644 struct xmit_buf *pxmitbuf = NULL;
645 struct xmit_priv *pxmitpriv = &adapt->xmitpriv;
646 struct pkt_attrib *pattrib = &pxmitframe->attrib;
647 struct mlme_priv *pmlmepriv = &adapt->mlmepriv;
648
649 spin_lock_bh(&pxmitpriv->lock);
650
651 if (rtw_txframes_sta_ac_pending(adapt, pattrib) > 0)
652 goto enqueue;
653
654 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
655 goto enqueue;
656
657 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
658 if (pxmitbuf == NULL)
659 goto enqueue;
660
661 spin_unlock_bh(&pxmitpriv->lock);
662
663 pxmitframe->pxmitbuf = pxmitbuf;
664 pxmitframe->buf_addr = pxmitbuf->pbuf;
665 pxmitbuf->priv_data = pxmitframe;
666
667 if (xmitframe_direct(adapt, pxmitframe) != _SUCCESS) {
668 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
669 rtw_free_xmitframe(pxmitpriv, pxmitframe);
670 }
671
672 return true;
673
674enqueue:
675 res = rtw_xmitframe_enqueue(adapt, pxmitframe);
676 spin_unlock_bh(&pxmitpriv->lock);
677
678 if (res != _SUCCESS) {
679 RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("pre_xmitframe: enqueue xmitframe fail\n"));
680 rtw_free_xmitframe(pxmitpriv, pxmitframe);
681
682
683 pxmitpriv->tx_pkts--;
684 pxmitpriv->tx_drop++;
685 return true;
686 }
687
688 return false;
689}
690
691s32 rtl8188eu_mgnt_xmit(struct adapter *adapt, struct xmit_frame *pmgntframe)
692{
693 return rtw_dump_xframe(adapt, pmgntframe);
694}
695
696
697
698
699
700
701s32 rtl8188eu_hal_xmit(struct adapter *adapt, struct xmit_frame *pxmitframe)
702{
703 return pre_xmitframe(adapt, pxmitframe);
704}
705