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