linux/drivers/staging/rtl8723au/core/rtw_sta_mgt.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   4 *
   5 * This program is free software; you can redistribute it and/or modify it
   6 * under the terms of version 2 of the GNU General Public License as
   7 * published by the Free Software Foundation.
   8 *
   9 * This program is distributed in the hope that it will be useful, but WITHOUT
  10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  12 * more details.
  13 *
  14 ******************************************************************************/
  15#define _RTW_STA_MGT_C_
  16
  17#include <osdep_service.h>
  18#include <drv_types.h>
  19#include <recv_osdep.h>
  20#include <xmit_osdep.h>
  21#include <mlme_osdep.h>
  22#include <sta_info.h>
  23#include <rtl8723a_hal.h>
  24
  25static const u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
  26
  27static void _rtw_init_stainfo(struct sta_info *psta)
  28{
  29        memset((u8 *)psta, 0, sizeof(struct sta_info));
  30        spin_lock_init(&psta->lock);
  31        INIT_LIST_HEAD(&psta->list);
  32        INIT_LIST_HEAD(&psta->hash_list);
  33        _rtw_init_queue23a(&psta->sleep_q);
  34        psta->sleepq_len = 0;
  35        _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv);
  36        _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv);
  37#ifdef CONFIG_8723AU_AP_MODE
  38        INIT_LIST_HEAD(&psta->asoc_list);
  39        INIT_LIST_HEAD(&psta->auth_list);
  40        psta->expire_to = 0;
  41        psta->flags = 0;
  42        psta->capability = 0;
  43        psta->bpairwise_key_installed = false;
  44        psta->nonerp_set = 0;
  45        psta->no_short_slot_time_set = 0;
  46        psta->no_short_preamble_set = 0;
  47        psta->no_ht_gf_set = 0;
  48        psta->no_ht_set = 0;
  49        psta->ht_20mhz_set = 0;
  50        psta->keep_alive_trycnt = 0;
  51#endif  /*  CONFIG_8723AU_AP_MODE */
  52}
  53
  54int _rtw_init_sta_priv23a(struct sta_priv *pstapriv)
  55{
  56        int i;
  57
  58        spin_lock_init(&pstapriv->sta_hash_lock);
  59        pstapriv->asoc_sta_count = 0;
  60        for (i = 0; i < NUM_STA; i++)
  61                INIT_LIST_HEAD(&pstapriv->sta_hash[i]);
  62
  63#ifdef CONFIG_8723AU_AP_MODE
  64        pstapriv->sta_dz_bitmap = 0;
  65        pstapriv->tim_bitmap = 0;
  66        INIT_LIST_HEAD(&pstapriv->asoc_list);
  67        INIT_LIST_HEAD(&pstapriv->auth_list);
  68        spin_lock_init(&pstapriv->asoc_list_lock);
  69        spin_lock_init(&pstapriv->auth_list_lock);
  70        pstapriv->asoc_list_cnt = 0;
  71        pstapriv->auth_list_cnt = 0;
  72        pstapriv->auth_to = 3; /*  3*2 = 6 sec */
  73        pstapriv->assoc_to = 3;
  74        /* pstapriv->expire_to = 900;  900*2 = 1800 sec = 30 min,
  75            expire after no any traffic. */
  76        /* pstapriv->expire_to = 30;  30*2 = 60 sec = 1 min,
  77            expire after no any traffic. */
  78        pstapriv->expire_to = 3; /*  3*2 = 6 sec */
  79        pstapriv->max_num_sta = NUM_STA;
  80#endif
  81        return _SUCCESS;
  82}
  83
  84int _rtw_free_sta_priv23a(struct sta_priv *pstapriv)
  85{
  86        struct list_head *phead, *plist, *ptmp;
  87        struct sta_info *psta;
  88        struct recv_reorder_ctrl *preorder_ctrl;
  89        int index;
  90
  91        if (pstapriv) {
  92                /*      delete all reordering_ctrl_timer                */
  93                spin_lock_bh(&pstapriv->sta_hash_lock);
  94                for (index = 0; index < NUM_STA; index++) {
  95                        phead = &pstapriv->sta_hash[index];
  96
  97                        list_for_each_safe(plist, ptmp, phead) {
  98                                int i;
  99
 100                                psta = container_of(plist, struct sta_info,
 101                                                    hash_list);
 102                                for (i = 0; i < 16 ; i++) {
 103                                        preorder_ctrl = &psta->recvreorder_ctrl[i];
 104                                        del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
 105                                }
 106                        }
 107                }
 108                spin_unlock_bh(&pstapriv->sta_hash_lock);
 109                /*===============================*/
 110        }
 111        return _SUCCESS;
 112}
 113
 114struct sta_info *
 115rtw_alloc_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr, gfp_t gfp)
 116{
 117        struct list_head        *phash_list;
 118        struct sta_info *psta;
 119        struct recv_reorder_ctrl *preorder_ctrl;
 120        s32     index;
 121        int i = 0;
 122        u16  wRxSeqInitialValue = 0xffff;
 123
 124        psta = kmalloc(sizeof(struct sta_info), gfp);
 125        if (!psta)
 126                return NULL;
 127
 128        spin_lock_bh(&pstapriv->sta_hash_lock);
 129
 130        _rtw_init_stainfo(psta);
 131
 132        psta->padapter = pstapriv->padapter;
 133
 134        ether_addr_copy(psta->hwaddr, hwaddr);
 135
 136        index = wifi_mac_hash(hwaddr);
 137
 138        RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
 139                 "rtw_alloc_stainfo23a: index  = %x\n", index);
 140        if (index >= NUM_STA) {
 141                RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
 142                         "ERROR => rtw_alloc_stainfo23a: index >= NUM_STA\n");
 143                psta = NULL;
 144                goto exit;
 145        }
 146        phash_list = &pstapriv->sta_hash[index];
 147
 148        list_add_tail(&psta->hash_list, phash_list);
 149
 150        pstapriv->asoc_sta_count++;
 151
 152/*  For the SMC router, the sequence number of first packet of WPS
 153     handshake will be 0. */
 154/*  In this case, this packet will be dropped by recv_decache function
 155    if we use the 0x00 as the default value for tid_rxseq variable. */
 156/*  So, we initialize the tid_rxseq variable as the 0xffff. */
 157
 158        for (i = 0; i < 16; i++)
 159                memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
 160                        &wRxSeqInitialValue, 2);
 161
 162        RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_,
 163                 "alloc number_%d stainfo  with hwaddr = %pM\n",
 164                 pstapriv->asoc_sta_count, hwaddr);
 165
 166        init_addba_retry_timer23a(psta);
 167
 168        /* for A-MPDU Rx reordering buffer control */
 169        for (i = 0; i < 16; i++) {
 170                preorder_ctrl = &psta->recvreorder_ctrl[i];
 171
 172                preorder_ctrl->padapter = pstapriv->padapter;
 173
 174                preorder_ctrl->enable = false;
 175
 176                preorder_ctrl->indicate_seq = 0xffff;
 177                preorder_ctrl->wend_b = 0xffff;
 178                /* preorder_ctrl->wsize_b = (NR_RECVBUFF-2); */
 179                preorder_ctrl->wsize_b = 64;/* 64; */
 180
 181                _rtw_init_queue23a(&preorder_ctrl->pending_recvframe_queue);
 182
 183                rtw_init_recv_timer23a(preorder_ctrl);
 184        }
 185        /* init for DM */
 186        psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
 187        psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
 188
 189        /* init for the sequence number of received management frame */
 190        psta->RxMgmtFrameSeqNum = 0xffff;
 191exit:
 192        spin_unlock_bh(&pstapriv->sta_hash_lock);
 193        return psta;
 194}
 195
 196/*  using pstapriv->sta_hash_lock to protect */
 197int rtw_free_stainfo23a(struct rtw_adapter *padapter, struct sta_info *psta)
 198{
 199        struct recv_reorder_ctrl *preorder_ctrl;
 200        struct  sta_xmit_priv   *pstaxmitpriv;
 201        struct  xmit_priv       *pxmitpriv = &padapter->xmitpriv;
 202        struct  sta_priv *pstapriv = &padapter->stapriv;
 203        struct hw_xmit *phwxmit;
 204        int i;
 205
 206        if (psta == NULL)
 207                goto exit;
 208
 209        spin_lock_bh(&psta->lock);
 210        psta->state &= ~_FW_LINKED;
 211        spin_unlock_bh(&psta->lock);
 212
 213        pstaxmitpriv = &psta->sta_xmitpriv;
 214
 215        spin_lock_bh(&pxmitpriv->lock);
 216
 217        rtw_free_xmitframe_queue23a(pxmitpriv, &psta->sleep_q);
 218        psta->sleepq_len = 0;
 219
 220        /* vo */
 221        rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
 222        list_del_init(&pstaxmitpriv->vo_q.tx_pending);
 223        phwxmit = pxmitpriv->hwxmits;
 224        phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
 225        pstaxmitpriv->vo_q.qcnt = 0;
 226
 227        /* vi */
 228        rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
 229        list_del_init(&pstaxmitpriv->vi_q.tx_pending);
 230        phwxmit = pxmitpriv->hwxmits+1;
 231        phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
 232        pstaxmitpriv->vi_q.qcnt = 0;
 233
 234        /* be */
 235        rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
 236        list_del_init(&pstaxmitpriv->be_q.tx_pending);
 237        phwxmit = pxmitpriv->hwxmits+2;
 238        phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
 239        pstaxmitpriv->be_q.qcnt = 0;
 240
 241        /* bk */
 242        rtw_free_xmitframe_queue23a(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
 243        list_del_init(&pstaxmitpriv->bk_q.tx_pending);
 244        phwxmit = pxmitpriv->hwxmits+3;
 245        phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
 246        pstaxmitpriv->bk_q.qcnt = 0;
 247
 248        spin_unlock_bh(&pxmitpriv->lock);
 249
 250        list_del_init(&psta->hash_list);
 251        RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
 252                 "free number_%d stainfo  with hwaddr = %pM\n",
 253                 pstapriv->asoc_sta_count, psta->hwaddr);
 254        pstapriv->asoc_sta_count--;
 255
 256        /*  re-init sta_info; 20061114  will be init in alloc_stainfo */
 257        /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */
 258        /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */
 259
 260        del_timer_sync(&psta->addba_retry_timer);
 261
 262        /* for A-MPDU Rx reordering buffer control,
 263           cancel reordering_ctrl_timer */
 264        for (i = 0; i < 16; i++) {
 265                struct list_head        *phead, *plist;
 266                struct recv_frame *prframe;
 267                struct rtw_queue *ppending_recvframe_queue;
 268
 269                preorder_ctrl = &psta->recvreorder_ctrl[i];
 270
 271                del_timer_sync(&preorder_ctrl->reordering_ctrl_timer);
 272
 273                ppending_recvframe_queue =
 274                        &preorder_ctrl->pending_recvframe_queue;
 275
 276                spin_lock_bh(&ppending_recvframe_queue->lock);
 277                phead =         get_list_head(ppending_recvframe_queue);
 278                plist = phead->next;
 279
 280                while (!list_empty(phead)) {
 281                        prframe = container_of(plist, struct recv_frame, list);
 282                        plist = plist->next;
 283                        list_del_init(&prframe->list);
 284                        rtw_free_recvframe23a(prframe);
 285                }
 286                spin_unlock_bh(&ppending_recvframe_queue->lock);
 287        }
 288        if (!(psta->state & WIFI_AP_STATE))
 289                rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, false);
 290#ifdef CONFIG_8723AU_AP_MODE
 291        spin_lock_bh(&pstapriv->auth_list_lock);
 292        if (!list_empty(&psta->auth_list)) {
 293                list_del_init(&psta->auth_list);
 294                pstapriv->auth_list_cnt--;
 295        }
 296        spin_unlock_bh(&pstapriv->auth_list_lock);
 297
 298        psta->expire_to = 0;
 299
 300        psta->sleepq_ac_len = 0;
 301        psta->qos_info = 0;
 302
 303        psta->max_sp_len = 0;
 304        psta->uapsd_bk = 0;
 305        psta->uapsd_be = 0;
 306        psta->uapsd_vi = 0;
 307        psta->uapsd_vo = 0;
 308
 309        psta->has_legacy_ac = 0;
 310
 311        pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid);
 312        pstapriv->tim_bitmap &= ~CHKBIT(psta->aid);
 313
 314        if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) {
 315                pstapriv->sta_aid[psta->aid - 1] = NULL;
 316                psta->aid = 0;
 317        }
 318#endif  /*  CONFIG_8723AU_AP_MODE */
 319
 320        kfree(psta);
 321exit:
 322        return _SUCCESS;
 323}
 324
 325/*  free all stainfo which in sta_hash[all] */
 326void rtw_free_all_stainfo23a(struct rtw_adapter *padapter)
 327{
 328        struct list_head *plist, *phead, *ptmp;
 329        struct sta_info *psta;
 330        struct sta_priv *pstapriv = &padapter->stapriv;
 331        struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter);
 332        s32 index;
 333
 334        if (pstapriv->asoc_sta_count == 1)
 335                return;
 336
 337        spin_lock_bh(&pstapriv->sta_hash_lock);
 338
 339        for (index = 0; index < NUM_STA; index++) {
 340                phead = &pstapriv->sta_hash[index];
 341
 342                list_for_each_safe(plist, ptmp, phead) {
 343                        psta = container_of(plist, struct sta_info, hash_list);
 344
 345                        if (pbcmc_stainfo != psta)
 346                                rtw_free_stainfo23a(padapter, psta);
 347                }
 348        }
 349        spin_unlock_bh(&pstapriv->sta_hash_lock);
 350}
 351
 352/* any station allocated can be searched by hash list */
 353struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr)
 354{
 355        struct list_head *plist, *phead;
 356        struct sta_info *psta = NULL;
 357        u32     index;
 358        const u8 *addr;
 359
 360        if (hwaddr == NULL)
 361                return NULL;
 362
 363        if (is_multicast_ether_addr(hwaddr))
 364                addr = bc_addr;
 365        else
 366                addr = hwaddr;
 367
 368        index = wifi_mac_hash(addr);
 369
 370        spin_lock_bh(&pstapriv->sta_hash_lock);
 371
 372        phead = &pstapriv->sta_hash[index];
 373
 374        list_for_each(plist, phead) {
 375                psta = container_of(plist, struct sta_info, hash_list);
 376
 377                /*  if found the matched address */
 378                if (ether_addr_equal(psta->hwaddr, addr))
 379                        break;
 380
 381                psta = NULL;
 382        }
 383        spin_unlock_bh(&pstapriv->sta_hash_lock);
 384        return psta;
 385}
 386
 387int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter)
 388{
 389        struct  sta_priv *pstapriv = &padapter->stapriv;
 390        struct sta_info         *psta;
 391        struct tx_servq *ptxservq;
 392        int res = _SUCCESS;
 393
 394        psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL);
 395        if (psta == NULL) {
 396                res = _FAIL;
 397                RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_,
 398                         "rtw_alloc_stainfo23a fail\n");
 399                return res;
 400        }
 401        /*  default broadcast & multicast use macid 1 */
 402        psta->mac_id = 1;
 403
 404        ptxservq = &psta->sta_xmitpriv.be_q;
 405        return _SUCCESS;
 406}
 407
 408struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter)
 409{
 410        struct sta_info         *psta;
 411        struct sta_priv         *pstapriv = &padapter->stapriv;
 412
 413        psta = rtw_get_stainfo23a(pstapriv, bc_addr);
 414        return psta;
 415}
 416
 417bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr)
 418{
 419        bool res = true;
 420#ifdef CONFIG_8723AU_AP_MODE
 421        struct list_head *plist, *phead;
 422        struct rtw_wlan_acl_node *paclnode;
 423        bool match = false;
 424        struct sta_priv *pstapriv = &padapter->stapriv;
 425        struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
 426        struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q;
 427
 428        spin_lock_bh(&pacl_node_q->lock);
 429        phead = get_list_head(pacl_node_q);
 430
 431        list_for_each(plist, phead) {
 432                paclnode = container_of(plist, struct rtw_wlan_acl_node, list);
 433
 434                if (ether_addr_equal(paclnode->addr, mac_addr)) {
 435                        if (paclnode->valid) {
 436                                match = true;
 437                                break;
 438                        }
 439                }
 440        }
 441        spin_unlock_bh(&pacl_node_q->lock);
 442
 443        if (pacl_list->mode == 1)/* accept unless in deny list */
 444                res = (match) ?  false : true;
 445        else if (pacl_list->mode == 2)/* deny unless in accept list */
 446                res = (match) ?  true : false;
 447        else
 448                 res = true;
 449#endif
 450        return res;
 451}
 452