root/drivers/staging/rtl8712/rtl871x_sta_mgt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _init_stainfo
  2. _r8712_init_sta_priv
  3. mfree_all_stainfo
  4. _r8712_free_sta_priv
  5. r8712_alloc_stainfo
  6. r8712_free_stainfo
  7. r8712_free_all_stainfo
  8. r8712_get_stainfo
  9. r8712_init_bcmc_stainfo
  10. r8712_get_bcmc_stainfo
  11. r8712_access_ctrl

   1 // SPDX-License-Identifier: GPL-2.0
   2 /******************************************************************************
   3  * rtl871x_sta_mgt.c
   4  *
   5  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   6  * Linux device driver for RTL8192SU
   7  *
   8  * Modifications for inclusion into the Linux staging tree are
   9  * Copyright(c) 2010 Larry Finger. All rights reserved.
  10  *
  11  * Contact information:
  12  * WLAN FAE <wlanfae@realtek.com>
  13  * Larry Finger <Larry.Finger@lwfinger.net>
  14  *
  15  ******************************************************************************/
  16 
  17 #define _RTL871X_STA_MGT_C_
  18 
  19 #include "osdep_service.h"
  20 #include "drv_types.h"
  21 #include "recv_osdep.h"
  22 #include "xmit_osdep.h"
  23 #include "sta_info.h"
  24 
  25 static void _init_stainfo(struct sta_info *psta)
  26 {
  27         memset((u8 *)psta, 0, sizeof(struct sta_info));
  28         spin_lock_init(&psta->lock);
  29         INIT_LIST_HEAD(&psta->list);
  30         INIT_LIST_HEAD(&psta->hash_list);
  31         _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
  32         _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
  33         INIT_LIST_HEAD(&psta->asoc_list);
  34         INIT_LIST_HEAD(&psta->auth_list);
  35 }
  36 
  37 int _r8712_init_sta_priv(struct sta_priv *pstapriv)
  38 {
  39         struct sta_info *psta;
  40         s32 i;
  41 
  42         pstapriv->pallocated_stainfo_buf = kmalloc(sizeof(struct sta_info) *
  43                                                    NUM_STA + 4, GFP_ATOMIC);
  44         if (!pstapriv->pallocated_stainfo_buf)
  45                 return -ENOMEM;
  46         pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
  47                 ((addr_t)(pstapriv->pallocated_stainfo_buf) & 3);
  48         _init_queue(&pstapriv->free_sta_queue);
  49         spin_lock_init(&pstapriv->sta_hash_lock);
  50         pstapriv->asoc_sta_count = 0;
  51         _init_queue(&pstapriv->sleep_q);
  52         _init_queue(&pstapriv->wakeup_q);
  53         psta = (struct sta_info *)(pstapriv->pstainfo_buf);
  54         for (i = 0; i < NUM_STA; i++) {
  55                 _init_stainfo(psta);
  56                 INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
  57                 list_add_tail(&psta->list, &pstapriv->free_sta_queue.queue);
  58                 psta++;
  59         }
  60         INIT_LIST_HEAD(&pstapriv->asoc_list);
  61         INIT_LIST_HEAD(&pstapriv->auth_list);
  62         return 0;
  63 }
  64 
  65 /* this function is used to free the memory of lock || sema for all stainfos */
  66 static void mfree_all_stainfo(struct sta_priv *pstapriv)
  67 {
  68         unsigned long irqL;
  69         struct list_head *plist, *phead;
  70 
  71         spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
  72         phead = &pstapriv->free_sta_queue.queue;
  73         plist = phead->next;
  74         while (!end_of_queue_search(phead, plist))
  75                 plist = plist->next;
  76 
  77         spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
  78 }
  79 
  80 void _r8712_free_sta_priv(struct sta_priv *pstapriv)
  81 {
  82         if (pstapriv) {
  83                 /* be done before free sta_hash_lock */
  84                 mfree_all_stainfo(pstapriv);
  85                 kfree(pstapriv->pallocated_stainfo_buf);
  86         }
  87 }
  88 
  89 struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
  90 {
  91         s32     index;
  92         struct list_head *phash_list;
  93         struct sta_info *psta;
  94         struct  __queue *pfree_sta_queue;
  95         struct recv_reorder_ctrl *preorder_ctrl;
  96         int i = 0;
  97         u16  wRxSeqInitialValue = 0xffff;
  98         unsigned long flags;
  99 
 100         pfree_sta_queue = &pstapriv->free_sta_queue;
 101         spin_lock_irqsave(&pfree_sta_queue->lock, flags);
 102         psta = list_first_entry_or_null(&pfree_sta_queue->queue,
 103                                         struct sta_info, list);
 104         if (psta) {
 105                 list_del_init(&psta->list);
 106                 _init_stainfo(psta);
 107                 memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
 108                 index = wifi_mac_hash(hwaddr);
 109                 if (index >= NUM_STA) {
 110                         psta = NULL;
 111                         goto exit;
 112                 }
 113                 phash_list = &pstapriv->sta_hash[index];
 114                 list_add_tail(&psta->hash_list, phash_list);
 115                 pstapriv->asoc_sta_count++;
 116 
 117 /* For the SMC router, the sequence number of first packet of WPS handshake
 118  * will be 0. In this case, this packet will be dropped by recv_decache function
 119  * if we use the 0x00 as the default value for tid_rxseq variable. So, we
 120  * initialize the tid_rxseq variable as the 0xffff.
 121  */
 122                 for (i = 0; i < 16; i++)
 123                         memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
 124                                 &wRxSeqInitialValue, 2);
 125                 /* for A-MPDU Rx reordering buffer control */
 126                 for (i = 0; i < 16; i++) {
 127                         preorder_ctrl = &psta->recvreorder_ctrl[i];
 128                         preorder_ctrl->padapter = pstapriv->padapter;
 129                         preorder_ctrl->indicate_seq = 0xffff;
 130                         preorder_ctrl->wend_b = 0xffff;
 131                         preorder_ctrl->wsize_b = 64;
 132                         _init_queue(&preorder_ctrl->pending_recvframe_queue);
 133                         r8712_init_recv_timer(preorder_ctrl);
 134                 }
 135         }
 136 exit:
 137         spin_unlock_irqrestore(&pfree_sta_queue->lock, flags);
 138         return psta;
 139 }
 140 
 141 /* using pstapriv->sta_hash_lock to protect */
 142 void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta)
 143 {
 144         int i;
 145         unsigned long irqL0;
 146         struct  __queue *pfree_sta_queue;
 147         struct recv_reorder_ctrl *preorder_ctrl;
 148         struct  sta_xmit_priv *pstaxmitpriv;
 149         struct  xmit_priv *pxmitpriv = &padapter->xmitpriv;
 150         struct  sta_priv *pstapriv = &padapter->stapriv;
 151 
 152         if (psta == NULL)
 153                 return;
 154         pfree_sta_queue = &pstapriv->free_sta_queue;
 155         pstaxmitpriv = &psta->sta_xmitpriv;
 156         spin_lock_irqsave(&(pxmitpriv->vo_pending.lock), irqL0);
 157         r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
 158         list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
 159         spin_unlock_irqrestore(&(pxmitpriv->vo_pending.lock), irqL0);
 160         spin_lock_irqsave(&(pxmitpriv->vi_pending.lock), irqL0);
 161         r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
 162         list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
 163         spin_unlock_irqrestore(&(pxmitpriv->vi_pending.lock), irqL0);
 164         spin_lock_irqsave(&(pxmitpriv->bk_pending.lock), irqL0);
 165         r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
 166         list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
 167         spin_unlock_irqrestore(&(pxmitpriv->bk_pending.lock), irqL0);
 168         spin_lock_irqsave(&(pxmitpriv->be_pending.lock), irqL0);
 169         r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
 170         list_del_init(&(pstaxmitpriv->be_q.tx_pending));
 171         spin_unlock_irqrestore(&(pxmitpriv->be_pending.lock), irqL0);
 172         list_del_init(&psta->hash_list);
 173         pstapriv->asoc_sta_count--;
 174         /* re-init sta_info; 20061114 */
 175         _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
 176         _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
 177         /* for A-MPDU Rx reordering buffer control,
 178          * cancel reordering_ctrl_timer
 179          */
 180         for (i = 0; i < 16; i++) {
 181                 preorder_ctrl = &psta->recvreorder_ctrl[i];
 182                 del_timer(&preorder_ctrl->reordering_ctrl_timer);
 183         }
 184         spin_lock(&(pfree_sta_queue->lock));
 185         /* insert into free_sta_queue; 20061114 */
 186         list_add_tail(&psta->list, &pfree_sta_queue->queue);
 187         spin_unlock(&(pfree_sta_queue->lock));
 188 }
 189 
 190 /* free all stainfo which in sta_hash[all] */
 191 void r8712_free_all_stainfo(struct _adapter *padapter)
 192 {
 193         unsigned long irqL;
 194         struct list_head *plist, *phead;
 195         s32 index;
 196         struct sta_info *psta = NULL;
 197         struct  sta_priv *pstapriv = &padapter->stapriv;
 198         struct sta_info *pbcmc_stainfo = r8712_get_bcmc_stainfo(padapter);
 199 
 200         if (pstapriv->asoc_sta_count == 1)
 201                 return;
 202         spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 203         for (index = 0; index < NUM_STA; index++) {
 204                 phead = &(pstapriv->sta_hash[index]);
 205                 plist = phead->next;
 206                 while (!end_of_queue_search(phead, plist)) {
 207                         psta = container_of(plist,
 208                                             struct sta_info, hash_list);
 209                         plist = plist->next;
 210                         if (pbcmc_stainfo != psta)
 211                                 r8712_free_stainfo(padapter, psta);
 212                 }
 213         }
 214         spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 215 }
 216 
 217 /* any station allocated can be searched by hash list */
 218 struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
 219 {
 220         unsigned long    irqL;
 221         struct list_head *plist, *phead;
 222         struct sta_info *psta = NULL;
 223         u32     index;
 224 
 225         if (hwaddr == NULL)
 226                 return NULL;
 227         index = wifi_mac_hash(hwaddr);
 228         spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 229         phead = &(pstapriv->sta_hash[index]);
 230         plist = phead->next;
 231         while (!end_of_queue_search(phead, plist)) {
 232                 psta = container_of(plist, struct sta_info, hash_list);
 233                 if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) {
 234                         /* if found the matched address */
 235                         break;
 236                 }
 237                 psta = NULL;
 238                 plist = plist->next;
 239         }
 240         spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 241         return psta;
 242 }
 243 
 244 void r8712_init_bcmc_stainfo(struct _adapter *padapter)
 245 {
 246         unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 247         struct  sta_priv *pstapriv = &padapter->stapriv;
 248 
 249         r8712_alloc_stainfo(pstapriv, bcast_addr);
 250 }
 251 
 252 struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter)
 253 {
 254         struct sta_priv *pstapriv = &padapter->stapriv;
 255         u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 256 
 257         return r8712_get_stainfo(pstapriv, bc_addr);
 258 }
 259 
 260 
 261 u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr)
 262 {
 263         return true;
 264 }

/* [<][>][^][v][top][bottom][index][help] */