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_listhead(&psta
->list
);
42 _init_listhead(&psta
->hash_list
);
43 _r8712_init_sta_xmit_priv(&psta
->sta_xmitpriv
);
44 _r8712_init_sta_recv_priv(&psta
->sta_recvpriv
);
45 _init_listhead(&psta
->asoc_list
);
46 _init_listhead(&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
== NULL
)
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_listhead(&(pstapriv
->sta_hash
[i
]));
69 list_insert_tail(&psta
->list
,
70 get_list_head(&pstapriv
->free_sta_queue
));
73 _init_listhead(&pstapriv
->asoc_list
);
74 _init_listhead(&pstapriv
->auth_list
);
78 /* this function is used to free the memory of lock || sema for all stainfos */
79 static void mfree_all_stainfo(struct sta_priv
*pstapriv
)
82 struct list_head
*plist
, *phead
;
83 struct sta_info
*psta
= NULL
;
85 spin_lock_irqsave(&pstapriv
->sta_hash_lock
, irqL
);
86 phead
= get_list_head(&pstapriv
->free_sta_queue
);
87 plist
= get_next(phead
);
88 while ((end_of_queue_search(phead
, plist
)) == false) {
89 psta
= LIST_CONTAINOR(plist
, struct sta_info
, list
);
90 plist
= get_next(plist
);
93 spin_unlock_irqrestore(&pstapriv
->sta_hash_lock
, irqL
);
97 static void mfree_sta_priv_lock(struct sta_priv
*pstapriv
)
99 mfree_all_stainfo(pstapriv
); /* be done before free sta_hash_lock */
102 u32
_r8712_free_sta_priv(struct sta_priv
*pstapriv
)
105 mfree_sta_priv_lock(pstapriv
);
106 kfree(pstapriv
->pallocated_stainfo_buf
);
111 struct sta_info
*r8712_alloc_stainfo(struct sta_priv
*pstapriv
, u8
*hwaddr
)
115 struct list_head
*phash_list
;
116 struct sta_info
*psta
;
117 struct __queue
*pfree_sta_queue
;
118 struct recv_reorder_ctrl
*preorder_ctrl
;
120 u16 wRxSeqInitialValue
= 0xffff;
123 pfree_sta_queue
= &pstapriv
->free_sta_queue
;
124 spin_lock_irqsave(&(pfree_sta_queue
->lock
), flags
);
125 if (_queue_empty(pfree_sta_queue
) == true)
128 psta
= LIST_CONTAINOR(get_next(&pfree_sta_queue
->queue
),
129 struct sta_info
, list
);
130 list_delete(&(psta
->list
));
133 memcpy(psta
->hwaddr
, hwaddr
, ETH_ALEN
);
134 index
= wifi_mac_hash(hwaddr
);
135 if (index
>= NUM_STA
) {
139 phash_list
= &(pstapriv
->sta_hash
[index
]);
140 list_insert_tail(&psta
->hash_list
, phash_list
);
141 pstapriv
->asoc_sta_count
++;
143 /* For the SMC router, the sequence number of first packet of WPS handshake
144 * will be 0. In this case, this packet will be dropped by recv_decache function
145 * if we use the 0x00 as the default value for tid_rxseq variable. So, we
146 * initialize the tid_rxseq variable as the 0xffff.
148 for (i
= 0; i
< 16; i
++)
149 memcpy(&psta
->sta_recvpriv
.rxcache
.tid_rxseq
[i
],
150 &wRxSeqInitialValue
, 2);
151 /* for A-MPDU Rx reordering buffer control */
152 for (i
= 0; i
< 16; i
++) {
153 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
154 preorder_ctrl
->padapter
= pstapriv
->padapter
;
155 preorder_ctrl
->indicate_seq
= 0xffff;
156 preorder_ctrl
->wend_b
= 0xffff;
157 preorder_ctrl
->wsize_b
= 64;
158 _init_queue(&preorder_ctrl
->pending_recvframe_queue
);
159 r8712_init_recv_timer(preorder_ctrl
);
163 spin_unlock_irqrestore(&(pfree_sta_queue
->lock
), flags
);
167 /* using pstapriv->sta_hash_lock to protect */
168 void r8712_free_stainfo(struct _adapter
*padapter
, struct sta_info
*psta
)
172 struct __queue
*pfree_sta_queue
;
173 struct recv_reorder_ctrl
*preorder_ctrl
;
174 struct sta_xmit_priv
*pstaxmitpriv
;
175 struct xmit_priv
*pxmitpriv
= &padapter
->xmitpriv
;
176 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
180 pfree_sta_queue
= &pstapriv
->free_sta_queue
;
181 pstaxmitpriv
= &psta
->sta_xmitpriv
;
182 spin_lock_irqsave(&(pxmitpriv
->vo_pending
.lock
), irqL0
);
183 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->vo_q
.sta_pending
);
184 list_delete(&(pstaxmitpriv
->vo_q
.tx_pending
));
185 spin_unlock_irqrestore(&(pxmitpriv
->vo_pending
.lock
), irqL0
);
186 spin_lock_irqsave(&(pxmitpriv
->vi_pending
.lock
), irqL0
);
187 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->vi_q
.sta_pending
);
188 list_delete(&(pstaxmitpriv
->vi_q
.tx_pending
));
189 spin_unlock_irqrestore(&(pxmitpriv
->vi_pending
.lock
), irqL0
);
190 spin_lock_irqsave(&(pxmitpriv
->bk_pending
.lock
), irqL0
);
191 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->bk_q
.sta_pending
);
192 list_delete(&(pstaxmitpriv
->bk_q
.tx_pending
));
193 spin_unlock_irqrestore(&(pxmitpriv
->bk_pending
.lock
), irqL0
);
194 spin_lock_irqsave(&(pxmitpriv
->be_pending
.lock
), irqL0
);
195 r8712_free_xmitframe_queue(pxmitpriv
, &pstaxmitpriv
->be_q
.sta_pending
);
196 list_delete(&(pstaxmitpriv
->be_q
.tx_pending
));
197 spin_unlock_irqrestore(&(pxmitpriv
->be_pending
.lock
), irqL0
);
198 list_delete(&psta
->hash_list
);
199 pstapriv
->asoc_sta_count
--;
200 /* re-init sta_info; 20061114 */
201 _r8712_init_sta_xmit_priv(&psta
->sta_xmitpriv
);
202 _r8712_init_sta_recv_priv(&psta
->sta_recvpriv
);
203 /* for A-MPDU Rx reordering buffer control,
204 * cancel reordering_ctrl_timer */
205 for (i
= 0; i
< 16; i
++) {
206 preorder_ctrl
= &psta
->recvreorder_ctrl
[i
];
207 _cancel_timer_ex(&preorder_ctrl
->reordering_ctrl_timer
);
209 spin_lock(&(pfree_sta_queue
->lock
));
210 /* insert into free_sta_queue; 20061114 */
211 list_insert_tail(&psta
->list
, get_list_head(pfree_sta_queue
));
212 spin_unlock(&(pfree_sta_queue
->lock
));
215 /* free all stainfo which in sta_hash[all] */
216 void r8712_free_all_stainfo(struct _adapter
*padapter
)
219 struct list_head
*plist
, *phead
;
221 struct sta_info
*psta
= NULL
;
222 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
223 struct sta_info
*pbcmc_stainfo
= r8712_get_bcmc_stainfo(padapter
);
225 if (pstapriv
->asoc_sta_count
== 1)
227 spin_lock_irqsave(&pstapriv
->sta_hash_lock
, irqL
);
228 for (index
= 0; index
< NUM_STA
; index
++) {
229 phead
= &(pstapriv
->sta_hash
[index
]);
230 plist
= get_next(phead
);
231 while ((end_of_queue_search(phead
, plist
)) == false) {
232 psta
= LIST_CONTAINOR(plist
,
233 struct sta_info
, hash_list
);
234 plist
= get_next(plist
);
235 if (pbcmc_stainfo
!= psta
)
236 r8712_free_stainfo(padapter
, psta
);
239 spin_unlock_irqrestore(&pstapriv
->sta_hash_lock
, irqL
);
242 /* any station allocated can be searched by hash list */
243 struct sta_info
*r8712_get_stainfo(struct sta_priv
*pstapriv
, u8
*hwaddr
)
246 struct list_head
*plist
, *phead
;
247 struct sta_info
*psta
= NULL
;
252 index
= wifi_mac_hash(hwaddr
);
253 spin_lock_irqsave(&pstapriv
->sta_hash_lock
, irqL
);
254 phead
= &(pstapriv
->sta_hash
[index
]);
255 plist
= get_next(phead
);
256 while ((end_of_queue_search(phead
, plist
)) == false) {
257 psta
= LIST_CONTAINOR(plist
, struct sta_info
, hash_list
);
258 if ((!memcmp(psta
->hwaddr
, hwaddr
, ETH_ALEN
))) {
259 /* if found the matched address */
263 plist
= get_next(plist
);
265 spin_unlock_irqrestore(&pstapriv
->sta_hash_lock
, irqL
);
269 void r8712_init_bcmc_stainfo(struct _adapter
*padapter
)
271 struct sta_info
*psta
;
272 struct tx_servq
*ptxservq
;
273 unsigned char bcast_addr
[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
274 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
276 psta
= r8712_alloc_stainfo(pstapriv
, bcast_addr
);
279 ptxservq
= &(psta
->sta_xmitpriv
.be_q
);
282 struct sta_info
*r8712_get_bcmc_stainfo(struct _adapter
*padapter
)
284 struct sta_info
*psta
;
285 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
286 u8 bc_addr
[ETH_ALEN
] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
288 psta
= r8712_get_stainfo(pstapriv
, bc_addr
);
293 u8
r8712_access_ctrl(struct wlan_acl_pool
*pacl_list
, u8
*mac_addr
)
This page took 0.040696 seconds and 5 git commands to generate.