1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTW_MLME_C_
8 
9 #include <linux/etherdevice.h>
10 #include <drv_types.h>
11 #include <rtw_debug.h>
12 #include <hal_btcoex.h>
13 #include <linux/jiffies.h>
14 
15 extern u8 rtw_do_join(struct adapter *padapter);
16 
17 int	rtw_init_mlme_priv(struct adapter *padapter)
18 {
19 	int	i;
20 	u8 *pbuf;
21 	struct wlan_network	*pnetwork;
22 	struct mlme_priv 	*pmlmepriv = &padapter->mlmepriv;
23 	int	res = _SUCCESS;
24 
25 	pmlmepriv->nic_hdl = (u8 *)padapter;
26 
27 	pmlmepriv->pscanned = NULL;
28 	pmlmepriv->fw_state = WIFI_STATION_STATE; /*  Must sync with rtw_wdev_alloc() */
29 	/*  wdev->iftype = NL80211_IFTYPE_STATION */
30 	pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
31 	pmlmepriv->scan_mode = SCAN_ACTIVE;/*  1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
32 
33 	spin_lock_init(&pmlmepriv->lock);
34 	_rtw_init_queue(&pmlmepriv->free_bss_pool);
35 	_rtw_init_queue(&pmlmepriv->scanned_queue);
36 
37 	set_scanned_network_val(pmlmepriv, 0);
38 
39 	memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
40 
41 	pbuf = vzalloc(array_size(MAX_BSS_CNT, sizeof(struct wlan_network)));
42 
43 	if (pbuf == NULL) {
44 		res = _FAIL;
45 		goto exit;
46 	}
47 	pmlmepriv->free_bss_buf = pbuf;
48 
49 	pnetwork = (struct wlan_network *)pbuf;
50 
51 	for (i = 0; i < MAX_BSS_CNT; i++) {
52 		INIT_LIST_HEAD(&pnetwork->list);
53 
54 		list_add_tail(&pnetwork->list, &pmlmepriv->free_bss_pool.queue);
55 
56 		pnetwork++;
57 	}
58 
59 	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
60 
61 	rtw_clear_scan_deny(padapter);
62 
63 	#define RTW_ROAM_SCAN_RESULT_EXP_MS 5000
64 	#define RTW_ROAM_RSSI_DIFF_TH 10
65 	#define RTW_ROAM_SCAN_INTERVAL_MS 10000
66 
67 	pmlmepriv->roam_flags = 0
68 		| RTW_ROAM_ON_EXPIRED
69 		| RTW_ROAM_ON_RESUME
70 		#ifdef CONFIG_LAYER2_ROAMING_ACTIVE /* FIXME */
71 		| RTW_ROAM_ACTIVE
72 		#endif
73 		;
74 
75 	pmlmepriv->roam_scanr_exp_ms = RTW_ROAM_SCAN_RESULT_EXP_MS;
76 	pmlmepriv->roam_rssi_diff_th = RTW_ROAM_RSSI_DIFF_TH;
77 	pmlmepriv->roam_scan_int_ms = RTW_ROAM_SCAN_INTERVAL_MS;
78 
79 	rtw_init_mlme_timer(padapter);
80 
81 exit:
82 
83 	return res;
84 }
85 
86 static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
87 {
88 	if (*ppie) {
89 		kfree(*ppie);
90 		*plen = 0;
91 		*ppie = NULL;
92 	}
93 }
94 
95 void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
96 {
97 	rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
98 	rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
99 	rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
100 	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
101 	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
102 	rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
103 
104 	rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
105 	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
106 	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
107 	rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
108 	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
109 }
110 
111 void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
112 {
113 	if (pmlmepriv) {
114 		rtw_free_mlme_priv_ie_data(pmlmepriv);
115 		if (pmlmepriv->free_bss_buf) {
116 			vfree(pmlmepriv->free_bss_buf);
117 		}
118 	}
119 }
120 
121 /*
122 struct	wlan_network *_rtw_dequeue_network(struct __queue *queue)
123 {
124 	_irqL irqL;
125 
126 	struct wlan_network *pnetwork;
127 
128 	spin_lock_bh(&queue->lock);
129 
130 	if (list_empty(&queue->queue))
131 
132 		pnetwork = NULL;
133 
134 	else
135 	{
136 		pnetwork = LIST_CONTAINOR(get_next(&queue->queue), struct wlan_network, list);
137 
138 		list_del_init(&(pnetwork->list));
139 	}
140 
141 	spin_unlock_bh(&queue->lock);
142 
143 	return pnetwork;
144 }
145 */
146 
147 struct	wlan_network *rtw_alloc_network(struct	mlme_priv *pmlmepriv)
148 {
149 	struct	wlan_network	*pnetwork;
150 	struct __queue *free_queue = &pmlmepriv->free_bss_pool;
151 	struct list_head *plist = NULL;
152 
153 	spin_lock_bh(&free_queue->lock);
154 
155 	if (list_empty(&free_queue->queue)) {
156 		pnetwork = NULL;
157 		goto exit;
158 	}
159 	plist = get_next(&(free_queue->queue));
160 
161 	pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
162 
163 	list_del_init(&pnetwork->list);
164 
165 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
166 		 ("rtw_alloc_network: ptr =%p\n", plist));
167 	pnetwork->network_type = 0;
168 	pnetwork->fixed = false;
169 	pnetwork->last_scanned = jiffies;
170 	pnetwork->aid = 0;
171 	pnetwork->join_res = 0;
172 
173 	pmlmepriv->num_of_scanned++;
174 
175 exit:
176 	spin_unlock_bh(&free_queue->lock);
177 
178 	return pnetwork;
179 }
180 
181 void _rtw_free_network(struct	mlme_priv *pmlmepriv, struct wlan_network *pnetwork, u8 isfreeall)
182 {
183 	unsigned int delta_time;
184 	u32 lifetime = SCANQUEUE_LIFETIME;
185 /* 	_irqL irqL; */
186 	struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
187 
188 	if (pnetwork == NULL)
189 		return;
190 
191 	if (pnetwork->fixed == true)
192 		return;
193 
194 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
195 		(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true))
196 		lifetime = 1;
197 
198 	if (!isfreeall) {
199 		delta_time = jiffies_to_msecs(jiffies - pnetwork->last_scanned);
200 		if (delta_time < lifetime)/*  unit:msec */
201 			return;
202 	}
203 
204 	spin_lock_bh(&free_queue->lock);
205 
206 	list_del_init(&(pnetwork->list));
207 
208 	list_add_tail(&(pnetwork->list), &(free_queue->queue));
209 
210 	pmlmepriv->num_of_scanned--;
211 
212 
213 	/* DBG_871X("_rtw_free_network:SSID =%s\n", pnetwork->network.Ssid.Ssid); */
214 
215 	spin_unlock_bh(&free_queue->lock);
216 }
217 
218 void _rtw_free_network_nolock(struct	mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
219 {
220 
221 	struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
222 
223 	if (pnetwork == NULL)
224 		return;
225 
226 	if (pnetwork->fixed == true)
227 		return;
228 
229 	/* spin_lock_irqsave(&free_queue->lock, irqL); */
230 
231 	list_del_init(&(pnetwork->list));
232 
233 	list_add_tail(&(pnetwork->list), get_list_head(free_queue));
234 
235 	pmlmepriv->num_of_scanned--;
236 
237 	/* spin_unlock_irqrestore(&free_queue->lock, irqL); */
238 }
239 
240 /*
241 	return the wlan_network with the matching addr
242 
243 	Shall be called under atomic context... to avoid possible racing condition...
244 */
245 struct wlan_network *_rtw_find_network(struct __queue *scanned_queue, u8 *addr)
246 {
247 	struct list_head	*phead, *plist;
248 	struct	wlan_network *pnetwork = NULL;
249 	u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
250 
251 	if (!memcmp(zero_addr, addr, ETH_ALEN)) {
252 		pnetwork = NULL;
253 		goto exit;
254 	}
255 
256 	/* spin_lock_bh(&scanned_queue->lock); */
257 
258 	phead = get_list_head(scanned_queue);
259 	plist = get_next(phead);
260 
261 	while (plist != phead) {
262 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
263 
264 		if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
265 			break;
266 
267 		plist = get_next(plist);
268 	}
269 
270 	if (plist == phead)
271 		pnetwork = NULL;
272 
273 	/* spin_unlock_bh(&scanned_queue->lock); */
274 
275 exit:
276 	return pnetwork;
277 }
278 
279 void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
280 {
281 	struct list_head *phead, *plist;
282 	struct wlan_network *pnetwork;
283 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
284 	struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
285 
286 	spin_lock_bh(&scanned_queue->lock);
287 
288 	phead = get_list_head(scanned_queue);
289 	plist = get_next(phead);
290 
291 	while (phead != plist) {
292 
293 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
294 
295 		plist = get_next(plist);
296 
297 		_rtw_free_network(pmlmepriv, pnetwork, isfreeall);
298 
299 	}
300 
301 	spin_unlock_bh(&scanned_queue->lock);
302 }
303 
304 
305 
306 
307 sint rtw_if_up(struct adapter *padapter)
308 {
309 
310 	sint res;
311 
312 	if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
313 		(check_fwstate(&padapter->mlmepriv, _FW_LINKED) == false)) {
314 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
315 		res = false;
316 	} else
317 		res =  true;
318 	return res;
319 }
320 
321 
322 void rtw_generate_random_ibss(u8 *pibss)
323 {
324 	unsigned long curtime = jiffies;
325 
326 	pibss[0] = 0x02;  /* in ad-hoc mode bit1 must set to 1 */
327 	pibss[1] = 0x11;
328 	pibss[2] = 0x87;
329 	pibss[3] = (u8)(curtime & 0xff) ;/* p[0]; */
330 	pibss[4] = (u8)((curtime>>8) & 0xff) ;/* p[1]; */
331 	pibss[5] = (u8)((curtime>>16) & 0xff) ;/* p[2]; */
332 	return;
333 }
334 
335 u8 *rtw_get_capability_from_ie(u8 *ie)
336 {
337 	return ie + 8 + 2;
338 }
339 
340 
341 u16 rtw_get_capability(struct wlan_bssid_ex *bss)
342 {
343 	__le16	val;
344 
345 	memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2);
346 
347 	return le16_to_cpu(val);
348 }
349 
350 u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
351 {
352 	return ie + 8;
353 }
354 
355 void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
356 {
357 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_mlme_priv\n"));
358 	_rtw_free_mlme_priv(pmlmepriv);
359 }
360 
361 /*
362 static struct	wlan_network *rtw_dequeue_network(struct __queue *queue)
363 {
364 	struct wlan_network *pnetwork;
365 
366 	pnetwork = _rtw_dequeue_network(queue);
367 	return pnetwork;
368 }
369 */
370 
371 void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnetwork);
372 void rtw_free_network_nolock(struct adapter *padapter, struct wlan_network *pnetwork)
373 {
374 	/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_network ==> ssid = %s\n\n" , pnetwork->network.Ssid.Ssid)); */
375 	_rtw_free_network_nolock(&(padapter->mlmepriv), pnetwork);
376 	rtw_cfg80211_unlink_bss(padapter, pnetwork);
377 }
378 
379 /*
380 	return the wlan_network with the matching addr
381 
382 	Shall be called under atomic context... to avoid possible racing condition...
383 */
384 struct	wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
385 {
386 	struct	wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr);
387 
388 	return pnetwork;
389 }
390 
391 int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
392 {
393 	int ret = true;
394 	struct security_priv *psecuritypriv = &adapter->securitypriv;
395 
396 	if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
397 		    (pnetwork->network.Privacy == 0))
398 		ret = false;
399 	else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
400 		 (pnetwork->network.Privacy == 1))
401 		ret = false;
402 	else
403 		ret = true;
404 
405 	return ret;
406 
407 }
408 
409 inline int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
410 {
411 	/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("(%s,%d)(%s,%d)\n", */
412 	/* 		a->Ssid.Ssid, a->Ssid.SsidLength, b->Ssid.Ssid, b->Ssid.SsidLength)); */
413 	return (a->Ssid.SsidLength == b->Ssid.SsidLength)
414 		&&  !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
415 }
416 
417 int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 feature)
418 {
419 	u16 s_cap, d_cap;
420 	__le16 tmps, tmpd;
421 
422 	if (rtw_bug_check(dst, src, &s_cap, &d_cap) == false)
423 			return false;
424 
425 	memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->IEs), 2);
426 	memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->IEs), 2);
427 
428 
429 	s_cap = le16_to_cpu(tmps);
430 	d_cap = le16_to_cpu(tmpd);
431 
432 	return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
433 		/* 	(src->Configuration.DSConfig == dst->Configuration.DSConfig) && */
434 			((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN))) &&
435 			((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength))) &&
436 			((s_cap & WLAN_CAPABILITY_IBSS) ==
437 			(d_cap & WLAN_CAPABILITY_IBSS)) &&
438 			((s_cap & WLAN_CAPABILITY_BSS) ==
439 			(d_cap & WLAN_CAPABILITY_BSS));
440 
441 }
442 
443 struct wlan_network *_rtw_find_same_network(struct __queue *scanned_queue, struct wlan_network *network)
444 {
445 	struct list_head *phead, *plist;
446 	struct wlan_network *found = NULL;
447 
448 	phead = get_list_head(scanned_queue);
449 	plist = get_next(phead);
450 
451 	while (plist != phead) {
452 		found = LIST_CONTAINOR(plist, struct wlan_network, list);
453 
454 		if (is_same_network(&network->network, &found->network, 0))
455 			break;
456 
457 		plist = get_next(plist);
458 	}
459 
460 	if (plist == phead)
461 		found = NULL;
462 
463 	return found;
464 }
465 
466 struct	wlan_network	*rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
467 {
468 	struct list_head	*plist, *phead;
469 
470 
471 	struct	wlan_network	*pwlan = NULL;
472 	struct	wlan_network	*oldest = NULL;
473 
474 	phead = get_list_head(scanned_queue);
475 
476 	plist = get_next(phead);
477 
478 	while (1) {
479 
480 		if (phead == plist)
481 			break;
482 
483 		pwlan = LIST_CONTAINOR(plist, struct wlan_network, list);
484 
485 		if (pwlan->fixed != true) {
486 			if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
487 				oldest = pwlan;
488 		}
489 
490 		plist = get_next(plist);
491 	}
492 	return oldest;
493 
494 }
495 
496 void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
497 	struct adapter *padapter, bool update_ie)
498 {
499 	long rssi_ori = dst->Rssi;
500 
501 	u8 sq_smp = src->PhyInfo.SignalQuality;
502 
503 	u8 ss_final;
504 	u8 sq_final;
505 	long rssi_final;
506 
507 	#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1
508 	if (strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
509 		DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT", ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n"
510 			, FUNC_ADPT_ARG(padapter)
511 			, src->Ssid.Ssid, MAC_ARG(src->MacAddress), src->Configuration.DSConfig
512 			, ss_ori, sq_ori, rssi_ori
513 			, ss_smp, sq_smp, rssi_smp
514 		);
515 	}
516 	#endif
517 
518 	/* The rule below is 1/5 for sample value, 4/5 for history value */
519 	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src, 0)) {
520 		/* Take the recvpriv's value for the connected AP*/
521 		ss_final = padapter->recvpriv.signal_strength;
522 		sq_final = padapter->recvpriv.signal_qual;
523 		/* the rssi value here is undecorated, and will be used for antenna diversity */
524 		if (sq_smp != 101) /* from the right channel */
525 			rssi_final = (src->Rssi+dst->Rssi*4)/5;
526 		else
527 			rssi_final = rssi_ori;
528 	} else {
529 		if (sq_smp != 101) { /* from the right channel */
530 			ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
531 			sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
532 			rssi_final = (src->Rssi+dst->Rssi*4)/5;
533 		} else {
534 			/* bss info not receiving from the right channel, use the original RX signal infos */
535 			ss_final = dst->PhyInfo.SignalStrength;
536 			sq_final = dst->PhyInfo.SignalQuality;
537 			rssi_final = dst->Rssi;
538 		}
539 
540 	}
541 
542 	if (update_ie) {
543 		dst->Reserved[0] = src->Reserved[0];
544 		dst->Reserved[1] = src->Reserved[1];
545 		memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
546 	}
547 
548 	dst->PhyInfo.SignalStrength = ss_final;
549 	dst->PhyInfo.SignalQuality = sq_final;
550 	dst->Rssi = rssi_final;
551 
552 	#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1
553 	if (strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
554 		DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT"), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n"
555 			, FUNC_ADPT_ARG(padapter)
556 			, dst->Ssid.Ssid, MAC_ARG(dst->MacAddress), dst->PhyInfo.SignalStrength, dst->PhyInfo.SignalQuality, dst->Rssi);
557 	}
558 	#endif
559 }
560 
561 static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
562 {
563 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
564 
565 	rtw_bug_check(&(pmlmepriv->cur_network.network),
566 		&(pmlmepriv->cur_network.network),
567 		&(pmlmepriv->cur_network.network),
568 		&(pmlmepriv->cur_network.network));
569 
570 	if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork, 0))) {
571 		/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"Same Network\n"); */
572 
573 		/* if (pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
574 		{
575 			update_network(&(pmlmepriv->cur_network.network), pnetwork, adapter, true);
576 			rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(struct ndis_802_11_fix_ie),
577 									pmlmepriv->cur_network.network.IELength);
578 		}
579 	}
580 }
581 
582 
583 /*
584 
585 Caller must hold pmlmepriv->lock first.
586 
587 
588 */
589 void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
590 {
591 	struct list_head	*plist, *phead;
592 	u32 bssid_ex_sz;
593 	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
594 	struct __queue	*queue	= &(pmlmepriv->scanned_queue);
595 	struct wlan_network	*pnetwork = NULL;
596 	struct wlan_network	*oldest = NULL;
597 	int target_find = 0;
598 	u8 feature = 0;
599 
600 	spin_lock_bh(&queue->lock);
601 	phead = get_list_head(queue);
602 	plist = get_next(phead);
603 
604 	while (1) {
605 		if (phead == plist)
606 			break;
607 
608 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
609 
610 		rtw_bug_check(pnetwork, pnetwork, pnetwork, pnetwork);
611 
612 		if (is_same_network(&(pnetwork->network), target, feature)) {
613 			target_find = 1;
614 			break;
615 		}
616 
617 		if (rtw_roam_flags(adapter)) {
618 			/* TODO: don't  select netowrk in the same ess as oldest if it's new enough*/
619 		}
620 
621 		if (oldest == NULL || time_after(oldest->last_scanned, pnetwork->last_scanned))
622 			oldest = pnetwork;
623 
624 		plist = get_next(plist);
625 
626 	}
627 
628 
629 	/* If we didn't find a match, then get a new network slot to initialize
630 	 * with this beacon's information */
631 	/* if (phead == plist) { */
632 	if (!target_find) {
633 		if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
634 			/* If there are no more slots, expire the oldest */
635 			/* list_del_init(&oldest->list); */
636 			pnetwork = oldest;
637 			if (pnetwork == NULL) {
638 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
639 				goto exit;
640 			}
641 			memcpy(&(pnetwork->network), target,  get_wlan_bssid_ex_sz(target));
642 			/*  variable initialize */
643 			pnetwork->fixed = false;
644 			pnetwork->last_scanned = jiffies;
645 
646 			pnetwork->network_type = 0;
647 			pnetwork->aid = 0;
648 			pnetwork->join_res = 0;
649 
650 			/* bss info not receiving from the right channel */
651 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
652 				pnetwork->network.PhyInfo.SignalQuality = 0;
653 		} else {
654 			/* Otherwise just pull from the free list */
655 
656 			pnetwork = rtw_alloc_network(pmlmepriv); /*  will update scan_time */
657 
658 			if (pnetwork == NULL) {
659 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
660 				goto exit;
661 			}
662 
663 			bssid_ex_sz = get_wlan_bssid_ex_sz(target);
664 			target->Length = bssid_ex_sz;
665 			memcpy(&(pnetwork->network), target, bssid_ex_sz);
666 
667 			pnetwork->last_scanned = jiffies;
668 
669 			/* bss info not receiving from the right channel */
670 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
671 				pnetwork->network.PhyInfo.SignalQuality = 0;
672 
673 			list_add_tail(&(pnetwork->list), &(queue->queue));
674 
675 		}
676 	} else {
677 		/* we have an entry and we are going to update it. But this entry may
678 		 * be already expired. In this case we do the same as we found a new
679 		 * net and call the new_net handler
680 		 */
681 		bool update_ie = true;
682 
683 		pnetwork->last_scanned = jiffies;
684 
685 		/* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
686 		if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
687 			update_ie = false;
688 
689 		/*  probe resp(3) > beacon(1) > probe req(2) */
690 		if ((target->Reserved[0] != 2) &&
691 			(target->Reserved[0] >= pnetwork->network.Reserved[0])
692 			) {
693 			update_ie = true;
694 		} else {
695 			update_ie = false;
696 		}
697 
698 		update_network(&(pnetwork->network), target, adapter, update_ie);
699 	}
700 
701 exit:
702 	spin_unlock_bh(&queue->lock);
703 }
704 
705 void rtw_add_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork);
706 void rtw_add_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
707 {
708 	/* struct __queue	*queue	= &(pmlmepriv->scanned_queue); */
709 
710 	/* spin_lock_bh(&queue->lock); */
711 
712 	update_current_network(adapter, pnetwork);
713 
714 	rtw_update_scanned_network(adapter, pnetwork);
715 
716 	/* spin_unlock_bh(&queue->lock); */
717 }
718 
719 /* select the desired network based on the capability of the (i)bss. */
720 /*  check items: (1) security */
721 /* 			   (2) network_type */
722 /* 			   (3) WMM */
723 /* 			   (4) HT */
724 /*                      (5) others */
725 int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork);
726 int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
727 {
728 	struct security_priv *psecuritypriv = &adapter->securitypriv;
729 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
730 	u32 desired_encmode;
731 	u32 privacy;
732 
733 	/* u8 wps_ie[512]; */
734 	uint wps_ielen;
735 
736 	int bselected = true;
737 
738 	desired_encmode = psecuritypriv->ndisencryptstatus;
739 	privacy = pnetwork->network.Privacy;
740 
741 	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
742 		if (rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen) != NULL)
743 			return true;
744 		else
745 			return false;
746 
747 	}
748 	if (adapter->registrypriv.wifi_spec == 1) { /* for  correct flow of 8021X  to do.... */
749 		u8 *p = NULL;
750 		uint ie_len = 0;
751 
752 		if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
753 	    bselected = false;
754 
755 		if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
756 			p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));
757 			if (p && ie_len > 0) {
758 				bselected = true;
759 			} else {
760 				bselected = false;
761 			}
762 		}
763 	}
764 
765 
766 	if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
767 		DBG_871X("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
768 		bselected = false;
769 	}
770 
771 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
772 		if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
773 			bselected = false;
774 	}
775 
776 
777 	return bselected;
778 }
779 
780 /* TODO: Perry : For Power Management */
781 void rtw_atimdone_event_callback(struct adapter	*adapter, u8 *pbuf)
782 {
783 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_event\n"));
784 }
785 
786 
787 void rtw_survey_event_callback(struct adapter	*adapter, u8 *pbuf)
788 {
789 	u32 len;
790 	struct wlan_bssid_ex *pnetwork;
791 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
792 
793 	pnetwork = (struct wlan_bssid_ex *)pbuf;
794 
795 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_survey_event_callback, ssid =%s\n",  pnetwork->Ssid.Ssid));
796 
797 	len = get_wlan_bssid_ex_sz(pnetwork);
798 	if (len > (sizeof(struct wlan_bssid_ex))) {
799 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n ****rtw_survey_event_callback: return a wrong bss ***\n"));
800 		return;
801 	}
802 
803 
804 	spin_lock_bh(&pmlmepriv->lock);
805 
806 	/*  update IBSS_network 's timestamp */
807 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) {
808 		/* RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,"rtw_survey_event_callback : WIFI_ADHOC_MASTER_STATE\n\n"); */
809 		if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
810 			struct wlan_network *ibss_wlan = NULL;
811 
812 			memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
813 			spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
814 			ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
815 			if (ibss_wlan) {
816 				memcpy(ibss_wlan->network.IEs, pnetwork->IEs, 8);
817 				spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
818 				goto exit;
819 			}
820 			spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
821 		}
822 	}
823 
824 	/*  lock pmlmepriv->lock when you accessing network_q */
825 	if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false) {
826 		if (pnetwork->Ssid.Ssid[0] == 0) {
827 			pnetwork->Ssid.SsidLength = 0;
828 		}
829 		rtw_add_network(adapter, pnetwork);
830 	}
831 
832 exit:
833 
834 	spin_unlock_bh(&pmlmepriv->lock);
835 
836 	return;
837 }
838 
839 
840 
841 void rtw_surveydone_event_callback(struct adapter	*adapter, u8 *pbuf)
842 {
843 	u8 timer_cancelled = false;
844 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
845 
846 	spin_lock_bh(&pmlmepriv->lock);
847 	if (pmlmepriv->wps_probe_req_ie) {
848 		pmlmepriv->wps_probe_req_ie_len = 0;
849 		kfree(pmlmepriv->wps_probe_req_ie);
850 		pmlmepriv->wps_probe_req_ie = NULL;
851 	}
852 
853 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
854 
855 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
856 		/* u8 timer_cancelled; */
857 
858 		timer_cancelled = true;
859 		/* _cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled); */
860 
861 		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
862 	} else {
863 
864 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status =%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
865 	}
866 	spin_unlock_bh(&pmlmepriv->lock);
867 
868 	if (timer_cancelled)
869 		_cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
870 
871 
872 	spin_lock_bh(&pmlmepriv->lock);
873 
874 	rtw_set_signal_stat_timer(&adapter->recvpriv);
875 
876 	if (pmlmepriv->to_join == true) {
877 		if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
878 			if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
879 				set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
880 
881 				if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
882 					_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
883 				} else {
884 					struct wlan_bssid_ex    *pdev_network = &(adapter->registrypriv.dev_network);
885 					u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
886 
887 					/* pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;because don't set assoc_timer */
888 					_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
889 
890 					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
891 
892 					memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
893 
894 					rtw_update_registrypriv_dev_network(adapter);
895 					rtw_generate_random_ibss(pibss);
896 
897 					pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
898 
899 					if (rtw_createbss_cmd(adapter) != _SUCCESS) {
900 					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error =>rtw_createbss_cmd status FAIL\n"));
901 					}
902 
903 					pmlmepriv->to_join = false;
904 				}
905 			}
906 		} else {
907 			int s_ret;
908 			set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
909 			pmlmepriv->to_join = false;
910 			s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
911 			if (_SUCCESS == s_ret) {
912 			     _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
913 			} else if (s_ret == 2) {/* there is no need to wait for join */
914 				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
915 				rtw_indicate_connect(adapter);
916 			} else {
917 				DBG_871X("try_to_join, but select scanning queue fail, to_roam:%d\n", rtw_to_roam(adapter));
918 
919 				if (rtw_to_roam(adapter) != 0) {
920 					if (rtw_dec_to_roam(adapter) == 0
921 						|| _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
922 					) {
923 						rtw_set_to_roam(adapter, 0);
924 						rtw_free_assoc_resources(adapter, 1);
925 						rtw_indicate_disconnect(adapter);
926 					} else {
927 						pmlmepriv->to_join = true;
928 					}
929 				} else
930 					rtw_indicate_disconnect(adapter);
931 
932 				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
933 			}
934 		}
935 	} else {
936 		if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
937 			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
938 				&& check_fwstate(pmlmepriv, _FW_LINKED)) {
939 				if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
940 					receive_disconnect(adapter, pmlmepriv->cur_network.network.MacAddress
941 						, WLAN_REASON_ACTIVE_ROAM);
942 				}
943 			}
944 		}
945 	}
946 
947 	/* DBG_871X("scan complete in %dms\n", jiffies_to_msecs(jiffies - pmlmepriv->scan_start_time)); */
948 
949 	spin_unlock_bh(&pmlmepriv->lock);
950 
951 	rtw_os_xmit_schedule(adapter);
952 
953 	rtw_cfg80211_surveydone_event_callback(adapter);
954 
955 	rtw_indicate_scan_done(adapter, false);
956 }
957 
958 void rtw_dummy_event_callback(struct adapter *adapter, u8 *pbuf)
959 {
960 }
961 
962 void rtw_fwdbg_event_callback(struct adapter *adapter, u8 *pbuf)
963 {
964 }
965 
966 static void free_scanqueue(struct	mlme_priv *pmlmepriv)
967 {
968 	struct __queue *free_queue = &pmlmepriv->free_bss_pool;
969 	struct __queue *scan_queue = &pmlmepriv->scanned_queue;
970 	struct list_head	*plist, *phead, *ptemp;
971 
972 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
973 	spin_lock_bh(&scan_queue->lock);
974 	spin_lock_bh(&free_queue->lock);
975 
976 	phead = get_list_head(scan_queue);
977 	plist = get_next(phead);
978 
979 	while (plist != phead) {
980 		ptemp = get_next(plist);
981 		list_del_init(plist);
982 		list_add_tail(plist, &free_queue->queue);
983 		plist = ptemp;
984 		pmlmepriv->num_of_scanned--;
985 	}
986 
987 	spin_unlock_bh(&free_queue->lock);
988 	spin_unlock_bh(&scan_queue->lock);
989 }
990 
991 static void rtw_reset_rx_info(struct debug_priv *pdbgpriv)
992 {
993 	pdbgpriv->dbg_rx_ampdu_drop_count = 0;
994 	pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0;
995 	pdbgpriv->dbg_rx_ampdu_loss_count = 0;
996 	pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0;
997 	pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0;
998 }
999 
1000 static void find_network(struct adapter *adapter)
1001 {
1002 	struct wlan_network *pwlan = NULL;
1003 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
1004 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1005 
1006 	pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1007 	if (pwlan)
1008 		pwlan->fixed = false;
1009 	else
1010 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_assoc_resources : pwlan == NULL\n\n"));
1011 
1012 
1013 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) &&
1014 	    (adapter->stapriv.asoc_sta_count == 1))
1015 		rtw_free_network_nolock(adapter, pwlan);
1016 }
1017 
1018 /*
1019 *rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
1020 */
1021 void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
1022 {
1023 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
1024 	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
1025 	struct	sta_priv *pstapriv = &adapter->stapriv;
1026 	struct dvobj_priv *psdpriv = adapter->dvobj;
1027 	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
1028 
1029 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
1030 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress ="MAC_FMT" ssid =%s\n",
1031 		MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.Ssid));
1032 
1033 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
1034 		struct sta_info *psta;
1035 
1036 		psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
1037 		spin_lock_bh(&(pstapriv->sta_hash_lock));
1038 		rtw_free_stainfo(adapter,  psta);
1039 
1040 		spin_unlock_bh(&(pstapriv->sta_hash_lock));
1041 
1042 	}
1043 
1044 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)) {
1045 		struct sta_info *psta;
1046 
1047 		rtw_free_all_stainfo(adapter);
1048 
1049 		psta = rtw_get_bcmc_stainfo(adapter);
1050 		rtw_free_stainfo(adapter, psta);
1051 
1052 		rtw_init_bcmc_stainfo(adapter);
1053 	}
1054 
1055 	find_network(adapter);
1056 
1057 	if (lock_scanned_queue)
1058 		adapter->securitypriv.key_mask = 0;
1059 
1060 	rtw_reset_rx_info(pdbgpriv);
1061 }
1062 
1063 /*
1064 *rtw_indicate_connect: the caller has to lock pmlmepriv->lock
1065 */
1066 void rtw_indicate_connect(struct adapter *padapter)
1067 {
1068 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1069 
1070 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect\n"));
1071 
1072 	pmlmepriv->to_join = false;
1073 
1074 	if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
1075 
1076 		set_fwstate(pmlmepriv, _FW_LINKED);
1077 
1078 		rtw_os_indicate_connect(padapter);
1079 	}
1080 
1081 	rtw_set_to_roam(padapter, 0);
1082 	rtw_set_scan_deny(padapter, 3000);
1083 
1084 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect: fw_state = 0x%08x\n", get_fwstate(pmlmepriv)));
1085 }
1086 
1087 /*
1088 *rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
1089 */
1090 void rtw_indicate_disconnect(struct adapter *padapter)
1091 {
1092 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1093 
1094 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect\n"));
1095 
1096 	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
1097 
1098 	/* DBG_871X("clear wps when %s\n", __func__); */
1099 
1100 	if (rtw_to_roam(padapter) > 0)
1101 		_clr_fwstate_(pmlmepriv, _FW_LINKED);
1102 
1103 	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)
1104 		|| (rtw_to_roam(padapter) <= 0)
1105 	) {
1106 		rtw_os_indicate_disconnect(padapter);
1107 
1108 		/* set ips_deny_time to avoid enter IPS before LPS leave */
1109 		rtw_set_ips_deny(padapter, 3000);
1110 
1111 		_clr_fwstate_(pmlmepriv, _FW_LINKED);
1112 
1113 		rtw_clear_scan_deny(padapter);
1114 	}
1115 
1116 	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
1117 }
1118 
1119 inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
1120 {
1121 	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1122 
1123 	rtw_os_indicate_scan_done(padapter, aborted);
1124 
1125 	if (is_primary_adapter(padapter) &&
1126 	    (!adapter_to_pwrctl(padapter)->bInSuspend) &&
1127 	    (!check_fwstate(&padapter->mlmepriv,
1128 			    WIFI_ASOC_STATE|WIFI_UNDER_LINKING))) {
1129 		struct pwrctrl_priv *pwrpriv;
1130 
1131 		pwrpriv = adapter_to_pwrctl(padapter);
1132 		rtw_set_ips_deny(padapter, 0);
1133 		_set_timer(&padapter->mlmepriv.dynamic_chk_timer, 1);
1134 	}
1135 }
1136 
1137 void rtw_scan_abort(struct adapter *adapter)
1138 {
1139 	unsigned long start;
1140 	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1141 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
1142 
1143 	start = jiffies;
1144 	pmlmeext->scan_abort = true;
1145 	while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)
1146 		&& jiffies_to_msecs(start) <= 200) {
1147 
1148 		if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1149 			break;
1150 
1151 		DBG_871X(FUNC_NDEV_FMT"fw_state = _FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
1152 		msleep(20);
1153 	}
1154 
1155 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
1156 		if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
1157 			DBG_871X(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
1158 		rtw_indicate_scan_done(adapter, true);
1159 	}
1160 	pmlmeext->scan_abort = false;
1161 }
1162 
1163 static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
1164 {
1165 	int i;
1166 	struct sta_info *bmc_sta, *psta = NULL;
1167 	struct recv_reorder_ctrl *preorder_ctrl;
1168 	struct sta_priv *pstapriv = &padapter->stapriv;
1169 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1170 
1171 	psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
1172 	if (psta == NULL) {
1173 		psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
1174 	}
1175 
1176 	if (psta) { /* update ptarget_sta */
1177 
1178 		DBG_871X("%s\n", __func__);
1179 
1180 		psta->aid  = pnetwork->join_res;
1181 
1182 		update_sta_info(padapter, psta);
1183 
1184 		/* update station supportRate */
1185 		psta->bssratelen = rtw_get_rateset_len(pnetwork->network.SupportedRates);
1186 		memcpy(psta->bssrateset, pnetwork->network.SupportedRates, psta->bssratelen);
1187 		rtw_hal_update_sta_rate_mask(padapter, psta);
1188 
1189 		psta->wireless_mode = pmlmeext->cur_wireless_mode;
1190 		psta->raid = networktype_to_raid_ex(padapter, psta);
1191 
1192 
1193 		/* sta mode */
1194 		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
1195 
1196 		/* security related */
1197 		if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1198 			padapter->securitypriv.binstallGrpkey = false;
1199 			padapter->securitypriv.busetkipkey = false;
1200 			padapter->securitypriv.bgrpkey_handshake = false;
1201 
1202 			psta->ieee8021x_blocked = true;
1203 			psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
1204 
1205 			memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
1206 
1207 			memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
1208 			memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
1209 
1210 			memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
1211 			psta->dot11txpn.val = psta->dot11txpn.val + 1;
1212 			memset((u8 *)&psta->dot11wtxpn, 0, sizeof(union pn48));
1213 			memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
1214 		}
1215 
1216 		/* 	Commented by Albert 2012/07/21 */
1217 		/* 	When doing the WPS, the wps_ie_len won't equal to 0 */
1218 		/* 	And the Wi-Fi driver shouldn't allow the data packet to be transmitted. */
1219 		if (padapter->securitypriv.wps_ie_len != 0) {
1220 			psta->ieee8021x_blocked = true;
1221 			padapter->securitypriv.wps_ie_len = 0;
1222 		}
1223 
1224 
1225 		/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
1226 		/* if A-MPDU Rx is enabled, resetting  rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
1227 		/* todo: check if AP can send A-MPDU packets */
1228 		for (i = 0; i < 16 ; i++) {
1229 			/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1230 			preorder_ctrl = &psta->recvreorder_ctrl[i];
1231 			preorder_ctrl->enable = false;
1232 			preorder_ctrl->indicate_seq = 0xffff;
1233 			#ifdef DBG_RX_SEQ
1234 			DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
1235 				preorder_ctrl->indicate_seq);
1236 			#endif
1237 			preorder_ctrl->wend_b = 0xffff;
1238 			preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
1239 		}
1240 
1241 
1242 		bmc_sta = rtw_get_bcmc_stainfo(padapter);
1243 		if (bmc_sta) {
1244 			for (i = 0; i < 16 ; i++) {
1245 				/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
1246 				preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1247 				preorder_ctrl->enable = false;
1248 				preorder_ctrl->indicate_seq = 0xffff;
1249 				#ifdef DBG_RX_SEQ
1250 				DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u\n", __func__, __LINE__,
1251 					preorder_ctrl->indicate_seq);
1252 				#endif
1253 				preorder_ctrl->wend_b = 0xffff;
1254 				preorder_ctrl->wsize_b = 64;/* max_ampdu_sz;ex. 32(kbytes) -> wsize_b =32 */
1255 			}
1256 		}
1257 	}
1258 
1259 	return psta;
1260 
1261 }
1262 
1263 /* pnetwork : returns from rtw_joinbss_event_callback */
1264 /* ptarget_wlan: found from scanned_queue */
1265 static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network  *pnetwork)
1266 {
1267 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1268 	struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
1269 
1270 	DBG_871X("%s\n", __func__);
1271 
1272 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nfw_state:%x, BSSID:"MAC_FMT"\n"
1273 		, get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
1274 
1275 
1276 	/*  why not use ptarget_wlan?? */
1277 	memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
1278 	/*  some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
1279 	cur_network->network.IELength = ptarget_wlan->network.IELength;
1280 	memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
1281 
1282 	cur_network->aid = pnetwork->join_res;
1283 
1284 
1285 	rtw_set_signal_stat_timer(&padapter->recvpriv);
1286 
1287 	padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
1288 	padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
1289 	/* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
1290 	padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
1291 	#if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
1292 		DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"
1293 			"\n"
1294 			, FUNC_ADPT_ARG(padapter)
1295 			, padapter->recvpriv.signal_strength
1296 			, padapter->recvpriv.rssi
1297 			, padapter->recvpriv.signal_qual
1298 	);
1299 	#endif
1300 
1301 	rtw_set_signal_stat_timer(&padapter->recvpriv);
1302 
1303 	/* update fw_state will clr _FW_UNDER_LINKING here indirectly */
1304 	switch (pnetwork->network.InfrastructureMode) {
1305 	case Ndis802_11Infrastructure:
1306 
1307 			if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
1308 				pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
1309 			else
1310 				pmlmepriv->fw_state = WIFI_STATION_STATE;
1311 
1312 			break;
1313 	case Ndis802_11IBSS:
1314 			pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1315 			break;
1316 	default:
1317 			pmlmepriv->fw_state = WIFI_NULL_STATE;
1318 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
1319 			break;
1320 	}
1321 
1322 	rtw_update_protection(padapter, (cur_network->network.IEs) + sizeof(struct ndis_802_11_fix_ie),
1323 									(cur_network->network.IELength));
1324 
1325 	rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength, (u8) cur_network->network.Configuration.DSConfig);
1326 }
1327 
1328 /* Notes: the function could be > passive_level (the same context as Rx tasklet) */
1329 /* pnetwork : returns from rtw_joinbss_event_callback */
1330 /* ptarget_wlan: found from scanned_queue */
1331 /* if join_res > 0, for (fw_state ==WIFI_STATION_STATE), we check if  "ptarget_sta" & "ptarget_wlan" exist. */
1332 /* if join_res > 0, for (fw_state ==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
1333 /* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */
1334 /*  */
1335 /* define REJOIN */
1336 void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
1337 {
1338 	static u8 retry;
1339 	u8 timer_cancelled;
1340 	struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
1341 	struct	sta_priv *pstapriv = &adapter->stapriv;
1342 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1343 	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
1344 	struct wlan_network	*cur_network = &(pmlmepriv->cur_network);
1345 	struct wlan_network	*pcur_wlan = NULL, *ptarget_wlan = NULL;
1346 	unsigned int		the_same_macaddr = false;
1347 
1348 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("joinbss event call back received with res =%d\n", pnetwork->join_res));
1349 
1350 	rtw_get_encrypt_decrypt_from_registrypriv(adapter);
1351 
1352 
1353 	if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1354 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@   joinbss event call back  for Any SSid\n"));
1355 	} else {
1356 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@   rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
1357 	}
1358 
1359 	the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
1360 
1361 	pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
1362 	if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
1363 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
1364 		return;
1365 	}
1366 
1367 	spin_lock_bh(&pmlmepriv->lock);
1368 
1369 	pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
1370 	pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
1371 
1372 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\n rtw_joinbss_event_callback !! spin_lock_irqsave\n"));
1373 
1374 	if (pnetwork->join_res > 0) {
1375 		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1376 		retry = 0;
1377 		if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1378 			/* s1. find ptarget_wlan */
1379 			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1380 				if (the_same_macaddr == true) {
1381 					ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1382 				} else {
1383 					pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1384 					if (pcur_wlan)
1385 						pcur_wlan->fixed = false;
1386 
1387 					pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
1388 					if (pcur_sta)
1389 						rtw_free_stainfo(adapter,  pcur_sta);
1390 
1391 					ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1392 					if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1393 						if (ptarget_wlan)
1394 							ptarget_wlan->fixed = true;
1395 					}
1396 				}
1397 
1398 			} else {
1399 				ptarget_wlan = _rtw_find_same_network(&pmlmepriv->scanned_queue, pnetwork);
1400 				if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1401 					if (ptarget_wlan)
1402 						ptarget_wlan->fixed = true;
1403 				}
1404 			}
1405 
1406 			/* s2. update cur_network */
1407 			if (ptarget_wlan) {
1408 				rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork);
1409 			} else {
1410 				DBG_871X_LEVEL(_drv_always_, "Can't find ptarget_wlan when joinbss_event callback\n");
1411 				spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1412 				goto ignore_joinbss_callback;
1413 			}
1414 
1415 
1416 			/* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
1417 			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1418 				ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
1419 				if (ptarget_sta == NULL) {
1420 					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't update stainfo when joinbss_event callback\n"));
1421 					spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1422 					goto ignore_joinbss_callback;
1423 				}
1424 			}
1425 
1426 			/* s4. indicate connect */
1427 			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1428 				pmlmepriv->cur_network_scanned = ptarget_wlan;
1429 				rtw_indicate_connect(adapter);
1430 			} else {
1431 				/* adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback */
1432 				RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
1433 			}
1434 
1435 
1436 			/* s5. Cancel assoc_timer */
1437 			_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
1438 
1439 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancel assoc_timer\n"));
1440 
1441 		} else {
1442 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
1443 			spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1444 			goto ignore_joinbss_callback;
1445 		}
1446 
1447 		spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1448 
1449 	} else if (pnetwork->join_res == -4) {
1450 		rtw_reset_securitypriv(adapter);
1451 		_set_timer(&pmlmepriv->assoc_timer, 1);
1452 
1453 		/* rtw_free_assoc_resources(adapter, 1); */
1454 
1455 		if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == true) {
1456 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("fail! clear _FW_UNDER_LINKING ^^^fw_state =%x\n", get_fwstate(pmlmepriv)));
1457 			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1458 		}
1459 
1460 	} else {/* if join_res < 0 (join fails), then try again */
1461 
1462 		#ifdef REJOIN
1463 		res = _FAIL;
1464 		if (retry < 2) {
1465 			res = rtw_select_and_join_from_scanned_queue(pmlmepriv);
1466 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_select_and_join_from_scanned_queue again! res:%d\n", res));
1467 		}
1468 
1469 		if (res == _SUCCESS) {
1470 			/* extend time of assoc_timer */
1471 			_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
1472 			retry++;
1473 		} else if (res == 2) {/* there is no need to wait for join */
1474 			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1475 			rtw_indicate_connect(adapter);
1476 		} else {
1477 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Set Assoc_Timer = 1; can't find match ssid in scanned_q\n"));
1478 		#endif
1479 
1480 			_set_timer(&pmlmepriv->assoc_timer, 1);
1481 			/* rtw_free_assoc_resources(adapter, 1); */
1482 			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1483 
1484 		#ifdef REJOIN
1485 			retry = 0;
1486 		}
1487 		#endif
1488 	}
1489 
1490 ignore_joinbss_callback:
1491 
1492 	spin_unlock_bh(&pmlmepriv->lock);
1493 }
1494 
1495 void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
1496 {
1497 	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
1498 
1499 	mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
1500 
1501 	rtw_os_xmit_schedule(adapter);
1502 }
1503 
1504 /* FOR STA, AP , AD-HOC mode */
1505 void rtw_sta_media_status_rpt(struct adapter *adapter, struct sta_info *psta, u32 mstatus)
1506 {
1507 	u16 media_status_rpt;
1508 
1509 	if (psta == NULL)
1510 		return;
1511 
1512 	media_status_rpt = (u16)((psta->mac_id<<8)|mstatus); /*   MACID|OPMODE:1 connect */
1513 	rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status_rpt);
1514 }
1515 
1516 void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
1517 {
1518 	struct sta_info *psta;
1519 	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1520 	struct stassoc_event	*pstassoc	= (struct stassoc_event *)pbuf;
1521 	struct wlan_network	*cur_network = &(pmlmepriv->cur_network);
1522 	struct wlan_network	*ptarget_wlan = NULL;
1523 
1524 	if (rtw_access_ctrl(adapter, pstassoc->macaddr) == false)
1525 		return;
1526 
1527 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1528 		psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
1529 		if (psta) {
1530 			u8 *passoc_req = NULL;
1531 			u32 assoc_req_len = 0;
1532 
1533 			rtw_sta_media_status_rpt(adapter, psta, 1);
1534 
1535 #ifndef CONFIG_AUTO_AP_MODE
1536 
1537 			ap_sta_info_defer_update(adapter, psta);
1538 
1539 			/* report to upper layer */
1540 			DBG_871X("indicate_sta_assoc_event to upper layer - hostapd\n");
1541 			spin_lock_bh(&psta->lock);
1542 			if (psta->passoc_req && psta->assoc_req_len > 0) {
1543 				passoc_req = rtw_zmalloc(psta->assoc_req_len);
1544 				if (passoc_req) {
1545 					assoc_req_len = psta->assoc_req_len;
1546 					memcpy(passoc_req, psta->passoc_req, assoc_req_len);
1547 
1548 					kfree(psta->passoc_req);
1549 					psta->passoc_req = NULL;
1550 					psta->assoc_req_len = 0;
1551 				}
1552 			}
1553 			spin_unlock_bh(&psta->lock);
1554 
1555 			if (passoc_req && assoc_req_len > 0) {
1556 				rtw_cfg80211_indicate_sta_assoc(adapter, passoc_req, assoc_req_len);
1557 
1558 				kfree(passoc_req);
1559 			}
1560 #endif /* CONFIG_AUTO_AP_MODE */
1561 		}
1562 		return;
1563 	}
1564 
1565 	/* for AD-HOC mode */
1566 	psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
1567 	if (psta != NULL) {
1568 		/* the sta have been in sta_info_queue => do nothing */
1569 
1570 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error: rtw_stassoc_event_callback: sta has been in sta_hash_queue\n"));
1571 
1572 		return; /* between drv has received this event before and  fw have not yet to set key to CAM_ENTRY) */
1573 	}
1574 
1575 	psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
1576 	if (psta == NULL) {
1577 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't alloc sta_info when rtw_stassoc_event_callback\n"));
1578 		return;
1579 	}
1580 
1581 	/* to do : init sta_info variable */
1582 	psta->qos_option = 0;
1583 	psta->mac_id = (uint)pstassoc->cam_id;
1584 	/* psta->aid = (uint)pstassoc->cam_id; */
1585 	DBG_871X("%s\n", __func__);
1586 	/* for ad-hoc mode */
1587 	rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true);
1588 
1589 	rtw_sta_media_status_rpt(adapter, psta, 1);
1590 
1591 	if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1592 		psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1593 
1594 
1595 	psta->ieee8021x_blocked = false;
1596 
1597 	spin_lock_bh(&pmlmepriv->lock);
1598 
1599 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
1600 		(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
1601 		if (adapter->stapriv.asoc_sta_count == 2) {
1602 			spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1603 			ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1604 			pmlmepriv->cur_network_scanned = ptarget_wlan;
1605 			if (ptarget_wlan)
1606 				ptarget_wlan->fixed = true;
1607 			spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1608 			/*  a sta + bc/mc_stainfo (not Ibss_stainfo) */
1609 			rtw_indicate_connect(adapter);
1610 		}
1611 	}
1612 
1613 	spin_unlock_bh(&pmlmepriv->lock);
1614 
1615 
1616 	mlmeext_sta_add_event_callback(adapter, psta);
1617 }
1618 
1619 void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
1620 {
1621 	int mac_id = (-1);
1622 	struct sta_info *psta;
1623 	struct wlan_network *pwlan = NULL;
1624 	struct wlan_bssid_ex    *pdev_network = NULL;
1625 	u8 *pibss = NULL;
1626 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1627 	struct	stadel_event *pstadel	= (struct stadel_event *)pbuf;
1628 	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
1629 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1630 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1631 
1632 	psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
1633 	if (psta)
1634 		mac_id = psta->mac_id;
1635 	else
1636 		mac_id = pstadel->mac_id;
1637 
1638 	DBG_871X("%s(mac_id =%d) =" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
1639 
1640 	if (mac_id >= 0) {
1641 		u16 media_status;
1642 		media_status = (mac_id<<8)|0; /*   MACID|OPMODE:0 means disconnect */
1643 		/* for STA, AP, ADHOC mode, report disconnect stauts to FW */
1644 		rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1645 	}
1646 
1647 	/* if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) */
1648 	if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
1649 		return;
1650 
1651 
1652 	mlmeext_sta_del_event_callback(adapter);
1653 
1654 	spin_lock_bh(&pmlmepriv->lock);
1655 
1656 	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1657 		u16 reason = *((unsigned short *)(pstadel->rsvd));
1658 		bool roam = false;
1659 		struct wlan_network *roam_target = NULL;
1660 
1661 		if (adapter->registrypriv.wifi_spec == 1) {
1662 			roam = false;
1663 		} else if (reason == WLAN_REASON_EXPIRATION_CHK && rtw_chk_roam_flags(adapter, RTW_ROAM_ON_EXPIRED)) {
1664 			roam = true;
1665 		} else if (reason == WLAN_REASON_ACTIVE_ROAM && rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
1666 			roam = true;
1667 			roam_target = pmlmepriv->roam_network;
1668 		}
1669 
1670 		if (roam) {
1671 			if (rtw_to_roam(adapter) > 0)
1672 				rtw_dec_to_roam(adapter); /* this stadel_event is caused by roaming, decrease to_roam */
1673 			else if (rtw_to_roam(adapter) == 0)
1674 				rtw_set_to_roam(adapter, adapter->registrypriv.max_roaming_times);
1675 		} else {
1676 			rtw_set_to_roam(adapter, 0);
1677 		}
1678 
1679 		rtw_free_uc_swdec_pending_queue(adapter);
1680 
1681 		rtw_free_assoc_resources(adapter, 1);
1682 		rtw_indicate_disconnect(adapter);
1683 
1684 		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1685 		/*  remove the network entry in scanned_queue */
1686 		pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1687 		if (pwlan) {
1688 			pwlan->fixed = false;
1689 			rtw_free_network_nolock(adapter, pwlan);
1690 		}
1691 		spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1692 
1693 		_rtw_roaming(adapter, roam_target);
1694 	}
1695 
1696 	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1697 	      check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1698 
1699 		rtw_free_stainfo(adapter,  psta);
1700 
1701 		if (adapter->stapriv.asoc_sta_count == 1) {/* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1702 			/* rtw_indicate_disconnect(adapter);removed@20091105 */
1703 			spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1704 			/* free old ibss network */
1705 			/* pwlan = rtw_find_network(&pmlmepriv->scanned_queue, pstadel->macaddr); */
1706 			pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1707 			if (pwlan) {
1708 				pwlan->fixed = false;
1709 				rtw_free_network_nolock(adapter, pwlan);
1710 			}
1711 			spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
1712 			/* re-create ibss */
1713 			pdev_network = &(adapter->registrypriv.dev_network);
1714 			pibss = adapter->registrypriv.dev_network.MacAddress;
1715 
1716 			memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1717 
1718 			memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
1719 
1720 			rtw_update_registrypriv_dev_network(adapter);
1721 
1722 			rtw_generate_random_ibss(pibss);
1723 
1724 			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1725 				set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1726 				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1727 			}
1728 
1729 			if (rtw_createbss_cmd(adapter) != _SUCCESS) {
1730 
1731 				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error =>stadel_event_callback: rtw_createbss_cmd status FAIL***\n "));
1732 
1733 			}
1734 
1735 
1736 		}
1737 
1738 	}
1739 
1740 	spin_unlock_bh(&pmlmepriv->lock);
1741 }
1742 
1743 void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
1744 {
1745 	struct reportpwrstate_parm *preportpwrstate;
1746 
1747 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_cpwm_event_callback !!!\n"));
1748 	preportpwrstate = (struct reportpwrstate_parm *)pbuf;
1749 	preportpwrstate->state |= (u8)(adapter_to_pwrctl(padapter)->cpwm_tog + 0x80);
1750 	cpwm_int_hdl(padapter, preportpwrstate);
1751 }
1752 
1753 
1754 void rtw_wmm_event_callback(struct adapter *padapter, u8 *pbuf)
1755 {
1756 	WMMOnAssocRsp(padapter);
1757 }
1758 
1759 /*
1760 * _rtw_join_timeout_handler - Timeout/failure handler for CMD JoinBss
1761 * @adapter: pointer to struct adapter structure
1762 */
1763 void _rtw_join_timeout_handler(struct timer_list *t)
1764 {
1765 	struct adapter *adapter = from_timer(adapter, t,
1766 						  mlmepriv.assoc_timer);
1767 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
1768 
1769 	DBG_871X("%s, fw_state =%x\n", __func__, get_fwstate(pmlmepriv));
1770 
1771 	if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1772 		return;
1773 
1774 	spin_lock_bh(&pmlmepriv->lock);
1775 
1776 	if (rtw_to_roam(adapter) > 0) { /* join timeout caused by roaming */
1777 		while (1) {
1778 			rtw_dec_to_roam(adapter);
1779 			if (rtw_to_roam(adapter) != 0) { /* try another */
1780 				int do_join_r;
1781 				DBG_871X("%s try another roaming\n", __func__);
1782 				do_join_r = rtw_do_join(adapter);
1783 				if (_SUCCESS != do_join_r) {
1784 					DBG_871X("%s roaming do_join return %d\n", __func__, do_join_r);
1785 					continue;
1786 				}
1787 				break;
1788 			} else {
1789 				DBG_871X("%s We've try roaming but fail\n", __func__);
1790 				rtw_indicate_disconnect(adapter);
1791 				break;
1792 			}
1793 		}
1794 
1795 	} else {
1796 		rtw_indicate_disconnect(adapter);
1797 		free_scanqueue(pmlmepriv);/*  */
1798 
1799 		/* indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED */
1800 		rtw_cfg80211_indicate_disconnect(adapter);
1801 
1802 	}
1803 
1804 	spin_unlock_bh(&pmlmepriv->lock);
1805 }
1806 
1807 /*
1808 * rtw_scan_timeout_handler - Timeout/Failure handler for CMD SiteSurvey
1809 * @adapter: pointer to struct adapter structure
1810 */
1811 void rtw_scan_timeout_handler(struct timer_list *t)
1812 {
1813 	struct adapter *adapter = from_timer(adapter, t,
1814 						  mlmepriv.scan_to_timer);
1815 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
1816 
1817 	DBG_871X(FUNC_ADPT_FMT" fw_state =%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
1818 
1819 	spin_lock_bh(&pmlmepriv->lock);
1820 
1821 	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1822 
1823 	spin_unlock_bh(&pmlmepriv->lock);
1824 
1825 	rtw_indicate_scan_done(adapter, true);
1826 }
1827 
1828 void rtw_mlme_reset_auto_scan_int(struct adapter *adapter)
1829 {
1830 	struct mlme_priv *mlme = &adapter->mlmepriv;
1831 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1832 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1833 
1834 	if (pmlmeinfo->VHT_enable) /* disable auto scan when connect to 11AC AP */
1835 		mlme->auto_scan_int_ms = 0;
1836 	else if (adapter->registrypriv.wifi_spec && is_client_associated_to_ap(adapter) == true)
1837 		mlme->auto_scan_int_ms = 60*1000;
1838 	else if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
1839 		if (check_fwstate(mlme, WIFI_STATION_STATE) && check_fwstate(mlme, _FW_LINKED))
1840 			mlme->auto_scan_int_ms = mlme->roam_scan_int_ms;
1841 	} else
1842 		mlme->auto_scan_int_ms = 0; /* disabled */
1843 
1844 	return;
1845 }
1846 
1847 static void rtw_auto_scan_handler(struct adapter *padapter)
1848 {
1849 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1850 
1851 	rtw_mlme_reset_auto_scan_int(padapter);
1852 
1853 	if (pmlmepriv->auto_scan_int_ms != 0
1854 		&& jiffies_to_msecs(jiffies - pmlmepriv->scan_start_time) > pmlmepriv->auto_scan_int_ms) {
1855 
1856 		if (!padapter->registrypriv.wifi_spec) {
1857 			if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true) {
1858 				DBG_871X(FUNC_ADPT_FMT" _FW_UNDER_SURVEY|_FW_UNDER_LINKING\n", FUNC_ADPT_ARG(padapter));
1859 				goto exit;
1860 			}
1861 
1862 			if (pmlmepriv->LinkDetectInfo.bBusyTraffic == true) {
1863 				DBG_871X(FUNC_ADPT_FMT" exit BusyTraffic\n", FUNC_ADPT_ARG(padapter));
1864 				goto exit;
1865 			}
1866 		}
1867 
1868 		DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1869 
1870 		rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1871 	}
1872 
1873 exit:
1874 	return;
1875 }
1876 
1877 void rtw_dynamic_check_timer_handler(struct adapter *adapter)
1878 {
1879 	if (!adapter)
1880 		return;
1881 
1882 	if (adapter->hw_init_completed == false)
1883 		return;
1884 
1885 	if ((adapter->bDriverStopped == true) || (adapter->bSurpriseRemoved == true))
1886 		return;
1887 
1888 	if (adapter->net_closed == true)
1889 		return;
1890 
1891 	if (is_primary_adapter(adapter))
1892 		DBG_871X("IsBtDisabled =%d, IsBtControlLps =%d\n", hal_btcoex_IsBtDisabled(adapter), hal_btcoex_IsBtControlLps(adapter));
1893 
1894 	if ((adapter_to_pwrctl(adapter)->bFwCurrentInPSMode == true)
1895 		&& (hal_btcoex_IsBtControlLps(adapter) == false)
1896 		) {
1897 		u8 bEnterPS;
1898 
1899 		linked_status_chk(adapter);
1900 
1901 		bEnterPS = traffic_status_watchdog(adapter, 1);
1902 		if (bEnterPS) {
1903 			/* rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 1); */
1904 			rtw_hal_dm_watchdog_in_lps(adapter);
1905 		} else {
1906 			/* call rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1) in traffic_status_watchdog() */
1907 		}
1908 
1909 	} else {
1910 		if (is_primary_adapter(adapter)) {
1911 			rtw_dynamic_chk_wk_cmd(adapter);
1912 		}
1913 	}
1914 
1915 	/* auto site survey */
1916 	rtw_auto_scan_handler(adapter);
1917 }
1918 
1919 
1920 inline bool rtw_is_scan_deny(struct adapter *adapter)
1921 {
1922 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1923 	return (atomic_read(&mlmepriv->set_scan_deny) != 0) ? true : false;
1924 }
1925 
1926 inline void rtw_clear_scan_deny(struct adapter *adapter)
1927 {
1928 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1929 	atomic_set(&mlmepriv->set_scan_deny, 0);
1930 
1931 	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1932 }
1933 
1934 void rtw_set_scan_deny(struct adapter *adapter, u32 ms)
1935 {
1936 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
1937 
1938 	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
1939 	atomic_set(&mlmepriv->set_scan_deny, 1);
1940 	_set_timer(&mlmepriv->set_scan_deny_timer, ms);
1941 }
1942 
1943 /*
1944 * Select a new roaming candidate from the original @param candidate and @param competitor
1945 * @return true: candidate is updated
1946 * @return false: candidate is not updated
1947 */
1948 static int rtw_check_roaming_candidate(struct mlme_priv *mlme
1949 	, struct wlan_network **candidate, struct wlan_network *competitor)
1950 {
1951 	int updated = false;
1952 	struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
1953 
1954 	if (is_same_ess(&competitor->network, &mlme->cur_network.network) == false)
1955 		goto exit;
1956 
1957 	if (rtw_is_desired_network(adapter, competitor) == false)
1958 		goto exit;
1959 
1960 	DBG_871X("roam candidate:%s %s("MAC_FMT", ch%3u) rssi:%d, age:%5d\n",
1961 		(competitor == mlme->cur_network_scanned)?"*":" ",
1962 		competitor->network.Ssid.Ssid,
1963 		MAC_ARG(competitor->network.MacAddress),
1964 		competitor->network.Configuration.DSConfig,
1965 		(int)competitor->network.Rssi,
1966 		jiffies_to_msecs(jiffies - competitor->last_scanned)
1967 	);
1968 
1969 	/* got specific addr to roam */
1970 	if (!is_zero_mac_addr(mlme->roam_tgt_addr)) {
1971 		if (!memcmp(mlme->roam_tgt_addr, competitor->network.MacAddress, ETH_ALEN))
1972 			goto update;
1973 		else
1974 			goto exit;
1975 	}
1976 	if (jiffies_to_msecs(jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms)
1977 		goto exit;
1978 
1979 	if (competitor->network.Rssi - mlme->cur_network_scanned->network.Rssi < mlme->roam_rssi_diff_th)
1980 		goto exit;
1981 
1982 	if (*candidate != NULL && (*candidate)->network.Rssi >= competitor->network.Rssi)
1983 		goto exit;
1984 
1985 update:
1986 	*candidate = competitor;
1987 	updated = true;
1988 
1989 exit:
1990 	return updated;
1991 }
1992 
1993 int rtw_select_roaming_candidate(struct mlme_priv *mlme)
1994 {
1995 	int ret = _FAIL;
1996 	struct list_head	*phead;
1997 	struct adapter *adapter;
1998 	struct __queue	*queue	= &(mlme->scanned_queue);
1999 	struct	wlan_network	*pnetwork = NULL;
2000 	struct	wlan_network	*candidate = NULL;
2001 
2002 	if (mlme->cur_network_scanned == NULL) {
2003 		rtw_warn_on(1);
2004 		return ret;
2005 	}
2006 
2007 	spin_lock_bh(&(mlme->scanned_queue.lock));
2008 	phead = get_list_head(queue);
2009 	adapter = (struct adapter *)mlme->nic_hdl;
2010 
2011 	mlme->pscanned = get_next(phead);
2012 
2013 	while (phead != mlme->pscanned) {
2014 
2015 		pnetwork = LIST_CONTAINOR(mlme->pscanned, struct wlan_network, list);
2016 		if (pnetwork == NULL) {
2017 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork == NULL)\n", __func__));
2018 			ret = _FAIL;
2019 			goto exit;
2020 		}
2021 
2022 		mlme->pscanned = get_next(mlme->pscanned);
2023 
2024 		DBG_871X("%s("MAC_FMT", ch%u) rssi:%d\n"
2025 			, pnetwork->network.Ssid.Ssid
2026 			, MAC_ARG(pnetwork->network.MacAddress)
2027 			, pnetwork->network.Configuration.DSConfig
2028 			, (int)pnetwork->network.Rssi);
2029 
2030 		rtw_check_roaming_candidate(mlme, &candidate, pnetwork);
2031 
2032 	}
2033 
2034 	if (candidate == NULL) {
2035 		DBG_871X("%s: return _FAIL(candidate == NULL)\n", __func__);
2036 		ret = _FAIL;
2037 		goto exit;
2038 	} else {
2039 		DBG_871X("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
2040 			candidate->network.Ssid.Ssid, MAC_ARG(candidate->network.MacAddress),
2041 			candidate->network.Configuration.DSConfig);
2042 
2043 		mlme->roam_network = candidate;
2044 
2045 		if (!memcmp(candidate->network.MacAddress, mlme->roam_tgt_addr, ETH_ALEN))
2046 			eth_zero_addr(mlme->roam_tgt_addr);
2047 	}
2048 
2049 	ret = _SUCCESS;
2050 exit:
2051 	spin_unlock_bh(&(mlme->scanned_queue.lock));
2052 
2053 	return ret;
2054 }
2055 
2056 /*
2057 * Select a new join candidate from the original @param candidate and @param competitor
2058 * @return true: candidate is updated
2059 * @return false: candidate is not updated
2060 */
2061 static int rtw_check_join_candidate(struct mlme_priv *mlme
2062 	, struct wlan_network **candidate, struct wlan_network *competitor)
2063 {
2064 	int updated = false;
2065 	struct adapter *adapter = container_of(mlme, struct adapter, mlmepriv);
2066 
2067 
2068 	/* check bssid, if needed */
2069 	if (mlme->assoc_by_bssid == true) {
2070 		if (memcmp(competitor->network.MacAddress, mlme->assoc_bssid, ETH_ALEN))
2071 			goto exit;
2072 	}
2073 
2074 	/* check ssid, if needed */
2075 	if (mlme->assoc_ssid.Ssid[0] && mlme->assoc_ssid.SsidLength) {
2076 		if (competitor->network.Ssid.SsidLength != mlme->assoc_ssid.SsidLength
2077 			|| memcmp(competitor->network.Ssid.Ssid, mlme->assoc_ssid.Ssid, mlme->assoc_ssid.SsidLength)
2078 		)
2079 			goto exit;
2080 	}
2081 
2082 	if (rtw_is_desired_network(adapter, competitor)  == false)
2083 		goto exit;
2084 
2085 	if (rtw_to_roam(adapter) > 0) {
2086 		if (jiffies_to_msecs(jiffies - competitor->last_scanned) >= mlme->roam_scanr_exp_ms
2087 			|| is_same_ess(&competitor->network, &mlme->cur_network.network) == false
2088 		)
2089 			goto exit;
2090 	}
2091 
2092 	if (*candidate == NULL || (*candidate)->network.Rssi < competitor->network.Rssi) {
2093 		*candidate = competitor;
2094 		updated = true;
2095 	}
2096 
2097 	if (updated) {
2098 		DBG_871X("[by_bssid:%u][assoc_ssid:%s]"
2099 			"[to_roam:%u] "
2100 			"new candidate: %s("MAC_FMT", ch%u) rssi:%d\n",
2101 			mlme->assoc_by_bssid,
2102 			mlme->assoc_ssid.Ssid,
2103 			rtw_to_roam(adapter),
2104 			(*candidate)->network.Ssid.Ssid,
2105 			MAC_ARG((*candidate)->network.MacAddress),
2106 			(*candidate)->network.Configuration.DSConfig,
2107 			(int)(*candidate)->network.Rssi
2108 		);
2109 	}
2110 
2111 exit:
2112 	return updated;
2113 }
2114 
2115 /*
2116 Calling context:
2117 The caller of the sub-routine will be in critical section...
2118 
2119 The caller must hold the following spinlock
2120 
2121 pmlmepriv->lock
2122 
2123 
2124 */
2125 
2126 int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
2127 {
2128 	int ret;
2129 	struct list_head	*phead;
2130 	struct adapter *adapter;
2131 	struct __queue	*queue	= &(pmlmepriv->scanned_queue);
2132 	struct	wlan_network	*pnetwork = NULL;
2133 	struct	wlan_network	*candidate = NULL;
2134 
2135 	adapter = (struct adapter *)pmlmepriv->nic_hdl;
2136 
2137 	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
2138 
2139 	if (pmlmepriv->roam_network) {
2140 		candidate = pmlmepriv->roam_network;
2141 		pmlmepriv->roam_network = NULL;
2142 		goto candidate_exist;
2143 	}
2144 
2145 	phead = get_list_head(queue);
2146 	pmlmepriv->pscanned = get_next(phead);
2147 
2148 	while (phead != pmlmepriv->pscanned) {
2149 
2150 		pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
2151 		if (pnetwork == NULL) {
2152 			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork == NULL)\n", __func__));
2153 			ret = _FAIL;
2154 			goto exit;
2155 		}
2156 
2157 		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
2158 
2159 		DBG_871X("%s("MAC_FMT", ch%u) rssi:%d\n"
2160 			, pnetwork->network.Ssid.Ssid
2161 			, MAC_ARG(pnetwork->network.MacAddress)
2162 			, pnetwork->network.Configuration.DSConfig
2163 			, (int)pnetwork->network.Rssi);
2164 
2165 		rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
2166 
2167 	}
2168 
2169 	if (candidate == NULL) {
2170 		DBG_871X("%s: return _FAIL(candidate == NULL)\n", __func__);
2171 #ifdef CONFIG_WOWLAN
2172 		_clr_fwstate_(pmlmepriv, _FW_LINKED|_FW_UNDER_LINKING);
2173 #endif
2174 		ret = _FAIL;
2175 		goto exit;
2176 	} else {
2177 		DBG_871X("%s: candidate: %s("MAC_FMT", ch:%u)\n", __func__,
2178 			candidate->network.Ssid.Ssid, MAC_ARG(candidate->network.MacAddress),
2179 			candidate->network.Configuration.DSConfig);
2180 		goto candidate_exist;
2181 	}
2182 
2183 candidate_exist:
2184 
2185 	/*  check for situation of  _FW_LINKED */
2186 	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
2187 		DBG_871X("%s: _FW_LINKED while ask_for_joinbss!!!\n", __func__);
2188 
2189 		rtw_disassoc_cmd(adapter, 0, true);
2190 		rtw_indicate_disconnect(adapter);
2191 		rtw_free_assoc_resources(adapter, 0);
2192 	}
2193 
2194 	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
2195 	ret = rtw_joinbss_cmd(adapter, candidate);
2196 
2197 exit:
2198 	spin_unlock_bh(&(pmlmepriv->scanned_queue.lock));
2199 	return ret;
2200 }
2201 
2202 sint rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
2203 {
2204 	struct	cmd_obj *pcmd;
2205 	struct	setauth_parm *psetauthparm;
2206 	struct	cmd_priv *pcmdpriv = &(adapter->cmdpriv);
2207 	sint		res = _SUCCESS;
2208 
2209 	pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
2210 	if (pcmd == NULL) {
2211 		res = _FAIL;  /* try again */
2212 		goto exit;
2213 	}
2214 
2215 	psetauthparm = rtw_zmalloc(sizeof(struct setauth_parm));
2216 	if (psetauthparm == NULL) {
2217 		kfree((unsigned char *)pcmd);
2218 		res = _FAIL;
2219 		goto exit;
2220 	}
2221 
2222 	psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
2223 
2224 	pcmd->cmdcode = _SetAuth_CMD_;
2225 	pcmd->parmbuf = (unsigned char *)psetauthparm;
2226 	pcmd->cmdsz =  (sizeof(struct setauth_parm));
2227 	pcmd->rsp = NULL;
2228 	pcmd->rspsz = 0;
2229 
2230 
2231 	INIT_LIST_HEAD(&pcmd->list);
2232 
2233 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("after enqueue set_auth_cmd, auth_mode =%x\n", psecuritypriv->dot11AuthAlgrthm));
2234 
2235 	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2236 
2237 exit:
2238 	return res;
2239 }
2240 
2241 sint rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, sint keyid, u8 set_tx, bool enqueue)
2242 {
2243 	u8 keylen;
2244 	struct cmd_obj		*pcmd;
2245 	struct setkey_parm	*psetkeyparm;
2246 	struct cmd_priv 	*pcmdpriv = &(adapter->cmdpriv);
2247 	sint	res = _SUCCESS;
2248 
2249 	psetkeyparm = rtw_zmalloc(sizeof(struct setkey_parm));
2250 	if (psetkeyparm == NULL) {
2251 		res = _FAIL;
2252 		goto exit;
2253 	}
2254 
2255 	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
2256 		psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
2257 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key: psetkeyparm->algorithm =(unsigned char)psecuritypriv->dot118021XGrpPrivacy =%d\n", psetkeyparm->algorithm));
2258 	} else {
2259 		psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
2260 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key: psetkeyparm->algorithm =(u8)psecuritypriv->dot11PrivacyAlgrthm =%d\n", psetkeyparm->algorithm));
2261 
2262 	}
2263 	psetkeyparm->keyid = (u8)keyid;/* 0~3 */
2264 	psetkeyparm->set_tx = set_tx;
2265 	if (is_wep_enc(psetkeyparm->algorithm))
2266 		adapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
2267 
2268 	DBG_871X("==> rtw_set_key algorithm(%x), keyid(%x), key_mask(%x)\n", psetkeyparm->algorithm, psetkeyparm->keyid, adapter->securitypriv.key_mask);
2269 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key: psetkeyparm->algorithm =%d psetkeyparm->keyid =(u8)keyid =%d\n", psetkeyparm->algorithm, keyid));
2270 
2271 	switch (psetkeyparm->algorithm) {
2272 
2273 	case _WEP40_:
2274 		keylen = 5;
2275 		memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
2276 		break;
2277 	case _WEP104_:
2278 		keylen = 13;
2279 		memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
2280 		break;
2281 	case _TKIP_:
2282 		keylen = 16;
2283 		memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
2284 		psetkeyparm->grpkey = 1;
2285 		break;
2286 	case _AES_:
2287 		keylen = 16;
2288 		memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
2289 		psetkeyparm->grpkey = 1;
2290 		break;
2291 	default:
2292 		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n rtw_set_key:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n", psecuritypriv->dot11PrivacyAlgrthm));
2293 		res = _FAIL;
2294 		kfree((unsigned char *)psetkeyparm);
2295 		goto exit;
2296 	}
2297 
2298 
2299 	if (enqueue) {
2300 		pcmd = rtw_zmalloc(sizeof(struct cmd_obj));
2301 		if (pcmd == NULL) {
2302 			kfree((unsigned char *)psetkeyparm);
2303 			res = _FAIL;  /* try again */
2304 			goto exit;
2305 		}
2306 
2307 		pcmd->cmdcode = _SetKey_CMD_;
2308 		pcmd->parmbuf = (u8 *)psetkeyparm;
2309 		pcmd->cmdsz =  (sizeof(struct setkey_parm));
2310 		pcmd->rsp = NULL;
2311 		pcmd->rspsz = 0;
2312 
2313 		INIT_LIST_HEAD(&pcmd->list);
2314 
2315 		res = rtw_enqueue_cmd(pcmdpriv, pcmd);
2316 	} else {
2317 		setkey_hdl(adapter, (u8 *)psetkeyparm);
2318 		kfree((u8 *) psetkeyparm);
2319 	}
2320 exit:
2321 	return res;
2322 }
2323 
2324 /* adjust IEs for rtw_joinbss_cmd in WMM */
2325 int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
2326 {
2327 	unsigned	int ielength = 0;
2328 	unsigned int i, j;
2329 
2330 	i = 12; /* after the fixed IE */
2331 	while (i < in_len) {
2332 		ielength = initial_out_len;
2333 
2334 		if (in_ie[i] == 0xDD && in_ie[i+2] == 0x00 && in_ie[i+3] == 0x50  && in_ie[i+4] == 0xF2 && in_ie[i+5] == 0x02 && i+5 < in_len) { /* WMM element ID and OUI */
2335 			for (j = i; j < i + 9; j++) {
2336 					out_ie[ielength] = in_ie[j];
2337 					ielength++;
2338 			}
2339 			out_ie[initial_out_len + 1] = 0x07;
2340 			out_ie[initial_out_len + 6] = 0x00;
2341 			out_ie[initial_out_len + 8] = 0x00;
2342 
2343 			break;
2344 		}
2345 
2346 		i += (in_ie[i+1]+2); /*  to the next IE element */
2347 	}
2348 
2349 	return ielength;
2350 
2351 }
2352 
2353 
2354 /*  */
2355 /*  Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.) */
2356 /*  Added by Annie, 2006-05-07. */
2357 /*  */
2358 /*  Search by BSSID, */
2359 /*  Return Value: */
2360 /* 		-1		:if there is no pre-auth key in the  table */
2361 /* 		>= 0		:if there is pre-auth key, and   return the entry id */
2362 /*  */
2363 /*  */
2364 
2365 static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
2366 {
2367 	struct security_priv *psecuritypriv = &Adapter->securitypriv;
2368 	int i = 0;
2369 
2370 	do {
2371 		if ((psecuritypriv->PMKIDList[i].bUsed) &&
2372 				(!memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN))) {
2373 			break;
2374 		} else {
2375 			i++;
2376 			/* continue; */
2377 		}
2378 
2379 	} while (i < NUM_PMKID_CACHE);
2380 
2381 	if (i == NUM_PMKID_CACHE) {
2382 		i = -1;/*  Could not find. */
2383 	} else {
2384 		/*  There is one Pre-Authentication Key for the specific BSSID. */
2385 	}
2386 
2387 	return i;
2388 
2389 }
2390 
2391 /*  */
2392 /*  Check the RSN IE length */
2393 /*  If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */
2394 /*  0-11th element in the array are the fixed IE */
2395 /*  12th element in the array is the IE */
2396 /*  13th element in the array is the IE length */
2397 /*  */
2398 
2399 static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len)
2400 {
2401 	struct security_priv *psecuritypriv = &Adapter->securitypriv;
2402 
2403 	if (ie[13] <= 20) {
2404 		/*  The RSN IE didn't include the PMK ID, append the PMK information */
2405 			ie[ie_len] = 1;
2406 			ie_len++;
2407 			ie[ie_len] = 0;	/* PMKID count = 0x0100 */
2408 			ie_len++;
2409 			memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
2410 
2411 			ie_len += 16;
2412 			ie[13] += 18;/* PMKID length = 2+16 */
2413 
2414 	}
2415 	return ie_len;
2416 }
2417 
2418 sint rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
2419 {
2420 	u8 authmode = 0x0;
2421 	uint	ielength;
2422 	int iEntry;
2423 
2424 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
2425 	struct security_priv *psecuritypriv = &adapter->securitypriv;
2426 	uint	ndisauthmode = psecuritypriv->ndisauthtype;
2427 
2428 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
2429 		 ("+rtw_restruct_sec_ie: ndisauthmode =%d\n", ndisauthmode));
2430 
2431 	/* copy fixed ie only */
2432 	memcpy(out_ie, in_ie, 12);
2433 	ielength = 12;
2434 	if ((ndisauthmode == Ndis802_11AuthModeWPA) || (ndisauthmode == Ndis802_11AuthModeWPAPSK))
2435 			authmode = _WPA_IE_ID_;
2436 	if ((ndisauthmode == Ndis802_11AuthModeWPA2) || (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
2437 			authmode = _WPA2_IE_ID_;
2438 
2439 	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
2440 		memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
2441 
2442 		ielength += psecuritypriv->wps_ie_len;
2443 	} else if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
2444 		/* copy RSN or SSN */
2445 		memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2);
2446 		/* debug for CONFIG_IEEE80211W
2447 		{
2448 			int jj;
2449 			printk("supplicant_ie_length =%d &&&&&&&&&&&&&&&&&&&\n", psecuritypriv->supplicant_ie[1]+2);
2450 			for (jj = 0; jj < psecuritypriv->supplicant_ie[1]+2; jj++)
2451 				printk(" %02x ", psecuritypriv->supplicant_ie[jj]);
2452 			printk("\n");
2453 		}*/
2454 		ielength += psecuritypriv->supplicant_ie[1]+2;
2455 		rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie);
2456 	}
2457 
2458 	iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
2459 	if (iEntry < 0) {
2460 		return ielength;
2461 	} else {
2462 		if (authmode == _WPA2_IE_ID_)
2463 			ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
2464 	}
2465 	return ielength;
2466 }
2467 
2468 void rtw_init_registrypriv_dev_network(struct adapter *adapter)
2469 {
2470 	struct registry_priv *pregistrypriv = &adapter->registrypriv;
2471 	struct eeprom_priv *peepriv = &adapter->eeprompriv;
2472 	struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
2473 	u8 *myhwaddr = myid(peepriv);
2474 
2475 	memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
2476 
2477 	memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
2478 
2479 	pdev_network->Configuration.Length = sizeof(struct ndis_802_11_conf);
2480 	pdev_network->Configuration.BeaconPeriod = 100;
2481 	pdev_network->Configuration.FHConfig.Length = 0;
2482 	pdev_network->Configuration.FHConfig.HopPattern = 0;
2483 	pdev_network->Configuration.FHConfig.HopSet = 0;
2484 	pdev_network->Configuration.FHConfig.DwellTime = 0;
2485 }
2486 
2487 void rtw_update_registrypriv_dev_network(struct adapter *adapter)
2488 {
2489 	int sz = 0;
2490 	struct registry_priv *pregistrypriv = &adapter->registrypriv;
2491 	struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
2492 	struct	security_priv *psecuritypriv = &adapter->securitypriv;
2493 	struct	wlan_network	*cur_network = &adapter->mlmepriv.cur_network;
2494 	/* struct	xmit_priv *pxmitpriv = &adapter->xmitpriv; */
2495 
2496 	pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0) ; /*  adhoc no 802.1x */
2497 
2498 	pdev_network->Rssi = 0;
2499 
2500 	switch (pregistrypriv->wireless_mode) {
2501 	case WIRELESS_11B:
2502 		pdev_network->NetworkTypeInUse = (Ndis802_11DS);
2503 		break;
2504 	case WIRELESS_11G:
2505 	case WIRELESS_11BG:
2506 	case WIRELESS_11_24N:
2507 	case WIRELESS_11G_24N:
2508 	case WIRELESS_11BG_24N:
2509 		pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
2510 		break;
2511 	case WIRELESS_11A:
2512 	case WIRELESS_11A_5N:
2513 		pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
2514 		break;
2515 	case WIRELESS_11ABGN:
2516 		if (pregistrypriv->channel > 14)
2517 			pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
2518 		else
2519 			pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
2520 		break;
2521 	default:
2522 		/*  TODO */
2523 		break;
2524 	}
2525 
2526 	pdev_network->Configuration.DSConfig = (pregistrypriv->channel);
2527 	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("pregistrypriv->channel =%d, pdev_network->Configuration.DSConfig = 0x%x\n", pregistrypriv->channel, pdev_network->Configuration.DSConfig));
2528 
2529 	if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
2530 		pdev_network->Configuration.ATIMWindow = (0);
2531 
2532 	pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode);
2533 
2534 	/*  1. Supported rates */
2535 	/*  2. IE */
2536 
2537 	/* rtw_set_supported_rate(pdev_network->SupportedRates, pregistrypriv->wireless_mode) ;  will be called in rtw_generate_ie */
2538 	sz = rtw_generate_ie(pregistrypriv);
2539 
2540 	pdev_network->IELength = sz;
2541 
2542 	pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex  *)pdev_network);
2543 
2544 	/* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */
2545 	/* pdev_network->IELength = cpu_to_le32(sz); */
2546 }
2547 
2548 void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
2549 {
2550 }
2551 
2552 /* the function is at passive_level */
2553 void rtw_joinbss_reset(struct adapter *padapter)
2554 {
2555 	u8 threshold;
2556 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2557 
2558 	struct ht_priv 	*phtpriv = &pmlmepriv->htpriv;
2559 
2560 	/* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
2561 
2562 	pmlmepriv->num_FortyMHzIntolerant = 0;
2563 
2564 	pmlmepriv->num_sta_no_ht = 0;
2565 
2566 	phtpriv->ampdu_enable = false;/* reset to disabled */
2567 
2568 	/*  TH = 1 => means that invalidate usb rx aggregation */
2569 	/*  TH = 0 => means that validate usb rx aggregation, use init value. */
2570 	if (phtpriv->ht_option) {
2571 		if (padapter->registrypriv.wifi_spec == 1)
2572 			threshold = 1;
2573 		else
2574 			threshold = 0;
2575 		rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
2576 	} else {
2577 		threshold = 1;
2578 		rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
2579 	}
2580 }
2581 
2582 void rtw_ht_use_default_setting(struct adapter *padapter)
2583 {
2584 	struct mlme_priv 	*pmlmepriv = &padapter->mlmepriv;
2585 	struct ht_priv 	*phtpriv = &pmlmepriv->htpriv;
2586 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
2587 	bool		bHwLDPCSupport = false, bHwSTBCSupport = false;
2588 	bool		bHwSupportBeamformer = false, bHwSupportBeamformee = false;
2589 
2590 	if (pregistrypriv->wifi_spec)
2591 		phtpriv->bss_coexist = 1;
2592 	else
2593 		phtpriv->bss_coexist = 0;
2594 
2595 	phtpriv->sgi_40m = TEST_FLAG(pregistrypriv->short_gi, BIT1) ? true : false;
2596 	phtpriv->sgi_20m = TEST_FLAG(pregistrypriv->short_gi, BIT0) ? true : false;
2597 
2598 	/*  LDPC support */
2599 	rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
2600 	CLEAR_FLAGS(phtpriv->ldpc_cap);
2601 	if (bHwLDPCSupport) {
2602 		if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT4))
2603 			SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX);
2604 	}
2605 	rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
2606 	if (bHwLDPCSupport) {
2607 		if (TEST_FLAG(pregistrypriv->ldpc_cap, BIT5))
2608 			SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX);
2609 	}
2610 	if (phtpriv->ldpc_cap)
2611 		DBG_871X("[HT] Support LDPC = 0x%02X\n", phtpriv->ldpc_cap);
2612 
2613 	/*  STBC */
2614 	rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
2615 	CLEAR_FLAGS(phtpriv->stbc_cap);
2616 	if (bHwSTBCSupport) {
2617 		if (TEST_FLAG(pregistrypriv->stbc_cap, BIT5))
2618 			SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX);
2619 	}
2620 	rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
2621 	if (bHwSTBCSupport) {
2622 		if (TEST_FLAG(pregistrypriv->stbc_cap, BIT4))
2623 			SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX);
2624 	}
2625 	if (phtpriv->stbc_cap)
2626 		DBG_871X("[HT] Support STBC = 0x%02X\n", phtpriv->stbc_cap);
2627 
2628 	/*  Beamforming setting */
2629 	rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&bHwSupportBeamformer);
2630 	rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&bHwSupportBeamformee);
2631 	CLEAR_FLAGS(phtpriv->beamform_cap);
2632 	if (TEST_FLAG(pregistrypriv->beamform_cap, BIT4) && bHwSupportBeamformer) {
2633 		SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
2634 		DBG_871X("[HT] Support Beamformer\n");
2635 	}
2636 	if (TEST_FLAG(pregistrypriv->beamform_cap, BIT5) && bHwSupportBeamformee) {
2637 		SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
2638 		DBG_871X("[HT] Support Beamformee\n");
2639 	}
2640 }
2641 
2642 void rtw_build_wmm_ie_ht(struct adapter *padapter, u8 *out_ie, uint *pout_len)
2643 {
2644 	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
2645 	int out_len;
2646 	u8 *pframe;
2647 
2648 	if (padapter->mlmepriv.qospriv.qos_option == 0) {
2649 		out_len = *pout_len;
2650 		pframe = rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_,
2651 							_WMM_IE_Length_, WMM_IE, pout_len);
2652 
2653 		padapter->mlmepriv.qospriv.qos_option = 1;
2654 	}
2655 }
2656 
2657 /* the function is >= passive_level */
2658 unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, u8 channel)
2659 {
2660 	u32 ielen, out_len;
2661 	enum HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
2662 	unsigned char *p, *pframe;
2663 	struct rtw_ieee80211_ht_cap ht_capie;
2664 	u8 cbw40_enable = 0, stbc_rx_enable = 0, rf_type = 0, operation_bw = 0;
2665 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
2666 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2667 	struct ht_priv 	*phtpriv = &pmlmepriv->htpriv;
2668 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2669 
2670 	phtpriv->ht_option = false;
2671 
2672 	out_len = *pout_len;
2673 
2674 	memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
2675 
2676 	ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_DSSSCCK40);
2677 
2678 	if (phtpriv->sgi_20m)
2679 		ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_20);
2680 
2681 	/* Get HT BW */
2682 	if (in_ie == NULL) {
2683 		/* TDLS: TODO 20/40 issue */
2684 		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
2685 			operation_bw = padapter->mlmeextpriv.cur_bwmode;
2686 			if (operation_bw > CHANNEL_WIDTH_40)
2687 				operation_bw = CHANNEL_WIDTH_40;
2688 		} else
2689 			/* TDLS: TODO 40? */
2690 			operation_bw = CHANNEL_WIDTH_40;
2691 	} else {
2692 		p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
2693 		if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
2694 			struct HT_info_element *pht_info = (struct HT_info_element *)(p+2);
2695 			if (pht_info->infos[0] & BIT(2)) {
2696 				switch (pht_info->infos[0] & 0x3) {
2697 				case 1:
2698 				case 3:
2699 					operation_bw = CHANNEL_WIDTH_40;
2700 					break;
2701 				default:
2702 					operation_bw = CHANNEL_WIDTH_20;
2703 					break;
2704 				}
2705 			} else {
2706 				operation_bw = CHANNEL_WIDTH_20;
2707 			}
2708 		}
2709 	}
2710 
2711 	/* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
2712 	if (channel > 14) {
2713 		if ((pregistrypriv->bw_mode & 0xf0) > 0)
2714 			cbw40_enable = 1;
2715 	} else {
2716 		if ((pregistrypriv->bw_mode & 0x0f) > 0)
2717 			cbw40_enable = 1;
2718 	}
2719 
2720 	if ((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) {
2721 		ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH);
2722 		if (phtpriv->sgi_40m)
2723 			ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SGI_40);
2724 	}
2725 
2726 	if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX))
2727 		ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_TX_STBC);
2728 
2729 	/* todo: disable SM power save mode */
2730 	ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_SM_PS);
2731 
2732 	if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
2733 		if ((channel <= 14 && pregistrypriv->rx_stbc == 0x1) ||	/* enable for 2.4GHz */
2734 			(pregistrypriv->wifi_spec == 1)) {
2735 			stbc_rx_enable = 1;
2736 			DBG_871X("declare supporting RX STBC\n");
2737 		}
2738 	}
2739 
2740 	/* fill default supported_mcs_set */
2741 	memcpy(ht_capie.supp_mcs_set, pmlmeext->default_supported_mcs_set, 16);
2742 
2743 	/* update default supported_mcs_set */
2744 	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
2745 
2746 	switch (rf_type) {
2747 	case RF_1T1R:
2748 		if (stbc_rx_enable)
2749 			ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_1R);/* RX STBC One spatial stream */
2750 
2751 		set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_1R);
2752 		break;
2753 
2754 	case RF_2T2R:
2755 	case RF_1T2R:
2756 	default:
2757 		if (stbc_rx_enable)
2758 			ht_capie.cap_info |= cpu_to_le16(IEEE80211_HT_CAP_RX_STBC_2R);/* RX STBC two spatial stream */
2759 
2760 		#ifdef CONFIG_DISABLE_MCS13TO15
2761 		if (((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) && (pregistrypriv->wifi_spec != 1))
2762 				set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R_13TO15_OFF);
2763 		else
2764 				set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R);
2765 		#else /* CONFIG_DISABLE_MCS13TO15 */
2766 			set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R);
2767 		#endif /* CONFIG_DISABLE_MCS13TO15 */
2768 		break;
2769 	}
2770 
2771 	{
2772 		u32 rx_packet_offset, max_recvbuf_sz;
2773 		rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
2774 		rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
2775 	}
2776 
2777 	if (padapter->driver_rx_ampdu_factor != 0xFF)
2778 		max_rx_ampdu_factor =
2779 		  (enum HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor;
2780 	else
2781 		rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR,
2782 				    &max_rx_ampdu_factor);
2783 
2784 	/* rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor); */
2785 	ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03);
2786 
2787 	if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
2788 		ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
2789 	else
2790 		ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
2791 
2792 	pframe = rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_,
2793 						sizeof(struct rtw_ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len);
2794 
2795 	phtpriv->ht_option = true;
2796 
2797 	if (in_ie != NULL) {
2798 		p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
2799 		if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
2800 			out_len = *pout_len;
2801 			pframe = rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2, pout_len);
2802 		}
2803 	}
2804 
2805 	return phtpriv->ht_option;
2806 
2807 }
2808 
2809 /* the function is > passive_level (in critical_section) */
2810 void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len, u8 channel)
2811 {
2812 	u8 *p, max_ampdu_sz;
2813 	int len;
2814 	/* struct sta_info *bmc_sta, *psta; */
2815 	struct rtw_ieee80211_ht_cap *pht_capie;
2816 	struct ieee80211_ht_addt_info *pht_addtinfo;
2817 	/* struct recv_reorder_ctrl *preorder_ctrl; */
2818 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2819 	struct ht_priv 	*phtpriv = &pmlmepriv->htpriv;
2820 	/* struct recv_priv *precvpriv = &padapter->recvpriv; */
2821 	struct registry_priv *pregistrypriv = &padapter->registrypriv;
2822 	/* struct wlan_network *pcur_network = &(pmlmepriv->cur_network);; */
2823 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2824 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
2825 	u8 cbw40_enable = 0;
2826 
2827 
2828 	if (!phtpriv->ht_option)
2829 		return;
2830 
2831 	if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2832 		return;
2833 
2834 	DBG_871X("+rtw_update_ht_cap()\n");
2835 
2836 	/* maybe needs check if ap supports rx ampdu. */
2837 	if ((phtpriv->ampdu_enable == false) && (pregistrypriv->ampdu_enable == 1)) {
2838 		if (pregistrypriv->wifi_spec == 1) {
2839 			/* remove this part because testbed AP should disable RX AMPDU */
2840 			/* phtpriv->ampdu_enable = false; */
2841 			phtpriv->ampdu_enable = true;
2842 		} else {
2843 			phtpriv->ampdu_enable = true;
2844 		}
2845 	} else if (pregistrypriv->ampdu_enable == 2) {
2846 		/* remove this part because testbed AP should disable RX AMPDU */
2847 		/* phtpriv->ampdu_enable = true; */
2848 	}
2849 
2850 
2851 	/* check Max Rx A-MPDU Size */
2852 	len = 0;
2853 	p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fix_ie));
2854 	if (p && len > 0) {
2855 		pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
2856 		max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR);
2857 		max_ampdu_sz = 1 << (max_ampdu_sz+3); /*  max_ampdu_sz (kbytes); */
2858 
2859 		/* DBG_871X("rtw_update_ht_cap(): max_ampdu_sz =%d\n", max_ampdu_sz); */
2860 		phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2861 
2862 	}
2863 
2864 
2865 	len = 0;
2866 	p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fix_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fix_ie));
2867 	if (p && len > 0) {
2868 		pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
2869 		/* todo: */
2870 	}
2871 
2872 	if (channel > 14) {
2873 		if ((pregistrypriv->bw_mode & 0xf0) > 0)
2874 			cbw40_enable = 1;
2875 	} else {
2876 		if ((pregistrypriv->bw_mode & 0x0f) > 0)
2877 			cbw40_enable = 1;
2878 	}
2879 
2880 	/* update cur_bwmode & cur_ch_offset */
2881 	if ((cbw40_enable) &&
2882 	    (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
2883 	      BIT(1)) && (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
2884 		int i;
2885 		u8 rf_type;
2886 
2887 		rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
2888 
2889 		/* update the MCS set */
2890 		for (i = 0; i < 16; i++)
2891 			pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
2892 
2893 		/* update the MCS rates */
2894 		switch (rf_type) {
2895 		case RF_1T1R:
2896 		case RF_1T2R:
2897 			set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);
2898 			break;
2899 		case RF_2T2R:
2900 		default:
2901 #ifdef CONFIG_DISABLE_MCS13TO15
2902 			if (pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 && pregistrypriv->wifi_spec != 1)
2903 				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R_13TO15_OFF);
2904 			else
2905 				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
2906 #else /* CONFIG_DISABLE_MCS13TO15 */
2907 			set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
2908 #endif /* CONFIG_DISABLE_MCS13TO15 */
2909 		}
2910 
2911 		/* switch to the 40M Hz mode according to the AP */
2912 		/* pmlmeext->cur_bwmode = CHANNEL_WIDTH_40; */
2913 		switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
2914 		case EXTCHNL_OFFSET_UPPER:
2915 			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2916 			break;
2917 
2918 		case EXTCHNL_OFFSET_LOWER:
2919 			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2920 			break;
2921 
2922 		default:
2923 			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2924 			break;
2925 		}
2926 	}
2927 
2928 	/*  */
2929 	/*  Config SM Power Save setting */
2930 	/*  */
2931 	pmlmeinfo->SM_PS =
2932 		(le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) &
2933 		 0x0C) >> 2;
2934 	if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2935 		DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2936 
2937 	/*  */
2938 	/*  Config current HT Protection mode. */
2939 	/*  */
2940 	pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
2941 }
2942 
2943 void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe)
2944 {
2945 	u8 issued;
2946 	int priority;
2947 	struct sta_info *psta = NULL;
2948 	struct ht_priv *phtpriv;
2949 	struct pkt_attrib *pattrib = &pxmitframe->attrib;
2950 	s32 bmcst = IS_MCAST(pattrib->ra);
2951 
2952 	/* if (bmcst || (padapter->mlmepriv.LinkDetectInfo.bTxBusyTraffic == false)) */
2953 	if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100))
2954 		return;
2955 
2956 	priority = pattrib->priority;
2957 
2958 	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
2959 	if (pattrib->psta != psta) {
2960 		DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
2961 		return;
2962 	}
2963 
2964 	if (psta == NULL) {
2965 		DBG_871X("%s, psta ==NUL\n", __func__);
2966 		return;
2967 	}
2968 
2969 	if (!(psta->state & _FW_LINKED)) {
2970 		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
2971 		return;
2972 	}
2973 
2974 
2975 	phtpriv = &psta->htpriv;
2976 
2977 	if ((phtpriv->ht_option == true) && (phtpriv->ampdu_enable == true)) {
2978 		issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2979 		issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2980 
2981 		if (0 == issued) {
2982 			DBG_871X("rtw_issue_addbareq_cmd, p =%d\n", priority);
2983 			psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
2984 			rtw_addbareq_cmd(padapter, (u8) priority, pattrib->ra);
2985 		}
2986 	}
2987 
2988 }
2989 
2990 void rtw_append_exented_cap(struct adapter *padapter, u8 *out_ie, uint *pout_len)
2991 {
2992 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2993 	struct ht_priv 	*phtpriv = &pmlmepriv->htpriv;
2994 	u8 cap_content[8] = {0};
2995 	u8 *pframe;
2996 
2997 
2998 	if (phtpriv->bss_coexist) {
2999 		SET_EXT_CAPABILITY_ELE_BSS_COEXIST(cap_content, 1);
3000 	}
3001 
3002 	pframe = rtw_set_ie(out_ie + *pout_len, EID_EXTCapability, 8, cap_content, pout_len);
3003 }
3004 
3005 inline void rtw_set_to_roam(struct adapter *adapter, u8 to_roam)
3006 {
3007 	if (to_roam == 0)
3008 		adapter->mlmepriv.to_join = false;
3009 	adapter->mlmepriv.to_roam = to_roam;
3010 }
3011 
3012 inline u8 rtw_dec_to_roam(struct adapter *adapter)
3013 {
3014 	adapter->mlmepriv.to_roam--;
3015 	return adapter->mlmepriv.to_roam;
3016 }
3017 
3018 inline u8 rtw_to_roam(struct adapter *adapter)
3019 {
3020 	return adapter->mlmepriv.to_roam;
3021 }
3022 
3023 void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
3024 {
3025 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3026 
3027 	spin_lock_bh(&pmlmepriv->lock);
3028 	_rtw_roaming(padapter, tgt_network);
3029 	spin_unlock_bh(&pmlmepriv->lock);
3030 }
3031 void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
3032 {
3033 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
3034 	struct wlan_network *cur_network = &pmlmepriv->cur_network;
3035 	int do_join_r;
3036 
3037 	if (0 < rtw_to_roam(padapter)) {
3038 		DBG_871X("roaming from %s("MAC_FMT"), length:%d\n",
3039 				cur_network->network.Ssid.Ssid, MAC_ARG(cur_network->network.MacAddress),
3040 				cur_network->network.Ssid.SsidLength);
3041 		memcpy(&pmlmepriv->assoc_ssid, &cur_network->network.Ssid, sizeof(struct ndis_802_11_ssid));
3042 
3043 		pmlmepriv->assoc_by_bssid = false;
3044 
3045 		while (1) {
3046 			do_join_r = rtw_do_join(padapter);
3047 			if (_SUCCESS == do_join_r) {
3048 				break;
3049 			} else {
3050 				DBG_871X("roaming do_join return %d\n", do_join_r);
3051 				rtw_dec_to_roam(padapter);
3052 
3053 				if (rtw_to_roam(padapter) > 0) {
3054 					continue;
3055 				} else {
3056 					DBG_871X("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
3057 					rtw_indicate_disconnect(padapter);
3058 					break;
3059 				}
3060 			}
3061 		}
3062 	}
3063 
3064 }
3065 
3066 sint rtw_linked_check(struct adapter *padapter)
3067 {
3068 	if ((check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) ||
3069 			(check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == true)) {
3070 		if (padapter->stapriv.asoc_sta_count > 2)
3071 			return true;
3072 	} else {	/* Station mode */
3073 		if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == true)
3074 			return true;
3075 	}
3076 	return false;
3077 }
3078