1 /******************************************************************************
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
16 * You should have received a copy of the GNU General Public License along with
17 * this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_STA_MGT_C_
31 #include "osdep_service.h"
32 #include "drv_types.h"
33 #include "recv_osdep.h"
34 #include "xmit_osdep.h"
37 static void _init_stainfo(struct sta_info
*psta
)
39 memset((u8
*)psta
, 0, sizeof(struct sta_info
));
40 spin_lock_init(&psta
->lock
);
41 INIT_LIST_HEAD(&psta
->list
);
42 INIT_LIST_HEAD(&psta
->hash_list
);
43 _r8712_init_sta_xmit_priv(&psta
->sta_xmitpriv
);
44 _r8712_init_sta_recv_priv(&psta
->sta_recvpriv
);
45 INIT_LIST_HEAD(&psta
->asoc_list
);
46 INIT_LIST_HEAD(&psta
->auth_list
);
49 u32
_r8712_init_sta_priv(struct sta_priv
*pstapriv
)
51 struct sta_info
*psta
;
54 pstapriv
->pallocated_stainfo_buf
= kmalloc(sizeof(struct sta_info
) *
55 NUM_STA
+ 4, GFP_ATOMIC
);
56 if (!pstapriv
->pallocated_stainfo_buf
)
58 pstapriv
->pstainfo_buf
= pstapriv
->pallocated_stainfo_buf
+ 4 -
59 ((addr_t
)(pstapriv
->pallocated_stainfo_buf
) & 3);
60 _init_queue(&pstapriv
->free_sta_queue
);
61 spin_lock_init(&pstapriv
->sta_hash_lock
);
62 pstapriv
->asoc_sta_count
= 0;
63 _init_queue(&pstapriv
->sleep_q
);
64 _init_queue(&pstapriv
->wakeup_q
);
65 psta
= (struct sta_info
*)(pstapriv
->pstainfo_buf
);
66 for (i
= 0; i
< NUM_STA
; i
++) {
68 INIT_LIST_HEAD(&(pstapriv
->sta_hash
[i
]));
69 list_add_tail(&psta
->list
, &pstapriv
->free_sta_queue
.queue
);
72 INIT_LIST_HEAD(&pstapriv
->asoc_list
);
73 INIT_LIST_HEAD(&pstapriv
->auth_list
);
77 /* this function is used to free the memory of lock || sema for all stainfos */
78 static void mfree_all_stainfo(struct sta_priv
*pstapriv
)
81 struct list_head
*plist
, *phead
;
83 spin_lock_irqsave(&pstapriv
->sta_hash_lock
, irqL
);
84 phead
= &pstapriv
->free_sta_queue
.queue
;
86 while (!end_of_queue_search(phead
, plist
))
89 spin_unlock_irqrestore(&pstapriv
->sta_hash_lock
, irqL
);
92 u32
_r8712_free_sta_priv(struct sta_priv
*pstapriv
)
95 /* be done before free sta_hash_lock */
96 mfree_all_stainfo(pstapriv
);
97 kfree(pstapriv
->pallocated_stainfo_buf
);
102 struct sta_info
*r8712_alloc_stainfo(struct sta_priv
*pstapriv
, u8
*hwaddr
)
105 struct list_head
*phash_list
;
106 struct sta_info
*psta
;
107 struct __queue
*pfree_sta_queue
;
108 struct recv_reorder_ctrl
*preorder_ctrl
;
110 u16 wRxSeqInitialValue
= 0xffff;
113 pfree_sta_queue
= &pstapriv
->free_sta_queue
;
114 spin_lock_irqsave(&pfree_sta_queue
->lock
, flags
);
115 psta
= list_first_entry_or_null(&pfree_sta_queue
->queue
,
116 struct sta_info
, list
);
118 list_del_init(&psta
->list
);
120 memcpy(psta
->hwaddr
, hwaddr
, ETH_ALEN
);
121 index
= wifi_mac_hash(hwaddr
);
122 if (index
>= NUM_STA
) {
126 phash_list
= &pstapriv
->sta_hash
[index
];
127 list_add_tail(&psta
->hash_list
, phash_list
);
128 pstapriv
->asoc_sta_count
++;
130 /* For the SMC router, the sequence number of first packet of WPS handshake
131 * will be 0. In this case, this packet will be dropped by recv_decache function
132 * if we use the 0x00 as the default value for tid_rxseq variable. So, we
133 * initialize the tid_rxseq variable as the 0xffff.
135 for (i
= 0; i
< 16; i
++)
136 memcpy(&psta
->sta_recvpriv
.rxcache
.tid_rxseq
[i
],
137 &wRxSeqInitialValue
, 2);
138 /* for A-MPDU Rx reordering buffer control */
139 for (i
= 0; i
< 16; i
++) {
140 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
141 preorder_ctrl
->padapter
= pstapriv
->padapter
;
142 preorder_ctrl
->indicate_seq
= 0xffff;
143 preorder_ctrl
->wend_b
= 0xffff;
144 preorder_ctrl
->wsize_b
= 64;
145 _init_queue(&preorder_ctrl
->pending_recvframe_queue
);
146 r8712_init_recv_timer(preorder_ctrl
);
150 spin_unlock_irqrestore(&pfree_sta_queue
->lock
, flags
);
154 /* using pstapriv->sta_hash_lock to protect */
155 void r8712_free_stainfo(struct _adapter
*padapter
, struct sta_info
*psta
)
159 struct __queue
*pfree_sta_queue
;
160 struct recv_reorder_ctrl
*preorder_ctrl
;
161 struct sta_xmit_priv
*pstaxmitpriv
;
162 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
163 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
167 pfree_sta_queue
= &pstapriv
->free_sta_queue
;
168 pstaxmitpriv
= &psta
->sta_xmitpriv
;
169 spin_lock_irqsave(&(pxmitpriv
->vo_pending
.lock
), irqL0
);
170 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->vo_q
.sta_pending
);
171 list_del_init(&(pstaxmitpriv
->vo_q
.tx_pending
));
172 spin_unlock_irqrestore(&(pxmitpriv
->vo_pending
.lock
), irqL0
);
173 spin_lock_irqsave(&(pxmitpriv
->vi_pending
.lock
), irqL0
);
174 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->vi_q
.sta_pending
);
175 list_del_init(&(pstaxmitpriv
->vi_q
.tx_pending
));
176 spin_unlock_irqrestore(&(pxmitpriv
->vi_pending
.lock
), irqL0
);
177 spin_lock_irqsave(&(pxmitpriv
->bk_pending
.lock
), irqL0
);
178 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->bk_q
.sta_pending
);
179 list_del_init(&(pstaxmitpriv
->bk_q
.tx_pending
));
180 spin_unlock_irqrestore(&(pxmitpriv
->bk_pending
.lock
), irqL0
);
181 spin_lock_irqsave(&(pxmitpriv
->be_pending
.lock
), irqL0
);
182 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->be_q
.sta_pending
);
183 list_del_init(&(pstaxmitpriv
->be_q
.tx_pending
));
184 spin_unlock_irqrestore(&(pxmitpriv
->be_pending
.lock
), irqL0
);
185 list_del_init(&psta
->hash_list
);
186 pstapriv
->asoc_sta_count
--;
187 /* re-init sta_info; 20061114 */
188 _r8712_init_sta_xmit_priv(&psta
->sta_xmitpriv
);
189 _r8712_init_sta_recv_priv(&psta
->sta_recvpriv
);
190 /* for A-MPDU Rx reordering buffer control,
191 * cancel reordering_ctrl_timer */
192 for (i
= 0; i
< 16; i
++) {
193 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
194 del_timer(&preorder_ctrl
->reordering_ctrl_timer
);
196 spin_lock(&(pfree_sta_queue
->lock
));
197 /* insert into free_sta_queue; 20061114 */
198 list_add_tail(&psta
->list
, &pfree_sta_queue
->queue
);
199 spin_unlock(&(pfree_sta_queue
->lock
));
202 /* free all stainfo which in sta_hash[all] */
203 void r8712_free_all_stainfo(struct _adapter
*padapter
)
206 struct list_head
*plist
, *phead
;
208 struct sta_info
*psta
= NULL
;
209 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
210 struct sta_info
*pbcmc_stainfo
= r8712_get_bcmc_stainfo(padapter
);
212 if (pstapriv
->asoc_sta_count
== 1)
214 spin_lock_irqsave(&pstapriv
->sta_hash_lock
, irqL
);
215 for (index
= 0; index
< NUM_STA
; index
++) {
216 phead
= &(pstapriv
->sta_hash
[index
]);
218 while (!end_of_queue_search(phead
, plist
)) {
219 psta
= container_of(plist
,
220 struct sta_info
, hash_list
);
222 if (pbcmc_stainfo
!= psta
)
223 r8712_free_stainfo(padapter
, psta
);
226 spin_unlock_irqrestore(&pstapriv
->sta_hash_lock
, irqL
);
229 /* any station allocated can be searched by hash list */
230 struct sta_info
*r8712_get_stainfo(struct sta_priv
*pstapriv
, u8
*hwaddr
)
233 struct list_head
*plist
, *phead
;
234 struct sta_info
*psta
= NULL
;
239 index
= wifi_mac_hash(hwaddr
);
240 spin_lock_irqsave(&pstapriv
->sta_hash_lock
, irqL
);
241 phead
= &(pstapriv
->sta_hash
[index
]);
243 while (!end_of_queue_search(phead
, plist
)) {
244 psta
= container_of(plist
, struct sta_info
, hash_list
);
245 if ((!memcmp(psta
->hwaddr
, hwaddr
, ETH_ALEN
))) {
246 /* if found the matched address */
252 spin_unlock_irqrestore(&pstapriv
->sta_hash_lock
, irqL
);
256 void r8712_init_bcmc_stainfo(struct _adapter
*padapter
)
258 unsigned char bcast_addr
[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
259 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
261 r8712_alloc_stainfo(pstapriv
, bcast_addr
);
264 struct sta_info
*r8712_get_bcmc_stainfo(struct _adapter
*padapter
)
266 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
267 u8 bc_addr
[ETH_ALEN
] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
269 return r8712_get_stainfo(pstapriv
, bc_addr
);
273 u8
r8712_access_ctrl(struct wlan_acl_pool
*pacl_list
, u8
*mac_addr
)
This page took 0.038728 seconds and 5 git commands to generate.