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