1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#define _RTL8192C_XMIT_C_
16#include <osdep_service.h>
17#include <drv_types.h>
18#include <wifi.h>
19#include <osdep_intf.h>
20#include <usb_ops.h>
21
22#include <rtl8723a_hal.h>
23
24static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz)
25{
26 int blnSetTxDescOffset;
27 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
28
29 if (pdvobj->ishighspeed) {
30 if (((sz + TXDESC_SIZE) % 512) == 0)
31 blnSetTxDescOffset = 1;
32 else
33 blnSetTxDescOffset = 0;
34 } else {
35 if (((sz + TXDESC_SIZE) % 64) == 0)
36 blnSetTxDescOffset = 1;
37 else
38 blnSetTxDescOffset = 0;
39 }
40 return blnSetTxDescOffset;
41}
42
43static void rtl8192cu_cal_txdesc_chksum(struct tx_desc *ptxdesc)
44{
45 __le16 *usPtr = (__le16 *)ptxdesc;
46 u32 count = 16;
47 u32 index;
48 u16 checksum = 0;
49
50
51 ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
52
53 for (index = 0 ; index < count ; index++)
54 checksum = checksum ^ le16_to_cpu(*(usPtr + index));
55
56 ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum);
57}
58
59static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
60{
61 if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
62 switch (pattrib->encrypt) {
63
64 case WLAN_CIPHER_SUITE_WEP40:
65 case WLAN_CIPHER_SUITE_WEP104:
66 ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
67 break;
68 case WLAN_CIPHER_SUITE_TKIP:
69
70 ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
71 break;
72 case WLAN_CIPHER_SUITE_CCMP:
73 ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000);
74 break;
75 case 0:
76 default:
77 break;
78 }
79 }
80}
81
82static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
83{
84
85
86 switch (pattrib->vcs_mode) {
87 case RTS_CTS:
88 *pdw |= cpu_to_le32(BIT(12));
89 break;
90 case CTS_TO_SELF:
91 *pdw |= cpu_to_le32(BIT(11));
92 break;
93 case NONE_VCS:
94 default:
95 break;
96 }
97
98 if (pattrib->vcs_mode) {
99 *pdw |= cpu_to_le32(BIT(13));
100
101
102 if (pattrib->ht_en) {
103 *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(27)) : 0;
104
105 if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
106 *pdw |= cpu_to_le32((0x01<<28)&0x30000000);
107 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
108 *pdw |= cpu_to_le32((0x02<<28)&0x30000000);
109 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
110 *pdw |= 0;
111 else
112 *pdw |= cpu_to_le32((0x03<<28)&0x30000000);
113 }
114 }
115}
116
117static void fill_txdesc_phy(struct pkt_attrib *pattrib, __le32 *pdw)
118{
119 if (pattrib->ht_en) {
120 *pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
121
122 if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
123 *pdw |= cpu_to_le32((0x01<<20)&0x003f0000);
124 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
125 *pdw |= cpu_to_le32((0x02<<20)&0x003f0000);
126 else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
127 *pdw |= 0;
128 else
129 *pdw |= cpu_to_le32((0x03<<20)&0x003f0000);
130 }
131}
132
133static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz)
134{
135 int pull = 0;
136 uint qsel;
137 struct rtw_adapter *padapter = pxmitframe->padapter;
138 struct pkt_attrib *pattrib = &pxmitframe->attrib;
139 struct hal_data_8723a *pHalData = GET_HAL_DATA(padapter);
140 struct dm_priv *pdmpriv = &pHalData->dmpriv;
141 struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
142 struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
143 struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
144 int bmcst = is_multicast_ether_addr(pattrib->ra);
145
146 if (urb_zero_packet_chk(padapter, sz) == 0) {
147 ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
148 pull = 1;
149 pxmitframe->pkt_offset--;
150 }
151
152 memset(ptxdesc, 0, sizeof(struct tx_desc));
153
154 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
155
156 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
157
158 qsel = (uint)(pattrib->qsel & 0x0000001f);
159 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
160
161 ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
162
163 fill_txdesc_sectype(pattrib, ptxdesc);
164
165 if (pattrib->ampdu_en)
166 ptxdesc->txdw1 |= cpu_to_le32(BIT(5));
167 else
168 ptxdesc->txdw1 |= cpu_to_le32(BIT(6));
169
170
171
172
173 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
174
175
176 if (pattrib->qos_en)
177 ptxdesc->txdw4 |= cpu_to_le32(BIT(6));
178
179 if ((pattrib->ether_type != 0x888e) &&
180 (pattrib->ether_type != 0x0806) &&
181 (pattrib->dhcp_pkt != 1)) {
182
183
184 fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
185 fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
186
187 ptxdesc->txdw4 |= cpu_to_le32(0x00000008);
188 ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);
189
190
191 ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]);
192 } else {
193
194
195
196
197 ptxdesc->txdw1 |= cpu_to_le32(BIT(6));
198
199 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));
200
201 if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
202 ptxdesc->txdw4 |= cpu_to_le32(BIT(24));
203
204 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
205 }
206 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
207
208 ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
209
210 qsel = (uint)(pattrib->qsel&0x0000001f);
211 ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00);
212
213 ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
214
215
216
217 if (pxmitframe->ack_report)
218 ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
219
220
221 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
222
223
224 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));
225
226
227 ptxdesc->txdw5 |= cpu_to_le32(BIT(17));
228 ptxdesc->txdw5 |= cpu_to_le32(0x00180000);
229
230 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
231 } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
232 DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
233 } else {
234 DBG_8723A("pxmitframe->frame_tag = %d\n",
235 pxmitframe->frame_tag);
236
237
238 ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);
239
240 ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);
241
242
243
244
245 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
246
247
248 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));
249
250
251 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
252 }
253
254
255
256
257
258
259
260 if (!pattrib->qos_en) {
261
262 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
263
264 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
265 }
266
267
268 ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff);
269 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
270 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);
271
272 if (bmcst)
273 ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
274
275 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
276 "offset0-txdesc = 0x%x\n", ptxdesc->txdw0);
277
278
279
280 if (pxmitframe->pkt_offset > 0)
281 ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
282
283 rtl8192cu_cal_txdesc_chksum(ptxdesc);
284 return pull;
285}
286
287static int rtw_dump_xframe(struct rtw_adapter *padapter,
288 struct xmit_frame *pxmitframe)
289{
290 int ret = _SUCCESS;
291 int inner_ret = _SUCCESS;
292 int t, sz, w_sz, pull = 0;
293 u8 *mem_addr;
294 u32 ff_hwaddr;
295 struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
296 struct pkt_attrib *pattrib = &pxmitframe->attrib;
297 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
298
299 if (pxmitframe->frame_tag == DATA_FRAMETAG &&
300 pxmitframe->attrib.ether_type != ETH_P_ARP &&
301 pxmitframe->attrib.ether_type != ETH_P_PAE &&
302 pxmitframe->attrib.dhcp_pkt != 1)
303 rtw_issue_addbareq_cmd23a(padapter, pxmitframe);
304
305 mem_addr = pxmitframe->buf_addr;
306
307 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "rtw_dump_xframe()\n");
308
309 for (t = 0; t < pattrib->nr_frags; t++) {
310 if (inner_ret != _SUCCESS && ret == _SUCCESS)
311 ret = _FAIL;
312
313 if (t != (pattrib->nr_frags - 1)) {
314 RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
315 "pattrib->nr_frags =%d\n", pattrib->nr_frags);
316
317 sz = pxmitpriv->frag_len;
318 sz = sz - 4 - pattrib->icv_len;
319 } else {
320
321 sz = pattrib->last_txcmdsz;
322 }
323
324 pull = update_txdesc(pxmitframe, mem_addr, sz);
325
326 if (pull) {
327 mem_addr += PACKET_OFFSET_SZ;
328
329 pxmitframe->buf_addr = mem_addr;
330
331 w_sz = sz + TXDESC_SIZE;
332 } else {
333 w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
334 }
335
336 ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe);
337 inner_ret = rtl8723au_write_port(padapter, ff_hwaddr,
338 w_sz, pxmitbuf);
339 rtw_count_tx_stats23a(padapter, pxmitframe, sz);
340
341 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
342 "rtw_write_port, w_sz =%d\n", w_sz);
343
344 mem_addr += w_sz;
345
346 mem_addr = PTR_ALIGN(mem_addr, 4);
347 }
348
349 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
350
351 if (ret != _SUCCESS)
352 rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
353
354 return ret;
355}
356
357bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
358 struct xmit_priv *pxmitpriv,
359 struct xmit_buf *pxmitbuf)
360{
361 struct hw_xmit *phwxmits;
362 struct xmit_frame *pxmitframe;
363 int hwentry;
364 int res = _SUCCESS, xcnt = 0;
365
366 phwxmits = pxmitpriv->hwxmits;
367 hwentry = pxmitpriv->hwxmit_entry;
368
369 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, "xmitframe_complete()\n");
370
371 if (pxmitbuf == NULL) {
372 pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
373 if (!pxmitbuf)
374 return false;
375 }
376 pxmitframe = rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry);
377
378 if (pxmitframe) {
379 pxmitframe->pxmitbuf = pxmitbuf;
380
381 pxmitframe->buf_addr = pxmitbuf->pbuf;
382
383 pxmitbuf->priv_data = pxmitframe;
384
385 if (pxmitframe->frame_tag == DATA_FRAMETAG) {
386 if (pxmitframe->attrib.priority <= 15)
387 res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
388
389 rtw_os_xmit_complete23a(padapter, pxmitframe);
390 }
391
392 RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
393 "xmitframe_complete(): rtw_dump_xframe\n");
394
395 if (res == _SUCCESS) {
396 rtw_dump_xframe(padapter, pxmitframe);
397 } else {
398 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
399 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
400 }
401 xcnt++;
402 } else {
403 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
404 return false;
405 }
406 return true;
407}
408
409static int xmitframe_direct(struct rtw_adapter *padapter,
410 struct xmit_frame *pxmitframe)
411{
412 int res;
413
414 res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
415 if (res == _SUCCESS)
416 rtw_dump_xframe(padapter, pxmitframe);
417 return res;
418}
419
420
421
422
423
424
425bool rtl8723au_hal_xmit(struct rtw_adapter *padapter,
426 struct xmit_frame *pxmitframe)
427{
428 int res;
429 struct xmit_buf *pxmitbuf = NULL;
430 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
431 struct pkt_attrib *pattrib = &pxmitframe->attrib;
432 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
433
434 pattrib->qsel = pattrib->priority;
435 spin_lock_bh(&pxmitpriv->lock);
436
437#ifdef CONFIG_8723AU_AP_MODE
438 if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
439 struct sta_info *psta;
440 struct sta_priv *pstapriv = &padapter->stapriv;
441
442 spin_unlock_bh(&pxmitpriv->lock);
443
444 if (pattrib->psta)
445 psta = pattrib->psta;
446 else
447 psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
448
449 if (psta) {
450 if (psta->sleepq_len > (NR_XMITFRAME>>3))
451 wakeup_sta_to_xmit23a(padapter, psta);
452 }
453
454 return false;
455 }
456#endif
457
458 if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0)
459 goto enqueue;
460
461 if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
462 goto enqueue;
463
464 pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
465 if (pxmitbuf == NULL)
466 goto enqueue;
467
468 spin_unlock_bh(&pxmitpriv->lock);
469
470 pxmitframe->pxmitbuf = pxmitbuf;
471 pxmitframe->buf_addr = pxmitbuf->pbuf;
472 pxmitbuf->priv_data = pxmitframe;
473
474 if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) {
475 rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
476 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
477 }
478 return true;
479
480enqueue:
481 res = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
482 spin_unlock_bh(&pxmitpriv->lock);
483
484 if (res != _SUCCESS) {
485 RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
486 "pre_xmitframe: enqueue xmitframe fail\n");
487 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
488
489
490 pxmitpriv->tx_pkts--;
491 pxmitpriv->tx_drop++;
492 return true;
493 }
494 return false;
495}
496
497int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter,
498 struct xmit_frame *pmgntframe)
499{
500 return rtw_dump_xframe(padapter, pmgntframe);
501}
502
503int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter,
504 struct xmit_frame *pxmitframe)
505{
506 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
507 int err;
508
509 err = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
510 if (err != _SUCCESS) {
511 rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
512
513
514 pxmitpriv->tx_pkts--;
515 pxmitpriv->tx_drop++;
516 } else {
517 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
518 }
519 return err;
520}
521