Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8723au / hal / rtl8723au_xmit.c
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 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 _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 /* include <rtl8192c_hal.h> */
22 #include <rtl8723a_hal.h>
23
24 static 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
43 static void rtl8192cu_cal_txdesc_chksum(struct tx_desc  *ptxdesc)
44 {
45                 __le16  *usPtr = (__le16 *)ptxdesc;
46                 u32 count = 16;         /*  (32 bytes / 2 bytes per XOR) => 16 times */
47                 u32 index;
48                 u16 checksum = 0;
49
50                 /* Clear first */
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
59 static 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                 /* SEC_TYPE */
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                         /* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */
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
82 static void fill_txdesc_vcs(struct pkt_attrib *pattrib, __le32 *pdw)
83 {
84         /* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
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                 /*  Set RTS BW */
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
117 static 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
133 static 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                 /* offset 4 */
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));/* AGG EN */
167                 else
168                         ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
169
170                 /* offset 8 */
171
172                 /* offset 12 */
173                 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
174
175                 /* offset 16 , offset 20 */
176                 if (pattrib->qos_en)
177                         ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */
178
179                 if ((pattrib->ether_type != 0x888e) &&
180                     (pattrib->ether_type != 0x0806) &&
181                     (pattrib->dhcp_pkt != 1)) {
182                         /* Non EAP & ARP & DHCP type data packet */
183
184                         fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
185                         fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
186
187                         ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */
188                         ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/*  */
189
190                         /* use REG_INIDATA_RATE_SEL value */
191                         ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]);
192                 } else {
193                         /*  EAP data packet and ARP packet. */
194                         /*  Use the 1M data rate to send the EAP/ARP packet. */
195                         /*  This will maybe make the handshake smooth. */
196
197                         ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
198
199                         ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
200
201                         if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
202                                 ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/*  DATA_SHORT */
203
204                         ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
205                 }
206         } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
207                 /* offset 4 */
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                 /* offset 8 */
216                 /* CCX-TXRPT ack for xmit mgmt frames. */
217                 if (pxmitframe->ack_report)
218                         ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
219
220                 /* offset 12 */
221                 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
222
223                 /* offset 16 */
224                 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
225
226                 /* offset 20 */
227                 ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */
228                 ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
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                 /* offset 4 */
238                 ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */
239
240                 ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */
241
242                 /* offset 8 */
243
244                 /* offset 12 */
245                 ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
246
247                 /* offset 16 */
248                 ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
249
250                 /* offset 20 */
251                 ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
252         }
253
254         /*  (1) The sequence number of each non-Qos frame / broadcast / multicast / */
255         /*  mgnt frame should be controled by Hw because Fw will also send null data */
256         /*  which we cannot control when Fw LPS enable. */
257         /*  --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
258         /*  (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
259         /*  (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
260         if (!pattrib->qos_en) {
261                 /*  Hw set sequence number */
262                 ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
263                 /* set bit3 to 1. */
264                 ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
265         }
266
267         /* offset 0 */
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);/* 32 bytes for TX Desc */
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         /* offset 4 */
279         /*  pkt_offset, unit:8 bytes padding */
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
287 static 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                         /* no frag */
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; /* pull txdesc head */
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
357 bool 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)/* TID0~15 */
387                                 res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
388
389                         rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */
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
409 static 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  * Return
422  *      true    dump packet directly
423  *      false   enqueue packet
424  */
425 bool 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
480 enqueue:
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                 /*  Trick, make the statistics correct */
490                 pxmitpriv->tx_pkts--;
491                 pxmitpriv->tx_drop++;
492                 return true;
493         }
494         return false;
495 }
496
497 int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter,
498                         struct xmit_frame *pmgntframe)
499 {
500         return rtw_dump_xframe(padapter, pmgntframe);
501 }
502
503 int 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                 /*  Trick, make the statistics correct */
514                 pxmitpriv->tx_pkts--;
515                 pxmitpriv->tx_drop++;
516         } else {
517                 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
518         }
519         return err;
520 }