linux/drivers/staging/rtl8723bs/core/rtw_recv.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/******************************************************************************
   3 *
   4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
   5 *
   6 ******************************************************************************/
   7#define _RTW_RECV_C_
   8
   9#include <drv_types.h>
  10#include <rtw_debug.h>
  11#include <linux/jiffies.h>
  12#include <rtw_recv.h>
  13#include <net/cfg80211.h>
  14
  15static u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
  16static u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
  17
  18static void rtw_signal_stat_timer_hdl(struct timer_list *t);
  19
  20void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
  21{
  22        memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
  23
  24        spin_lock_init(&psta_recvpriv->lock);
  25
  26        /* for (i = 0; i<MAX_RX_NUMBLKS; i++) */
  27        /*      _rtw_init_queue(&psta_recvpriv->blk_strms[i]); */
  28
  29        _rtw_init_queue(&psta_recvpriv->defrag_q);
  30}
  31
  32sint _rtw_init_recv_priv(struct recv_priv *precvpriv, struct adapter *padapter)
  33{
  34        sint i;
  35        union recv_frame *precvframe;
  36        sint    res = _SUCCESS;
  37
  38        spin_lock_init(&precvpriv->lock);
  39
  40        _rtw_init_queue(&precvpriv->free_recv_queue);
  41        _rtw_init_queue(&precvpriv->recv_pending_queue);
  42        _rtw_init_queue(&precvpriv->uc_swdec_pending_queue);
  43
  44        precvpriv->adapter = padapter;
  45
  46        precvpriv->free_recvframe_cnt = NR_RECVFRAME;
  47
  48        precvpriv->pallocated_frame_buf = vzalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
  49
  50        if (!precvpriv->pallocated_frame_buf) {
  51                res = _FAIL;
  52                goto exit;
  53        }
  54
  55        precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
  56        /* precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ - */
  57        /*                                              ((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1)); */
  58
  59        precvframe = (union recv_frame *) precvpriv->precv_frame_buf;
  60
  61
  62        for (i = 0; i < NR_RECVFRAME; i++) {
  63                INIT_LIST_HEAD(&(precvframe->u.list));
  64
  65                list_add_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));
  66
  67                rtw_os_recv_resource_alloc(padapter, precvframe);
  68
  69                precvframe->u.hdr.len = 0;
  70
  71                precvframe->u.hdr.adapter = padapter;
  72                precvframe++;
  73
  74        }
  75
  76        res = rtw_hal_init_recv_priv(padapter);
  77
  78        timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl,
  79                    0);
  80
  81        precvpriv->signal_stat_sampling_interval = 2000; /* ms */
  82
  83        rtw_set_signal_stat_timer(precvpriv);
  84
  85exit:
  86        return res;
  87}
  88
  89void _rtw_free_recv_priv(struct recv_priv *precvpriv)
  90{
  91        struct adapter  *padapter = precvpriv->adapter;
  92
  93        rtw_free_uc_swdec_pending_queue(padapter);
  94
  95        rtw_os_recv_resource_free(precvpriv);
  96
  97        if (precvpriv->pallocated_frame_buf)
  98                vfree(precvpriv->pallocated_frame_buf);
  99
 100        rtw_hal_free_recv_priv(padapter);
 101}
 102
 103union recv_frame *_rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
 104{
 105
 106        union recv_frame  *precvframe;
 107        struct list_head        *plist, *phead;
 108        struct adapter *padapter;
 109        struct recv_priv *precvpriv;
 110
 111        if (list_empty(&pfree_recv_queue->queue))
 112                precvframe = NULL;
 113        else {
 114                phead = get_list_head(pfree_recv_queue);
 115
 116                plist = get_next(phead);
 117
 118                precvframe = (union recv_frame *)plist;
 119
 120                list_del_init(&precvframe->u.hdr.list);
 121                padapter = precvframe->u.hdr.adapter;
 122                if (padapter) {
 123                        precvpriv = &padapter->recvpriv;
 124                        if (pfree_recv_queue == &precvpriv->free_recv_queue)
 125                                precvpriv->free_recvframe_cnt--;
 126                }
 127        }
 128        return precvframe;
 129}
 130
 131union recv_frame *rtw_alloc_recvframe(struct __queue *pfree_recv_queue)
 132{
 133        union recv_frame  *precvframe;
 134
 135        spin_lock_bh(&pfree_recv_queue->lock);
 136
 137        precvframe = _rtw_alloc_recvframe(pfree_recv_queue);
 138
 139        spin_unlock_bh(&pfree_recv_queue->lock);
 140
 141        return precvframe;
 142}
 143
 144int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_queue)
 145{
 146        struct adapter *padapter = precvframe->u.hdr.adapter;
 147        struct recv_priv *precvpriv = &padapter->recvpriv;
 148
 149        rtw_os_free_recvframe(precvframe);
 150
 151
 152        spin_lock_bh(&pfree_recv_queue->lock);
 153
 154        list_del_init(&(precvframe->u.hdr.list));
 155
 156        precvframe->u.hdr.len = 0;
 157
 158        list_add_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));
 159
 160        if (padapter) {
 161                if (pfree_recv_queue == &precvpriv->free_recv_queue)
 162                                precvpriv->free_recvframe_cnt++;
 163        }
 164        spin_unlock_bh(&pfree_recv_queue->lock);
 165        return _SUCCESS;
 166}
 167
 168
 169
 170
 171sint _rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
 172{
 173
 174        struct adapter *padapter = precvframe->u.hdr.adapter;
 175        struct recv_priv *precvpriv = &padapter->recvpriv;
 176
 177        /* INIT_LIST_HEAD(&(precvframe->u.hdr.list)); */
 178        list_del_init(&(precvframe->u.hdr.list));
 179
 180
 181        list_add_tail(&(precvframe->u.hdr.list), get_list_head(queue));
 182
 183        if (padapter)
 184                if (queue == &precvpriv->free_recv_queue)
 185                        precvpriv->free_recvframe_cnt++;
 186
 187        return _SUCCESS;
 188}
 189
 190sint rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
 191{
 192        sint ret;
 193
 194        /* _spinlock(&pfree_recv_queue->lock); */
 195        spin_lock_bh(&queue->lock);
 196        ret = _rtw_enqueue_recvframe(precvframe, queue);
 197        /* spin_unlock(&pfree_recv_queue->lock); */
 198        spin_unlock_bh(&queue->lock);
 199
 200        return ret;
 201}
 202
 203/*
 204sint    rtw_enqueue_recvframe(union recv_frame *precvframe, struct __queue *queue)
 205{
 206        return rtw_free_recvframe(precvframe, queue);
 207}
 208*/
 209
 210
 211
 212
 213/*
 214caller : defrag ; recvframe_chk_defrag in recv_thread  (passive)
 215pframequeue: defrag_queue : will be accessed in recv_thread  (passive)
 216
 217using spinlock to protect
 218
 219*/
 220
 221void rtw_free_recvframe_queue(struct __queue *pframequeue,  struct __queue *pfree_recv_queue)
 222{
 223        union   recv_frame      *precvframe;
 224        struct list_head        *plist, *phead;
 225
 226        spin_lock(&pframequeue->lock);
 227
 228        phead = get_list_head(pframequeue);
 229        plist = get_next(phead);
 230
 231        while (phead != plist) {
 232                precvframe = (union recv_frame *)plist;
 233
 234                plist = get_next(plist);
 235
 236                rtw_free_recvframe(precvframe, pfree_recv_queue);
 237        }
 238
 239        spin_unlock(&pframequeue->lock);
 240}
 241
 242u32 rtw_free_uc_swdec_pending_queue(struct adapter *adapter)
 243{
 244        u32 cnt = 0;
 245        union recv_frame *pending_frame;
 246        while ((pending_frame = rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {
 247                rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);
 248                cnt++;
 249        }
 250
 251        if (cnt)
 252                DBG_871X(FUNC_ADPT_FMT" dequeue %d\n", FUNC_ADPT_ARG(adapter), cnt);
 253
 254        return cnt;
 255}
 256
 257
 258sint rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, struct __queue *queue)
 259{
 260        spin_lock_bh(&queue->lock);
 261
 262        list_del_init(&precvbuf->list);
 263        list_add(&precvbuf->list, get_list_head(queue));
 264
 265        spin_unlock_bh(&queue->lock);
 266
 267        return _SUCCESS;
 268}
 269
 270sint rtw_enqueue_recvbuf(struct recv_buf *precvbuf, struct __queue *queue)
 271{
 272        spin_lock_bh(&queue->lock);
 273
 274        list_del_init(&precvbuf->list);
 275
 276        list_add_tail(&precvbuf->list, get_list_head(queue));
 277        spin_unlock_bh(&queue->lock);
 278        return _SUCCESS;
 279
 280}
 281
 282struct recv_buf *rtw_dequeue_recvbuf(struct __queue *queue)
 283{
 284        struct recv_buf *precvbuf;
 285        struct list_head        *plist, *phead;
 286
 287        spin_lock_bh(&queue->lock);
 288
 289        if (list_empty(&queue->queue))
 290                precvbuf = NULL;
 291        else {
 292                phead = get_list_head(queue);
 293
 294                plist = get_next(phead);
 295
 296                precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list);
 297
 298                list_del_init(&precvbuf->list);
 299
 300        }
 301
 302        spin_unlock_bh(&queue->lock);
 303
 304        return precvbuf;
 305
 306}
 307
 308sint recvframe_chkmic(struct adapter *adapter,  union recv_frame *precvframe);
 309sint recvframe_chkmic(struct adapter *adapter,  union recv_frame *precvframe)
 310{
 311
 312        sint    i, res = _SUCCESS;
 313        u32 datalen;
 314        u8 miccode[8];
 315        u8 bmic_err = false, brpt_micerror = true;
 316        u8 *pframe, *payload, *pframemic;
 317        u8 *mickey;
 318        /* u8 *iv, rxdata_key_idx = 0; */
 319        struct  sta_info        *stainfo;
 320        struct  rx_pkt_attrib   *prxattrib = &precvframe->u.hdr.attrib;
 321        struct  security_priv *psecuritypriv = &adapter->securitypriv;
 322
 323        struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
 324        struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
 325
 326        stainfo = rtw_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
 327
 328        if (prxattrib->encrypt == _TKIP_) {
 329                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic:prxattrib->encrypt == _TKIP_\n"));
 330                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic:da = 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
 331                        prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2], prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5]));
 332
 333                /* calculate mic code */
 334                if (stainfo) {
 335                        if (IS_MCAST(prxattrib->ra)) {
 336                                /* mickey =&psecuritypriv->dot118021XGrprxmickey.skey[0]; */
 337                                /* iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen; */
 338                                /* rxdata_key_idx =(((iv[3])>>6)&0x3) ; */
 339                                mickey = &psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
 340
 341                                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n recvframe_chkmic: bcmc key\n"));
 342                                /* DBG_871X("\n recvframe_chkmic: bcmc key psecuritypriv->dot118021XGrpKeyid(%d), pmlmeinfo->key_index(%d) , recv key_id(%d)\n", */
 343                                /*                                                              psecuritypriv->dot118021XGrpKeyid, pmlmeinfo->key_index, rxdata_key_idx); */
 344
 345                                if (psecuritypriv->binstallGrpkey == false) {
 346                                        res = _FAIL;
 347                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n"));
 348                                        DBG_871X("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n");
 349                                        goto exit;
 350                                }
 351                        } else {
 352                                mickey = &stainfo->dot11tkiprxmickey.skey[0];
 353                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n recvframe_chkmic: unicast key\n"));
 354                        }
 355
 356                        datalen = precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;/* icv_len included the mic code */
 357                        pframe = precvframe->u.hdr.rx_data;
 358                        payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
 359
 360                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n prxattrib->iv_len =%d prxattrib->icv_len =%d\n", prxattrib->iv_len, prxattrib->icv_len));
 361
 362
 363                        rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], (unsigned char)prxattrib->priority); /* care the length of the data */
 364
 365                        pframemic = payload+datalen;
 366
 367                        bmic_err = false;
 368
 369                        for (i = 0; i < 8; i++) {
 370                                if (miccode[i] != *(pframemic+i)) {
 371                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x) ", i, miccode[i], i, *(pframemic+i)));
 372                                        bmic_err = true;
 373                                }
 374                        }
 375
 376
 377                        if (bmic_err == true) {
 378
 379                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n *(pframemic-8)-*(pframemic-1) = 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
 380                                        *(pframemic-8), *(pframemic-7), *(pframemic-6), *(pframemic-5), *(pframemic-4), *(pframemic-3), *(pframemic-2), *(pframemic-1)));
 381                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n *(pframemic-16)-*(pframemic-9) = 0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
 382                                        *(pframemic-16), *(pframemic-15), *(pframemic-14), *(pframemic-13), *(pframemic-12), *(pframemic-11), *(pframemic-10), *(pframemic-9)));
 383
 384                                {
 385                                        uint i;
 386                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n ======demp packet (len =%d) ======\n", precvframe->u.hdr.len));
 387                                        for (i = 0; i < precvframe->u.hdr.len; i = i+8) {
 388                                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
 389                                                        *(precvframe->u.hdr.rx_data+i), *(precvframe->u.hdr.rx_data+i+1),
 390                                                        *(precvframe->u.hdr.rx_data+i+2), *(precvframe->u.hdr.rx_data+i+3),
 391                                                        *(precvframe->u.hdr.rx_data+i+4), *(precvframe->u.hdr.rx_data+i+5),
 392                                                        *(precvframe->u.hdr.rx_data+i+6), *(precvframe->u.hdr.rx_data+i+7)));
 393                                        }
 394                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n ======demp packet end [len =%d]======\n", precvframe->u.hdr.len));
 395                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("\n hrdlen =%d,\n", prxattrib->hdrlen));
 396                                }
 397
 398                                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ra = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey =%d ",
 399                                        prxattrib->ra[0], prxattrib->ra[1], prxattrib->ra[2],
 400                                        prxattrib->ra[3], prxattrib->ra[4], prxattrib->ra[5], psecuritypriv->binstallGrpkey));
 401
 402                                /*  double check key_index for some timing issue , */
 403                                /*  cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue */
 404                                if ((IS_MCAST(prxattrib->ra) == true)  && (prxattrib->key_index != pmlmeinfo->key_index))
 405                                        brpt_micerror = false;
 406
 407                                if ((prxattrib->bdecrypted == true) && (brpt_micerror == true)) {
 408                                        rtw_handle_tkip_mic_err(adapter, (u8)IS_MCAST(prxattrib->ra));
 409                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
 410                                        DBG_871X(" mic error :prxattrib->bdecrypted =%d\n", prxattrib->bdecrypted);
 411                                } else {
 412                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" mic error :prxattrib->bdecrypted =%d ", prxattrib->bdecrypted));
 413                                        DBG_871X(" mic error :prxattrib->bdecrypted =%d\n", prxattrib->bdecrypted);
 414                                }
 415
 416                                res = _FAIL;
 417
 418                        } else {
 419                                /* mic checked ok */
 420                                if ((psecuritypriv->bcheck_grpkey == false) && (IS_MCAST(prxattrib->ra) == true)) {
 421                                        psecuritypriv->bcheck_grpkey = true;
 422                                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("psecuritypriv->bcheck_grpkey =true"));
 423                                }
 424                        }
 425
 426                } else
 427                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic: rtw_get_stainfo == NULL!!!\n"));
 428
 429                recvframe_pull_tail(precvframe, 8);
 430
 431        }
 432
 433exit:
 434        return res;
 435
 436}
 437
 438/* decrypt and set the ivlen, icvlen of the recv_frame */
 439union recv_frame *decryptor(struct adapter *padapter, union recv_frame *precv_frame);
 440union recv_frame *decryptor(struct adapter *padapter, union recv_frame *precv_frame)
 441{
 442
 443        struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
 444        struct security_priv *psecuritypriv = &padapter->securitypriv;
 445        union recv_frame *return_packet = precv_frame;
 446        u32  res = _SUCCESS;
 447
 448        DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt);
 449
 450        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("prxstat->decrypted =%x prxattrib->encrypt = 0x%03x\n", prxattrib->bdecrypted, prxattrib->encrypt));
 451
 452        if (prxattrib->encrypt > 0) {
 453                u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen;
 454                prxattrib->key_index = (((iv[3])>>6)&0x3);
 455
 456                if (prxattrib->key_index > WEP_KEYS) {
 457                        DBG_871X("prxattrib->key_index(%d) > WEP_KEYS\n", prxattrib->key_index);
 458
 459                        switch (prxattrib->encrypt) {
 460                        case _WEP40_:
 461                        case _WEP104_:
 462                                prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex;
 463                                break;
 464                        case _TKIP_:
 465                        case _AES_:
 466                        default:
 467                                prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid;
 468                                break;
 469                        }
 470                }
 471        }
 472
 473        if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) || (psecuritypriv->sw_decrypt == true))) {
 474                psecuritypriv->hw_decrypted = false;
 475
 476                #ifdef DBG_RX_DECRYPTOR
 477                DBG_871X("[%s] %d:prxstat->bdecrypted:%d,  prxattrib->encrypt:%d,  Setting psecuritypriv->hw_decrypted = %d\n",
 478                        __func__,
 479                        __LINE__,
 480                        prxattrib->bdecrypted,
 481                        prxattrib->encrypt,
 482                        psecuritypriv->hw_decrypted);
 483                #endif
 484
 485                switch (prxattrib->encrypt) {
 486                case _WEP40_:
 487                case _WEP104_:
 488                        DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wep);
 489                        rtw_wep_decrypt(padapter, (u8 *)precv_frame);
 490                        break;
 491                case _TKIP_:
 492                        DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_tkip);
 493                        res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);
 494                        break;
 495                case _AES_:
 496                        DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_aes);
 497                        res = rtw_aes_decrypt(padapter, (u8 *)precv_frame);
 498                        break;
 499                default:
 500                                break;
 501                }
 502        } else if (prxattrib->bdecrypted == 1
 503                && prxattrib->encrypt > 0
 504                && (psecuritypriv->busetkipkey == 1 || prxattrib->encrypt != _TKIP_)
 505                ) {
 506                DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_hw);
 507
 508                psecuritypriv->hw_decrypted = true;
 509                #ifdef DBG_RX_DECRYPTOR
 510                DBG_871X("[%s] %d:prxstat->bdecrypted:%d,  prxattrib->encrypt:%d,  Setting psecuritypriv->hw_decrypted = %d\n",
 511                        __func__,
 512                        __LINE__,
 513                        prxattrib->bdecrypted,
 514                        prxattrib->encrypt,
 515                        psecuritypriv->hw_decrypted);
 516
 517                #endif
 518        } else {
 519                DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_unknown);
 520                #ifdef DBG_RX_DECRYPTOR
 521                DBG_871X("[%s] %d:prxstat->bdecrypted:%d,  prxattrib->encrypt:%d,  Setting psecuritypriv->hw_decrypted = %d\n",
 522                        __func__,
 523                        __LINE__,
 524                        prxattrib->bdecrypted,
 525                        prxattrib->encrypt,
 526                        psecuritypriv->hw_decrypted);
 527                #endif
 528        }
 529
 530        if (res == _FAIL) {
 531                rtw_free_recvframe(return_packet, &padapter->recvpriv.free_recv_queue);
 532                return_packet = NULL;
 533        } else
 534                prxattrib->bdecrypted = true;
 535
 536        return return_packet;
 537}
 538
 539/* set the security information in the recv_frame */
 540union recv_frame *portctrl(struct adapter *adapter, union recv_frame *precv_frame);
 541union recv_frame *portctrl(struct adapter *adapter, union recv_frame *precv_frame)
 542{
 543        u8 *psta_addr = NULL;
 544        u8 *ptr;
 545        uint  auth_alg;
 546        struct recv_frame_hdr *pfhdr;
 547        struct sta_info *psta;
 548        struct sta_priv *pstapriv;
 549        union recv_frame *prtnframe;
 550        u16 ether_type = 0;
 551        u16  eapol_type = 0x888e;/* for Funia BD's WPA issue */
 552        struct rx_pkt_attrib *pattrib;
 553
 554        pstapriv = &adapter->stapriv;
 555
 556        auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
 557
 558        ptr = get_recvframe_data(precv_frame);
 559        pfhdr = &precv_frame->u.hdr;
 560        pattrib = &pfhdr->attrib;
 561        psta_addr = pattrib->ta;
 562
 563        prtnframe = NULL;
 564
 565        psta = rtw_get_stainfo(pstapriv, psta_addr);
 566
 567        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:adapter->securitypriv.dot11AuthAlgrthm =%d\n", adapter->securitypriv.dot11AuthAlgrthm));
 568
 569        if (auth_alg == 2) {
 570                if ((psta) && (psta->ieee8021x_blocked)) {
 571                        __be16 be_tmp;
 572
 573                        /* blocked */
 574                        /* only accept EAPOL frame */
 575                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked == 1\n"));
 576
 577                        prtnframe = precv_frame;
 578
 579                        /* get ether_type */
 580                        ptr = ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
 581                        memcpy(&be_tmp, ptr, 2);
 582                        ether_type = ntohs(be_tmp);
 583
 584                        if (ether_type == eapol_type)
 585                                prtnframe = precv_frame;
 586                        else {
 587                                /* free this frame */
 588                                rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue);
 589                                prtnframe = NULL;
 590                        }
 591                } else {
 592                        /* allowed */
 593                        /* check decryption status, and decrypt the frame if needed */
 594                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:psta->ieee8021x_blocked == 0\n"));
 595                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("portctrl:precv_frame->hdr.attrib.privacy =%x\n", precv_frame->u.hdr.attrib.privacy));
 596
 597                        if (pattrib->bdecrypted == 0)
 598                                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("portctrl:prxstat->decrypted =%x\n", pattrib->bdecrypted));
 599
 600                        prtnframe = precv_frame;
 601                        /* check is the EAPOL frame or not (Rekey) */
 602                        /* if (ether_type == eapol_type) { */
 603                        /*      RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("########portctrl:ether_type == 0x888e\n")); */
 604                                /* check Rekey */
 605
 606                        /*      prtnframe =precv_frame; */
 607                        /*  */
 608                        /* else { */
 609                        /*      RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("########portctrl:ether_type = 0x%04x\n", ether_type)); */
 610                        /*  */
 611                }
 612        } else
 613                prtnframe = precv_frame;
 614
 615        return prtnframe;
 616}
 617
 618sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache);
 619sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache)
 620{
 621        sint tid = precv_frame->u.hdr.attrib.priority;
 622
 623        u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
 624                (precv_frame->u.hdr.attrib.frag_num & 0xf);
 625
 626        if (tid > 15) {
 627                RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl = 0x%x, tid = 0x%x\n", seq_ctrl, tid));
 628
 629                return _FAIL;
 630        }
 631
 632        if (1) { /* if (bretry) */
 633                if (seq_ctrl == prxcache->tid_rxseq[tid]) {
 634                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, seq_ctrl = 0x%x, tid = 0x%x, tid_rxseq = 0x%x\n", seq_ctrl, tid, prxcache->tid_rxseq[tid]));
 635
 636                        return _FAIL;
 637                }
 638        }
 639
 640        prxcache->tid_rxseq[tid] = seq_ctrl;
 641
 642        return _SUCCESS;
 643
 644}
 645
 646void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame);
 647void process_pwrbit_data(struct adapter *padapter, union recv_frame *precv_frame)
 648{
 649        unsigned char pwrbit;
 650        u8 *ptr = precv_frame->u.hdr.rx_data;
 651        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 652        struct sta_priv *pstapriv = &padapter->stapriv;
 653        struct sta_info *psta = NULL;
 654
 655        psta = rtw_get_stainfo(pstapriv, pattrib->src);
 656
 657        pwrbit = GetPwrMgt(ptr);
 658
 659        if (psta) {
 660                if (pwrbit) {
 661                        if (!(psta->state & WIFI_SLEEP_STATE)) {
 662                                /* psta->state |= WIFI_SLEEP_STATE; */
 663                                /* pstapriv->sta_dz_bitmap |= BIT(psta->aid); */
 664
 665                                stop_sta_xmit(padapter, psta);
 666
 667                                /* DBG_871X("to sleep, sta_dz_bitmap =%x\n", pstapriv->sta_dz_bitmap); */
 668                        }
 669                } else {
 670                        if (psta->state & WIFI_SLEEP_STATE) {
 671                                /* psta->state ^= WIFI_SLEEP_STATE; */
 672                                /* pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); */
 673
 674                                wakeup_sta_to_xmit(padapter, psta);
 675
 676                                /* DBG_871X("to wakeup, sta_dz_bitmap =%x\n", pstapriv->sta_dz_bitmap); */
 677                        }
 678                }
 679
 680        }
 681}
 682
 683void process_wmmps_data(struct adapter *padapter, union recv_frame *precv_frame);
 684void process_wmmps_data(struct adapter *padapter, union recv_frame *precv_frame)
 685{
 686        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 687        struct sta_priv *pstapriv = &padapter->stapriv;
 688        struct sta_info *psta = NULL;
 689
 690        psta = rtw_get_stainfo(pstapriv, pattrib->src);
 691
 692        if (!psta)
 693                return;
 694
 695        if (!psta->qos_option)
 696                return;
 697
 698        if (!(psta->qos_info&0xf))
 699                return;
 700
 701        if (psta->state&WIFI_SLEEP_STATE) {
 702                u8 wmmps_ac = 0;
 703
 704                switch (pattrib->priority) {
 705                case 1:
 706                case 2:
 707                        wmmps_ac = psta->uapsd_bk&BIT(1);
 708                        break;
 709                case 4:
 710                case 5:
 711                        wmmps_ac = psta->uapsd_vi&BIT(1);
 712                        break;
 713                case 6:
 714                case 7:
 715                        wmmps_ac = psta->uapsd_vo&BIT(1);
 716                        break;
 717                case 0:
 718                case 3:
 719                default:
 720                        wmmps_ac = psta->uapsd_be&BIT(1);
 721                        break;
 722                }
 723
 724                if (wmmps_ac) {
 725                        if (psta->sleepq_ac_len > 0)
 726                                /* process received triggered frame */
 727                                xmit_delivery_enabled_frames(padapter, psta);
 728                        else
 729                                /* issue one qos null frame with More data bit = 0 and the EOSP bit set (= 1) */
 730                                issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0);
 731                }
 732        }
 733}
 734
 735void count_rx_stats(struct adapter *padapter, union recv_frame *prframe, struct sta_info *sta);
 736void count_rx_stats(struct adapter *padapter, union recv_frame *prframe, struct sta_info *sta)
 737{
 738        int     sz;
 739        struct sta_info         *psta = NULL;
 740        struct stainfo_stats    *pstats = NULL;
 741        struct rx_pkt_attrib    *pattrib = &prframe->u.hdr.attrib;
 742        struct recv_priv        *precvpriv = &padapter->recvpriv;
 743
 744        sz = get_recvframe_len(prframe);
 745        precvpriv->rx_bytes += sz;
 746
 747        padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
 748
 749        if ((!MacAddr_isBcst(pattrib->dst)) && (!IS_MCAST(pattrib->dst))) {
 750                padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
 751        }
 752
 753        if (sta)
 754                psta = sta;
 755        else
 756                psta = prframe->u.hdr.psta;
 757
 758        if (psta) {
 759                pstats = &psta->sta_stats;
 760
 761                pstats->rx_data_pkts++;
 762                pstats->rx_bytes += sz;
 763        }
 764
 765        traffic_check_for_leave_lps(padapter, false, 0);
 766}
 767
 768sint sta2sta_data_frame(
 769        struct adapter *adapter,
 770        union recv_frame *precv_frame,
 771        struct sta_info **psta
 772);
 773sint sta2sta_data_frame(
 774        struct adapter *adapter,
 775        union recv_frame *precv_frame,
 776        struct sta_info **psta
 777)
 778{
 779        u8 *ptr = precv_frame->u.hdr.rx_data;
 780        sint ret = _SUCCESS;
 781        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 782        struct  sta_priv        *pstapriv = &adapter->stapriv;
 783        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
 784        u8 *mybssid  = get_bssid(pmlmepriv);
 785        u8 *myhwaddr = myid(&adapter->eeprompriv);
 786        u8 *sta_addr = NULL;
 787        sint bmcast = IS_MCAST(pattrib->dst);
 788
 789        /* DBG_871X("[%s] %d, seqnum:%d\n", __func__, __LINE__, pattrib->seq_num); */
 790
 791        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) ||
 792                (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true)) {
 793
 794                /*  filter packets that SA is myself or multicast or broadcast */
 795                if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
 796                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA ==myself\n"));
 797                        ret = _FAIL;
 798                        goto exit;
 799                }
 800
 801                if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN))  && (!bmcast)) {
 802                        ret = _FAIL;
 803                        goto exit;
 804                }
 805
 806                if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
 807                   !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
 808                   (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
 809                        ret = _FAIL;
 810                        goto exit;
 811                }
 812
 813                sta_addr = pattrib->src;
 814
 815        } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
 816                /*  For Station mode, sa and bssid should always be BSSID, and DA is my mac-address */
 817                if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN)) {
 818                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("bssid != TA under STATION_MODE; drop pkt\n"));
 819                        ret = _FAIL;
 820                        goto exit;
 821                }
 822
 823                sta_addr = pattrib->bssid;
 824        } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
 825                if (bmcast) {
 826                        /*  For AP mode, if DA == MCAST, then BSSID should be also MCAST */
 827                        if (!IS_MCAST(pattrib->bssid)) {
 828                                        ret = _FAIL;
 829                                        goto exit;
 830                        }
 831                } else { /*  not mc-frame */
 832                        /*  For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
 833                        if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {
 834                                ret = _FAIL;
 835                                goto exit;
 836                        }
 837
 838                        sta_addr = pattrib->src;
 839                }
 840
 841        } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) {
 842                memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
 843                memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
 844                memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
 845                memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
 846                memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
 847
 848                sta_addr = mybssid;
 849        } else
 850                ret  = _FAIL;
 851
 852
 853
 854        if (bmcast)
 855                *psta = rtw_get_bcmc_stainfo(adapter);
 856        else
 857                *psta = rtw_get_stainfo(pstapriv, sta_addr); /*  get ap_info */
 858
 859        if (!*psta) {
 860                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under sta2sta_data_frame ; drop pkt\n"));
 861                ret = _FAIL;
 862                goto exit;
 863        }
 864
 865exit:
 866        return ret;
 867}
 868
 869sint ap2sta_data_frame(
 870        struct adapter *adapter,
 871        union recv_frame *precv_frame,
 872        struct sta_info **psta);
 873sint ap2sta_data_frame(
 874        struct adapter *adapter,
 875        union recv_frame *precv_frame,
 876        struct sta_info **psta)
 877{
 878        u8 *ptr = precv_frame->u.hdr.rx_data;
 879        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
 880        sint ret = _SUCCESS;
 881        struct  sta_priv        *pstapriv = &adapter->stapriv;
 882        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
 883        u8 *mybssid  = get_bssid(pmlmepriv);
 884        u8 *myhwaddr = myid(&adapter->eeprompriv);
 885        sint bmcast = IS_MCAST(pattrib->dst);
 886
 887        if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true)
 888                && (check_fwstate(pmlmepriv, _FW_LINKED) == true
 889                        || check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
 890                ) {
 891
 892                /*  filter packets that SA is myself or multicast or broadcast */
 893                if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
 894                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" SA ==myself\n"));
 895                        #ifdef DBG_RX_DROP_FRAME
 896                        DBG_871X("DBG_RX_DROP_FRAME %s SA ="MAC_FMT", myhwaddr ="MAC_FMT"\n",
 897                                __func__, MAC_ARG(pattrib->src), MAC_ARG(myhwaddr));
 898                        #endif
 899                        ret = _FAIL;
 900                        goto exit;
 901                }
 902
 903                /*  da should be for me */
 904                if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
 905                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
 906                                (" ap2sta_data_frame:  compare DA fail; DA ="MAC_FMT"\n", MAC_ARG(pattrib->dst)));
 907                        #ifdef DBG_RX_DROP_FRAME
 908                        DBG_871X("DBG_RX_DROP_FRAME %s DA ="MAC_FMT"\n", __func__, MAC_ARG(pattrib->dst));
 909                        #endif
 910                        ret = _FAIL;
 911                        goto exit;
 912                }
 913
 914
 915                /*  check BSSID */
 916                if (!memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
 917                     !memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
 918                     (memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
 919                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_,
 920                                (" ap2sta_data_frame:  compare BSSID fail ; BSSID ="MAC_FMT"\n", MAC_ARG(pattrib->bssid)));
 921                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("mybssid ="MAC_FMT"\n", MAC_ARG(mybssid)));
 922                        #ifdef DBG_RX_DROP_FRAME
 923                        DBG_871X("DBG_RX_DROP_FRAME %s BSSID ="MAC_FMT", mybssid ="MAC_FMT"\n",
 924                                __func__, MAC_ARG(pattrib->bssid), MAC_ARG(mybssid));
 925                        DBG_871X("this adapter = %d, buddy adapter = %d\n", adapter->adapter_type, adapter->pbuddystruct adapter->adapter_type);
 926                        #endif
 927
 928                        if (!bmcast) {
 929                                DBG_871X("issue_deauth to the nonassociated ap =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));
 930                                issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
 931                        }
 932
 933                        ret = _FAIL;
 934                        goto exit;
 935                }
 936
 937                if (bmcast)
 938                        *psta = rtw_get_bcmc_stainfo(adapter);
 939                else
 940                        *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /*  get ap_info */
 941
 942                if (!*psta) {
 943                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("ap2sta: can't get psta under STATION_MODE ; drop pkt\n"));
 944                        #ifdef DBG_RX_DROP_FRAME
 945                        DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under STATION_MODE ; drop pkt\n", __func__);
 946                        #endif
 947                        ret = _FAIL;
 948                        goto exit;
 949                }
 950
 951                if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
 952                }
 953
 954                if (GetFrameSubType(ptr) & BIT(6)) {
 955                        /* No data, will not indicate to upper layer, temporily count it here */
 956                        count_rx_stats(adapter, precv_frame, *psta);
 957                        ret = RTW_RX_HANDLED;
 958                        goto exit;
 959                }
 960
 961        } else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true) &&
 962                     (check_fwstate(pmlmepriv, _FW_LINKED) == true)) {
 963                memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
 964                memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
 965                memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
 966                memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
 967                memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
 968
 969                /*  */
 970                memcpy(pattrib->bssid,  mybssid, ETH_ALEN);
 971
 972
 973                *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /*  get sta_info */
 974                if (!*psta) {
 975                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under MP_MODE ; drop pkt\n"));
 976                        #ifdef DBG_RX_DROP_FRAME
 977                        DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt\n", __func__);
 978                        #endif
 979                        ret = _FAIL;
 980                        goto exit;
 981                }
 982
 983
 984        } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
 985                /* Special case */
 986                ret = RTW_RX_HANDLED;
 987                goto exit;
 988        } else {
 989                if (!memcmp(myhwaddr, pattrib->dst, ETH_ALEN) && (!bmcast)) {
 990                        *psta = rtw_get_stainfo(pstapriv, pattrib->bssid); /*  get sta_info */
 991                        if (!*psta) {
 992
 993                                /* for AP multicast issue , modify by yiwei */
 994                                static unsigned long send_issue_deauth_time;
 995
 996                                /* DBG_871X("After send deauth , %u ms has elapsed.\n", jiffies_to_msecs(jiffies - send_issue_deauth_time)); */
 997
 998                                if (jiffies_to_msecs(jiffies - send_issue_deauth_time) > 10000 || send_issue_deauth_time == 0) {
 999                                        send_issue_deauth_time = jiffies;
1000
1001                                        DBG_871X("issue_deauth to the ap =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));
1002
1003                                        issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1004                                }
1005                        }
1006                }
1007
1008                ret = _FAIL;
1009                #ifdef DBG_RX_DROP_FRAME
1010                DBG_871X("DBG_RX_DROP_FRAME %s fw_state:0x%x\n", __func__, get_fwstate(pmlmepriv));
1011                #endif
1012        }
1013
1014exit:
1015        return ret;
1016}
1017
1018sint sta2ap_data_frame(
1019        struct adapter *adapter,
1020        union recv_frame *precv_frame,
1021        struct sta_info **psta);
1022sint sta2ap_data_frame(
1023        struct adapter *adapter,
1024        union recv_frame *precv_frame,
1025        struct sta_info **psta)
1026{
1027        u8 *ptr = precv_frame->u.hdr.rx_data;
1028        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
1029        struct  sta_priv        *pstapriv = &adapter->stapriv;
1030        struct  mlme_priv *pmlmepriv = &adapter->mlmepriv;
1031        unsigned char *mybssid  = get_bssid(pmlmepriv);
1032        sint ret = _SUCCESS;
1033
1034        if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true) {
1035                /* For AP mode, RA =BSSID, TX =STA(SRC_ADDR), A3 =DST_ADDR */
1036                if (memcmp(pattrib->bssid, mybssid, ETH_ALEN)) {
1037                        ret = _FAIL;
1038                        goto exit;
1039                }
1040
1041                *psta = rtw_get_stainfo(pstapriv, pattrib->src);
1042                if (!*psta) {
1043                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("can't get psta under AP_MODE; drop pkt\n"));
1044                        DBG_871X("issue_deauth to sta =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
1045
1046                        issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1047
1048                        ret = RTW_RX_HANDLED;
1049                        goto exit;
1050                }
1051
1052                process_pwrbit_data(adapter, precv_frame);
1053
1054                if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
1055                        process_wmmps_data(adapter, precv_frame);
1056                }
1057
1058                if (GetFrameSubType(ptr) & BIT(6)) {
1059                        /* No data, will not indicate to upper layer, temporily count it here */
1060                        count_rx_stats(adapter, precv_frame, *psta);
1061                        ret = RTW_RX_HANDLED;
1062                        goto exit;
1063                }
1064        } else {
1065                u8 *myhwaddr = myid(&adapter->eeprompriv);
1066                if (memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
1067                        ret = RTW_RX_HANDLED;
1068                        goto exit;
1069                }
1070                DBG_871X("issue_deauth to sta =" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
1071                issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
1072                ret = RTW_RX_HANDLED;
1073                goto exit;
1074        }
1075
1076exit:
1077        return ret;
1078}
1079
1080sint validate_recv_ctrl_frame(struct adapter *padapter, union recv_frame *precv_frame);
1081sint validate_recv_ctrl_frame(struct adapter *padapter, union recv_frame *precv_frame)
1082{
1083        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
1084        struct sta_priv *pstapriv = &padapter->stapriv;
1085        u8 *pframe = precv_frame->u.hdr.rx_data;
1086        struct sta_info *psta = NULL;
1087        /* uint len = precv_frame->u.hdr.len; */
1088
1089        /* DBG_871X("+validate_recv_ctrl_frame\n"); */
1090
1091        if (GetFrameType(pframe) != WIFI_CTRL_TYPE)
1092                return _FAIL;
1093
1094        /* receive the frames that ra(a1) is my address */
1095        if (memcmp(GetAddr1Ptr(pframe), myid(&padapter->eeprompriv), ETH_ALEN))
1096                return _FAIL;
1097
1098        psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
1099        if (!psta)
1100                return _FAIL;
1101
1102        /* for rx pkt statistics */
1103        psta->sta_stats.rx_ctrl_pkts++;
1104
1105        /* only handle ps-poll */
1106        if (GetFrameSubType(pframe) == WIFI_PSPOLL) {
1107                u16 aid;
1108                u8 wmmps_ac = 0;
1109
1110                aid = GetAid(pframe);
1111                if (psta->aid != aid)
1112                        return _FAIL;
1113
1114                switch (pattrib->priority) {
1115                case 1:
1116                case 2:
1117                        wmmps_ac = psta->uapsd_bk&BIT(0);
1118                        break;
1119                case 4:
1120                case 5:
1121                        wmmps_ac = psta->uapsd_vi&BIT(0);
1122                        break;
1123                case 6:
1124                case 7:
1125                        wmmps_ac = psta->uapsd_vo&BIT(0);
1126                        break;
1127                case 0:
1128                case 3:
1129                default:
1130                        wmmps_ac = psta->uapsd_be&BIT(0);
1131                        break;
1132                }
1133
1134                if (wmmps_ac)
1135                        return _FAIL;
1136
1137                if (psta->state & WIFI_STA_ALIVE_CHK_STATE) {
1138                        DBG_871X("%s alive check-rx ps-poll\n", __func__);
1139                        psta->expire_to = pstapriv->expire_to;
1140                        psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
1141                }
1142
1143                if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) {
1144                        struct list_head        *xmitframe_plist, *xmitframe_phead;
1145                        struct xmit_frame *pxmitframe = NULL;
1146                        struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
1147
1148                        /* spin_lock_bh(&psta->sleep_q.lock); */
1149                        spin_lock_bh(&pxmitpriv->lock);
1150
1151                        xmitframe_phead = get_list_head(&psta->sleep_q);
1152                        xmitframe_plist = get_next(xmitframe_phead);
1153
1154                        if (xmitframe_phead != xmitframe_plist) {
1155                                pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
1156
1157                                xmitframe_plist = get_next(xmitframe_plist);
1158
1159                                list_del_init(&pxmitframe->list);
1160
1161                                psta->sleepq_len--;
1162
1163                                if (psta->sleepq_len > 0)
1164                                        pxmitframe->attrib.mdata = 1;
1165                                else
1166                                        pxmitframe->attrib.mdata = 0;
1167
1168                                pxmitframe->attrib.triggered = 1;
1169
1170                                /* DBG_871X("handling ps-poll, q_len =%d, tim =%x\n", psta->sleepq_len, pstapriv->tim_bitmap); */
1171
1172                                rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
1173
1174                                if (psta->sleepq_len == 0) {
1175                                        pstapriv->tim_bitmap &= ~BIT(psta->aid);
1176
1177                                        /* DBG_871X("after handling ps-poll, tim =%x\n", pstapriv->tim_bitmap); */
1178
1179                                        /* update BCN for TIM IE */
1180                                        /* update_BCNTIM(padapter); */
1181                                        update_beacon(padapter, _TIM_IE_, NULL, true);
1182                                }
1183
1184                                /* spin_unlock_bh(&psta->sleep_q.lock); */
1185                                spin_unlock_bh(&pxmitpriv->lock);
1186
1187                        } else {
1188                                /* spin_unlock_bh(&psta->sleep_q.lock); */
1189                                spin_unlock_bh(&pxmitpriv->lock);
1190
1191                                /* DBG_871X("no buffered packets to xmit\n"); */
1192                                if (pstapriv->tim_bitmap&BIT(psta->aid)) {
1193                                        if (psta->sleepq_len == 0) {
1194                                                DBG_871X("no buffered packets to xmit\n");
1195
1196                                                /* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
1197                                                issue_nulldata_in_interrupt(padapter, psta->hwaddr);
1198                                        } else {
1199                                                DBG_871X("error!psta->sleepq_len =%d\n", psta->sleepq_len);
1200                                                psta->sleepq_len = 0;
1201                                        }
1202
1203                                        pstapriv->tim_bitmap &= ~BIT(psta->aid);
1204
1205                                        /* update BCN for TIM IE */
1206                                        /* update_BCNTIM(padapter); */
1207                                        update_beacon(padapter, _TIM_IE_, NULL, true);
1208                                }
1209                        }
1210                }
1211        }
1212
1213        return _FAIL;
1214
1215}
1216
1217union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame);
1218sint validate_recv_mgnt_frame(struct adapter *padapter, union recv_frame *precv_frame);
1219sint validate_recv_mgnt_frame(struct adapter *padapter, union recv_frame *precv_frame)
1220{
1221        /* struct mlme_priv *pmlmepriv = &adapter->mlmepriv; */
1222
1223        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n"));
1224
1225        precv_frame = recvframe_chk_defrag(padapter, precv_frame);
1226        if (!precv_frame) {
1227                RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("%s: fragment packet\n", __func__));
1228                return _SUCCESS;
1229        }
1230
1231        {
1232                /* for rx pkt statistics */
1233                struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->u.hdr.rx_data));
1234                if (psta) {
1235                        psta->sta_stats.rx_mgnt_pkts++;
1236                        if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_BEACON)
1237                                psta->sta_stats.rx_beacon_pkts++;
1238                        else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ)
1239                                psta->sta_stats.rx_probereq_pkts++;
1240                        else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) {
1241                                if (!memcmp(padapter->eeprompriv.mac_addr, GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN))
1242                                        psta->sta_stats.rx_probersp_pkts++;
1243                                else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data))
1244                                        || is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)))
1245                                        psta->sta_stats.rx_probersp_bm_pkts++;
1246                                else
1247                                        psta->sta_stats.rx_probersp_uo_pkts++;
1248                        }
1249                }
1250        }
1251
1252        mgt_dispatcher(padapter, precv_frame);
1253
1254        return _SUCCESS;
1255
1256}
1257
1258sint validate_recv_data_frame(struct adapter *adapter, union recv_frame *precv_frame);
1259sint validate_recv_data_frame(struct adapter *adapter, union recv_frame *precv_frame)
1260{
1261        u8 bretry;
1262        u8 *psa, *pda, *pbssid;
1263        struct sta_info *psta = NULL;
1264        u8 *ptr = precv_frame->u.hdr.rx_data;
1265        struct rx_pkt_attrib    *pattrib = &precv_frame->u.hdr.attrib;
1266        struct security_priv *psecuritypriv = &adapter->securitypriv;
1267        sint ret = _SUCCESS;
1268
1269        bretry = GetRetry(ptr);
1270        pda = get_da(ptr);
1271        psa = get_sa(ptr);
1272        pbssid = get_hdr_bssid(ptr);
1273
1274        if (!pbssid) {
1275                #ifdef DBG_RX_DROP_FRAME
1276                DBG_871X("DBG_RX_DROP_FRAME %s pbssid == NULL\n", __func__);
1277                #endif
1278                ret = _FAIL;
1279                goto exit;
1280        }
1281
1282        memcpy(pattrib->dst, pda, ETH_ALEN);
1283        memcpy(pattrib->src, psa, ETH_ALEN);
1284
1285        memcpy(pattrib->bssid, pbssid, ETH_ALEN);
1286
1287        switch (pattrib->to_fr_ds) {
1288        case 0:
1289                memcpy(pattrib->ra, pda, ETH_ALEN);
1290                memcpy(pattrib->ta, psa, ETH_ALEN);
1291                ret = sta2sta_data_frame(adapter, precv_frame, &psta);
1292                break;
1293
1294        case 1:
1295                memcpy(pattrib->ra, pda, ETH_ALEN);
1296                memcpy(pattrib->ta, pbssid, ETH_ALEN);
1297                ret = ap2sta_data_frame(adapter, precv_frame, &psta);
1298                break;
1299
1300        case 2:
1301                memcpy(pattrib->ra, pbssid, ETH_ALEN);
1302                memcpy(pattrib->ta, psa, ETH_ALEN);
1303                ret = sta2ap_data_frame(adapter, precv_frame, &psta);
1304                break;
1305
1306        case 3:
1307                memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
1308                memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
1309                ret = _FAIL;
1310                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" case 3\n"));
1311                break;
1312
1313        default:
1314                ret = _FAIL;
1315                break;
1316
1317        }
1318
1319        if (ret == _FAIL) {
1320                #ifdef DBG_RX_DROP_FRAME
1321                DBG_871X("DBG_RX_DROP_FRAME %s case:%d, res:%d\n", __func__, pattrib->to_fr_ds, ret);
1322                #endif
1323                goto exit;
1324        } else if (ret == RTW_RX_HANDLED) {
1325                goto exit;
1326        }
1327
1328
1329        if (!psta) {
1330                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, (" after to_fr_ds_chk; psta == NULL\n"));
1331                #ifdef DBG_RX_DROP_FRAME
1332                DBG_871X("DBG_RX_DROP_FRAME %s psta == NULL\n", __func__);
1333                #endif
1334                ret = _FAIL;
1335                goto exit;
1336        }
1337
1338        /* psta->rssi = prxcmd->rssi; */
1339        /* psta->signal_quality = prxcmd->sq; */
1340        precv_frame->u.hdr.psta = psta;
1341
1342
1343        pattrib->amsdu = 0;
1344        pattrib->ack_policy = 0;
1345        /* parsing QC field */
1346        if (pattrib->qos == 1) {
1347                pattrib->priority = GetPriority((ptr + 24));
1348                pattrib->ack_policy = GetAckpolicy((ptr + 24));
1349                pattrib->amsdu = GetAMsdu((ptr + 24));
1350                pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
1351
1352                if (pattrib->priority != 0 && pattrib->priority != 3)
1353                        adapter->recvpriv.bIsAnyNonBEPkts = true;
1354
1355        } else {
1356                pattrib->priority = 0;
1357                pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 30 : 24;
1358        }
1359
1360
1361        if (pattrib->order)/* HT-CTRL 11n */
1362                pattrib->hdrlen += 4;
1363
1364        precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
1365
1366        /*  decache, drop duplicate recv packets */
1367        if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL) {
1368                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decache : drop pkt\n"));
1369                #ifdef DBG_RX_DROP_FRAME
1370                DBG_871X("DBG_RX_DROP_FRAME %s recv_decache return _FAIL\n", __func__);
1371                #endif
1372                ret = _FAIL;
1373                goto exit;
1374        }
1375
1376        if (pattrib->privacy) {
1377
1378                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("validate_recv_data_frame:pattrib->privacy =%x\n", pattrib->privacy));
1379                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x)) =%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0], IS_MCAST(pattrib->ra)));
1380
1381                GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, IS_MCAST(pattrib->ra));
1382
1383                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n pattrib->encrypt =%d\n", pattrib->encrypt));
1384
1385                SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
1386        } else {
1387                pattrib->encrypt = 0;
1388                pattrib->iv_len = pattrib->icv_len = 0;
1389        }
1390
1391exit:
1392        return ret;
1393}
1394
1395static sint validate_80211w_mgmt(struct adapter *adapter, union recv_frame *precv_frame)
1396{
1397        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1398        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
1399        u8 *ptr = precv_frame->u.hdr.rx_data;
1400        u8 subtype;
1401
1402        subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */
1403
1404        /* only support station mode */
1405        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) && check_fwstate(pmlmepriv, _FW_LINKED)
1406                && adapter->securitypriv.binstallBIPkey == true) {
1407                /* unicast management frame decrypt */
1408                if (pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) &&
1409                        (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION)) {
1410                        u8 *mgmt_DATA;
1411                        u32 data_len = 0;
1412
1413                        pattrib->bdecrypted = 0;
1414                        pattrib->encrypt = _AES_;
1415                        pattrib->hdrlen = sizeof(struct ieee80211_hdr_3addr);
1416                        /* set iv and icv length */
1417                        SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
1418                        memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
1419                        memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
1420                        /* actual management data frame body */
1421                        data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
1422                        mgmt_DATA = rtw_zmalloc(data_len);
1423                        if (!mgmt_DATA) {
1424                                DBG_871X("%s mgmt allocate fail  !!!!!!!!!\n", __func__);
1425                                goto validate_80211w_fail;
1426                        }
1427                        precv_frame = decryptor(adapter, precv_frame);
1428                        /* save actual management data frame body */
1429                        memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len);
1430                        /* overwrite the iv field */
1431                        memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len);
1432                        /* remove the iv and icv length */
1433                        pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;
1434                        kfree(mgmt_DATA);
1435                        if (!precv_frame) {
1436                                DBG_871X("%s mgmt descrypt fail  !!!!!!!!!\n", __func__);
1437                                goto validate_80211w_fail;
1438                        }
1439                } else if (IS_MCAST(GetAddr1Ptr(ptr)) &&
1440                        (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) {
1441                        sint BIP_ret = _SUCCESS;
1442                        /* verify BIP MME IE of broadcast/multicast de-auth/disassoc packet */
1443                        BIP_ret = rtw_BIP_verify(adapter, (u8 *)precv_frame);
1444                        if (BIP_ret == _FAIL) {
1445                                /* DBG_871X("802.11w BIP verify fail\n"); */
1446                                goto validate_80211w_fail;
1447                        } else if (BIP_ret == RTW_RX_HANDLED) {
1448                                /* DBG_871X("802.11w recv none protected packet\n"); */
1449                                /* issue sa query request */
1450                                issue_action_SA_Query(adapter, NULL, 0, 0);
1451                                goto validate_80211w_fail;
1452                        }
1453                } else { /* 802.11w protect */
1454                        if (subtype == WIFI_ACTION) {
1455                                /* according 802.11-2012 standard, these five types are not robust types */
1456                                if (ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC          &&
1457                                        ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT              &&
1458                                        ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM &&
1459                                        ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED  &&
1460                                        ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P) {
1461                                        DBG_871X("action frame category =%d should robust\n", ptr[WLAN_HDR_A3_LEN]);
1462                                        goto validate_80211w_fail;
1463                                }
1464                        } else if (subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC) {
1465                                DBG_871X("802.11w recv none protected packet\n");
1466                                /* issue sa query request */
1467                                issue_action_SA_Query(adapter, NULL, 0, 0);
1468                                goto validate_80211w_fail;
1469                        }
1470                }
1471        }
1472        return _SUCCESS;
1473
1474validate_80211w_fail:
1475        return _FAIL;
1476
1477}
1478
1479static inline void dump_rx_packet(u8 *ptr)
1480{
1481        int i;
1482
1483        DBG_871X("#############################\n");
1484        for (i = 0; i < 64; i = i+8)
1485                DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
1486                *(ptr+i+1), *(ptr+i+2), *(ptr+i+3), *(ptr+i+4), *(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
1487        DBG_871X("#############################\n");
1488}
1489
1490sint validate_recv_frame(struct adapter *adapter, union recv_frame *precv_frame);
1491sint validate_recv_frame(struct adapter *adapter, union recv_frame *precv_frame)
1492{
1493        /* shall check frame subtype, to / from ds, da, bssid */
1494
1495        /* then call check if rx seq/frag. duplicated. */
1496
1497        u8 type;
1498        u8 subtype;
1499        sint retval = _SUCCESS;
1500        u8 bDumpRxPkt;
1501
1502        struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
1503
1504        u8 *ptr = precv_frame->u.hdr.rx_data;
1505        u8  ver = (unsigned char) (*ptr)&0x3;
1506
1507        /* add version chk */
1508        if (ver != 0) {
1509                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! (ver!= 0)\n"));
1510                retval = _FAIL;
1511                DBG_COUNTER(adapter->rx_logs.core_rx_pre_ver_err);
1512                goto exit;
1513        }
1514
1515        type =  GetFrameType(ptr);
1516        subtype = GetFrameSubType(ptr); /* bit(7)~bit(2) */
1517
1518        pattrib->to_fr_ds = get_tofr_ds(ptr);
1519
1520        pattrib->frag_num = GetFragNum(ptr);
1521        pattrib->seq_num = GetSequence(ptr);
1522
1523        pattrib->pw_save = GetPwrMgt(ptr);
1524        pattrib->mfrag = GetMFrag(ptr);
1525        pattrib->mdata = GetMData(ptr);
1526        pattrib->privacy = GetPrivacy(ptr);
1527        pattrib->order = GetOrder(ptr);
1528        rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
1529        if (bDumpRxPkt == 1) /* dump all rx packets */
1530                dump_rx_packet(ptr);
1531        else if ((bDumpRxPkt == 2) && (type == WIFI_MGT_TYPE))
1532                dump_rx_packet(ptr);
1533        else if ((bDumpRxPkt == 3) && (type == WIFI_DATA_TYPE))
1534                dump_rx_packet(ptr);
1535
1536        switch (type) {
1537        case WIFI_MGT_TYPE: /* mgnt */
1538                DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt);
1539                if (validate_80211w_mgmt(adapter, precv_frame) == _FAIL) {
1540                        retval = _FAIL;
1541                        DBG_COUNTER(padapter->rx_logs.core_rx_pre_mgmt_err_80211w);
1542                        break;
1543                }
1544
1545                retval = validate_recv_mgnt_frame(adapter, precv_frame);
1546                if (retval == _FAIL) {
1547                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_mgnt_frame fail\n"));
1548                        DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt_err);
1549                }
1550                retval = _FAIL; /*  only data frame return _SUCCESS */
1551                break;
1552        case WIFI_CTRL_TYPE: /* ctrl */
1553                DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl);
1554                retval = validate_recv_ctrl_frame(adapter, precv_frame);
1555                if (retval == _FAIL) {
1556                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_ctrl_frame fail\n"));
1557                        DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl_err);
1558                }
1559                retval = _FAIL; /*  only data frame return _SUCCESS */
1560                break;
1561        case WIFI_DATA_TYPE: /* data */
1562                DBG_COUNTER(adapter->rx_logs.core_rx_pre_data);
1563
1564                pattrib->qos = (subtype & BIT(7)) ? 1:0;
1565                retval = validate_recv_data_frame(adapter, precv_frame);
1566                if (retval == _FAIL) {
1567                        struct recv_priv *precvpriv = &adapter->recvpriv;
1568                        /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail\n")); */
1569                        precvpriv->rx_drop++;
1570                        DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_err);
1571                } else if (retval == _SUCCESS) {
1572#ifdef DBG_RX_DUMP_EAP
1573                        u8 bDumpRxPkt;
1574                        u16 eth_type;
1575
1576                        /*  dump eapol */
1577                        rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
1578                        /*  get ether_type */
1579                        memcpy(&eth_type, ptr + pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_SIZE, 2);
1580                        eth_type = ntohs((unsigned short) eth_type);
1581                        if ((bDumpRxPkt == 4) && (eth_type == 0x888e))
1582                                dump_rx_packet(ptr);
1583#endif
1584                } else
1585                        DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_handled);
1586                break;
1587        default:
1588                DBG_COUNTER(adapter->rx_logs.core_rx_pre_unknown);
1589                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("validate_recv_data_frame fail! type = 0x%x\n", type));
1590                #ifdef DBG_RX_DROP_FRAME
1591                DBG_871X("DBG_RX_DROP_FRAME validate_recv_data_frame fail! type = 0x%x\n", type);
1592                #endif
1593                retval = _FAIL;
1594                break;
1595        }
1596
1597exit:
1598        return retval;
1599}
1600
1601
1602/* remove the wlanhdr and add the eth_hdr */
1603sint wlanhdr_to_ethhdr(union recv_frame *precvframe);
1604sint wlanhdr_to_ethhdr(union recv_frame *precvframe)
1605{
1606        sint    rmv_len;
1607        u16 eth_type, len;
1608        u8 bsnaphdr;
1609        u8 *psnap_type;
1610        struct ieee80211_snap_hdr       *psnap;
1611        __be16 be_tmp;
1612        struct adapter                  *adapter = precvframe->u.hdr.adapter;
1613        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1614        u8 *ptr = get_recvframe_data(precvframe) ; /*  point to frame_ctrl field */
1615        struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
1616
1617        if (pattrib->encrypt) {
1618                recvframe_pull_tail(precvframe, pattrib->icv_len);
1619        }
1620
1621        psnap = (struct ieee80211_snap_hdr      *)(ptr+pattrib->hdrlen + pattrib->iv_len);
1622        psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
1623        /* convert hdr + possible LLC headers into Ethernet header */
1624        /* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */
1625        if ((!memcmp(psnap, rfc1042_header, SNAP_SIZE) &&
1626                (memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2)) &&
1627                (memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
1628                /* eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) || */
1629                 !memcmp(psnap, bridge_tunnel_header, SNAP_SIZE)) {
1630                /* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
1631                bsnaphdr = true;
1632        } else
1633                /* Leave Ethernet header part of hdr and full payload */
1634                bsnaphdr = false;
1635
1636        rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr?SNAP_SIZE:0);
1637        len = precvframe->u.hdr.len - rmv_len;
1638
1639        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("\n ===pattrib->hdrlen: %x,  pattrib->iv_len:%x ===\n\n", pattrib->hdrlen,  pattrib->iv_len));
1640
1641        memcpy(&be_tmp, ptr+rmv_len, 2);
1642        eth_type = ntohs(be_tmp); /* pattrib->ether_type */
1643        pattrib->eth_type = eth_type;
1644
1645#ifdef CONFIG_AUTO_AP_MODE
1646        if (0x8899 == pattrib->eth_type) {
1647                struct sta_info *psta = precvframe->u.hdr.psta;
1648
1649                DBG_871X("wlan rx: got eth_type = 0x%x\n", pattrib->eth_type);
1650
1651                if (psta && psta->isrc && psta->pid > 0) {
1652                        u16 rx_pid;
1653
1654                        rx_pid = *(u16 *)(ptr+rmv_len+2);
1655
1656                        DBG_871X("wlan rx(pid = 0x%x): sta("MAC_FMT") pid = 0x%x\n",
1657                                rx_pid, MAC_ARG(psta->hwaddr), psta->pid);
1658
1659                        if (rx_pid == psta->pid) {
1660                                int i;
1661                                u16 len = *(u16 *)(ptr+rmv_len+4);
1662                                /* u16 ctrl_type = *(u16*)(ptr+rmv_len+6); */
1663
1664                                /* DBG_871X("RC: len = 0x%x, ctrl_type = 0x%x\n", len, ctrl_type); */
1665                                DBG_871X("RC: len = 0x%x\n", len);
1666
1667                                for (i = 0; i < len ; i++)
1668                                        DBG_871X("0x%x\n", *(ptr+rmv_len+6+i));
1669                                        /* DBG_871X("0x%x\n", *(ptr+rmv_len+8+i)); */
1670
1671                                DBG_871X("RC-end\n");
1672                        }
1673                }
1674        }
1675#endif /* CONFIG_AUTO_AP_MODE */
1676
1677        if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
1678                ptr += rmv_len;
1679                *ptr = 0x87;
1680                *(ptr+1) = 0x12;
1681
1682                eth_type = 0x8712;
1683                /*  append rx status for mp test packets */
1684                ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24);
1685                memcpy(ptr, get_rxmem(precvframe), 24);
1686                ptr += 24;
1687        } else
1688                ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr) + (bsnaphdr?2:0)));
1689
1690        memcpy(ptr, pattrib->dst, ETH_ALEN);
1691        memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
1692
1693        if (!bsnaphdr) {
1694                be_tmp = htons(len);
1695                memcpy(ptr+12, &be_tmp, 2);
1696        }
1697
1698        return _SUCCESS;
1699}
1700
1701/* perform defrag */
1702static union recv_frame *recvframe_defrag(struct adapter *adapter,
1703                                          struct __queue *defrag_q)
1704{
1705        struct list_head         *plist, *phead;
1706        u8  wlanhdr_offset;
1707        u8 curfragnum;
1708        struct recv_frame_hdr *pfhdr, *pnfhdr;
1709        union recv_frame *prframe, *pnextrframe;
1710        struct __queue  *pfree_recv_queue;
1711
1712        curfragnum = 0;
1713        pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
1714
1715        phead = get_list_head(defrag_q);
1716        plist = get_next(phead);
1717        prframe = (union recv_frame *)plist;
1718        pfhdr = &prframe->u.hdr;
1719        list_del_init(&(prframe->u.list));
1720
1721        if (curfragnum != pfhdr->attrib.frag_num) {
1722                /* the first fragment number must be 0 */
1723                /* free the whole queue */
1724                rtw_free_recvframe(prframe, pfree_recv_queue);
1725                rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
1726
1727                return NULL;
1728        }
1729
1730        curfragnum++;
1731
1732        plist = get_list_head(defrag_q);
1733
1734        plist = get_next(plist);
1735
1736        while (phead != plist) {
1737                pnextrframe = (union recv_frame *)plist;
1738                pnfhdr = &pnextrframe->u.hdr;
1739
1740
1741                /* check the fragment sequence  (2nd ~n fragment frame) */
1742
1743                if (curfragnum != pnfhdr->attrib.frag_num) {
1744                        /* the fragment number must be increasing  (after decache) */
1745                        /* release the defrag_q & prframe */
1746                        rtw_free_recvframe(prframe, pfree_recv_queue);
1747                        rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
1748                        return NULL;
1749                }
1750
1751                curfragnum++;
1752
1753                /* copy the 2nd~n fragment frame's payload to the first fragment */
1754                /* get the 2nd~last fragment frame's payload */
1755
1756                wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
1757
1758                recvframe_pull(pnextrframe, wlanhdr_offset);
1759
1760                /* append  to first fragment frame's tail (if privacy frame, pull the ICV) */
1761                recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
1762
1763                /* memcpy */
1764                memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
1765
1766                recvframe_put(prframe, pnfhdr->len);
1767
1768                pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
1769                plist = get_next(plist);
1770
1771        }
1772
1773        /* free the defrag_q queue and return the prframe */
1774        rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
1775
1776        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Performance defrag!!!!!\n"));
1777
1778        return prframe;
1779}
1780
1781/* check if need to defrag, if needed queue the frame to defrag_q */
1782union recv_frame *recvframe_chk_defrag(struct adapter *padapter, union recv_frame *precv_frame)
1783{
1784        u8 ismfrag;
1785        u8 fragnum;
1786        u8 *psta_addr;
1787        struct recv_frame_hdr *pfhdr;
1788        struct sta_info *psta;
1789        struct sta_priv *pstapriv;
1790        struct list_head *phead;
1791        union recv_frame *prtnframe = NULL;
1792        struct __queue *pfree_recv_queue, *pdefrag_q;
1793
1794        pstapriv = &padapter->stapriv;
1795
1796        pfhdr = &precv_frame->u.hdr;
1797
1798        pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
1799
1800        /* need to define struct of wlan header frame ctrl */
1801        ismfrag = pfhdr->attrib.mfrag;
1802        fragnum = pfhdr->attrib.frag_num;
1803
1804        psta_addr = pfhdr->attrib.ta;
1805        psta = rtw_get_stainfo(pstapriv, psta_addr);
1806        if (!psta) {
1807                u8 type = GetFrameType(pfhdr->rx_data);
1808                if (type != WIFI_DATA_TYPE) {
1809                        psta = rtw_get_bcmc_stainfo(padapter);
1810                        pdefrag_q = &psta->sta_recvpriv.defrag_q;
1811                } else
1812                        pdefrag_q = NULL;
1813        } else
1814                pdefrag_q = &psta->sta_recvpriv.defrag_q;
1815
1816        if ((ismfrag == 0) && (fragnum == 0))
1817                prtnframe = precv_frame;/* isn't a fragment frame */
1818
1819        if (ismfrag == 1) {
1820                /* 0~(n-1) fragment frame */
1821                /* enqueue to defraf_g */
1822                if (pdefrag_q) {
1823                        if (fragnum == 0)
1824                                /* the first fragment */
1825                                if (!list_empty(&pdefrag_q->queue))
1826                                        /* free current defrag_q */
1827                                        rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
1828
1829
1830                        /* Then enqueue the 0~(n-1) fragment into the defrag_q */
1831
1832                        /* spin_lock(&pdefrag_q->lock); */
1833                        phead = get_list_head(pdefrag_q);
1834                        list_add_tail(&pfhdr->list, phead);
1835                        /* spin_unlock(&pdefrag_q->lock); */
1836
1837                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("Enqueuq: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
1838
1839                        prtnframe = NULL;
1840
1841                } else {
1842                        /* can't find this ta's defrag_queue, so free this recv_frame */
1843                        rtw_free_recvframe(precv_frame, pfree_recv_queue);
1844                        prtnframe = NULL;
1845                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
1846                }
1847
1848        }
1849
1850        if ((ismfrag == 0) && (fragnum != 0)) {
1851                /* the last fragment frame */
1852                /* enqueue the last fragment */
1853                if (pdefrag_q) {
1854                        /* spin_lock(&pdefrag_q->lock); */
1855                        phead = get_list_head(pdefrag_q);
1856                        list_add_tail(&pfhdr->list, phead);
1857                        /* spin_unlock(&pdefrag_q->lock); */
1858
1859                        /* call recvframe_defrag to defrag */
1860                        RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("defrag: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
1861                        precv_frame = recvframe_defrag(padapter, pdefrag_q);
1862                        prtnframe = precv_frame;
1863
1864                } else {
1865                        /* can't find this ta's defrag_queue, so free this recv_frame */
1866                        rtw_free_recvframe(precv_frame, pfree_recv_queue);
1867                        prtnframe = NULL;
1868                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("Free because pdefrag_q == NULL: ismfrag = %d, fragnum = %d\n", ismfrag, fragnum));
1869                }
1870
1871        }
1872
1873
1874        if ((prtnframe) && (prtnframe->u.hdr.attrib.privacy)) {
1875                /* after defrag we must check tkip mic code */
1876                if (recvframe_chkmic(padapter,  prtnframe) == _FAIL) {
1877                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chkmic(padapter,  prtnframe) == _FAIL\n"));
1878                        rtw_free_recvframe(prtnframe, pfree_recv_queue);
1879                        prtnframe = NULL;
1880                }
1881        }
1882        return prtnframe;
1883}
1884
1885static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
1886{
1887        int     a_len, padding_len;
1888        u16 nSubframe_Length;
1889        u8 nr_subframes, i;
1890        u8 *pdata;
1891        _pkt *sub_pkt, *subframes[MAX_SUBFRAME_COUNT];
1892        struct recv_priv *precvpriv = &padapter->recvpriv;
1893        struct __queue *pfree_recv_queue = &(precvpriv->free_recv_queue);
1894
1895        nr_subframes = 0;
1896
1897        recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
1898
1899        if (prframe->u.hdr.attrib.iv_len > 0)
1900                recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
1901
1902        a_len = prframe->u.hdr.len;
1903
1904        pdata = prframe->u.hdr.rx_data;
1905
1906        while (a_len > ETH_HLEN) {
1907
1908                /* Offset 12 denote 2 mac address */
1909                nSubframe_Length = RTW_GET_BE16(pdata + 12);
1910
1911                if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
1912                        DBG_871X("nRemain_Length is %d and nSubframe_Length is : %d\n", a_len, nSubframe_Length);
1913                        break;
1914                }
1915
1916                sub_pkt = rtw_os_alloc_msdu_pkt(prframe, nSubframe_Length, pdata);
1917                if (!sub_pkt) {
1918                        DBG_871X("%s(): allocate sub packet fail !!!\n", __func__);
1919                        break;
1920                }
1921
1922                /* move the data point to data content */
1923                pdata += ETH_HLEN;
1924                a_len -= ETH_HLEN;
1925
1926                subframes[nr_subframes++] = sub_pkt;
1927
1928                if (nr_subframes >= MAX_SUBFRAME_COUNT) {
1929                        DBG_871X("ParseSubframe(): Too many Subframes! Packets dropped!\n");
1930                        break;
1931                }
1932
1933                pdata += nSubframe_Length;
1934                a_len -= nSubframe_Length;
1935                if (a_len != 0) {
1936                        padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1));
1937                        if (padding_len == 4) {
1938                                padding_len = 0;
1939                        }
1940
1941                        if (a_len < padding_len) {
1942                                DBG_871X("ParseSubframe(): a_len < padding_len !\n");
1943                                break;
1944                        }
1945                        pdata += padding_len;
1946                        a_len -= padding_len;
1947                }
1948        }
1949
1950        for (i = 0; i < nr_subframes; i++) {
1951                sub_pkt = subframes[i];
1952
1953                /* Indicate the packets to upper layer */
1954                if (sub_pkt) {
1955                        rtw_os_recv_indicate_pkt(padapter, sub_pkt, &prframe->u.hdr.attrib);
1956                }
1957        }
1958
1959        prframe->u.hdr.len = 0;
1960        rtw_free_recvframe(prframe, pfree_recv_queue);/* free this recv_frame */
1961
1962        return  _SUCCESS;
1963}
1964
1965int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
1966int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
1967{
1968        struct adapter *padapter = preorder_ctrl->padapter;
1969        struct dvobj_priv *psdpriv = padapter->dvobj;
1970        struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
1971        u8 wsize = preorder_ctrl->wsize_b;
1972        u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) & 0xFFF;/*  4096; */
1973
1974        /*  Rx Reorder initialize condition. */
1975        if (preorder_ctrl->indicate_seq == 0xFFFF) {
1976                preorder_ctrl->indicate_seq = seq_num;
1977                #ifdef DBG_RX_SEQ
1978                DBG_871X("DBG_RX_SEQ %s:%d init IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
1979                        preorder_ctrl->indicate_seq, seq_num);
1980                #endif
1981
1982                /* DbgPrint("check_indicate_seq, 1st->indicate_seq =%d\n", precvpriv->indicate_seq); */
1983        }
1984
1985        /* DbgPrint("enter->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
1986
1987        /*  Drop out the packet which SeqNum is smaller than WinStart */
1988        if (SN_LESS(seq_num, preorder_ctrl->indicate_seq)) {
1989                /* RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum)); */
1990                /* DbgPrint("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
1991
1992                #ifdef DBG_RX_DROP_FRAME
1993                DBG_871X("%s IndicateSeq: %d > NewSeq: %d\n", __func__,
1994                        preorder_ctrl->indicate_seq, seq_num);
1995                #endif
1996
1997
1998                return false;
1999        }
2000
2001        /*  */
2002        /*  Sliding window manipulation. Conditions includes: */
2003        /*  1. Incoming SeqNum is equal to WinStart =>Window shift 1 */
2004        /*  2. Incoming SeqNum is larger than the WinEnd => Window shift N */
2005        /*  */
2006        if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq)) {
2007                preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
2008
2009                #ifdef DBG_RX_SEQ
2010                DBG_871X("DBG_RX_SEQ %s:%d SN_EQUAL IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2011                        preorder_ctrl->indicate_seq, seq_num);
2012                #endif
2013        } else if (SN_LESS(wend, seq_num)) {
2014                /* RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum)); */
2015                /* DbgPrint("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
2016
2017                /*  boundary situation, when seq_num cross 0xFFF */
2018                if (seq_num >= (wsize - 1))
2019                        preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
2020                else
2021                        preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
2022                pdbgpriv->dbg_rx_ampdu_window_shift_cnt++;
2023                #ifdef DBG_RX_SEQ
2024                DBG_871X("DBG_RX_SEQ %s:%d SN_LESS(wend, seq_num) IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2025                        preorder_ctrl->indicate_seq, seq_num);
2026                #endif
2027        }
2028
2029        /* DbgPrint("exit->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num); */
2030
2031        return true;
2032}
2033
2034int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe);
2035int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe)
2036{
2037        struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
2038        struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2039        struct list_head        *phead, *plist;
2040        union recv_frame *pnextrframe;
2041        struct rx_pkt_attrib *pnextattrib;
2042
2043        /* DbgPrint("+enqueue_reorder_recvframe()\n"); */
2044
2045        /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */
2046        /* spin_lock(&ppending_recvframe_queue->lock); */
2047
2048
2049        phead = get_list_head(ppending_recvframe_queue);
2050        plist = get_next(phead);
2051
2052        while (phead != plist) {
2053                pnextrframe = (union recv_frame *)plist;
2054                pnextattrib = &pnextrframe->u.hdr.attrib;
2055
2056                if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
2057                        plist = get_next(plist);
2058                else if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
2059                        /* Duplicate entry is found!! Do not insert current entry. */
2060                        /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
2061                        /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
2062                        return false;
2063                else
2064                        break;
2065
2066                /* DbgPrint("enqueue_reorder_recvframe():while\n"); */
2067
2068        }
2069
2070
2071        /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */
2072        /* spin_lock(&ppending_recvframe_queue->lock); */
2073
2074        list_del_init(&(prframe->u.hdr.list));
2075
2076        list_add_tail(&(prframe->u.hdr.list), plist);
2077
2078        /* spin_unlock(&ppending_recvframe_queue->lock); */
2079        /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
2080
2081
2082        /* RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum)); */
2083        return true;
2084
2085}
2086
2087void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq);
2088void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq)
2089{
2090        if (current_seq < prev_seq)
2091                pdbgpriv->dbg_rx_ampdu_loss_count += (4096 + current_seq - prev_seq);
2092        else
2093                pdbgpriv->dbg_rx_ampdu_loss_count += (current_seq - prev_seq);
2094
2095}
2096int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced);
2097int recv_indicatepkts_in_order(struct adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced)
2098{
2099        struct list_head        *phead, *plist;
2100        union recv_frame *prframe;
2101        struct rx_pkt_attrib *pattrib;
2102        /* u8 index = 0; */
2103        int bPktInBuf = false;
2104        struct recv_priv *precvpriv = &padapter->recvpriv;
2105        struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2106        struct dvobj_priv *psdpriv = padapter->dvobj;
2107        struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
2108
2109        DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_in_oder);
2110
2111        /* DbgPrint("+recv_indicatepkts_in_order\n"); */
2112
2113        /* spin_lock_irqsave(&ppending_recvframe_queue->lock, irql); */
2114        /* spin_lock(&ppending_recvframe_queue->lock); */
2115
2116        phead =         get_list_head(ppending_recvframe_queue);
2117        plist = get_next(phead);
2118
2119        /*  Handling some condition for forced indicate case. */
2120        if (bforced == true) {
2121                pdbgpriv->dbg_rx_ampdu_forced_indicate_count++;
2122                if (list_empty(phead)) {
2123                        /*  spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
2124                        /* spin_unlock(&ppending_recvframe_queue->lock); */
2125                        return true;
2126                }
2127
2128                prframe = (union recv_frame *)plist;
2129                pattrib = &prframe->u.hdr.attrib;
2130
2131                #ifdef DBG_RX_SEQ
2132                DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2133                        preorder_ctrl->indicate_seq, pattrib->seq_num);
2134                #endif
2135                recv_indicatepkts_pkt_loss_cnt(pdbgpriv, preorder_ctrl->indicate_seq, pattrib->seq_num);
2136                preorder_ctrl->indicate_seq = pattrib->seq_num;
2137
2138        }
2139
2140        /*  Prepare indication list and indication. */
2141        /*  Check if there is any packet need indicate. */
2142        while (!list_empty(phead)) {
2143
2144                prframe = (union recv_frame *)plist;
2145                pattrib = &prframe->u.hdr.attrib;
2146
2147                if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
2148                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2149                                 ("recv_indicatepkts_in_order: indicate =%d seq =%d amsdu =%d\n",
2150                                  preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
2151
2152                        plist = get_next(plist);
2153                        list_del_init(&(prframe->u.hdr.list));
2154
2155                        if (SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
2156                                preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
2157                                #ifdef DBG_RX_SEQ
2158                                DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2159                                        preorder_ctrl->indicate_seq, pattrib->seq_num);
2160                                #endif
2161                        }
2162
2163                        /* Set this as a lock to make sure that only one thread is indicating packet. */
2164                        /* pTS->RxIndicateState = RXTS_INDICATE_PROCESSING; */
2165
2166                        /*  Indicate packets */
2167                        /* RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!!\n")); */
2168
2169
2170                        /* indicate this recv_frame */
2171                        /* DbgPrint("recv_indicatepkts_in_order, indicate_seq =%d, seq_num =%d\n", precvpriv->indicate_seq, pattrib->seq_num); */
2172                        if (!pattrib->amsdu) {
2173                                /* DBG_871X("recv_indicatepkts_in_order, amsdu!= 1, indicate_seq =%d, seq_num =%d\n", preorder_ctrl->indicate_seq, pattrib->seq_num); */
2174
2175                                if ((padapter->bDriverStopped == false) &&
2176                                    (padapter->bSurpriseRemoved == false))
2177                                        rtw_recv_indicatepkt(padapter, prframe);/* indicate this recv_frame */
2178
2179                        } else if (pattrib->amsdu == 1) {
2180                                if (amsdu_to_msdu(padapter, prframe) != _SUCCESS)
2181                                        rtw_free_recvframe(prframe, &precvpriv->free_recv_queue);
2182
2183                        } else {
2184                                /* error condition; */
2185                        }
2186
2187
2188                        /* Update local variables. */
2189                        bPktInBuf = false;
2190
2191                } else {
2192                        bPktInBuf = true;
2193                        break;
2194                }
2195
2196                /* DbgPrint("recv_indicatepkts_in_order():while\n"); */
2197
2198        }
2199
2200        /* spin_unlock(&ppending_recvframe_queue->lock); */
2201        /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
2202
2203        return bPktInBuf;
2204}
2205
2206int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *prframe);
2207int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *prframe)
2208{
2209        int retval = _SUCCESS;
2210        struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
2211        struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
2212        struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2213        struct dvobj_priv *psdpriv = padapter->dvobj;
2214        struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
2215
2216        DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_reoder);
2217
2218        if (!pattrib->amsdu) {
2219                /* s1. */
2220                wlanhdr_to_ethhdr(prframe);
2221
2222                if (pattrib->qos != 1) {
2223                        if ((padapter->bDriverStopped == false) &&
2224                            (padapter->bSurpriseRemoved == false)) {
2225                                RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@  recv_indicatepkt_reorder -recv_func recv_indicatepkt\n"));
2226
2227                                rtw_recv_indicatepkt(padapter, prframe);
2228                                return _SUCCESS;
2229
2230                        }
2231
2232                        #ifdef DBG_RX_DROP_FRAME
2233                        DBG_871X("DBG_RX_DROP_FRAME %s pattrib->qos != 1\n", __func__);
2234                        #endif
2235
2236                        return _FAIL;
2237
2238                }
2239
2240                if (preorder_ctrl->enable == false) {
2241                        /* indicate this recv_frame */
2242                        preorder_ctrl->indicate_seq = pattrib->seq_num;
2243                        #ifdef DBG_RX_SEQ
2244                        DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2245                                preorder_ctrl->indicate_seq, pattrib->seq_num);
2246                        #endif
2247
2248                        rtw_recv_indicatepkt(padapter, prframe);
2249
2250                        preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
2251                        #ifdef DBG_RX_SEQ
2252                        DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2253                                preorder_ctrl->indicate_seq, pattrib->seq_num);
2254                        #endif
2255
2256                        return _SUCCESS;
2257                }
2258        } else if (pattrib->amsdu == 1) { /* temp filter -> means didn't support A-MSDUs in a A-MPDU */
2259                if (preorder_ctrl->enable == false) {
2260                        preorder_ctrl->indicate_seq = pattrib->seq_num;
2261                        #ifdef DBG_RX_SEQ
2262                        DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2263                                preorder_ctrl->indicate_seq, pattrib->seq_num);
2264                        #endif
2265
2266                        retval = amsdu_to_msdu(padapter, prframe);
2267
2268                        preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
2269                        #ifdef DBG_RX_SEQ
2270                        DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __func__, __LINE__,
2271                                preorder_ctrl->indicate_seq, pattrib->seq_num);
2272                        #endif
2273
2274                        if (retval != _SUCCESS) {
2275                                #ifdef DBG_RX_DROP_FRAME
2276                                DBG_871X("DBG_RX_DROP_FRAME %s amsdu_to_msdu fail\n", __func__);
2277                                #endif
2278                        }
2279
2280                        return retval;
2281                }
2282        }
2283
2284        spin_lock_bh(&ppending_recvframe_queue->lock);
2285
2286        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
2287                 ("recv_indicatepkt_reorder: indicate =%d seq =%d\n",
2288                  preorder_ctrl->indicate_seq, pattrib->seq_num));
2289
2290        /* s2. check if winstart_b(indicate_seq) needs to been updated */
2291        if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num)) {
2292                pdbgpriv->dbg_rx_ampdu_drop_count++;
2293                #ifdef DBG_RX_DROP_FRAME
2294                DBG_871X("DBG_RX_DROP_FRAME %s check_indicate_seq fail\n", __func__);
2295                #endif
2296                goto _err_exit;
2297        }
2298
2299
2300        /* s3. Insert all packet into Reorder Queue to maintain its ordering. */
2301        if (!enqueue_reorder_recvframe(preorder_ctrl, prframe)) {
2302                /* DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n"); */
2303                /* spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql); */
2304                /* return _FAIL; */
2305                #ifdef DBG_RX_DROP_FRAME
2306                DBG_871X("DBG_RX_DROP_FRAME %s enqueue_reorder_recvframe fail\n", __func__);
2307                #endif
2308                goto _err_exit;
2309        }
2310
2311
2312        /* s4. */
2313        /*  Indication process. */
2314        /*  After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets */
2315        /*  with the SeqNum smaller than latest WinStart and buffer other packets. */
2316        /*  */
2317        /*  For Rx Reorder condition: */
2318        /*  1. All packets with SeqNum smaller than WinStart => Indicate */
2319        /*  2. All packets with SeqNum larger than or equal to WinStart => Buffer it. */
2320        /*  */
2321
2322        /* recv_indicatepkts_in_order(padapter, preorder_ctrl, true); */
2323        if (recv_indicatepkts_in_order(padapter, preorder_ctrl, false) == true) {
2324                _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
2325                spin_unlock_bh(&ppending_recvframe_queue->lock);
2326        } else {
2327                spin_unlock_bh(&ppending_recvframe_queue->lock);
2328                del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
2329        }
2330
2331        return _SUCCESS;
2332
2333_err_exit:
2334        spin_unlock_bh(&ppending_recvframe_queue->lock);
2335
2336        return _FAIL;
2337}
2338
2339
2340void rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
2341{
2342        struct recv_reorder_ctrl *preorder_ctrl =
2343                from_timer(preorder_ctrl, t, reordering_ctrl_timer);
2344        struct adapter *padapter = preorder_ctrl->padapter;
2345        struct __queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
2346
2347
2348        if (padapter->bDriverStopped || padapter->bSurpriseRemoved)
2349                return;
2350
2351        /* DBG_871X("+rtw_reordering_ctrl_timeout_handler() =>\n"); */
2352
2353        spin_lock_bh(&ppending_recvframe_queue->lock);
2354
2355        if (recv_indicatepkts_in_order(padapter, preorder_ctrl, true) == true)
2356                _set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
2357
2358        spin_unlock_bh(&ppending_recvframe_queue->lock);
2359
2360}
2361
2362int process_recv_indicatepkts(struct adapter *padapter, union recv_frame *prframe);
2363int process_recv_indicatepkts(struct adapter *padapter, union recv_frame *prframe)
2364{
2365        int retval = _SUCCESS;
2366        /* struct recv_priv *precvpriv = &padapter->recvpriv; */
2367        /* struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib; */
2368        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2369        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
2370
2371        DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate);
2372
2373        if (phtpriv->ht_option == true) { /* B/G/N Mode */
2374                /* prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority]; */
2375
2376                if (recv_indicatepkt_reorder(padapter, prframe) != _SUCCESS) { /*  including perform A-MPDU Rx Ordering Buffer Control */
2377                        #ifdef DBG_RX_DROP_FRAME
2378                        DBG_871X("DBG_RX_DROP_FRAME %s recv_indicatepkt_reorder error!\n", __func__);
2379                        #endif
2380
2381                        if ((padapter->bDriverStopped == false) &&
2382                            (padapter->bSurpriseRemoved == false)) {
2383                                retval = _FAIL;
2384                                return retval;
2385                        }
2386                }
2387        } else { /* B/G mode */
2388                retval = wlanhdr_to_ethhdr(prframe);
2389                if (retval != _SUCCESS) {
2390                        RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("wlanhdr_to_ethhdr: drop pkt\n"));
2391                        #ifdef DBG_RX_DROP_FRAME
2392                        DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr error!\n", __func__);
2393                        #endif
2394                        return retval;
2395                }
2396
2397                if ((padapter->bDriverStopped == false) && (padapter->bSurpriseRemoved == false)) {
2398                        /* indicate this recv_frame */
2399                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n"));
2400                        rtw_recv_indicatepkt(padapter, prframe);
2401
2402
2403                } else {
2404                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n"));
2405
2406                        RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
2407                        retval = _FAIL;
2408                        return retval;
2409                }
2410
2411        }
2412
2413        return retval;
2414
2415}
2416
2417static int recv_func_prehandle(struct adapter *padapter, union recv_frame *rframe)
2418{
2419        int ret = _SUCCESS;
2420        struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
2421
2422        DBG_COUNTER(padapter->rx_logs.core_rx_pre);
2423
2424        /* check the frame crtl field and decache */
2425        ret = validate_recv_frame(padapter, rframe);
2426        if (ret != _SUCCESS) {
2427                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
2428                rtw_free_recvframe(rframe, pfree_recv_queue);/* free this recv_frame */
2429                goto exit;
2430        }
2431
2432exit:
2433        return ret;
2434}
2435
2436static int recv_func_posthandle(struct adapter *padapter, union recv_frame *prframe)
2437{
2438        int ret = _SUCCESS;
2439        union recv_frame *orig_prframe = prframe;
2440        struct recv_priv *precvpriv = &padapter->recvpriv;
2441        struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
2442
2443        DBG_COUNTER(padapter->rx_logs.core_rx_post);
2444
2445        prframe = decryptor(padapter, prframe);
2446        if (!prframe) {
2447                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("decryptor: drop pkt\n"));
2448                #ifdef DBG_RX_DROP_FRAME
2449                DBG_871X("DBG_RX_DROP_FRAME %s decryptor: drop pkt\n", __func__);
2450                #endif
2451                ret = _FAIL;
2452                DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_err);
2453                goto _recv_data_drop;
2454        }
2455
2456        prframe = recvframe_chk_defrag(padapter, prframe);
2457        if (!prframe)   {
2458                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recvframe_chk_defrag: drop pkt\n"));
2459                #ifdef DBG_RX_DROP_FRAME
2460                DBG_871X("DBG_RX_DROP_FRAME %s recvframe_chk_defrag: drop pkt\n", __func__);
2461                #endif
2462                DBG_COUNTER(padapter->rx_logs.core_rx_post_defrag_err);
2463                goto _recv_data_drop;
2464        }
2465
2466        prframe = portctrl(padapter, prframe);
2467        if (!prframe) {
2468                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("portctrl: drop pkt\n"));
2469                #ifdef DBG_RX_DROP_FRAME
2470                DBG_871X("DBG_RX_DROP_FRAME %s portctrl: drop pkt\n", __func__);
2471                #endif
2472                ret = _FAIL;
2473                DBG_COUNTER(padapter->rx_logs.core_rx_post_portctrl_err);
2474                goto _recv_data_drop;
2475        }
2476
2477        count_rx_stats(padapter, prframe, NULL);
2478
2479        ret = process_recv_indicatepkts(padapter, prframe);
2480        if (ret != _SUCCESS) {
2481                RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("recv_func: process_recv_indicatepkts fail!\n"));
2482                #ifdef DBG_RX_DROP_FRAME
2483                DBG_871X("DBG_RX_DROP_FRAME %s process_recv_indicatepkts fail!\n", __func__);
2484                #endif
2485                rtw_free_recvframe(orig_prframe, pfree_recv_queue);/* free this recv_frame */
2486                DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_err);
2487                goto _recv_data_drop;
2488        }
2489
2490_recv_data_drop:
2491        precvpriv->rx_drop++;
2492        return ret;
2493}
2494
2495
2496int recv_func(struct adapter *padapter, union recv_frame *rframe);
2497int recv_func(struct adapter *padapter, union recv_frame *rframe)
2498{
2499        int ret;
2500        struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib;
2501        struct recv_priv *recvpriv = &padapter->recvpriv;
2502        struct security_priv *psecuritypriv = &padapter->securitypriv;
2503        struct mlme_priv *mlmepriv = &padapter->mlmepriv;
2504
2505        /* check if need to handle uc_swdec_pending_queue*/
2506        if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey) {
2507                union recv_frame *pending_frame;
2508                int cnt = 0;
2509
2510                while ((pending_frame = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {
2511                        cnt++;
2512                        DBG_COUNTER(padapter->rx_logs.core_rx_dequeue);
2513                        recv_func_posthandle(padapter, pending_frame);
2514                }
2515
2516                if (cnt)
2517                        DBG_871X(FUNC_ADPT_FMT" dequeue %d from uc_swdec_pending_queue\n",
2518                                FUNC_ADPT_ARG(padapter), cnt);
2519        }
2520
2521        DBG_COUNTER(padapter->rx_logs.core_rx);
2522        ret = recv_func_prehandle(padapter, rframe);
2523
2524        if (ret == _SUCCESS) {
2525
2526                /* check if need to enqueue into uc_swdec_pending_queue*/
2527                if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
2528                        !IS_MCAST(prxattrib->ra) && prxattrib->encrypt > 0 &&
2529                        (prxattrib->bdecrypted == 0 || psecuritypriv->sw_decrypt == true) &&
2530                        psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK &&
2531                        !psecuritypriv->busetkipkey) {
2532                        DBG_COUNTER(padapter->rx_logs.core_rx_enqueue);
2533                        rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
2534                        /* DBG_871X("%s: no key, enqueue uc_swdec_pending_queue\n", __func__); */
2535
2536                        if (recvpriv->free_recvframe_cnt < NR_RECVFRAME/4) {
2537                                /* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt  */
2538                                rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
2539                                if (rframe)
2540                                        goto do_posthandle;
2541                        }
2542                        goto exit;
2543                }
2544
2545do_posthandle:
2546                ret = recv_func_posthandle(padapter, rframe);
2547        }
2548
2549exit:
2550        return ret;
2551}
2552
2553
2554s32 rtw_recv_entry(union recv_frame *precvframe)
2555{
2556        struct adapter *padapter;
2557        struct recv_priv *precvpriv;
2558        s32 ret = _SUCCESS;
2559
2560/*      RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+rtw_recv_entry\n")); */
2561
2562        padapter = precvframe->u.hdr.adapter;
2563
2564        precvpriv = &padapter->recvpriv;
2565
2566        ret = recv_func(padapter, precvframe);
2567        if (ret == _FAIL) {
2568                RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("rtw_recv_entry: recv_func return fail!!!\n"));
2569                goto _recv_entry_drop;
2570        }
2571
2572
2573        precvpriv->rx_pkts++;
2574
2575        return ret;
2576
2577_recv_entry_drop:
2578
2579        /* RT_TRACE(_module_rtl871x_recv_c_, _drv_err_, ("_recv_entry_drop\n")); */
2580
2581        return ret;
2582}
2583
2584static void rtw_signal_stat_timer_hdl(struct timer_list *t)
2585{
2586        struct adapter *adapter =
2587                from_timer(adapter, t, recvpriv.signal_stat_timer);
2588        struct recv_priv *recvpriv = &adapter->recvpriv;
2589
2590        u32 tmp_s, tmp_q;
2591        u8 avg_signal_strength = 0;
2592        u8 avg_signal_qual = 0;
2593        u32 num_signal_strength = 0;
2594        u32 num_signal_qual = 0;
2595        u8 _alpha = 5; /*  this value is based on converging_constant = 5000 and sampling_interval = 1000 */
2596
2597        if (adapter->recvpriv.is_signal_dbg) {
2598                /* update the user specific value, signal_strength_dbg, to signal_strength, rssi */
2599                adapter->recvpriv.signal_strength = adapter->recvpriv.signal_strength_dbg;
2600                adapter->recvpriv.rssi = (s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);
2601        } else {
2602
2603                if (recvpriv->signal_strength_data.update_req == 0) {/*  update_req is clear, means we got rx */
2604                        avg_signal_strength = recvpriv->signal_strength_data.avg_val;
2605                        num_signal_strength = recvpriv->signal_strength_data.total_num;
2606                        /*  after avg_vals are acquired, we can re-stat the signal values */
2607                        recvpriv->signal_strength_data.update_req = 1;
2608                }
2609
2610                if (recvpriv->signal_qual_data.update_req == 0) {/*  update_req is clear, means we got rx */
2611                        avg_signal_qual = recvpriv->signal_qual_data.avg_val;
2612                        num_signal_qual = recvpriv->signal_qual_data.total_num;
2613                        /*  after avg_vals are acquired, we can re-stat the signal values */
2614                        recvpriv->signal_qual_data.update_req = 1;
2615                }
2616
2617                if (num_signal_strength == 0) {
2618                        if (rtw_get_on_cur_ch_time(adapter) == 0
2619                                || jiffies_to_msecs(jiffies - rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval
2620                        ) {
2621                                goto set_timer;
2622                        }
2623                }
2624
2625                if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == true
2626                        || check_fwstate(&adapter->mlmepriv, _FW_LINKED) == false
2627                ) {
2628                        goto set_timer;
2629                }
2630
2631                /* update value of signal_strength, rssi, signal_qual */
2632                tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength);
2633                if (tmp_s % _alpha)
2634                        tmp_s = tmp_s/_alpha + 1;
2635                else
2636                        tmp_s = tmp_s/_alpha;
2637                if (tmp_s > 100)
2638                        tmp_s = 100;
2639
2640                tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual);
2641                if (tmp_q % _alpha)
2642                        tmp_q = tmp_q/_alpha + 1;
2643                else
2644                        tmp_q = tmp_q/_alpha;
2645                if (tmp_q > 100)
2646                        tmp_q = 100;
2647
2648                recvpriv->signal_strength = tmp_s;
2649                recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
2650                recvpriv->signal_qual = tmp_q;
2651
2652                #if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
2653                DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"
2654                        ", num_signal_strength:%u, num_signal_qual:%u"
2655                        ", on_cur_ch_ms:%d"
2656                        "\n"
2657                        , FUNC_ADPT_ARG(adapter)
2658                        , recvpriv->signal_strength
2659                        , recvpriv->rssi
2660                        , recvpriv->signal_qual
2661                        , num_signal_strength, num_signal_qual
2662                        , rtw_get_on_cur_ch_time(adapter) ? jiffies_to_msecs(jiffies - rtw_get_on_cur_ch_time(adapter)) : 0
2663                );
2664                #endif
2665        }
2666
2667set_timer:
2668        rtw_set_signal_stat_timer(recvpriv);
2669
2670}
2671