Merge tag 'hyperv-next-signed-20210831' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.git] / drivers / staging / rtl8712 / rtl8712_recv.c
1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  * rtl8712_recv.c
4  *
5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
6  * Linux device driver for RTL8192SU
7  *
8  * Modifications for inclusion into the Linux staging tree are
9  * Copyright(c) 2010 Larry Finger. All rights reserved.
10  *
11  * Contact information:
12  * WLAN FAE <wlanfae@realtek.com>
13  * Larry Finger <Larry.Finger@lwfinger.net>
14  *
15  ******************************************************************************/
16
17 #define _RTL8712_RECV_C_
18
19 #include <linux/if_ether.h>
20 #include <linux/ip.h>
21 #include <net/cfg80211.h>
22
23 #include "osdep_service.h"
24 #include "drv_types.h"
25 #include "recv_osdep.h"
26 #include "mlme_osdep.h"
27 #include "ethernet.h"
28 #include "usb_ops.h"
29 #include "wifi.h"
30
31 static void recv_tasklet(struct tasklet_struct *t);
32
33 void r8712_init_recv_priv(struct recv_priv *precvpriv,
34                           struct _adapter *padapter)
35 {
36         int i;
37         struct recv_buf *precvbuf;
38         addr_t tmpaddr = 0;
39         int alignment = 0;
40         struct sk_buff *pskb = NULL;
41
42         /*init recv_buf*/
43         _init_queue(&precvpriv->free_recv_buf_queue);
44         precvpriv->pallocated_recv_buf =
45                 kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC);
46         if (!precvpriv->pallocated_recv_buf)
47                 return;
48         precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
49                               ((addr_t)(precvpriv->pallocated_recv_buf) & 3);
50         precvbuf = (struct recv_buf *)precvpriv->precv_buf;
51         for (i = 0; i < NR_RECVBUFF; i++) {
52                 INIT_LIST_HEAD(&precvbuf->list);
53                 spin_lock_init(&precvbuf->recvbuf_lock);
54                 if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf))
55                         break;
56                 precvbuf->ref_cnt = 0;
57                 precvbuf->adapter = padapter;
58                 list_add_tail(&precvbuf->list,
59                               &(precvpriv->free_recv_buf_queue.queue));
60                 precvbuf++;
61         }
62         precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
63         tasklet_setup(&precvpriv->recv_tasklet, recv_tasklet);
64         skb_queue_head_init(&precvpriv->rx_skb_queue);
65
66         skb_queue_head_init(&precvpriv->free_recv_skb_queue);
67         for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
68                 pskb = netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ +
69                        RECVBUFF_ALIGN_SZ);
70                 if (pskb) {
71                         tmpaddr = (addr_t)pskb->data;
72                         alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
73                         skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
74                         skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
75                 }
76                 pskb = NULL;
77         }
78 }
79
80 void r8712_free_recv_priv(struct recv_priv *precvpriv)
81 {
82         int i;
83         struct recv_buf *precvbuf;
84         struct _adapter *padapter = precvpriv->adapter;
85
86         precvbuf = (struct recv_buf *)precvpriv->precv_buf;
87         for (i = 0; i < NR_RECVBUFF; i++) {
88                 r8712_os_recvbuf_resource_free(padapter, precvbuf);
89                 precvbuf++;
90         }
91         kfree(precvpriv->pallocated_recv_buf);
92         skb_queue_purge(&precvpriv->rx_skb_queue);
93         if (skb_queue_len(&precvpriv->rx_skb_queue))
94                 netdev_warn(padapter->pnetdev, "r8712u: rx_skb_queue not empty\n");
95         skb_queue_purge(&precvpriv->free_recv_skb_queue);
96         if (skb_queue_len(&precvpriv->free_recv_skb_queue))
97                 netdev_warn(padapter->pnetdev, "r8712u: free_recv_skb_queue not empty %d\n",
98                             skb_queue_len(&precvpriv->free_recv_skb_queue));
99 }
100
101 void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf)
102 {
103         precvbuf->transfer_len = 0;
104         precvbuf->len = 0;
105         precvbuf->ref_cnt = 0;
106         if (precvbuf->pbuf) {
107                 precvbuf->pdata = precvbuf->pbuf;
108                 precvbuf->phead = precvbuf->pbuf;
109                 precvbuf->ptail = precvbuf->pbuf;
110                 precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
111         }
112 }
113
114 void r8712_free_recvframe(union recv_frame *precvframe,
115                           struct  __queue *pfree_recv_queue)
116 {
117         unsigned long irqL;
118         struct _adapter *padapter = precvframe->u.hdr.adapter;
119         struct recv_priv *precvpriv = &padapter->recvpriv;
120
121         if (precvframe->u.hdr.pkt) {
122                 dev_kfree_skb_any(precvframe->u.hdr.pkt);/*free skb by driver*/
123                 precvframe->u.hdr.pkt = NULL;
124         }
125         spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
126         list_del_init(&(precvframe->u.hdr.list));
127         list_add_tail(&(precvframe->u.hdr.list), &pfree_recv_queue->queue);
128         if (padapter) {
129                 if (pfree_recv_queue == &precvpriv->free_recv_queue)
130                         precvpriv->free_recvframe_cnt++;
131         }
132         spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
133 }
134
135 static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
136                                                   struct recv_stat *prxstat)
137 {
138         u16 drvinfo_sz;
139
140         drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
141         drvinfo_sz <<= 3;
142         /*TODO:
143          * Offset 0
144          */
145         pattrib->bdecrypted = (le32_to_cpu(prxstat->rxdw0) & BIT(27)) == 0;
146         pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) != 0;
147         /*Offset 4*/
148         /*Offset 8*/
149         /*Offset 12*/
150         if (le32_to_cpu(prxstat->rxdw3) & BIT(13)) {
151                 pattrib->tcpchk_valid = 1; /* valid */
152                 if (le32_to_cpu(prxstat->rxdw3) & BIT(11))
153                         pattrib->tcp_chkrpt = 1; /* correct */
154                 else
155                         pattrib->tcp_chkrpt = 0; /* incorrect */
156                 if (le32_to_cpu(prxstat->rxdw3) & BIT(12))
157                         pattrib->ip_chkrpt = 1; /* correct */
158                 else
159                         pattrib->ip_chkrpt = 0; /* incorrect */
160         } else {
161                 pattrib->tcpchk_valid = 0; /* invalid */
162         }
163         pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f);
164         pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 14) & 0x1);
165         /*Offset 16*/
166         /*Offset 20*/
167         /*phy_info*/
168 }
169
170 /*perform defrag*/
171 static union recv_frame *recvframe_defrag(struct _adapter *adapter,
172                                           struct  __queue *defrag_q)
173 {
174         struct list_head *plist, *phead;
175         u8 wlanhdr_offset;
176         u8      curfragnum;
177         struct recv_frame_hdr *pfhdr, *pnfhdr;
178         union recv_frame *prframe, *pnextrframe;
179         struct  __queue *pfree_recv_queue;
180
181         pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
182         phead = &defrag_q->queue;
183         plist = phead->next;
184         prframe = container_of(plist, union recv_frame, u.list);
185         list_del_init(&prframe->u.list);
186         pfhdr = &prframe->u.hdr;
187         curfragnum = 0;
188         if (curfragnum != pfhdr->attrib.frag_num) {
189                 /*the first fragment number must be 0
190                  *free the whole queue
191                  */
192                 r8712_free_recvframe(prframe, pfree_recv_queue);
193                 r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
194                 return NULL;
195         }
196         curfragnum++;
197         plist = &defrag_q->queue;
198         plist = plist->next;
199         while (!end_of_queue_search(phead, plist)) {
200                 pnextrframe = container_of(plist, union recv_frame, u.list);
201                 pnfhdr = &pnextrframe->u.hdr;
202                 /*check the fragment sequence  (2nd ~n fragment frame) */
203                 if (curfragnum != pnfhdr->attrib.frag_num) {
204                         /* the fragment number must increase  (after decache)
205                          * release the defrag_q & prframe
206                          */
207                         r8712_free_recvframe(prframe, pfree_recv_queue);
208                         r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
209                         return NULL;
210                 }
211                 curfragnum++;
212                 /* copy the 2nd~n fragment frame's payload to the first fragment
213                  * get the 2nd~last fragment frame's payload
214                  */
215                 wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
216                 recvframe_pull(pnextrframe, wlanhdr_offset);
217                 /* append  to first fragment frame's tail (if privacy frame,
218                  * pull the ICV)
219                  */
220                 recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
221                 memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
222                 recvframe_put(prframe, pnfhdr->len);
223                 pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
224                 plist = plist->next;
225         }
226         /* free the defrag_q queue and return the prframe */
227         r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
228         return prframe;
229 }
230
231 /* check if need to defrag, if needed queue the frame to defrag_q */
232 union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter,
233                                              union recv_frame *precv_frame)
234 {
235         u8      ismfrag;
236         u8      fragnum;
237         u8   *psta_addr;
238         struct recv_frame_hdr *pfhdr;
239         struct sta_info *psta;
240         struct  sta_priv *pstapriv;
241         struct list_head *phead;
242         union recv_frame *prtnframe = NULL;
243         struct  __queue *pfree_recv_queue, *pdefrag_q;
244
245         pstapriv = &padapter->stapriv;
246         pfhdr = &precv_frame->u.hdr;
247         pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
248         /* need to define struct of wlan header frame ctrl */
249         ismfrag = pfhdr->attrib.mfrag;
250         fragnum = pfhdr->attrib.frag_num;
251         psta_addr = pfhdr->attrib.ta;
252         psta = r8712_get_stainfo(pstapriv, psta_addr);
253         if (!psta)
254                 pdefrag_q = NULL;
255         else
256                 pdefrag_q = &psta->sta_recvpriv.defrag_q;
257
258         if ((ismfrag == 0) && (fragnum == 0))
259                 prtnframe = precv_frame;/*isn't a fragment frame*/
260         if (ismfrag == 1) {
261                 /* 0~(n-1) fragment frame
262                  * enqueue to defraf_g
263                  */
264                 if (pdefrag_q) {
265                         if (fragnum == 0) {
266                                 /*the first fragment*/
267                                 if (!list_empty(&pdefrag_q->queue)) {
268                                         /*free current defrag_q */
269                                         r8712_free_recvframe_queue(pdefrag_q,
270                                                              pfree_recv_queue);
271                                 }
272                         }
273                         /* Then enqueue the 0~(n-1) fragment to the defrag_q */
274                         phead = &pdefrag_q->queue;
275                         list_add_tail(&pfhdr->list, phead);
276                         prtnframe = NULL;
277                 } else {
278                         /* can't find this ta's defrag_queue, so free this
279                          * recv_frame
280                          */
281                         r8712_free_recvframe(precv_frame, pfree_recv_queue);
282                         prtnframe = NULL;
283                 }
284         }
285         if ((ismfrag == 0) && (fragnum != 0)) {
286                 /* the last fragment frame
287                  * enqueue the last fragment
288                  */
289                 if (pdefrag_q) {
290                         phead = &pdefrag_q->queue;
291                         list_add_tail(&pfhdr->list, phead);
292                         /*call recvframe_defrag to defrag*/
293                         precv_frame = recvframe_defrag(padapter, pdefrag_q);
294                         prtnframe = precv_frame;
295                 } else {
296                         /* can't find this ta's defrag_queue, so free this
297                          *  recv_frame
298                          */
299                         r8712_free_recvframe(precv_frame, pfree_recv_queue);
300                         prtnframe = NULL;
301                 }
302         }
303         if (prtnframe && (prtnframe->u.hdr.attrib.privacy)) {
304                 /* after defrag we must check tkip mic code */
305                 if (r8712_recvframe_chkmic(padapter, prtnframe) == _FAIL) {
306                         r8712_free_recvframe(prtnframe, pfree_recv_queue);
307                         prtnframe = NULL;
308                 }
309         }
310         return prtnframe;
311 }
312
313 static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe)
314 {
315         int     a_len, padding_len;
316         u16     eth_type, nSubframe_Length;
317         u8      nr_subframes, i;
318         unsigned char *pdata;
319         struct rx_pkt_attrib *pattrib;
320         _pkt *sub_skb, *subframes[MAX_SUBFRAME_COUNT];
321         struct recv_priv *precvpriv = &padapter->recvpriv;
322         struct  __queue *pfree_recv_queue = &(precvpriv->free_recv_queue);
323
324         nr_subframes = 0;
325         pattrib = &prframe->u.hdr.attrib;
326         recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
327         if (prframe->u.hdr.attrib.iv_len > 0)
328                 recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
329         a_len = prframe->u.hdr.len;
330         pdata = prframe->u.hdr.rx_data;
331         while (a_len > ETH_HLEN) {
332                 /* Offset 12 denote 2 mac address */
333                 nSubframe_Length = *((u16 *)(pdata + 12));
334                 /*==m==>change the length order*/
335                 nSubframe_Length = (nSubframe_Length >> 8) +
336                                    (nSubframe_Length << 8);
337                 if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
338                         netdev_warn(padapter->pnetdev, "r8712u: nRemain_Length is %d and nSubframe_Length is: %d\n",
339                                     a_len, nSubframe_Length);
340                         goto exit;
341                 }
342                 /* move the data point to data content */
343                 pdata += ETH_HLEN;
344                 a_len -= ETH_HLEN;
345                 /* Allocate new skb for releasing to upper layer */
346                 sub_skb = dev_alloc_skb(nSubframe_Length + 12);
347                 if (!sub_skb)
348                         break;
349                 skb_reserve(sub_skb, 12);
350                 skb_put_data(sub_skb, pdata, nSubframe_Length);
351                 subframes[nr_subframes++] = sub_skb;
352                 if (nr_subframes >= MAX_SUBFRAME_COUNT) {
353                         netdev_warn(padapter->pnetdev, "r8712u: ParseSubframe(): Too many Subframes! Packets dropped!\n");
354                         break;
355                 }
356                 pdata += nSubframe_Length;
357                 a_len -= nSubframe_Length;
358                 if (a_len != 0) {
359                         padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & 3);
360                         if (padding_len == 4)
361                                 padding_len = 0;
362                         if (a_len < padding_len)
363                                 goto exit;
364                         pdata += padding_len;
365                         a_len -= padding_len;
366                 }
367         }
368         for (i = 0; i < nr_subframes; i++) {
369                 sub_skb = subframes[i];
370                 /* convert hdr + possible LLC headers into Ethernet header */
371                 eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7];
372                 if (sub_skb->len >= 8 &&
373                     ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
374                       eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
375                      !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
376                         /* remove RFC1042 or Bridge-Tunnel encapsulation and
377                          * replace EtherType
378                          */
379                         skb_pull(sub_skb, SNAP_SIZE);
380                         memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
381                                ETH_ALEN);
382                         memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
383                                ETH_ALEN);
384                 } else {
385                         __be16 len;
386                         /* Leave Ethernet header part of hdr and full payload */
387                         len = htons(sub_skb->len);
388                         memcpy(skb_push(sub_skb, 2), &len, 2);
389                         memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
390                                ETH_ALEN);
391                         memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
392                                ETH_ALEN);
393                 }
394                 /* Indicate the packets to upper layer */
395                 if (sub_skb) {
396                         sub_skb->protocol =
397                                  eth_type_trans(sub_skb, padapter->pnetdev);
398                         sub_skb->dev = padapter->pnetdev;
399                         if ((pattrib->tcpchk_valid == 1) &&
400                             (pattrib->tcp_chkrpt == 1)) {
401                                 sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
402                         } else {
403                                 sub_skb->ip_summed = CHECKSUM_NONE;
404                         }
405                         netif_rx(sub_skb);
406                 }
407         }
408 exit:
409         prframe->u.hdr.len = 0;
410         r8712_free_recvframe(prframe, pfree_recv_queue);
411 }
412
413 void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
414 {
415         __le32 voffset;
416         u8 *poffset;
417         u16 cmd_len, drvinfo_sz;
418         struct recv_stat *prxstat;
419
420         poffset = prxcmdbuf;
421         voffset = *(__le32 *)poffset;
422         prxstat = prxcmdbuf;
423         drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
424         drvinfo_sz <<= 3;
425         poffset += RXDESC_SIZE + drvinfo_sz;
426         do {
427                 voffset  = *(__le32 *)poffset;
428                 cmd_len = (u16)(le32_to_cpu(voffset) & 0xffff);
429                 r8712_event_handle(padapter, (__le32 *)poffset);
430                 poffset += (cmd_len + 8);/*8 bytes alignment*/
431         } while (le32_to_cpu(voffset) & BIT(31));
432 }
433
434 static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl,
435                               u16 seq_num)
436 {
437         u8 wsize = preorder_ctrl->wsize_b;
438         u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) % 4096;
439
440         /* Rx Reorder initialize condition.*/
441         if (preorder_ctrl->indicate_seq == 0xffff)
442                 preorder_ctrl->indicate_seq = seq_num;
443         /* Drop out the packet which SeqNum is smaller than WinStart */
444         if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
445                 return false;
446         /*
447          * Sliding window manipulation. Conditions includes:
448          * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
449          * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
450          */
451         if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq))
452                 preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq +
453                                               1) % 4096;
454         else if (SN_LESS(wend, seq_num)) {
455                 if (seq_num >= (wsize - 1))
456                         preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
457                 else
458                         preorder_ctrl->indicate_seq = 4095 - (wsize -
459                                                       (seq_num + 1)) + 1;
460         }
461         return true;
462 }
463
464 static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
465                                      union recv_frame *prframe)
466 {
467         struct list_head *phead, *plist;
468         union recv_frame *pnextrframe;
469         struct rx_pkt_attrib *pnextattrib;
470         struct  __queue *ppending_recvframe_queue =
471                                         &preorder_ctrl->pending_recvframe_queue;
472         struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
473
474         phead = &ppending_recvframe_queue->queue;
475         plist = phead->next;
476         while (!end_of_queue_search(phead, plist)) {
477                 pnextrframe = container_of(plist, union recv_frame, u.list);
478                 pnextattrib = &pnextrframe->u.hdr.attrib;
479
480                 if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
481                         return false;
482
483                 if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
484                         plist = plist->next;
485                 else
486                         break;
487         }
488         list_del_init(&(prframe->u.hdr.list));
489         list_add_tail(&(prframe->u.hdr.list), plist);
490         return true;
491 }
492
493 int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
494                                      struct recv_reorder_ctrl *preorder_ctrl,
495                                      int bforced)
496 {
497         struct list_head *phead, *plist;
498         union recv_frame *prframe;
499         struct rx_pkt_attrib *pattrib;
500         int bPktInBuf = false;
501         struct  __queue *ppending_recvframe_queue =
502                          &preorder_ctrl->pending_recvframe_queue;
503
504         phead = &ppending_recvframe_queue->queue;
505         plist = phead->next;
506         /* Handling some condition for forced indicate case.*/
507         if (bforced) {
508                 if (list_empty(phead))
509                         return true;
510
511                 prframe = container_of(plist, union recv_frame, u.list);
512                 pattrib = &prframe->u.hdr.attrib;
513                 preorder_ctrl->indicate_seq = pattrib->seq_num;
514         }
515         /* Prepare indication list and indication.
516          * Check if there is any packet need indicate.
517          */
518         while (!list_empty(phead)) {
519                 prframe = container_of(plist, union recv_frame, u.list);
520                 pattrib = &prframe->u.hdr.attrib;
521                 if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
522                         plist = plist->next;
523                         list_del_init(&(prframe->u.hdr.list));
524                         if (SN_EQUAL(preorder_ctrl->indicate_seq,
525                                      pattrib->seq_num))
526                                 preorder_ctrl->indicate_seq =
527                                   (preorder_ctrl->indicate_seq + 1) % 4096;
528                         /*indicate this recv_frame*/
529                         if (!pattrib->amsdu) {
530                                 if (!padapter->driver_stopped &&
531                                     !padapter->surprise_removed) {
532                                         /* indicate this recv_frame */
533                                         r8712_recv_indicatepkt(padapter,
534                                                                prframe);
535                                 }
536                         } else if (pattrib->amsdu == 1) {
537                                 amsdu_to_msdu(padapter, prframe);
538                         }
539                         /* Update local variables. */
540                         bPktInBuf = false;
541                 } else {
542                         bPktInBuf = true;
543                         break;
544                 }
545         }
546         return bPktInBuf;
547 }
548
549 static int recv_indicatepkt_reorder(struct _adapter *padapter,
550                                     union recv_frame *prframe)
551 {
552         unsigned long irql;
553         struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
554         struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
555         struct  __queue *ppending_recvframe_queue =
556                          &preorder_ctrl->pending_recvframe_queue;
557
558         if (!pattrib->amsdu) {
559                 /* s1. */
560                 r8712_wlanhdr_to_ethhdr(prframe);
561                 if (pattrib->qos != 1) {
562                         if (!padapter->driver_stopped &&
563                             !padapter->surprise_removed) {
564                                 r8712_recv_indicatepkt(padapter, prframe);
565                                 return 0;
566                         } else {
567                                 return -EINVAL;
568                         }
569                 }
570         }
571         spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
572         /*s2. check if winstart_b(indicate_seq) needs to be updated*/
573         if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
574                 goto _err_exit;
575         /*s3. Insert all packet into Reorder Queue to maintain its ordering.*/
576         if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
577                 goto _err_exit;
578         /*s4.
579          * Indication process.
580          * After Packet dropping and Sliding Window shifting as above, we can
581          * now just indicate the packets with the SeqNum smaller than latest
582          * WinStart and buffer other packets.
583          *
584          * For Rx Reorder condition:
585          * 1. All packets with SeqNum smaller than WinStart => Indicate
586          * 2. All packets with SeqNum larger than or equal to
587          * WinStart => Buffer it.
588          */
589         if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) {
590                 mod_timer(&preorder_ctrl->reordering_ctrl_timer,
591                           jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
592                 spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
593         } else {
594                 spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
595                 del_timer(&preorder_ctrl->reordering_ctrl_timer);
596         }
597         return 0;
598 _err_exit:
599         spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
600         return -ENOMEM;
601 }
602
603 void r8712_reordering_ctrl_timeout_handler(void *pcontext)
604 {
605         unsigned long irql;
606         struct recv_reorder_ctrl *preorder_ctrl = pcontext;
607         struct _adapter *padapter = preorder_ctrl->padapter;
608         struct  __queue *ppending_recvframe_queue =
609                                  &preorder_ctrl->pending_recvframe_queue;
610
611         if (padapter->driver_stopped || padapter->surprise_removed)
612                 return;
613         spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
614         r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, true);
615         spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
616 }
617
618 static int r8712_process_recv_indicatepkts(struct _adapter *padapter,
619                                            union recv_frame *prframe)
620 {
621         int retval = _SUCCESS;
622         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
623         struct ht_priv  *phtpriv = &pmlmepriv->htpriv;
624
625         if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
626                 if (recv_indicatepkt_reorder(padapter, prframe)) {
627                         /* including perform A-MPDU Rx Ordering Buffer Control*/
628                         if (!padapter->driver_stopped &&
629                             !padapter->surprise_removed)
630                                 return _FAIL;
631                 }
632         } else { /*B/G mode*/
633                 retval = r8712_wlanhdr_to_ethhdr(prframe);
634                 if (retval)
635                         return _FAIL;
636                 if (!padapter->driver_stopped && !padapter->surprise_removed) {
637                         /* indicate this recv_frame */
638                         r8712_recv_indicatepkt(padapter, prframe);
639                 } else {
640                         return _FAIL;
641                 }
642         }
643         return retval;
644 }
645
646 static u8 query_rx_pwr_percentage(s8 antpower)
647 {
648         if ((antpower <= -100) || (antpower >= 20))
649                 return  0;
650         else if (antpower >= 0)
651                 return  100;
652         else
653                 return 100 + antpower;
654 }
655
656 static u8 evm_db2percentage(s8 value)
657 {
658         /*
659          * -33dB~0dB to 0%~99%
660          */
661         s8 ret_val = clamp(-value, 0, 33) * 3;
662
663         if (ret_val == 99)
664                 ret_val = 100;
665
666         return ret_val;
667 }
668
669 s32 r8712_signal_scale_mapping(s32 cur_sig)
670 {
671         s32 ret_sig;
672
673         if (cur_sig >= 51 && cur_sig <= 100)
674                 ret_sig = 100;
675         else if (cur_sig >= 41 && cur_sig <= 50)
676                 ret_sig = 80 + ((cur_sig - 40) * 2);
677         else if (cur_sig >= 31 && cur_sig <= 40)
678                 ret_sig = 66 + (cur_sig - 30);
679         else if (cur_sig >= 21 && cur_sig <= 30)
680                 ret_sig = 54 + (cur_sig - 20);
681         else if (cur_sig >= 10 && cur_sig <= 20)
682                 ret_sig = 42 + (((cur_sig - 10) * 2) / 3);
683         else if (cur_sig >= 5 && cur_sig <= 9)
684                 ret_sig = 22 + (((cur_sig - 5) * 3) / 2);
685         else if (cur_sig >= 1 && cur_sig <= 4)
686                 ret_sig = 6 + (((cur_sig - 1) * 3) / 2);
687         else
688                 ret_sig = cur_sig;
689         return ret_sig;
690 }
691
692 static s32  translate2dbm(struct _adapter *padapter, u8 signal_strength_idx)
693 {
694         s32 signal_power; /* in dBm.*/
695         /* Translate to dBm (x=0.5y-95).*/
696         signal_power = (s32)((signal_strength_idx + 1) >> 1);
697         signal_power -= 95;
698         return signal_power;
699 }
700
701 static void query_rx_phy_status(struct _adapter *padapter,
702                                 union recv_frame *prframe)
703 {
704         u8 i, max_spatial_stream, evm;
705         struct recv_stat *prxstat = (struct recv_stat *)prframe->u.hdr.rx_head;
706         struct phy_stat *pphy_stat = (struct phy_stat *)(prxstat + 1);
707         u8 *pphy_head = (u8 *)(prxstat + 1);
708         s8 rx_pwr[4], rx_pwr_all;
709         u8 pwdb_all;
710         u32 rssi, total_rssi = 0;
711         u8 bcck_rate = 0, rf_rx_num = 0, cck_highpwr = 0;
712         struct phy_cck_rx_status *pcck_buf;
713         u8 sq;
714
715         /* Record it for next packet processing*/
716         bcck_rate = (prframe->u.hdr.attrib.mcs_rate <= 3 ? 1 : 0);
717         if (bcck_rate) {
718                 u8 report;
719
720                 /* CCK Driver info Structure is not the same as OFDM packet.*/
721                 pcck_buf = (struct phy_cck_rx_status *)pphy_stat;
722                 /* (1)Hardware does not provide RSSI for CCK
723                  * (2)PWDB, Average PWDB calculated by hardware
724                  * (for rate adaptive)
725                  */
726                 if (!cck_highpwr) {
727                         report = pcck_buf->cck_agc_rpt & 0xc0;
728                         report >>= 6;
729                         switch (report) {
730                         /* Modify the RF RNA gain value to -40, -20,
731                          * -2, 14 by Jenyu's suggestion
732                          * Note: different RF with the different
733                          * RNA gain.
734                          */
735                         case 0x3:
736                                 rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt &
737                                              0x3e);
738                                 break;
739                         case 0x2:
740                                 rx_pwr_all = -20 - (pcck_buf->cck_agc_rpt &
741                                              0x3e);
742                                 break;
743                         case 0x1:
744                                 rx_pwr_all = -2 - (pcck_buf->cck_agc_rpt &
745                                              0x3e);
746                                 break;
747                         case 0x0:
748                                 rx_pwr_all = 14 - (pcck_buf->cck_agc_rpt &
749                                              0x3e);
750                                 break;
751                         }
752                 } else {
753                         report = ((u8)(le32_to_cpu(pphy_stat->phydw1) >> 8)) &
754                                  0x60;
755                         report >>= 5;
756                         switch (report) {
757                         case 0x3:
758                                 rx_pwr_all = -40 - ((pcck_buf->cck_agc_rpt &
759                                              0x1f) << 1);
760                                 break;
761                         case 0x2:
762                                 rx_pwr_all = -20 - ((pcck_buf->cck_agc_rpt &
763                                              0x1f) << 1);
764                                 break;
765                         case 0x1:
766                                 rx_pwr_all = -2 - ((pcck_buf->cck_agc_rpt &
767                                              0x1f) << 1);
768                                 break;
769                         case 0x0:
770                                 rx_pwr_all = 14 - ((pcck_buf->cck_agc_rpt &
771                                              0x1f) << 1);
772                                 break;
773                         }
774                 }
775                 pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
776                 /* CCK gain is smaller than OFDM/MCS gain,*/
777                 /* so we add gain diff by experiences, the val is 6 */
778                 pwdb_all += 6;
779                 if (pwdb_all > 100)
780                         pwdb_all = 100;
781                 /* modify the offset to make the same gain index with OFDM.*/
782                 if (pwdb_all > 34 && pwdb_all <= 42)
783                         pwdb_all -= 2;
784                 else if (pwdb_all > 26 && pwdb_all <= 34)
785                         pwdb_all -= 6;
786                 else if (pwdb_all > 14 && pwdb_all <= 26)
787                         pwdb_all -= 8;
788                 else if (pwdb_all > 4 && pwdb_all <= 14)
789                         pwdb_all -= 4;
790                 /*
791                  * (3) Get Signal Quality (EVM)
792                  */
793                 if (pwdb_all > 40) {
794                         sq = 100;
795                 } else {
796                         sq = pcck_buf->sq_rpt;
797                         if (pcck_buf->sq_rpt > 64)
798                                 sq = 0;
799                         else if (pcck_buf->sq_rpt < 20)
800                                 sq = 100;
801                         else
802                                 sq = ((64 - sq) * 100) / 44;
803                 }
804                 prframe->u.hdr.attrib.signal_qual = sq;
805                 prframe->u.hdr.attrib.rx_mimo_signal_qual[0] = sq;
806                 prframe->u.hdr.attrib.rx_mimo_signal_qual[1] = -1;
807         } else {
808                 /* (1)Get RSSI for HT rate */
809                 for (i = 0; i < ((padapter->registrypriv.rf_config) &
810                             0x0f); i++) {
811                         rf_rx_num++;
812                         rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i]
813                                     & 0x3F) * 2) - 110;
814                         /* Translate DBM to percentage. */
815                         rssi = query_rx_pwr_percentage(rx_pwr[i]);
816                         total_rssi += rssi;
817                 }
818                 /* (2)PWDB, Average PWDB calculated by hardware (for
819                  * rate adaptive)
820                  */
821                 rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f)
822                              - 106;
823                 pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
824
825                 {
826                         /* (3)EVM of HT rate */
827                         if (prframe->u.hdr.attrib.htc &&
828                             prframe->u.hdr.attrib.mcs_rate >= 20 &&
829                             prframe->u.hdr.attrib.mcs_rate <= 27) {
830                                 /* both spatial stream make sense */
831                                 max_spatial_stream = 2;
832                         } else {
833                                 /* only spatial stream 1 makes sense */
834                                 max_spatial_stream = 1;
835                         }
836                         for (i = 0; i < max_spatial_stream; i++) {
837                                 evm = evm_db2percentage((pphy_head
838                                       [PHY_STAT_RXEVM_SHT + i]));/*dbm*/
839                                 prframe->u.hdr.attrib.signal_qual =
840                                          (u8)(evm & 0xff);
841                                 prframe->u.hdr.attrib.rx_mimo_signal_qual[i] =
842                                          (u8)(evm & 0xff);
843                         }
844                 }
845         }
846         /* UI BSS List signal strength(in percentage), make it good looking,
847          * from 0~100. It is assigned to the BSS List in
848          * GetValueFromBeaconOrProbeRsp().
849          */
850         if (bcck_rate) {
851                 prframe->u.hdr.attrib.signal_strength =
852                          (u8)r8712_signal_scale_mapping(pwdb_all);
853         } else {
854                 if (rf_rx_num != 0)
855                         prframe->u.hdr.attrib.signal_strength =
856                                  (u8)(r8712_signal_scale_mapping(total_rssi /=
857                                  rf_rx_num));
858         }
859 }
860
861 static void process_link_qual(struct _adapter *padapter,
862                               union recv_frame *prframe)
863 {
864         u32     last_evm = 0, tmpVal;
865         struct rx_pkt_attrib *pattrib;
866         struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
867
868         if (!prframe || !padapter)
869                 return;
870         pattrib = &prframe->u.hdr.attrib;
871         if (pattrib->signal_qual != 0) {
872                 /*
873                  * 1. Record the general EVM to the sliding window.
874                  */
875                 if (sqd->total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) {
876                         sqd->total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
877                         last_evm = sqd->elements[sqd->index];
878                         sqd->total_val -= last_evm;
879                 }
880                 sqd->total_val += pattrib->signal_qual;
881                 sqd->elements[sqd->index++] = pattrib->signal_qual;
882                 if (sqd->index >= PHY_LINKQUALITY_SLID_WIN_MAX)
883                         sqd->index = 0;
884
885                 /* <1> Showed on UI for user, in percentage. */
886                 tmpVal = sqd->total_val / sqd->total_num;
887                 padapter->recvpriv.signal = (u8)tmpVal;
888         }
889 }
890
891 static void process_rssi(struct _adapter *padapter, union recv_frame *prframe)
892 {
893         u32 last_rssi, tmp_val;
894         struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
895         struct smooth_rssi_data *ssd = &padapter->recvpriv.signal_strength_data;
896
897         if (ssd->total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
898                 ssd->total_num = PHY_RSSI_SLID_WIN_MAX;
899                 last_rssi = ssd->elements[ssd->index];
900                 ssd->total_val -= last_rssi;
901         }
902         ssd->total_val += pattrib->signal_strength;
903         ssd->elements[ssd->index++] = pattrib->signal_strength;
904         if (ssd->index >= PHY_RSSI_SLID_WIN_MAX)
905                 ssd->index = 0;
906         tmp_val = ssd->total_val / ssd->total_num;
907         padapter->recvpriv.rssi = (s8)translate2dbm(padapter, (u8)tmp_val);
908 }
909
910 static void process_phy_info(struct _adapter *padapter,
911                              union recv_frame *prframe)
912 {
913         query_rx_phy_status(padapter, prframe);
914         process_rssi(padapter, prframe);
915         process_link_qual(padapter,  prframe);
916 }
917
918 int recv_func(struct _adapter *padapter, void *pcontext)
919 {
920         struct rx_pkt_attrib *pattrib;
921         union recv_frame *prframe, *orig_prframe;
922         int retval = _SUCCESS;
923         struct  __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
924         struct  mlme_priv       *pmlmepriv = &padapter->mlmepriv;
925
926         prframe = pcontext;
927         orig_prframe = prframe;
928         pattrib = &prframe->u.hdr.attrib;
929         if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
930                 if (pattrib->crc_err == 1)
931                         padapter->mppriv.rx_crcerrpktcount++;
932                 else
933                         padapter->mppriv.rx_pktcount++;
934                 if (!check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE)) {
935                         /* free this recv_frame */
936                         r8712_free_recvframe(orig_prframe, pfree_recv_queue);
937                         goto _exit_recv_func;
938                 }
939         }
940         /* check the frame crtl field and decache */
941         retval = r8712_validate_recv_frame(padapter, prframe);
942         if (retval != _SUCCESS) {
943                 /* free this recv_frame */
944                 r8712_free_recvframe(orig_prframe, pfree_recv_queue);
945                 goto _exit_recv_func;
946         }
947         process_phy_info(padapter, prframe);
948         prframe = r8712_decryptor(padapter, prframe);
949         if (!prframe) {
950                 retval = _FAIL;
951                 goto _exit_recv_func;
952         }
953         prframe = r8712_recvframe_chk_defrag(padapter, prframe);
954         if (!prframe)
955                 goto _exit_recv_func;
956         prframe = r8712_portctrl(padapter, prframe);
957         if (!prframe) {
958                 retval = _FAIL;
959                 goto _exit_recv_func;
960         }
961         retval = r8712_process_recv_indicatepkts(padapter, prframe);
962         if (retval != _SUCCESS) {
963                 r8712_free_recvframe(orig_prframe, pfree_recv_queue);
964                 goto _exit_recv_func;
965         }
966 _exit_recv_func:
967         return retval;
968 }
969
970 static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
971 {
972         u8 *pbuf, shift_sz = 0;
973         u8      frag, mf;
974         uint    pkt_len;
975         u32 transfer_len;
976         struct recv_stat *prxstat;
977         u16     pkt_cnt, drvinfo_sz, pkt_offset, tmp_len, alloc_sz;
978         struct  __queue *pfree_recv_queue;
979         _pkt  *pkt_copy = NULL;
980         union recv_frame *precvframe = NULL;
981         struct recv_priv *precvpriv = &padapter->recvpriv;
982
983         pfree_recv_queue = &(precvpriv->free_recv_queue);
984         pbuf = pskb->data;
985         prxstat = (struct recv_stat *)pbuf;
986         pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
987         pkt_len =  le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
988         transfer_len = pskb->len;
989         /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R
990          * pairs. The packet count will be a big number so that the containing
991          * packet will effect the Rx reordering.
992          */
993         if (transfer_len < pkt_len) {
994                 /* In this case, it means the MAX_RECVBUF_SZ is too small to
995                  * get the data from 8712u.
996                  */
997                 return;
998         }
999         do {
1000                 prxstat = (struct recv_stat *)pbuf;
1001                 pkt_len =  le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
1002                 /* more fragment bit */
1003                 mf = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1;
1004                 /* ragmentation number */
1005                 frag = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf;
1006                 /* uint 2^3 = 8 bytes */
1007                 drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
1008                 drvinfo_sz <<= 3;
1009                 if (pkt_len <= 0)
1010                         return;
1011                 /* Qos data, wireless lan header length is 26 */
1012                 if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01)
1013                         shift_sz = 2;
1014                 precvframe = r8712_alloc_recvframe(pfree_recv_queue);
1015                 if (!precvframe)
1016                         return;
1017                 INIT_LIST_HEAD(&precvframe->u.hdr.list);
1018                 precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/
1019                 precvframe->u.hdr.len = 0;
1020                 tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE;
1021                 pkt_offset = (u16)round_up(tmp_len, 128);
1022                 /* for first fragment packet, driver need allocate 1536 +
1023                  * drvinfo_sz + RXDESC_SIZE to defrag packet.
1024                  */
1025                 if ((mf == 1) && (frag == 0))
1026                         /*1658+6=1664, 1664 is 128 alignment.*/
1027                         alloc_sz = max_t(u16, tmp_len, 1658);
1028                 else
1029                         alloc_sz = tmp_len;
1030                 /* 2 is for IP header 4 bytes alignment in QoS packet case.
1031                  * 4 is for skb->data 4 bytes alignment.
1032                  */
1033                 alloc_sz += 6;
1034                 pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
1035                 if (!pkt_copy)
1036                         return;
1037
1038                 precvframe->u.hdr.pkt = pkt_copy;
1039                 skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) % 4));
1040                 skb_reserve(pkt_copy, shift_sz);
1041                 memcpy(pkt_copy->data, pbuf, tmp_len);
1042                 precvframe->u.hdr.rx_head = pkt_copy->data;
1043                 precvframe->u.hdr.rx_data = pkt_copy->data;
1044                 precvframe->u.hdr.rx_tail = pkt_copy->data;
1045                 precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
1046
1047                 recvframe_put(precvframe, tmp_len);
1048                 recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
1049                 /* because the endian issue, driver avoid reference to the
1050                  * rxstat after calling update_recvframe_attrib_from_recvstat();
1051                  */
1052                 update_recvframe_attrib_from_recvstat(&precvframe->u.hdr.attrib,
1053                                                       prxstat);
1054                 r8712_recv_entry(precvframe);
1055                 transfer_len -= pkt_offset;
1056                 pbuf += pkt_offset;
1057                 pkt_cnt--;
1058                 precvframe = NULL;
1059                 pkt_copy = NULL;
1060         } while ((transfer_len > 0) && pkt_cnt > 0);
1061 }
1062
1063 static void recv_tasklet(struct tasklet_struct *t)
1064 {
1065         struct sk_buff *pskb;
1066         struct _adapter *padapter = from_tasklet(padapter, t,
1067                                                  recvpriv.recv_tasklet);
1068         struct recv_priv *precvpriv = &padapter->recvpriv;
1069
1070         while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
1071                 recvbuf2recvframe(padapter, pskb);
1072                 skb_reset_tail_pointer(pskb);
1073                 pskb->len = 0;
1074                 if (!skb_cloned(pskb))
1075                         skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
1076                 else
1077                         consume_skb(pskb);
1078         }
1079 }