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", index)); 140 if (index >= NUM_STA) { 141 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, 142 ("ERROR => rtw_alloc_stainfo23a: index >= NUM_STA")); 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 ("\n free number_%d stainfo with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", 253 pstapriv->asoc_sta_count, psta->hwaddr[0], 254 psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], 255 psta->hwaddr[4], psta->hwaddr[5])); 256 pstapriv->asoc_sta_count--; 257 258 /* re-init sta_info; 20061114 will be init in alloc_stainfo */ 259 /* _rtw_init_sta_xmit_priv23a(&psta->sta_xmitpriv); */ 260 /* _rtw_init_sta_recv_priv23a(&psta->sta_recvpriv); */ 261 262 del_timer_sync(&psta->addba_retry_timer); 263 264 /* for A-MPDU Rx reordering buffer control, 265 cancel reordering_ctrl_timer */ 266 for (i = 0; i < 16; i++) { 267 struct list_head *phead, *plist; 268 struct recv_frame *prframe; 269 struct rtw_queue *ppending_recvframe_queue; 270 271 preorder_ctrl = &psta->recvreorder_ctrl[i]; 272 273 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); 274 275 ppending_recvframe_queue = 276 &preorder_ctrl->pending_recvframe_queue; 277 278 spin_lock_bh(&ppending_recvframe_queue->lock); 279 phead = get_list_head(ppending_recvframe_queue); 280 plist = phead->next; 281 282 while (!list_empty(phead)) { 283 prframe = container_of(plist, struct recv_frame, list); 284 plist = plist->next; 285 list_del_init(&prframe->list); 286 rtw_free_recvframe23a(prframe); 287 } 288 spin_unlock_bh(&ppending_recvframe_queue->lock); 289 } 290 if (!(psta->state & WIFI_AP_STATE)) 291 rtl8723a_SetHalODMVar(padapter, HAL_ODM_STA_INFO, psta, false); 292#ifdef CONFIG_8723AU_AP_MODE 293 spin_lock_bh(&pstapriv->auth_list_lock); 294 if (!list_empty(&psta->auth_list)) { 295 list_del_init(&psta->auth_list); 296 pstapriv->auth_list_cnt--; 297 } 298 spin_unlock_bh(&pstapriv->auth_list_lock); 299 300 psta->expire_to = 0; 301 302 psta->sleepq_ac_len = 0; 303 psta->qos_info = 0; 304 305 psta->max_sp_len = 0; 306 psta->uapsd_bk = 0; 307 psta->uapsd_be = 0; 308 psta->uapsd_vi = 0; 309 psta->uapsd_vo = 0; 310 311 psta->has_legacy_ac = 0; 312 313 pstapriv->sta_dz_bitmap &= ~CHKBIT(psta->aid); 314 pstapriv->tim_bitmap &= ~CHKBIT(psta->aid); 315 316 if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { 317 pstapriv->sta_aid[psta->aid - 1] = NULL; 318 psta->aid = 0; 319 } 320#endif /* CONFIG_8723AU_AP_MODE */ 321 322 kfree(psta); 323exit: 324 return _SUCCESS; 325} 326 327/* free all stainfo which in sta_hash[all] */ 328void rtw_free_all_stainfo23a(struct rtw_adapter *padapter) 329{ 330 struct list_head *plist, *phead, *ptmp; 331 struct sta_info *psta; 332 struct sta_priv *pstapriv = &padapter->stapriv; 333 struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo23a(padapter); 334 s32 index; 335 336 if (pstapriv->asoc_sta_count == 1) 337 return; 338 339 spin_lock_bh(&pstapriv->sta_hash_lock); 340 341 for (index = 0; index < NUM_STA; index++) { 342 phead = &pstapriv->sta_hash[index]; 343 344 list_for_each_safe(plist, ptmp, phead) { 345 psta = container_of(plist, struct sta_info, hash_list); 346 347 if (pbcmc_stainfo != psta) 348 rtw_free_stainfo23a(padapter, psta); 349 } 350 } 351 spin_unlock_bh(&pstapriv->sta_hash_lock); 352} 353 354/* any station allocated can be searched by hash list */ 355struct sta_info *rtw_get_stainfo23a(struct sta_priv *pstapriv, const u8 *hwaddr) 356{ 357 struct list_head *plist, *phead; 358 struct sta_info *psta = NULL; 359 u32 index; 360 const u8 *addr; 361 362 if (hwaddr == NULL) 363 return NULL; 364 365 if (is_multicast_ether_addr(hwaddr)) 366 addr = bc_addr; 367 else 368 addr = hwaddr; 369 370 index = wifi_mac_hash(addr); 371 372 spin_lock_bh(&pstapriv->sta_hash_lock); 373 374 phead = &pstapriv->sta_hash[index]; 375 376 list_for_each(plist, phead) { 377 psta = container_of(plist, struct sta_info, hash_list); 378 379 /* if found the matched address */ 380 if (ether_addr_equal(psta->hwaddr, addr)) 381 break; 382 383 psta = NULL; 384 } 385 spin_unlock_bh(&pstapriv->sta_hash_lock); 386 return psta; 387} 388 389int rtw_init_bcmc_stainfo23a(struct rtw_adapter *padapter) 390{ 391 struct sta_priv *pstapriv = &padapter->stapriv; 392 struct sta_info *psta; 393 struct tx_servq *ptxservq; 394 int res = _SUCCESS; 395 396 psta = rtw_alloc_stainfo23a(pstapriv, bc_addr, GFP_KERNEL); 397 if (psta == NULL) { 398 res = _FAIL; 399 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, 400 ("rtw_alloc_stainfo23a fail")); 401 return res; 402 } 403 /* default broadcast & multicast use macid 1 */ 404 psta->mac_id = 1; 405 406 ptxservq = &psta->sta_xmitpriv.be_q; 407 return _SUCCESS; 408} 409 410struct sta_info *rtw_get_bcmc_stainfo23a(struct rtw_adapter *padapter) 411{ 412 struct sta_info *psta; 413 struct sta_priv *pstapriv = &padapter->stapriv; 414 415 psta = rtw_get_stainfo23a(pstapriv, bc_addr); 416 return psta; 417} 418 419bool rtw_access_ctrl23a(struct rtw_adapter *padapter, u8 *mac_addr) 420{ 421 bool res = true; 422#ifdef CONFIG_8723AU_AP_MODE 423 struct list_head *plist, *phead; 424 struct rtw_wlan_acl_node *paclnode; 425 bool match = false; 426 struct sta_priv *pstapriv = &padapter->stapriv; 427 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; 428 struct rtw_queue *pacl_node_q = &pacl_list->acl_node_q; 429 430 spin_lock_bh(&pacl_node_q->lock); 431 phead = get_list_head(pacl_node_q); 432 433 list_for_each(plist, phead) { 434 paclnode = container_of(plist, struct rtw_wlan_acl_node, list); 435 436 if (ether_addr_equal(paclnode->addr, mac_addr)) { 437 if (paclnode->valid) { 438 match = true; 439 break; 440 } 441 } 442 } 443 spin_unlock_bh(&pacl_node_q->lock); 444 445 if (pacl_list->mode == 1)/* accept unless in deny list */ 446 res = (match) ? false : true; 447 else if (pacl_list->mode == 2)/* deny unless in accept list */ 448 res = (match) ? true : false; 449 else 450 res = true; 451#endif 452 return res; 453} 454