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 * You should have received a copy of the GNU General Public License along with 15 * this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 17 * 18 * 19 ******************************************************************************/ 20#define _RTW_STA_MGT_C_ 21 22#include <osdep_service.h> 23#include <drv_types.h> 24#include <recv_osdep.h> 25#include <xmit_osdep.h> 26#include <mlme_osdep.h> 27#include <sta_info.h> 28#include <linux/vmalloc.h> 29 30static void _rtw_init_stainfo(struct sta_info *psta) 31{ 32 memset((u8 *)psta, 0, sizeof (struct sta_info)); 33 34 spin_lock_init(&psta->lock); 35 INIT_LIST_HEAD(&psta->list); 36 INIT_LIST_HEAD(&psta->hash_list); 37 _rtw_init_queue(&psta->sleep_q); 38 psta->sleepq_len = 0; 39 40 _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); 41 _rtw_init_sta_recv_priv(&psta->sta_recvpriv); 42 43#ifdef CONFIG_88EU_AP_MODE 44 45 INIT_LIST_HEAD(&psta->asoc_list); 46 47 INIT_LIST_HEAD(&psta->auth_list); 48 49 psta->expire_to = 0; 50 51 psta->flags = 0; 52 53 psta->capability = 0; 54 55 psta->bpairwise_key_installed = false; 56 57#ifdef CONFIG_88EU_AP_MODE 58 psta->nonerp_set = 0; 59 psta->no_short_slot_time_set = 0; 60 psta->no_short_preamble_set = 0; 61 psta->no_ht_gf_set = 0; 62 psta->no_ht_set = 0; 63 psta->ht_20mhz_set = 0; 64#endif 65 66 psta->under_exist_checking = 0; 67 68 psta->keep_alive_trycnt = 0; 69 70#endif /* CONFIG_88EU_AP_MODE */ 71 72} 73 74u32 _rtw_init_sta_priv(struct sta_priv *pstapriv) 75{ 76 struct sta_info *psta; 77 s32 i; 78 79 80 pstapriv->pallocated_stainfo_buf = vzalloc(sizeof(struct sta_info) * NUM_STA + 4); 81 82 if (!pstapriv->pallocated_stainfo_buf) 83 return _FAIL; 84 85 pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 - 86 ((size_t)(pstapriv->pallocated_stainfo_buf) & 3); 87 88 _rtw_init_queue(&pstapriv->free_sta_queue); 89 90 spin_lock_init(&pstapriv->sta_hash_lock); 91 92 pstapriv->asoc_sta_count = 0; 93 _rtw_init_queue(&pstapriv->sleep_q); 94 _rtw_init_queue(&pstapriv->wakeup_q); 95 96 psta = (struct sta_info *)(pstapriv->pstainfo_buf); 97 98 for (i = 0; i < NUM_STA; i++) { 99 _rtw_init_stainfo(psta); 100 101 INIT_LIST_HEAD(&(pstapriv->sta_hash[i])); 102 103 list_add_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue)); 104 105 psta++; 106 } 107 108#ifdef CONFIG_88EU_AP_MODE 109 110 pstapriv->sta_dz_bitmap = 0; 111 pstapriv->tim_bitmap = 0; 112 113 INIT_LIST_HEAD(&pstapriv->asoc_list); 114 INIT_LIST_HEAD(&pstapriv->auth_list); 115 spin_lock_init(&pstapriv->asoc_list_lock); 116 spin_lock_init(&pstapriv->auth_list_lock); 117 pstapriv->asoc_list_cnt = 0; 118 pstapriv->auth_list_cnt = 0; 119 120 pstapriv->auth_to = 3; /* 3*2 = 6 sec */ 121 pstapriv->assoc_to = 3; 122 pstapriv->expire_to = 3; /* 3*2 = 6 sec */ 123 pstapriv->max_num_sta = NUM_STA; 124#endif 125 126 127 return _SUCCESS; 128} 129 130inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta) 131{ 132 int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info); 133 134 if (!stainfo_offset_valid(offset)) 135 DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset); 136 137 return offset; 138} 139 140inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset) 141{ 142 if (!stainfo_offset_valid(offset)) 143 DBG_88E("%s invalid offset(%d), out of range!!!", __func__, offset); 144 145 return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info)); 146} 147 148/* this function is used to free the memory of lock || sema for all stainfos */ 149static void rtw_mfree_all_stainfo(struct sta_priv *pstapriv) 150{ 151 struct list_head *plist, *phead; 152 struct sta_info *psta = NULL; 153 154 155 spin_lock_bh(&pstapriv->sta_hash_lock); 156 157 phead = get_list_head(&pstapriv->free_sta_queue); 158 plist = phead->next; 159 160 while (phead != plist) { 161 psta = container_of(plist, struct sta_info , list); 162 plist = plist->next; 163 } 164 165 spin_unlock_bh(&pstapriv->sta_hash_lock); 166 167} 168 169static void rtw_mfree_sta_priv_lock(struct sta_priv *pstapriv) 170{ 171 rtw_mfree_all_stainfo(pstapriv); /* be done before free sta_hash_lock */ 172} 173 174u32 _rtw_free_sta_priv(struct sta_priv *pstapriv) 175{ 176 struct list_head *phead, *plist; 177 struct sta_info *psta = NULL; 178 struct recv_reorder_ctrl *preorder_ctrl; 179 int index; 180 181 if (pstapriv) { 182 /* delete all reordering_ctrl_timer */ 183 spin_lock_bh(&pstapriv->sta_hash_lock); 184 for (index = 0; index < NUM_STA; index++) { 185 phead = &(pstapriv->sta_hash[index]); 186 plist = phead->next; 187 188 while (phead != plist) { 189 int i; 190 psta = container_of(plist, struct sta_info , hash_list); 191 plist = plist->next; 192 193 for (i = 0; i < 16; i++) { 194 preorder_ctrl = &psta->recvreorder_ctrl[i]; 195 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); 196 } 197 } 198 } 199 spin_unlock_bh(&pstapriv->sta_hash_lock); 200 /*===============================*/ 201 202 rtw_mfree_sta_priv_lock(pstapriv); 203 204 if (pstapriv->pallocated_stainfo_buf) 205 vfree(pstapriv->pallocated_stainfo_buf); 206 } 207 208 return _SUCCESS; 209} 210 211struct sta_info *rtw_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) 212{ 213 s32 index; 214 struct list_head *phash_list; 215 struct sta_info *psta; 216 struct __queue *pfree_sta_queue; 217 struct recv_reorder_ctrl *preorder_ctrl; 218 int i = 0; 219 u16 wRxSeqInitialValue = 0xffff; 220 221 222 pfree_sta_queue = &pstapriv->free_sta_queue; 223 224 spin_lock_bh(&(pfree_sta_queue->lock)); 225 226 if (list_empty(&pfree_sta_queue->queue)) { 227 spin_unlock_bh(&pfree_sta_queue->lock); 228 psta = NULL; 229 } else { 230 psta = container_of((&pfree_sta_queue->queue)->next, struct sta_info, list); 231 list_del_init(&(psta->list)); 232 spin_unlock_bh(&pfree_sta_queue->lock); 233 _rtw_init_stainfo(psta); 234 memcpy(psta->hwaddr, hwaddr, ETH_ALEN); 235 index = wifi_mac_hash(hwaddr); 236 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, ("rtw_alloc_stainfo: index=%x", index)); 237 if (index >= NUM_STA) { 238 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("ERROR => rtw_alloc_stainfo: index >= NUM_STA")); 239 psta = NULL; 240 goto exit; 241 } 242 phash_list = &(pstapriv->sta_hash[index]); 243 244 spin_lock_bh(&(pstapriv->sta_hash_lock)); 245 246 list_add_tail(&psta->hash_list, phash_list); 247 248 pstapriv->asoc_sta_count++; 249 250 spin_unlock_bh(&pstapriv->sta_hash_lock); 251 252/* Commented by Albert 2009/08/13 */ 253/* For the SMC router, the sequence number of first packet of WPS handshake will be 0. */ 254/* In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable. */ 255/* So, we initialize the tid_rxseq variable as the 0xffff. */ 256 257 for (i = 0; i < 16; i++) 258 memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i], &wRxSeqInitialValue, 2); 259 260 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_info_, 261 ("alloc number_%d stainfo with hwaddr = %pM\n", 262 pstapriv->asoc_sta_count , hwaddr)); 263 264 init_addba_retry_timer(pstapriv->padapter, psta); 265 266 /* for A-MPDU Rx reordering buffer control */ 267 for (i = 0; i < 16; i++) { 268 preorder_ctrl = &psta->recvreorder_ctrl[i]; 269 270 preorder_ctrl->padapter = pstapriv->padapter; 271 272 preorder_ctrl->enable = false; 273 274 preorder_ctrl->indicate_seq = 0xffff; 275 preorder_ctrl->wend_b = 0xffff; 276 preorder_ctrl->wsize_b = 64;/* 64; */ 277 278 _rtw_init_queue(&preorder_ctrl->pending_recvframe_queue); 279 280 rtw_init_recv_timer(preorder_ctrl); 281 } 282 283 /* init for DM */ 284 psta->rssi_stat.UndecoratedSmoothedPWDB = (-1); 285 psta->rssi_stat.UndecoratedSmoothedCCK = (-1); 286 287 /* init for the sequence number of received management frame */ 288 psta->RxMgmtFrameSeqNum = 0xffff; 289 } 290 291exit: 292 return psta; 293} 294 295/* using pstapriv->sta_hash_lock to protect */ 296u32 rtw_free_stainfo(struct adapter *padapter , struct sta_info *psta) 297{ 298 int i; 299 struct __queue *pfree_sta_queue; 300 struct recv_reorder_ctrl *preorder_ctrl; 301 struct sta_xmit_priv *pstaxmitpriv; 302 struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 303 struct sta_priv *pstapriv = &padapter->stapriv; 304 305 306 if (psta == NULL) 307 goto exit; 308 309 pfree_sta_queue = &pstapriv->free_sta_queue; 310 311 pstaxmitpriv = &psta->sta_xmitpriv; 312 313 spin_lock_bh(&pxmitpriv->lock); 314 315 rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q); 316 psta->sleepq_len = 0; 317 318 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending); 319 320 list_del_init(&(pstaxmitpriv->vo_q.tx_pending)); 321 322 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending); 323 324 list_del_init(&(pstaxmitpriv->vi_q.tx_pending)); 325 326 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending); 327 328 list_del_init(&(pstaxmitpriv->bk_q.tx_pending)); 329 330 rtw_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending); 331 332 list_del_init(&(pstaxmitpriv->be_q.tx_pending)); 333 334 spin_unlock_bh(&pxmitpriv->lock); 335 336 list_del_init(&psta->hash_list); 337 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("\n free number_%d stainfo with hwaddr=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x\n", pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2], psta->hwaddr[3], psta->hwaddr[4], psta->hwaddr[5])); 338 pstapriv->asoc_sta_count--; 339 340 /* re-init sta_info; 20061114 */ 341 _rtw_init_sta_xmit_priv(&psta->sta_xmitpriv); 342 _rtw_init_sta_recv_priv(&psta->sta_recvpriv); 343 344 del_timer_sync(&psta->addba_retry_timer); 345 346 /* for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer */ 347 for (i = 0; i < 16; i++) { 348 struct list_head *phead, *plist; 349 struct recv_frame *prhdr; 350 struct recv_frame *prframe; 351 struct __queue *ppending_recvframe_queue; 352 struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue; 353 354 preorder_ctrl = &psta->recvreorder_ctrl[i]; 355 356 del_timer_sync(&preorder_ctrl->reordering_ctrl_timer); 357 358 ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue; 359 360 spin_lock_bh(&ppending_recvframe_queue->lock); 361 362 phead = get_list_head(ppending_recvframe_queue); 363 plist = phead->next; 364 365 while (!list_empty(phead)) { 366 prhdr = container_of(plist, struct recv_frame, list); 367 prframe = (struct recv_frame *)prhdr; 368 369 plist = plist->next; 370 371 list_del_init(&(prframe->list)); 372 373 rtw_free_recvframe(prframe, pfree_recv_queue); 374 } 375 376 spin_unlock_bh(&ppending_recvframe_queue->lock); 377 } 378 379 if (!(psta->state & WIFI_AP_STATE)) 380 rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, false); 381 382#ifdef CONFIG_88EU_AP_MODE 383 384 spin_lock_bh(&pstapriv->auth_list_lock); 385 if (!list_empty(&psta->auth_list)) { 386 list_del_init(&psta->auth_list); 387 pstapriv->auth_list_cnt--; 388 } 389 spin_unlock_bh(&pstapriv->auth_list_lock); 390 391 psta->expire_to = 0; 392 393 psta->sleepq_ac_len = 0; 394 psta->qos_info = 0; 395 396 psta->max_sp_len = 0; 397 psta->uapsd_bk = 0; 398 psta->uapsd_be = 0; 399 psta->uapsd_vi = 0; 400 psta->uapsd_vo = 0; 401 psta->has_legacy_ac = 0; 402 403 pstapriv->sta_dz_bitmap &= ~BIT(psta->aid); 404 pstapriv->tim_bitmap &= ~BIT(psta->aid); 405 406 if ((psta->aid > 0) && (pstapriv->sta_aid[psta->aid - 1] == psta)) { 407 pstapriv->sta_aid[psta->aid - 1] = NULL; 408 psta->aid = 0; 409 } 410 411 psta->under_exist_checking = 0; 412 413#endif /* CONFIG_88EU_AP_MODE */ 414 415 spin_lock_bh(&(pfree_sta_queue->lock)); 416 list_add_tail(&psta->list, get_list_head(pfree_sta_queue)); 417 spin_unlock_bh(&pfree_sta_queue->lock); 418 419exit: 420 421 422 return _SUCCESS; 423} 424 425/* free all stainfo which in sta_hash[all] */ 426void rtw_free_all_stainfo(struct adapter *padapter) 427{ 428 struct list_head *plist, *phead; 429 s32 index; 430 struct sta_info *psta = NULL; 431 struct sta_priv *pstapriv = &padapter->stapriv; 432 struct sta_info *pbcmc_stainfo = rtw_get_bcmc_stainfo(padapter); 433 434 435 if (pstapriv->asoc_sta_count == 1) 436 return; 437 438 spin_lock_bh(&pstapriv->sta_hash_lock); 439 440 for (index = 0; index < NUM_STA; index++) { 441 phead = &(pstapriv->sta_hash[index]); 442 plist = phead->next; 443 444 while (phead != plist) { 445 psta = container_of(plist, struct sta_info , hash_list); 446 447 plist = plist->next; 448 449 if (pbcmc_stainfo != psta) 450 rtw_free_stainfo(padapter , psta); 451 } 452 } 453 spin_unlock_bh(&pstapriv->sta_hash_lock); 454} 455 456/* any station allocated can be searched by hash list */ 457struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr) 458{ 459 struct list_head *plist, *phead; 460 struct sta_info *psta = NULL; 461 u32 index; 462 u8 *addr; 463 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 464 465 466 if (hwaddr == NULL) 467 return NULL; 468 469 if (IS_MCAST(hwaddr)) 470 addr = bc_addr; 471 else 472 addr = hwaddr; 473 474 index = wifi_mac_hash(addr); 475 476 spin_lock_bh(&pstapriv->sta_hash_lock); 477 478 phead = &(pstapriv->sta_hash[index]); 479 plist = phead->next; 480 481 while (phead != plist) { 482 psta = container_of(plist, struct sta_info, hash_list); 483 484 if ((!memcmp(psta->hwaddr, addr, ETH_ALEN)) == true) { 485 /* if found the matched address */ 486 break; 487 } 488 psta = NULL; 489 plist = plist->next; 490 } 491 492 spin_unlock_bh(&pstapriv->sta_hash_lock); 493 return psta; 494} 495 496u32 rtw_init_bcmc_stainfo(struct adapter *padapter) 497{ 498 struct sta_info *psta; 499 u32 res = _SUCCESS; 500 unsigned char bcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 501 struct sta_priv *pstapriv = &padapter->stapriv; 502 503 504 psta = rtw_alloc_stainfo(pstapriv, bcast_addr); 505 506 if (psta == NULL) { 507 res = _FAIL; 508 RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_err_, ("rtw_alloc_stainfo fail")); 509 goto exit; 510 } 511 512 /* default broadcast & multicast use macid 1 */ 513 psta->mac_id = 1; 514 515exit: 516 return res; 517} 518 519struct sta_info *rtw_get_bcmc_stainfo(struct adapter *padapter) 520{ 521 struct sta_info *psta; 522 struct sta_priv *pstapriv = &padapter->stapriv; 523 u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 524 psta = rtw_get_stainfo(pstapriv, bc_addr); 525 return psta; 526} 527 528u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr) 529{ 530 u8 res = true; 531#ifdef CONFIG_88EU_AP_MODE 532 struct list_head *plist, *phead; 533 struct rtw_wlan_acl_node *paclnode; 534 u8 match = false; 535 struct sta_priv *pstapriv = &padapter->stapriv; 536 struct wlan_acl_pool *pacl_list = &pstapriv->acl_list; 537 struct __queue *pacl_node_q = &pacl_list->acl_node_q; 538 539 spin_lock_bh(&(pacl_node_q->lock)); 540 phead = get_list_head(pacl_node_q); 541 plist = phead->next; 542 while (phead != plist) { 543 paclnode = container_of(plist, struct rtw_wlan_acl_node, list); 544 plist = plist->next; 545 546 if (!memcmp(paclnode->addr, mac_addr, ETH_ALEN)) { 547 if (paclnode->valid) { 548 match = true; 549 break; 550 } 551 } 552 } 553 spin_unlock_bh(&pacl_node_q->lock); 554 555 if (pacl_list->mode == 1)/* accept unless in deny list */ 556 res = (match) ? false : true; 557 else if (pacl_list->mode == 2)/* deny unless in accept list */ 558 res = (match) ? true : false; 559 else 560 res = true; 561 562#endif 563 564 return res; 565} 566