[go: nahoru, domu]

1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
17 *
18 *
19 ******************************************************************************/
20#define _RTW_MLME_C_
21
22
23#include <osdep_service.h>
24#include <drv_types.h>
25#include <recv_osdep.h>
26#include <xmit_osdep.h>
27#include <hal_intf.h>
28#include <mlme_osdep.h>
29#include <sta_info.h>
30#include <wifi.h>
31#include <wlan_bssdef.h>
32#include <rtw_ioctl_set.h>
33#include <linux/vmalloc.h>
34
35extern unsigned char	MCS_rate_2R[16];
36extern unsigned char	MCS_rate_1R[16];
37
38int rtw_init_mlme_priv(struct adapter *padapter)
39{
40	int	i;
41	u8	*pbuf;
42	struct wlan_network	*pnetwork;
43	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
44	int	res = _SUCCESS;
45
46	/*  We don't need to memset padapter->XXX to zero, because adapter is allocated by vzalloc(). */
47
48	pmlmepriv->nic_hdl = (u8 *)padapter;
49
50	pmlmepriv->pscanned = NULL;
51	pmlmepriv->fw_state = 0;
52	pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
53	pmlmepriv->scan_mode = SCAN_ACTIVE;/*  1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff) */
54
55	spin_lock_init(&(pmlmepriv->lock));
56	_rtw_init_queue(&(pmlmepriv->free_bss_pool));
57	_rtw_init_queue(&(pmlmepriv->scanned_queue));
58
59	set_scanned_network_val(pmlmepriv, 0);
60
61	memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
62
63	pbuf = vzalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
64
65	if (pbuf == NULL) {
66		res = _FAIL;
67		goto exit;
68	}
69	pmlmepriv->free_bss_buf = pbuf;
70
71	pnetwork = (struct wlan_network *)pbuf;
72
73	for (i = 0; i < MAX_BSS_CNT; i++) {
74		INIT_LIST_HEAD(&(pnetwork->list));
75
76		list_add_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
77
78		pnetwork++;
79	}
80
81	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
82
83	rtw_clear_scan_deny(padapter);
84
85	rtw_init_mlme_timer(padapter);
86
87exit:
88	return res;
89}
90
91#if defined(CONFIG_88EU_AP_MODE)
92static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
93{
94	kfree(*ppie);
95	*plen = 0;
96	*ppie = NULL;
97}
98
99void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
100{
101	rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
102	rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
103	rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
104	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
105	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
106	rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
107
108	rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
109	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
110	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
111	rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
112	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
113}
114#else
115void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
116{
117}
118#endif
119
120void rtw_free_mlme_priv(struct mlme_priv *pmlmepriv)
121{
122	rtw_free_mlme_priv_ie_data(pmlmepriv);
123
124	if (pmlmepriv) {
125		if (pmlmepriv->free_bss_buf)
126			vfree(pmlmepriv->free_bss_buf);
127	}
128}
129
130struct	wlan_network *_rtw_alloc_network(struct	mlme_priv *pmlmepriv)/* _queue *free_queue) */
131{
132	struct	wlan_network	*pnetwork;
133	struct __queue *free_queue = &pmlmepriv->free_bss_pool;
134	struct list_head *plist = NULL;
135
136	spin_lock_bh(&free_queue->lock);
137
138	if (list_empty(&free_queue->queue)) {
139		pnetwork = NULL;
140		goto exit;
141	}
142	plist = free_queue->queue.next;
143
144	pnetwork = container_of(plist , struct wlan_network, list);
145
146	list_del_init(&pnetwork->list);
147
148	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr=%p\n", plist));
149	pnetwork->network_type = 0;
150	pnetwork->fixed = false;
151	pnetwork->last_scanned = jiffies;
152	pnetwork->aid = 0;
153	pnetwork->join_res = 0;
154
155	pmlmepriv->num_of_scanned++;
156
157exit:
158	spin_unlock_bh(&free_queue->lock);
159
160	return pnetwork;
161}
162
163static void _rtw_free_network(struct	mlme_priv *pmlmepriv , struct wlan_network *pnetwork, u8 isfreeall)
164{
165	u32 curr_time, delta_time;
166	u32 lifetime = SCANQUEUE_LIFETIME;
167	struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
168
169	if (pnetwork == NULL)
170		return;
171
172	if (pnetwork->fixed)
173		return;
174	curr_time = jiffies;
175	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
176	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)))
177		lifetime = 1;
178	if (!isfreeall) {
179		delta_time = (curr_time - pnetwork->last_scanned)/HZ;
180		if (delta_time < lifetime)/*  unit:sec */
181			return;
182	}
183	spin_lock_bh(&free_queue->lock);
184	list_del_init(&(pnetwork->list));
185	list_add_tail(&(pnetwork->list), &(free_queue->queue));
186	pmlmepriv->num_of_scanned--;
187	spin_unlock_bh(&free_queue->lock);
188}
189
190void _rtw_free_network_nolock(struct	mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
191{
192	struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
193
194	if (pnetwork == NULL)
195		return;
196	if (pnetwork->fixed)
197		return;
198	list_del_init(&(pnetwork->list));
199	list_add_tail(&(pnetwork->list), get_list_head(free_queue));
200	pmlmepriv->num_of_scanned--;
201}
202
203/*
204	return the wlan_network with the matching addr
205
206	Shall be calle under atomic context... to avoid possible racing condition...
207*/
208struct wlan_network *rtw_find_network(struct __queue *scanned_queue, u8 *addr)
209{
210	struct list_head *phead, *plist;
211	struct	wlan_network *pnetwork = NULL;
212	u8 zero_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
213
214	if (!memcmp(zero_addr, addr, ETH_ALEN)) {
215		pnetwork = NULL;
216		goto exit;
217	}
218	phead = get_list_head(scanned_queue);
219	plist = phead->next;
220
221	while (plist != phead) {
222		pnetwork = container_of(plist, struct wlan_network , list);
223		if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
224			break;
225		plist = plist->next;
226	}
227	if (plist == phead)
228		pnetwork = NULL;
229exit:
230	return pnetwork;
231}
232
233
234void rtw_free_network_queue(struct adapter *padapter, u8 isfreeall)
235{
236	struct list_head *phead, *plist;
237	struct wlan_network *pnetwork;
238	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
239	struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
240
241	spin_lock_bh(&scanned_queue->lock);
242
243	phead = get_list_head(scanned_queue);
244	plist = phead->next;
245
246	while (phead != plist) {
247		pnetwork = container_of(plist, struct wlan_network, list);
248
249		plist = plist->next;
250
251		_rtw_free_network(pmlmepriv, pnetwork, isfreeall);
252	}
253	spin_unlock_bh(&scanned_queue->lock);
254}
255
256int rtw_if_up(struct adapter *padapter)
257{
258	int res;
259
260	if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
261	    (check_fwstate(&padapter->mlmepriv, _FW_LINKED) == false)) {
262		RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
263			 ("rtw_if_up:bDriverStopped(%d) OR bSurpriseRemoved(%d)",
264			 padapter->bDriverStopped, padapter->bSurpriseRemoved));
265		res = false;
266	} else {
267		res =  true;
268	}
269	return res;
270}
271
272void rtw_generate_random_ibss(u8 *pibss)
273{
274	u32	curtime = jiffies;
275
276	pibss[0] = 0x02;  /* in ad-hoc mode bit1 must set to 1 */
277	pibss[1] = 0x11;
278	pibss[2] = 0x87;
279	pibss[3] = (u8)(curtime & 0xff);/* p[0]; */
280	pibss[4] = (u8)((curtime>>8) & 0xff);/* p[1]; */
281	pibss[5] = (u8)((curtime>>16) & 0xff);/* p[2]; */
282	return;
283}
284
285u8 *rtw_get_capability_from_ie(u8 *ie)
286{
287	return ie + 8 + 2;
288}
289
290
291u16 rtw_get_capability(struct wlan_bssid_ex *bss)
292{
293	__le16	val;
294
295	memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2);
296
297	return le16_to_cpu(val);
298}
299
300u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
301{
302	return ie + 8;
303}
304
305static struct wlan_network *rtw_alloc_network(struct mlme_priv *pmlmepriv)
306{
307	return _rtw_alloc_network(pmlmepriv);
308}
309
310static void rtw_free_network_nolock(struct mlme_priv *pmlmepriv,
311				    struct wlan_network *pnetwork)
312{
313	_rtw_free_network_nolock(pmlmepriv, pnetwork);
314}
315
316int rtw_is_same_ibss(struct adapter *adapter, struct wlan_network *pnetwork)
317{
318	int ret = true;
319	struct security_priv *psecuritypriv = &adapter->securitypriv;
320
321	if ((psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_) &&
322	    (pnetwork->network.Privacy == 0))
323		ret = false;
324	else if ((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_) &&
325		 (pnetwork->network.Privacy == 1))
326		ret = false;
327	else
328		ret = true;
329	return ret;
330}
331
332static int is_same_ess(struct wlan_bssid_ex *a, struct wlan_bssid_ex *b)
333{
334	return (a->Ssid.SsidLength == b->Ssid.SsidLength) &&
335	       !memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength);
336}
337
338int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst)
339{
340	 u16 s_cap, d_cap;
341	__le16 le_scap, le_dcap;
342
343	memcpy((u8 *)&le_scap, rtw_get_capability_from_ie(src->IEs), 2);
344	memcpy((u8 *)&le_dcap, rtw_get_capability_from_ie(dst->IEs), 2);
345
346
347	s_cap = le16_to_cpu(le_scap);
348	d_cap = le16_to_cpu(le_dcap);
349
350	return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
351		((!memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) == true) &&
352		((!memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) == true) &&
353		((s_cap & WLAN_CAPABILITY_IBSS) ==
354		(d_cap & WLAN_CAPABILITY_IBSS)) &&
355		((s_cap & WLAN_CAPABILITY_BSS) ==
356		(d_cap & WLAN_CAPABILITY_BSS)));
357}
358
359struct	wlan_network	*rtw_get_oldest_wlan_network(struct __queue *scanned_queue)
360{
361	struct list_head *plist, *phead;
362	struct	wlan_network	*pwlan = NULL;
363	struct	wlan_network	*oldest = NULL;
364
365	phead = get_list_head(scanned_queue);
366
367	plist = phead->next;
368
369	while (1) {
370		if (phead == plist)
371			break;
372
373		pwlan = container_of(plist, struct wlan_network, list);
374
375		if (!pwlan->fixed) {
376			if (oldest == NULL || time_after(oldest->last_scanned, pwlan->last_scanned))
377				oldest = pwlan;
378		}
379
380		plist = plist->next;
381	}
382	return oldest;
383}
384
385void update_network(struct wlan_bssid_ex *dst, struct wlan_bssid_ex *src,
386	struct adapter *padapter, bool update_ie)
387{
388	long rssi_ori = dst->Rssi;
389	u8 sq_smp = src->PhyInfo.SignalQuality;
390	u8 ss_final;
391	u8 sq_final;
392	long rssi_final;
393
394	rtw_hal_antdiv_rssi_compared(padapter, dst, src); /* this will update src.Rssi, need consider again */
395
396	/* The rule below is 1/5 for sample value, 4/5 for history value */
397	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
398		/* Take the recvpriv's value for the connected AP*/
399		ss_final = padapter->recvpriv.signal_strength;
400		sq_final = padapter->recvpriv.signal_qual;
401		/* the rssi value here is undecorated, and will be used for antenna diversity */
402		if (sq_smp != 101) /* from the right channel */
403			rssi_final = (src->Rssi+dst->Rssi*4)/5;
404		else
405			rssi_final = rssi_ori;
406	} else {
407		if (sq_smp != 101) { /* from the right channel */
408			ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
409			sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
410			rssi_final = (src->Rssi+dst->Rssi*4)/5;
411		} else {
412			/* bss info not receiving from the right channel, use the original RX signal infos */
413			ss_final = dst->PhyInfo.SignalStrength;
414			sq_final = dst->PhyInfo.SignalQuality;
415			rssi_final = dst->Rssi;
416		}
417	}
418	if (update_ie)
419		memcpy((u8 *)dst, (u8 *)src, get_wlan_bssid_ex_sz(src));
420	dst->PhyInfo.SignalStrength = ss_final;
421	dst->PhyInfo.SignalQuality = sq_final;
422	dst->Rssi = rssi_final;
423
424}
425
426static void update_current_network(struct adapter *adapter, struct wlan_bssid_ex *pnetwork)
427{
428	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
429
430	if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) &&
431	    (is_same_network(&(pmlmepriv->cur_network.network), pnetwork))) {
432		update_network(&(pmlmepriv->cur_network.network), pnetwork, adapter, true);
433		rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(struct ndis_802_11_fixed_ie),
434				      pmlmepriv->cur_network.network.IELength);
435	}
436}
437
438/*
439Caller must hold pmlmepriv->lock first.
440*/
441void rtw_update_scanned_network(struct adapter *adapter, struct wlan_bssid_ex *target)
442{
443	struct list_head *plist, *phead;
444	u32	bssid_ex_sz;
445	struct mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
446	struct __queue *queue	= &(pmlmepriv->scanned_queue);
447	struct wlan_network	*pnetwork = NULL;
448	struct wlan_network	*oldest = NULL;
449
450	spin_lock_bh(&queue->lock);
451	phead = get_list_head(queue);
452	plist = phead->next;
453
454	while (phead != plist) {
455		pnetwork	= container_of(plist, struct wlan_network, list);
456
457		if (is_same_network(&(pnetwork->network), target))
458			break;
459		if ((oldest == ((struct wlan_network *)0)) ||
460		    time_after(oldest->last_scanned, pnetwork->last_scanned))
461			oldest = pnetwork;
462		plist = plist->next;
463	}
464	/* If we didn't find a match, then get a new network slot to initialize
465	 * with this beacon's information */
466	if (phead == plist) {
467		if (list_empty(&(pmlmepriv->free_bss_pool.queue))) {
468			/* If there are no more slots, expire the oldest */
469			pnetwork = oldest;
470
471			rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(target->PhyInfo.Optimum_antenna));
472			memcpy(&(pnetwork->network), target,  get_wlan_bssid_ex_sz(target));
473			/*  variable initialize */
474			pnetwork->fixed = false;
475			pnetwork->last_scanned = jiffies;
476
477			pnetwork->network_type = 0;
478			pnetwork->aid = 0;
479			pnetwork->join_res = 0;
480
481			/* bss info not receiving from the right channel */
482			if (pnetwork->network.PhyInfo.SignalQuality == 101)
483				pnetwork->network.PhyInfo.SignalQuality = 0;
484		} else {
485			/* Otherwise just pull from the free list */
486
487			pnetwork = rtw_alloc_network(pmlmepriv); /*  will update scan_time */
488
489			if (pnetwork == NULL) {
490				RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n\nsomething wrong here\n\n\n"));
491				goto exit;
492			}
493
494			bssid_ex_sz = get_wlan_bssid_ex_sz(target);
495			target->Length = bssid_ex_sz;
496			rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(target->PhyInfo.Optimum_antenna));
497			memcpy(&(pnetwork->network), target, bssid_ex_sz);
498
499			pnetwork->last_scanned = jiffies;
500
501			/* bss info not receiving from the right channel */
502			if (pnetwork->network.PhyInfo.SignalQuality == 101)
503				pnetwork->network.PhyInfo.SignalQuality = 0;
504			list_add_tail(&(pnetwork->list), &(queue->queue));
505		}
506	} else {
507		/* we have an entry and we are going to update it. But this entry may
508		 * be already expired. In this case we do the same as we found a new
509		 * net and call the new_net handler
510		 */
511		bool update_ie = true;
512
513		pnetwork->last_scanned = jiffies;
514
515		/* target.Reserved[0]== 1, means that scanned network is a bcn frame. */
516		if ((pnetwork->network.IELength > target->IELength) && (target->Reserved[0] == 1))
517			update_ie = false;
518
519		update_network(&(pnetwork->network), target, adapter, update_ie);
520	}
521
522exit:
523	spin_unlock_bh(&queue->lock);
524
525}
526
527static void rtw_add_network(struct adapter *adapter,
528			    struct wlan_bssid_ex *pnetwork)
529{
530	update_current_network(adapter, pnetwork);
531	rtw_update_scanned_network(adapter, pnetwork);
532}
533
534/*
535 * select the desired network based on the capability of the (i)bss.
536 * check items:	(1) security
537 *			(2) network_type
538 *			(3) WMM
539 *			(4) HT
540 *			(5) others
541 */
542static int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwork)
543{
544	struct security_priv *psecuritypriv = &adapter->securitypriv;
545	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
546	u32 desired_encmode;
547	u32 privacy;
548
549	/* u8 wps_ie[512]; */
550	uint wps_ielen;
551
552	int bselected = true;
553
554	desired_encmode = psecuritypriv->ndisencryptstatus;
555	privacy = pnetwork->network.Privacy;
556
557	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
558		if (rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen) != NULL)
559			return true;
560		else
561			return false;
562	}
563	if (adapter->registrypriv.wifi_spec == 1) { /* for  correct flow of 8021X  to do.... */
564		if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
565			bselected = false;
566	}
567
568
569	if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
570		DBG_88E("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
571		bselected = false;
572	}
573
574	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true) {
575		if (pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
576			bselected = false;
577	}
578
579
580	return bselected;
581}
582
583/* TODO: Perry: For Power Management */
584void rtw_atimdone_event_callback(struct adapter	*adapter , u8 *pbuf)
585{
586	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("receive atimdone_evet\n"));
587	return;
588}
589
590
591void rtw_survey_event_callback(struct adapter	*adapter, u8 *pbuf)
592{
593	u32 len;
594	struct wlan_bssid_ex *pnetwork;
595	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
596
597	pnetwork = (struct wlan_bssid_ex *)pbuf;
598
599	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_survey_event_callback, ssid=%s\n",  pnetwork->Ssid.Ssid));
600
601	len = get_wlan_bssid_ex_sz(pnetwork);
602	if (len > (sizeof(struct wlan_bssid_ex))) {
603		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n****rtw_survey_event_callback: return a wrong bss ***\n"));
604		return;
605	}
606	spin_lock_bh(&pmlmepriv->lock);
607
608	/*  update IBSS_network 's timestamp */
609	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == true) {
610		if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
611			struct wlan_network *ibss_wlan = NULL;
612
613			memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
614			spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
615			ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
616			if (ibss_wlan) {
617				memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
618				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
619				goto exit;
620			}
621			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
622		}
623	}
624
625	/*  lock pmlmepriv->lock when you accessing network_q */
626	if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == false) {
627		if (pnetwork->Ssid.Ssid[0] == 0)
628			pnetwork->Ssid.SsidLength = 0;
629		rtw_add_network(adapter, pnetwork);
630	}
631
632exit:
633
634	spin_unlock_bh(&pmlmepriv->lock);
635	return;
636}
637
638void rtw_surveydone_event_callback(struct adapter	*adapter, u8 *pbuf)
639{
640	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
641	struct mlme_ext_priv *pmlmeext;
642
643	spin_lock_bh(&pmlmepriv->lock);
644
645	if (pmlmepriv->wps_probe_req_ie) {
646		pmlmepriv->wps_probe_req_ie_len = 0;
647		kfree(pmlmepriv->wps_probe_req_ie);
648		pmlmepriv->wps_probe_req_ie = NULL;
649	}
650
651	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_surveydone_event_callback: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
652
653	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
654		del_timer_sync(&pmlmepriv->scan_to_timer);
655		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
656	} else {
657		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("nic status=%x, survey done event comes too late!\n", get_fwstate(pmlmepriv)));
658	}
659
660	rtw_set_signal_stat_timer(&adapter->recvpriv);
661
662	if (pmlmepriv->to_join) {
663		if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
664			if (check_fwstate(pmlmepriv, _FW_LINKED) == false) {
665				set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
666
667				if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
668					_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
669				} else {
670					struct wlan_bssid_ex    *pdev_network = &(adapter->registrypriv.dev_network);
671					u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
672
673					_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
674
675					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("switching to adhoc master\n"));
676
677					memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
678					memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
679
680					rtw_update_registrypriv_dev_network(adapter);
681					rtw_generate_random_ibss(pibss);
682
683					pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
684
685					if (rtw_createbss_cmd(adapter) != _SUCCESS)
686						RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error=>rtw_createbss_cmd status FAIL\n"));
687					pmlmepriv->to_join = false;
688				}
689			}
690		} else {
691			int s_ret;
692			set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
693			pmlmepriv->to_join = false;
694			s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
695			if (_SUCCESS == s_ret) {
696			     _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
697			} else if (s_ret == 2) { /* there is no need to wait for join */
698				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
699				rtw_indicate_connect(adapter);
700			} else {
701				DBG_88E("try_to_join, but select scanning queue fail, to_roaming:%d\n", pmlmepriv->to_roaming);
702				if (pmlmepriv->to_roaming != 0) {
703					if (--pmlmepriv->to_roaming == 0 ||
704					    _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) {
705						pmlmepriv->to_roaming = 0;
706						rtw_free_assoc_resources(adapter, 1);
707						rtw_indicate_disconnect(adapter);
708					} else {
709						pmlmepriv->to_join = true;
710					}
711				}
712				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
713			}
714		}
715	}
716
717	indicate_wx_scan_complete_event(adapter);
718
719	spin_unlock_bh(&pmlmepriv->lock);
720
721	rtw_os_xmit_schedule(adapter);
722
723	pmlmeext = &adapter->mlmeextpriv;
724}
725
726void rtw_dummy_event_callback(struct adapter *adapter , u8 *pbuf)
727{
728}
729
730void rtw_fwdbg_event_callback(struct adapter *adapter , u8 *pbuf)
731{
732}
733
734static void free_scanqueue(struct	mlme_priv *pmlmepriv)
735{
736	struct __queue *free_queue = &pmlmepriv->free_bss_pool;
737	struct __queue *scan_queue = &pmlmepriv->scanned_queue;
738	struct list_head *plist, *phead, *ptemp;
739
740	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
741	spin_lock_bh(&scan_queue->lock);
742	spin_lock_bh(&free_queue->lock);
743
744	phead = get_list_head(scan_queue);
745	plist = phead->next;
746
747	while (plist != phead) {
748		ptemp = plist->next;
749		list_del_init(plist);
750		list_add_tail(plist, &free_queue->queue);
751		plist = ptemp;
752		pmlmepriv->num_of_scanned--;
753	}
754
755	spin_unlock_bh(&free_queue->lock);
756	spin_unlock_bh(&scan_queue->lock);
757}
758
759/*
760*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
761*/
762void rtw_free_assoc_resources(struct adapter *adapter, int lock_scanned_queue)
763{
764	struct wlan_network *pwlan = NULL;
765	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
766	struct	sta_priv *pstapriv = &adapter->stapriv;
767	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
768
769	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
770	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
771		 ("tgt_network->network.MacAddress=%pM ssid=%s\n",
772		 tgt_network->network.MacAddress, tgt_network->network.Ssid.Ssid));
773
774	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
775		struct sta_info *psta;
776
777		psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
778
779		spin_lock_bh(&(pstapriv->sta_hash_lock));
780		rtw_free_stainfo(adapter,  psta);
781		spin_unlock_bh(&pstapriv->sta_hash_lock);
782	}
783
784	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE)) {
785		struct sta_info *psta;
786
787		rtw_free_all_stainfo(adapter);
788
789		psta = rtw_get_bcmc_stainfo(adapter);
790		spin_lock_bh(&(pstapriv->sta_hash_lock));
791		rtw_free_stainfo(adapter, psta);
792		spin_unlock_bh(&pstapriv->sta_hash_lock);
793
794		rtw_init_bcmc_stainfo(adapter);
795	}
796
797	if (lock_scanned_queue)
798		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
799
800	pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
801	if (pwlan)
802		pwlan->fixed = false;
803	else
804		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_free_assoc_resources:pwlan==NULL\n\n"));
805
806	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count == 1)))
807		rtw_free_network_nolock(pmlmepriv, pwlan);
808
809	if (lock_scanned_queue)
810		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
811	pmlmepriv->key_mask = 0;
812}
813
814/*
815*rtw_indicate_connect: the caller has to lock pmlmepriv->lock
816*/
817void rtw_indicate_connect(struct adapter *padapter)
818{
819	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
820
821	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect\n"));
822
823	pmlmepriv->to_join = false;
824
825	if (!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
826		set_fwstate(pmlmepriv, _FW_LINKED);
827
828		rtw_led_control(padapter, LED_CTL_LINK);
829
830		rtw_os_indicate_connect(padapter);
831	}
832
833	pmlmepriv->to_roaming = 0;
834
835	rtw_set_scan_deny(padapter, 3000);
836
837	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
838}
839
840/*
841*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
842*/
843void rtw_indicate_disconnect(struct adapter *padapter)
844{
845	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
846
847	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect\n"));
848
849	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING | WIFI_UNDER_WPS);
850
851
852	if (pmlmepriv->to_roaming > 0)
853		_clr_fwstate_(pmlmepriv, _FW_LINKED);
854
855	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) ||
856	    (pmlmepriv->to_roaming <= 0)) {
857		rtw_os_indicate_disconnect(padapter);
858
859		_clr_fwstate_(pmlmepriv, _FW_LINKED);
860		rtw_led_control(padapter, LED_CTL_NO_LINK);
861		rtw_clear_scan_deny(padapter);
862	}
863
864	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
865}
866
867inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
868{
869	rtw_os_indicate_scan_done(padapter, aborted);
870}
871
872void rtw_scan_abort(struct adapter *adapter)
873{
874	u32 start;
875	struct mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
876	struct mlme_ext_priv	*pmlmeext = &(adapter->mlmeextpriv);
877
878	start = jiffies;
879	pmlmeext->scan_abort = true;
880	while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) &&
881	       rtw_get_passing_time_ms(start) <= 200) {
882		if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
883			break;
884		DBG_88E(FUNC_NDEV_FMT"fw_state=_FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
885		msleep(20);
886	}
887	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
888		if (!adapter->bDriverStopped && !adapter->bSurpriseRemoved)
889			DBG_88E(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
890		rtw_indicate_scan_done(adapter, true);
891	}
892	pmlmeext->scan_abort = false;
893}
894
895static struct sta_info *rtw_joinbss_update_stainfo(struct adapter *padapter, struct wlan_network *pnetwork)
896{
897	int i;
898	struct sta_info *bmc_sta, *psta = NULL;
899	struct recv_reorder_ctrl *preorder_ctrl;
900	struct sta_priv *pstapriv = &padapter->stapriv;
901
902	psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
903	if (psta == NULL)
904		psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
905
906	if (psta) { /* update ptarget_sta */
907		DBG_88E("%s\n", __func__);
908		psta->aid  = pnetwork->join_res;
909			psta->mac_id = 0;
910		/* sta mode */
911		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, true);
912		/* security related */
913		if (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
914			padapter->securitypriv.binstallGrpkey = false;
915			padapter->securitypriv.busetkipkey = false;
916			padapter->securitypriv.bgrpkey_handshake = false;
917			psta->ieee8021x_blocked = true;
918			psta->dot118021XPrivacy = padapter->securitypriv.dot11PrivacyAlgrthm;
919			memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof(union Keytype));
920			memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof(union Keytype));
921			memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof(union Keytype));
922			memset((u8 *)&psta->dot11txpn, 0, sizeof(union pn48));
923			memset((u8 *)&psta->dot11rxpn, 0, sizeof(union pn48));
924		}
925		/*
926		 * Commented by Albert 2012/07/21
927		 * When doing the WPS, the wps_ie_len won't equal to 0
928		 * And the Wi-Fi driver shouldn't allow the data
929		 * packet to be tramsmitted.
930		 */
931		if (padapter->securitypriv.wps_ie_len != 0) {
932			psta->ieee8021x_blocked = true;
933			padapter->securitypriv.wps_ie_len = 0;
934		}
935		/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info */
936		/* if A-MPDU Rx is enabled, resetting  rx_ordering_ctrl wstart_b(indicate_seq) to default value = 0xffff */
937		/* todo: check if AP can send A-MPDU packets */
938		for (i = 0; i < 16; i++) {
939			/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
940			preorder_ctrl = &psta->recvreorder_ctrl[i];
941			preorder_ctrl->enable = false;
942			preorder_ctrl->indicate_seq = 0xffff;
943			preorder_ctrl->wend_b = 0xffff;
944			preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
945		}
946		bmc_sta = rtw_get_bcmc_stainfo(padapter);
947		if (bmc_sta) {
948			for (i = 0; i < 16; i++) {
949				/* preorder_ctrl = &precvpriv->recvreorder_ctrl[i]; */
950				preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
951				preorder_ctrl->enable = false;
952				preorder_ctrl->indicate_seq = 0xffff;
953				preorder_ctrl->wend_b = 0xffff;
954				preorder_ctrl->wsize_b = 64;/* max_ampdu_sz; ex. 32(kbytes) -> wsize_b = 32 */
955			}
956		}
957		/* misc. */
958		update_sta_info(padapter, psta);
959	}
960	return psta;
961}
962
963/* pnetwork: returns from rtw_joinbss_event_callback */
964/* ptarget_wlan: found from scanned_queue */
965static void rtw_joinbss_update_network(struct adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network  *pnetwork)
966{
967	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
968	struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
969
970	DBG_88E("%s\n", __func__);
971
972	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
973		 ("\nfw_state:%x, BSSID:%pM\n",
974		 get_fwstate(pmlmepriv), pnetwork->network.MacAddress));
975
976
977	/*  why not use ptarget_wlan?? */
978	memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
979	/*  some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs */
980	cur_network->network.IELength = ptarget_wlan->network.IELength;
981	memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
982
983	cur_network->aid = pnetwork->join_res;
984
985
986	rtw_set_signal_stat_timer(&padapter->recvpriv);
987	padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
988	padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
989	/* the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled) */
990	padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
991	rtw_set_signal_stat_timer(&padapter->recvpriv);
992
993	/* update fw_state will clr _FW_UNDER_LINKING here indirectly */
994	switch (pnetwork->network.InfrastructureMode) {
995	case Ndis802_11Infrastructure:
996		if (pmlmepriv->fw_state&WIFI_UNDER_WPS)
997			pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
998		else
999			pmlmepriv->fw_state = WIFI_STATION_STATE;
1000		break;
1001	case Ndis802_11IBSS:
1002		pmlmepriv->fw_state = WIFI_ADHOC_STATE;
1003		break;
1004	default:
1005		pmlmepriv->fw_state = WIFI_NULL_STATE;
1006		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Invalid network_mode\n"));
1007		break;
1008	}
1009
1010	rtw_update_protection(padapter, (cur_network->network.IEs) +
1011			      sizeof(struct ndis_802_11_fixed_ie),
1012			      (cur_network->network.IELength));
1013	rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength);
1014}
1015
1016/* Notes: the function could be > passive_level (the same context as Rx tasklet) */
1017/* pnetwork: returns from rtw_joinbss_event_callback */
1018/* ptarget_wlan: found from scanned_queue */
1019/* if join_res > 0, for (fw_state == WIFI_STATION_STATE), we check if  "ptarget_sta" & "ptarget_wlan" exist. */
1020/* if join_res > 0, for (fw_state == WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist. */
1021/* if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan != NULL). */
1022
1023void rtw_joinbss_event_prehandle(struct adapter *adapter, u8 *pbuf)
1024{
1025	struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
1026	struct	sta_priv *pstapriv = &adapter->stapriv;
1027	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
1028	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
1029	struct wlan_network	*cur_network = &(pmlmepriv->cur_network);
1030	struct wlan_network	*pcur_wlan = NULL, *ptarget_wlan = NULL;
1031	unsigned int		the_same_macaddr = false;
1032
1033	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("joinbss event call back received with res=%d\n", pnetwork->join_res));
1034
1035	rtw_get_encrypt_decrypt_from_registrypriv(adapter);
1036
1037
1038	if (pmlmepriv->assoc_ssid.SsidLength == 0)
1039		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@   joinbss event call back  for Any SSid\n"));
1040	else
1041		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("@@@@@   rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
1042
1043	the_same_macaddr = !memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
1044
1045	pnetwork->network.Length = get_wlan_bssid_ex_sz(&pnetwork->network);
1046	if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex)) {
1047		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
1048		return;
1049	}
1050
1051	spin_lock_bh(&pmlmepriv->lock);
1052
1053	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("\nrtw_joinbss_event_callback!! _enter_critical\n"));
1054
1055	if (pnetwork->join_res > 0) {
1056		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1057		if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
1058			/* s1. find ptarget_wlan */
1059			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1060				if (the_same_macaddr) {
1061					ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1062				} else {
1063					pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1064					if (pcur_wlan)
1065						pcur_wlan->fixed = false;
1066
1067					pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
1068					if (pcur_sta) {
1069						spin_lock_bh(&(pstapriv->sta_hash_lock));
1070						rtw_free_stainfo(adapter,  pcur_sta);
1071						spin_unlock_bh(&pstapriv->sta_hash_lock);
1072					}
1073
1074					ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1075					if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1076						if (ptarget_wlan)
1077							ptarget_wlan->fixed = true;
1078					}
1079				}
1080			} else {
1081				ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
1082				if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1083					if (ptarget_wlan)
1084						ptarget_wlan->fixed = true;
1085				}
1086			}
1087
1088			/* s2. update cur_network */
1089			if (ptarget_wlan) {
1090				rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork);
1091			} else {
1092				RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't find ptarget_wlan when joinbss_event callback\n"));
1093				spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1094				goto ignore_joinbss_callback;
1095			}
1096
1097
1098			/* s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode */
1099			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1100				ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
1101				if (ptarget_sta == NULL) {
1102					RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't update stainfo when joinbss_event callback\n"));
1103					spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1104					goto ignore_joinbss_callback;
1105				}
1106			}
1107
1108			/* s4. indicate connect */
1109				if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
1110					rtw_indicate_connect(adapter);
1111				} else {
1112					/* adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback */
1113					RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
1114				}
1115
1116			/* s5. Cancle assoc_timer */
1117			del_timer_sync(&pmlmepriv->assoc_timer);
1118
1119			RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("Cancle assoc_timer\n"));
1120
1121		} else {
1122			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));
1123			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1124			goto ignore_joinbss_callback;
1125		}
1126
1127		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1128
1129	} else if (pnetwork->join_res == -4) {
1130		rtw_reset_securitypriv(adapter);
1131		_set_timer(&pmlmepriv->assoc_timer, 1);
1132
1133		if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == true) {
1134			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", get_fwstate(pmlmepriv)));
1135			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1136		}
1137	} else { /* if join_res < 0 (join fails), then try again */
1138		_set_timer(&pmlmepriv->assoc_timer, 1);
1139		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1140	}
1141
1142ignore_joinbss_callback:
1143	spin_unlock_bh(&pmlmepriv->lock);
1144}
1145
1146void rtw_joinbss_event_callback(struct adapter *adapter, u8 *pbuf)
1147{
1148	struct wlan_network	*pnetwork	= (struct wlan_network *)pbuf;
1149
1150	mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
1151
1152	rtw_os_xmit_schedule(adapter);
1153}
1154
1155static u8 search_max_mac_id(struct adapter *padapter)
1156{
1157	u8 mac_id;
1158#if defined(CONFIG_88EU_AP_MODE)
1159	u8 aid;
1160	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1161	struct sta_priv *pstapriv = &padapter->stapriv;
1162#endif
1163	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
1164	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
1165
1166#if defined(CONFIG_88EU_AP_MODE)
1167	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1168		for (aid = (pstapriv->max_num_sta); aid > 0; aid--) {
1169			if (pstapriv->sta_aid[aid-1] != NULL)
1170				break;
1171		}
1172		mac_id = aid + 1;
1173	} else
1174#endif
1175	{/* adhoc  id =  31~2 */
1176		for (mac_id = (NUM_STA-1); mac_id >= IBSS_START_MAC_ID; mac_id--) {
1177			if (pmlmeinfo->FW_sta_info[mac_id].status == 1)
1178				break;
1179		}
1180	}
1181	return mac_id;
1182}
1183
1184/* FOR AP , AD-HOC mode */
1185void rtw_stassoc_hw_rpt(struct adapter *adapter, struct sta_info *psta)
1186{
1187	u16 media_status;
1188	u8 macid;
1189
1190	if (psta == NULL)
1191		return;
1192
1193	macid = search_max_mac_id(adapter);
1194	rtw_hal_set_hwreg(adapter, HW_VAR_TX_RPT_MAX_MACID, (u8 *)&macid);
1195	media_status = (psta->mac_id<<8)|1; /*   MACID|OPMODE:1 connect */
1196	rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1197}
1198
1199void rtw_stassoc_event_callback(struct adapter *adapter, u8 *pbuf)
1200{
1201	struct sta_info *psta;
1202	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1203	struct stassoc_event	*pstassoc = (struct stassoc_event *)pbuf;
1204	struct wlan_network	*cur_network = &(pmlmepriv->cur_network);
1205	struct wlan_network	*ptarget_wlan = NULL;
1206
1207	if (rtw_access_ctrl(adapter, pstassoc->macaddr) == false)
1208		return;
1209
1210#if defined(CONFIG_88EU_AP_MODE)
1211	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
1212		psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
1213		if (psta) {
1214			ap_sta_info_defer_update(adapter, psta);
1215			rtw_stassoc_hw_rpt(adapter, psta);
1216		}
1217		return;
1218	}
1219#endif
1220	/* for AD-HOC mode */
1221	psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
1222	if (psta != NULL) {
1223		/* the sta have been in sta_info_queue => do nothing */
1224		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error: rtw_stassoc_event_callback: sta has been in sta_hash_queue\n"));
1225		return; /* between drv has received this event before and  fw have not yet to set key to CAM_ENTRY) */
1226	}
1227	psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
1228	if (psta == NULL) {
1229		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Can't alloc sta_info when rtw_stassoc_event_callback\n"));
1230		return;
1231	}
1232	/* to do: init sta_info variable */
1233	psta->qos_option = 0;
1234	psta->mac_id = (uint)pstassoc->cam_id;
1235	DBG_88E("%s\n", __func__);
1236	/* for ad-hoc mode */
1237	rtw_hal_set_odm_var(adapter, HAL_ODM_STA_INFO, psta, true);
1238	rtw_stassoc_hw_rpt(adapter, psta);
1239	if (adapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)
1240		psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
1241	psta->ieee8021x_blocked = false;
1242	spin_lock_bh(&pmlmepriv->lock);
1243	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) ||
1244	    (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))) {
1245		if (adapter->stapriv.asoc_sta_count == 2) {
1246			spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1247			ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
1248			if (ptarget_wlan)
1249				ptarget_wlan->fixed = true;
1250			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1251			/*  a sta + bc/mc_stainfo (not Ibss_stainfo) */
1252			rtw_indicate_connect(adapter);
1253		}
1254	}
1255	spin_unlock_bh(&pmlmepriv->lock);
1256	mlmeext_sta_add_event_callback(adapter, psta);
1257}
1258
1259void rtw_stadel_event_callback(struct adapter *adapter, u8 *pbuf)
1260{
1261	int mac_id = -1;
1262	struct sta_info *psta;
1263	struct wlan_network *pwlan = NULL;
1264	struct wlan_bssid_ex *pdev_network = NULL;
1265	u8 *pibss = NULL;
1266	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
1267	struct	stadel_event *pstadel = (struct stadel_event *)pbuf;
1268	struct	sta_priv *pstapriv = &adapter->stapriv;
1269	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
1270
1271	psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
1272	if (psta)
1273		mac_id = psta->mac_id;
1274	else
1275		mac_id = pstadel->mac_id;
1276
1277	DBG_88E("%s(mac_id=%d)=%pM\n", __func__, mac_id, pstadel->macaddr);
1278
1279	if (mac_id >= 0) {
1280		u16 media_status;
1281		media_status = (mac_id<<8)|0; /*   MACID|OPMODE:0 means disconnect */
1282		/* for STA, AP, ADHOC mode, report disconnect stauts to FW */
1283		rtw_hal_set_hwreg(adapter, HW_VAR_H2C_MEDIA_STATUS_RPT, (u8 *)&media_status);
1284	}
1285
1286	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
1287		return;
1288
1289	mlmeext_sta_del_event_callback(adapter);
1290
1291	spin_lock_bh(&pmlmepriv->lock);
1292
1293	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
1294		if (pmlmepriv->to_roaming > 0)
1295			pmlmepriv->to_roaming--; /*  this stadel_event is caused by roaming, decrease to_roaming */
1296		else if (pmlmepriv->to_roaming == 0)
1297			pmlmepriv->to_roaming = adapter->registrypriv.max_roaming_times;
1298
1299		if (*((unsigned short *)(pstadel->rsvd)) != WLAN_REASON_EXPIRATION_CHK)
1300			pmlmepriv->to_roaming = 0; /*  don't roam */
1301
1302		rtw_free_uc_swdec_pending_queue(adapter);
1303
1304		rtw_free_assoc_resources(adapter, 1);
1305		rtw_indicate_disconnect(adapter);
1306		spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1307		/*  remove the network entry in scanned_queue */
1308		pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1309		if (pwlan) {
1310			pwlan->fixed = false;
1311			rtw_free_network_nolock(pmlmepriv, pwlan);
1312		}
1313		spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1314		_rtw_roaming(adapter, tgt_network);
1315	}
1316	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
1317	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1318		spin_lock_bh(&(pstapriv->sta_hash_lock));
1319		rtw_free_stainfo(adapter,  psta);
1320		spin_unlock_bh(&pstapriv->sta_hash_lock);
1321
1322		if (adapter->stapriv.asoc_sta_count == 1) { /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
1323			spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1324			/* free old ibss network */
1325			pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
1326			if (pwlan) {
1327				pwlan->fixed = false;
1328				rtw_free_network_nolock(pmlmepriv, pwlan);
1329			}
1330			spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1331			/* re-create ibss */
1332			pdev_network = &(adapter->registrypriv.dev_network);
1333			pibss = adapter->registrypriv.dev_network.MacAddress;
1334
1335			memcpy(pdev_network, &tgt_network->network, get_wlan_bssid_ex_sz(&tgt_network->network));
1336
1337			memset(&pdev_network->Ssid, 0, sizeof(struct ndis_802_11_ssid));
1338			memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(struct ndis_802_11_ssid));
1339
1340			rtw_update_registrypriv_dev_network(adapter);
1341
1342			rtw_generate_random_ibss(pibss);
1343
1344			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1345				set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1346				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1347			}
1348
1349			if (rtw_createbss_cmd(adapter) != _SUCCESS)
1350				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error=>stadel_event_callback: rtw_createbss_cmd status FAIL***\n "));
1351		}
1352	}
1353	spin_unlock_bh(&pmlmepriv->lock);
1354}
1355
1356void rtw_cpwm_event_callback(struct adapter *padapter, u8 *pbuf)
1357{
1358	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_cpwm_event_callback !!!\n"));
1359}
1360
1361/*
1362* _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
1363* @adapter: pointer to struct adapter structure
1364*/
1365void _rtw_join_timeout_handler (void *function_context)
1366{
1367	struct adapter *adapter = (struct adapter *)function_context;
1368	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
1369	int do_join_r;
1370
1371	DBG_88E("%s, fw_state=%x\n", __func__, get_fwstate(pmlmepriv));
1372
1373	if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1374		return;
1375
1376
1377	spin_lock_bh(&pmlmepriv->lock);
1378
1379	if (pmlmepriv->to_roaming > 0) { /*  join timeout caused by roaming */
1380		while (1) {
1381			pmlmepriv->to_roaming--;
1382			if (pmlmepriv->to_roaming != 0) { /* try another , */
1383				DBG_88E("%s try another roaming\n", __func__);
1384				do_join_r = rtw_do_join(adapter);
1385				if (_SUCCESS != do_join_r) {
1386					DBG_88E("%s roaming do_join return %d\n", __func__ , do_join_r);
1387					continue;
1388				}
1389				break;
1390			} else {
1391				DBG_88E("%s We've try roaming but fail\n", __func__);
1392				rtw_indicate_disconnect(adapter);
1393				break;
1394			}
1395		}
1396	} else {
1397		rtw_indicate_disconnect(adapter);
1398		free_scanqueue(pmlmepriv);/*  */
1399	}
1400	spin_unlock_bh(&pmlmepriv->lock);
1401}
1402
1403/*
1404* rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
1405* @adapter: pointer to struct adapter structure
1406*/
1407void rtw_scan_timeout_handler (void *function_context)
1408{
1409	struct adapter *adapter = (struct adapter *)function_context;
1410	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
1411
1412	DBG_88E(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
1413	spin_lock_bh(&pmlmepriv->lock);
1414	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1415	spin_unlock_bh(&pmlmepriv->lock);
1416	rtw_indicate_scan_done(adapter, true);
1417}
1418
1419static void rtw_auto_scan_handler(struct adapter *padapter)
1420{
1421	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1422
1423	/* auto site survey per 60sec */
1424	if (pmlmepriv->scan_interval > 0) {
1425		pmlmepriv->scan_interval--;
1426		if (pmlmepriv->scan_interval == 0) {
1427			DBG_88E("%s\n", __func__);
1428			rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
1429			pmlmepriv->scan_interval = SCAN_INTERVAL;/*  30*2 sec = 60sec */
1430		}
1431	}
1432}
1433
1434void rtw_dynamic_check_timer_handlder(void *function_context)
1435{
1436	struct adapter *adapter = (struct adapter *)function_context;
1437	struct registry_priv *pregistrypriv = &adapter->registrypriv;
1438
1439	if (!adapter)
1440		goto exit;
1441	if (!adapter->hw_init_completed)
1442		goto exit;
1443	if ((adapter->bDriverStopped) || (adapter->bSurpriseRemoved))
1444		goto exit;
1445	if (adapter->net_closed)
1446		goto exit;
1447	rtw_dynamic_chk_wk_cmd(adapter);
1448
1449	if (pregistrypriv->wifi_spec == 1) {
1450		/* auto site survey */
1451		rtw_auto_scan_handler(adapter);
1452	}
1453exit:
1454	_set_timer(&adapter->mlmepriv.dynamic_chk_timer, 2000);
1455}
1456
1457#define RTW_SCAN_RESULT_EXPIRE 2000
1458
1459/*
1460* Select a new join candidate from the original @param candidate and @param competitor
1461* @return true: candidate is updated
1462* @return false: candidate is not updated
1463*/
1464static int rtw_check_join_candidate(struct mlme_priv *pmlmepriv
1465	, struct wlan_network **candidate, struct wlan_network *competitor)
1466{
1467	int updated = false;
1468	struct adapter *adapter = container_of(pmlmepriv, struct adapter, mlmepriv);
1469
1470
1471	/* check bssid, if needed */
1472	if (pmlmepriv->assoc_by_bssid) {
1473		if (memcmp(competitor->network.MacAddress, pmlmepriv->assoc_bssid, ETH_ALEN))
1474			goto exit;
1475	}
1476
1477	/* check ssid, if needed */
1478	if (pmlmepriv->assoc_ssid.SsidLength) {
1479		if (competitor->network.Ssid.SsidLength != pmlmepriv->assoc_ssid.SsidLength ||
1480		    !memcmp(competitor->network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength) == false)
1481			goto exit;
1482	}
1483
1484	if (rtw_is_desired_network(adapter, competitor)  == false)
1485		goto exit;
1486
1487	if (pmlmepriv->to_roaming) {
1488		if (rtw_get_passing_time_ms((u32)competitor->last_scanned) >= RTW_SCAN_RESULT_EXPIRE ||
1489		    is_same_ess(&competitor->network, &pmlmepriv->cur_network.network) == false)
1490			goto exit;
1491	}
1492
1493	if (*candidate == NULL || (*candidate)->network.Rssi < competitor->network.Rssi) {
1494		*candidate = competitor;
1495		updated = true;
1496	}
1497	if (updated) {
1498		DBG_88E("[by_bssid:%u][assoc_ssid:%s]new candidate: %s(%pM rssi:%d\n",
1499			pmlmepriv->assoc_by_bssid,
1500			pmlmepriv->assoc_ssid.Ssid,
1501			(*candidate)->network.Ssid.Ssid,
1502			(*candidate)->network.MacAddress,
1503			(int)(*candidate)->network.Rssi);
1504		DBG_88E("[to_roaming:%u]\n", pmlmepriv->to_roaming);
1505	}
1506
1507exit:
1508	return updated;
1509}
1510
1511/*
1512Calling context:
1513The caller of the sub-routine will be in critical section...
1514The caller must hold the following spinlock
1515pmlmepriv->lock
1516*/
1517
1518int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv)
1519{
1520	int ret;
1521	struct list_head *phead;
1522	struct adapter *adapter;
1523	struct __queue *queue	= &(pmlmepriv->scanned_queue);
1524	struct	wlan_network	*pnetwork = NULL;
1525	struct	wlan_network	*candidate = NULL;
1526	u8	supp_ant_div = false;
1527
1528	spin_lock_bh(&(pmlmepriv->scanned_queue.lock));
1529	phead = get_list_head(queue);
1530	adapter = (struct adapter *)pmlmepriv->nic_hdl;
1531	pmlmepriv->pscanned = phead->next;
1532	while (phead != pmlmepriv->pscanned) {
1533		pnetwork = container_of(pmlmepriv->pscanned, struct wlan_network, list);
1534		if (pnetwork == NULL) {
1535			RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("%s return _FAIL:(pnetwork==NULL)\n", __func__));
1536			ret = _FAIL;
1537			goto exit;
1538		}
1539		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1540		rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
1541	}
1542	if (candidate == NULL) {
1543		DBG_88E("%s: return _FAIL(candidate==NULL)\n", __func__);
1544		ret = _FAIL;
1545		goto exit;
1546	} else {
1547		DBG_88E("%s: candidate: %s(%pM ch:%u)\n", __func__,
1548			candidate->network.Ssid.Ssid, candidate->network.MacAddress,
1549			candidate->network.Configuration.DSConfig);
1550	}
1551
1552
1553	/*  check for situation of  _FW_LINKED */
1554	if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1555		DBG_88E("%s: _FW_LINKED while ask_for_joinbss!!!\n", __func__);
1556
1557		rtw_disassoc_cmd(adapter, 0, true);
1558		rtw_indicate_disconnect(adapter);
1559		rtw_free_assoc_resources(adapter, 0);
1560	}
1561
1562	rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(supp_ant_div));
1563	if (supp_ant_div) {
1564		u8 cur_ant;
1565		rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(cur_ant));
1566		DBG_88E("#### Opt_Ant_(%s), cur_Ant(%s)\n",
1567			(2 == candidate->network.PhyInfo.Optimum_antenna) ? "A" : "B",
1568			(2 == cur_ant) ? "A" : "B"
1569		);
1570	}
1571
1572	ret = rtw_joinbss_cmd(adapter, candidate);
1573
1574exit:
1575	spin_unlock_bh(&pmlmepriv->scanned_queue.lock);
1576	return ret;
1577}
1578
1579int rtw_set_auth(struct adapter *adapter, struct security_priv *psecuritypriv)
1580{
1581	struct	cmd_obj *pcmd;
1582	struct	setauth_parm *psetauthparm;
1583	struct	cmd_priv *pcmdpriv = &(adapter->cmdpriv);
1584	int		res = _SUCCESS;
1585
1586	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1587	if (pcmd == NULL) {
1588		res = _FAIL;  /* try again */
1589		goto exit;
1590	}
1591
1592	psetauthparm = kzalloc(sizeof(struct setauth_parm), GFP_KERNEL);
1593	if (psetauthparm == NULL) {
1594		kfree(pcmd);
1595		res = _FAIL;
1596		goto exit;
1597	}
1598	memset(psetauthparm, 0, sizeof(struct setauth_parm));
1599	psetauthparm->mode = (unsigned char)psecuritypriv->dot11AuthAlgrthm;
1600	pcmd->cmdcode = _SetAuth_CMD_;
1601	pcmd->parmbuf = (unsigned char *)psetauthparm;
1602	pcmd->cmdsz =  (sizeof(struct setauth_parm));
1603	pcmd->rsp = NULL;
1604	pcmd->rspsz = 0;
1605	INIT_LIST_HEAD(&pcmd->list);
1606	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1607		 ("after enqueue set_auth_cmd, auth_mode=%x\n",
1608		 psecuritypriv->dot11AuthAlgrthm));
1609	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1610exit:
1611	return res;
1612}
1613
1614int rtw_set_key(struct adapter *adapter, struct security_priv *psecuritypriv, int keyid, u8 set_tx)
1615{
1616	u8	keylen;
1617	struct cmd_obj		*pcmd;
1618	struct setkey_parm	*psetkeyparm;
1619	struct cmd_priv		*pcmdpriv = &(adapter->cmdpriv);
1620	struct mlme_priv		*pmlmepriv = &(adapter->mlmepriv);
1621	int	res = _SUCCESS;
1622
1623	pcmd = kzalloc(sizeof(struct cmd_obj), GFP_KERNEL);
1624	if (pcmd == NULL)
1625		return _FAIL;  /* try again */
1626
1627	psetkeyparm = kzalloc(sizeof(struct setkey_parm), GFP_KERNEL);
1628	if (psetkeyparm == NULL) {
1629		res = _FAIL;
1630		goto err_free_cmd;
1631	}
1632
1633	memset(psetkeyparm, 0, sizeof(struct setkey_parm));
1634
1635	if (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) {
1636		psetkeyparm->algorithm = (unsigned char)psecuritypriv->dot118021XGrpPrivacy;
1637		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1638			 ("\n rtw_set_key: psetkeyparm->algorithm=(unsigned char)psecuritypriv->dot118021XGrpPrivacy=%d\n",
1639			 psetkeyparm->algorithm));
1640	} else {
1641		psetkeyparm->algorithm = (u8)psecuritypriv->dot11PrivacyAlgrthm;
1642		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1643			 ("\n rtw_set_key: psetkeyparm->algorithm=(u8)psecuritypriv->dot11PrivacyAlgrthm=%d\n",
1644			 psetkeyparm->algorithm));
1645	}
1646	psetkeyparm->keyid = (u8)keyid;/* 0~3 */
1647	psetkeyparm->set_tx = set_tx;
1648	pmlmepriv->key_mask |= BIT(psetkeyparm->keyid);
1649	DBG_88E("==> rtw_set_key algorithm(%x), keyid(%x), key_mask(%x)\n",
1650		psetkeyparm->algorithm, psetkeyparm->keyid, pmlmepriv->key_mask);
1651	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1652		 ("\n rtw_set_key: psetkeyparm->algorithm=%d psetkeyparm->keyid=(u8)keyid=%d\n",
1653		 psetkeyparm->algorithm, keyid));
1654
1655	switch (psetkeyparm->algorithm) {
1656	case _WEP40_:
1657		keylen = 5;
1658		memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
1659		break;
1660	case _WEP104_:
1661		keylen = 13;
1662		memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
1663		break;
1664	case _TKIP_:
1665		keylen = 16;
1666		memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1667		psetkeyparm->grpkey = 1;
1668		break;
1669	case _AES_:
1670		keylen = 16;
1671		memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
1672		psetkeyparm->grpkey = 1;
1673		break;
1674	default:
1675		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_,
1676			 ("\n rtw_set_key:psecuritypriv->dot11PrivacyAlgrthm=%x (must be 1 or 2 or 4 or 5)\n",
1677			 psecuritypriv->dot11PrivacyAlgrthm));
1678		res = _FAIL;
1679		goto err_free_parm;
1680	}
1681	pcmd->cmdcode = _SetKey_CMD_;
1682	pcmd->parmbuf = (u8 *)psetkeyparm;
1683	pcmd->cmdsz =  (sizeof(struct setkey_parm));
1684	pcmd->rsp = NULL;
1685	pcmd->rspsz = 0;
1686	INIT_LIST_HEAD(&pcmd->list);
1687	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
1688	return res;
1689
1690err_free_parm:
1691	kfree(psetkeyparm);
1692err_free_cmd:
1693	kfree(pcmd);
1694	return res;
1695}
1696
1697/* adjust IEs for rtw_joinbss_cmd in WMM */
1698int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
1699{
1700	unsigned	int ielength = 0;
1701	unsigned int i, j;
1702
1703	i = 12; /* after the fixed IE */
1704	while (i < in_len) {
1705		ielength = initial_out_len;
1706
1707		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) {
1708			/* WMM element ID and OUI */
1709			/* Append WMM IE to the last index of out_ie */
1710
1711			for (j = i; j < i + 9; j++) {
1712				out_ie[ielength] = in_ie[j];
1713				ielength++;
1714			}
1715			out_ie[initial_out_len + 1] = 0x07;
1716			out_ie[initial_out_len + 6] = 0x00;
1717			out_ie[initial_out_len + 8] = 0x00;
1718			break;
1719		}
1720		i += (in_ie[i+1]+2); /*  to the next IE element */
1721	}
1722	return ielength;
1723}
1724
1725/*
1726 * Ported from 8185: IsInPreAuthKeyList().
1727 * (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.)
1728 * Added by Annie, 2006-05-07.
1729 * Search by BSSID,
1730 * Return Value:
1731 *		-1	:if there is no pre-auth key in the table
1732 *		>= 0	:if there is pre-auth key, and return the entry id
1733 */
1734static int SecIsInPMKIDList(struct adapter *Adapter, u8 *bssid)
1735{
1736	struct security_priv *psecuritypriv = &Adapter->securitypriv;
1737	int i = 0;
1738
1739	do {
1740		if ((psecuritypriv->PMKIDList[i].bUsed) &&
1741		    (!memcmp(psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN))) {
1742			break;
1743		} else {
1744			i++;
1745			/* continue; */
1746		}
1747
1748	} while (i < NUM_PMKID_CACHE);
1749
1750	if (i == NUM_PMKID_CACHE)
1751		i = -1;/*  Could not find. */
1752
1753	return i;
1754}
1755
1756/*  */
1757/*  Check the RSN IE length */
1758/*  If the RSN IE length <= 20, the RSN IE didn't include the PMKID information */
1759/*  0-11th element in the array are the fixed IE */
1760/*  12th element in the array is the IE */
1761/*  13th element in the array is the IE length */
1762/*  */
1763
1764static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie_len)
1765{
1766	struct security_priv *psecuritypriv = &Adapter->securitypriv;
1767
1768	if (ie[13] <= 20) {
1769		/*  The RSN IE didn't include the PMK ID, append the PMK information */
1770		ie[ie_len] = 1;
1771		ie_len++;
1772		ie[ie_len] = 0;	/* PMKID count = 0x0100 */
1773		ie_len++;
1774		memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1775
1776		ie_len += 16;
1777		ie[13] += 18;/* PMKID length = 2+16 */
1778	}
1779	return ie_len;
1780}
1781
1782int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len)
1783{
1784	u8 authmode;
1785	uint	ielength;
1786	int iEntry;
1787
1788	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1789	struct security_priv *psecuritypriv = &adapter->securitypriv;
1790	uint	ndisauthmode = psecuritypriv->ndisauthtype;
1791	uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1792
1793	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
1794		 ("+rtw_restruct_sec_ie: ndisauthmode=%d ndissecuritytype=%d\n",
1795		  ndisauthmode, ndissecuritytype));
1796
1797	/* copy fixed ie only */
1798	memcpy(out_ie, in_ie, 12);
1799	ielength = 12;
1800	if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1801	    (ndisauthmode == Ndis802_11AuthModeWPAPSK))
1802			authmode = _WPA_IE_ID_;
1803	if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1804	    (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
1805		authmode = _WPA2_IE_ID_;
1806
1807	if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
1808		memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
1809
1810		ielength += psecuritypriv->wps_ie_len;
1811	} else if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1812		/* copy RSN or SSN */
1813		memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2);
1814		ielength += psecuritypriv->supplicant_ie[1]+2;
1815		rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie);
1816	}
1817
1818	iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1819	if (iEntry < 0) {
1820		return ielength;
1821	} else {
1822		if (authmode == _WPA2_IE_ID_)
1823			ielength = rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
1824	}
1825	return ielength;
1826}
1827
1828void rtw_init_registrypriv_dev_network(struct adapter *adapter)
1829{
1830	struct registry_priv *pregistrypriv = &adapter->registrypriv;
1831	struct eeprom_priv *peepriv = &adapter->eeprompriv;
1832	struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1833	u8 *myhwaddr = myid(peepriv);
1834
1835	memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1836
1837	memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(struct ndis_802_11_ssid));
1838
1839	pdev_network->Configuration.Length = sizeof(struct ndis_802_11_config);
1840	pdev_network->Configuration.BeaconPeriod = 100;
1841	pdev_network->Configuration.FHConfig.Length = 0;
1842	pdev_network->Configuration.FHConfig.HopPattern = 0;
1843	pdev_network->Configuration.FHConfig.HopSet = 0;
1844	pdev_network->Configuration.FHConfig.DwellTime = 0;
1845}
1846
1847void rtw_update_registrypriv_dev_network(struct adapter *adapter)
1848{
1849	int sz = 0;
1850	struct registry_priv *pregistrypriv = &adapter->registrypriv;
1851	struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1852	struct	security_priv *psecuritypriv = &adapter->securitypriv;
1853	struct	wlan_network	*cur_network = &adapter->mlmepriv.cur_network;
1854
1855	pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0); /*  adhoc no 802.1x */
1856
1857	pdev_network->Rssi = 0;
1858
1859	switch (pregistrypriv->wireless_mode) {
1860	case WIRELESS_11B:
1861		pdev_network->NetworkTypeInUse = (Ndis802_11DS);
1862		break;
1863	case WIRELESS_11G:
1864	case WIRELESS_11BG:
1865	case WIRELESS_11_24N:
1866	case WIRELESS_11G_24N:
1867	case WIRELESS_11BG_24N:
1868		pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
1869		break;
1870	case WIRELESS_11A:
1871	case WIRELESS_11A_5N:
1872		pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
1873		break;
1874	case WIRELESS_11ABGN:
1875		if (pregistrypriv->channel > 14)
1876			pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
1877		else
1878			pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
1879		break;
1880	default:
1881		/*  TODO */
1882		break;
1883	}
1884
1885	pdev_network->Configuration.DSConfig = (pregistrypriv->channel);
1886	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
1887		 ("pregistrypriv->channel=%d, pdev_network->Configuration.DSConfig=0x%x\n",
1888		 pregistrypriv->channel, pdev_network->Configuration.DSConfig));
1889
1890	if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1891		pdev_network->Configuration.ATIMWindow = (0);
1892
1893	pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode);
1894
1895	/*  1. Supported rates */
1896	/*  2. IE */
1897
1898	sz = rtw_generate_ie(pregistrypriv);
1899	pdev_network->IELength = sz;
1900	pdev_network->Length = get_wlan_bssid_ex_sz((struct wlan_bssid_ex  *)pdev_network);
1901
1902	/* notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd(); */
1903	/* pdev_network->IELength = cpu_to_le32(sz); */
1904}
1905
1906void rtw_get_encrypt_decrypt_from_registrypriv(struct adapter *adapter)
1907{
1908}
1909
1910/* the function is at passive_level */
1911void rtw_joinbss_reset(struct adapter *padapter)
1912{
1913	u8	threshold;
1914	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
1915	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
1916
1917	/* todo: if you want to do something io/reg/hw setting before join_bss, please add code here */
1918	pmlmepriv->num_FortyMHzIntolerant = 0;
1919
1920	pmlmepriv->num_sta_no_ht = 0;
1921
1922	phtpriv->ampdu_enable = false;/* reset to disabled */
1923
1924	/*  TH = 1 => means that invalidate usb rx aggregation */
1925	/*  TH = 0 => means that validate usb rx aggregation, use init value. */
1926	if (phtpriv->ht_option) {
1927		if (padapter->registrypriv.wifi_spec == 1)
1928			threshold = 1;
1929		else
1930			threshold = 0;
1931		rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
1932	} else {
1933		threshold = 1;
1934		rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
1935	}
1936}
1937
1938/* the function is >= passive_level */
1939unsigned int rtw_restructure_ht_ie(struct adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
1940{
1941	u32 ielen, out_len;
1942	enum ht_cap_ampdu_factor max_rx_ampdu_factor;
1943	unsigned char *p;
1944	struct rtw_ieee80211_ht_cap ht_capie;
1945	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1946	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
1947	struct qos_priv		*pqospriv = &pmlmepriv->qospriv;
1948	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
1949	u32 rx_packet_offset, max_recvbuf_sz;
1950
1951
1952	phtpriv->ht_option = false;
1953
1954	p = rtw_get_ie(in_ie+12, _HT_CAPABILITY_IE_, &ielen, in_len-12);
1955
1956	if (p && ielen > 0) {
1957		if (pqospriv->qos_option == 0) {
1958			out_len = *pout_len;
1959			rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_,
1960				   _WMM_IE_Length_, WMM_IE, pout_len);
1961
1962			pqospriv->qos_option = 1;
1963		}
1964
1965		out_len = *pout_len;
1966
1967		memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
1968
1969		ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |
1970				    IEEE80211_HT_CAP_SGI_20 |
1971				    IEEE80211_HT_CAP_SGI_40 |
1972				    IEEE80211_HT_CAP_TX_STBC |
1973				    IEEE80211_HT_CAP_DSSSCCK40;
1974
1975		rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
1976		rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
1977
1978		/*
1979		AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
1980		AMPDU_para [4:2]:Min MPDU Start Spacing
1981		*/
1982
1983		rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
1984		ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03);
1985
1986		if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_)
1987			ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
1988		else
1989			ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
1990
1991
1992		rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_,
1993			   sizeof(struct rtw_ieee80211_ht_cap), (unsigned char *)&ht_capie, pout_len);
1994
1995		phtpriv->ht_option = true;
1996
1997		p = rtw_get_ie(in_ie+12, _HT_ADD_INFO_IE_, &ielen, in_len-12);
1998		if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
1999			out_len = *pout_len;
2000			rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2 , pout_len);
2001		}
2002	}
2003	return phtpriv->ht_option;
2004}
2005
2006/* the function is > passive_level (in critical_section) */
2007void rtw_update_ht_cap(struct adapter *padapter, u8 *pie, uint ie_len)
2008{
2009	u8 *p, max_ampdu_sz;
2010	int len;
2011	struct rtw_ieee80211_ht_cap *pht_capie;
2012	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
2013	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
2014	struct registry_priv *pregistrypriv = &padapter->registrypriv;
2015	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
2016	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
2017
2018	if (!phtpriv->ht_option)
2019		return;
2020
2021	if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
2022		return;
2023
2024	DBG_88E("+rtw_update_ht_cap()\n");
2025
2026	/* maybe needs check if ap supports rx ampdu. */
2027	if ((!phtpriv->ampdu_enable) && (pregistrypriv->ampdu_enable == 1)) {
2028		if (pregistrypriv->wifi_spec == 1)
2029			phtpriv->ampdu_enable = false;
2030		else
2031			phtpriv->ampdu_enable = true;
2032	} else if (pregistrypriv->ampdu_enable == 2) {
2033		phtpriv->ampdu_enable = true;
2034	}
2035
2036
2037	/* check Max Rx A-MPDU Size */
2038	len = 0;
2039	p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_CAPABILITY_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie));
2040	if (p && len > 0) {
2041		pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
2042		max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR);
2043		max_ampdu_sz = 1 << (max_ampdu_sz+3); /*  max_ampdu_sz (kbytes); */
2044		phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
2045	}
2046	len = 0;
2047	p = rtw_get_ie(pie+sizeof(struct ndis_802_11_fixed_ie), _HT_ADD_INFO_IE_, &len, ie_len-sizeof(struct ndis_802_11_fixed_ie));
2048
2049	/* update cur_bwmode & cur_ch_offset */
2050	if ((pregistrypriv->cbw40_enable) &&
2051	    (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & BIT(1)) &&
2052	    (pmlmeinfo->HT_info.infos[0] & BIT(2))) {
2053		int i;
2054		u8	rf_type;
2055
2056		padapter->HalFunc.GetHwRegHandler(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
2057
2058		/* update the MCS rates */
2059		for (i = 0; i < 16; i++) {
2060			if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
2061				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
2062			else
2063				pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= MCS_rate_2R[i];
2064		}
2065		/* switch to the 40M Hz mode according to the AP */
2066		pmlmeext->cur_bwmode = HT_CHANNEL_WIDTH_40;
2067		switch ((pmlmeinfo->HT_info.infos[0] & 0x3)) {
2068		case HT_EXTCHNL_OFFSET_UPPER:
2069			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
2070			break;
2071		case HT_EXTCHNL_OFFSET_LOWER:
2072			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
2073			break;
2074		default:
2075			pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2076			break;
2077		}
2078	}
2079
2080	/*  Config SM Power Save setting */
2081	pmlmeinfo->SM_PS = (le16_to_cpu(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info) & 0x0C) >> 2;
2082	if (pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
2083		DBG_88E("%s(): WLAN_HT_CAP_SM_PS_STATIC\n", __func__);
2084
2085	/*  Config current HT Protection mode. */
2086	pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
2087}
2088
2089void rtw_issue_addbareq_cmd(struct adapter *padapter, struct xmit_frame *pxmitframe)
2090{
2091	u8 issued;
2092	int priority;
2093	struct sta_info *psta = NULL;
2094	struct ht_priv	*phtpriv;
2095	struct pkt_attrib *pattrib = &pxmitframe->attrib;
2096	s32 bmcst = IS_MCAST(pattrib->ra);
2097
2098	if (bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod < 100))
2099		return;
2100
2101	priority = pattrib->priority;
2102
2103	if (pattrib->psta)
2104		psta = pattrib->psta;
2105	else
2106		psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
2107
2108	if (psta == NULL)
2109		return;
2110
2111	phtpriv = &psta->htpriv;
2112
2113	if ((phtpriv->ht_option) && (phtpriv->ampdu_enable)) {
2114		issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
2115		issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
2116
2117		if (0 == issued) {
2118			DBG_88E("rtw_issue_addbareq_cmd, p=%d\n", priority);
2119			psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
2120			rtw_addbareq_cmd(padapter, (u8) priority, pattrib->ra);
2121		}
2122	}
2123}
2124
2125void rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
2126{
2127	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
2128
2129	spin_lock_bh(&pmlmepriv->lock);
2130	_rtw_roaming(padapter, tgt_network);
2131	spin_unlock_bh(&pmlmepriv->lock);
2132}
2133void _rtw_roaming(struct adapter *padapter, struct wlan_network *tgt_network)
2134{
2135	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
2136	int do_join_r;
2137
2138	struct wlan_network *pnetwork;
2139
2140	if (tgt_network != NULL)
2141		pnetwork = tgt_network;
2142	else
2143		pnetwork = &pmlmepriv->cur_network;
2144
2145	if (0 < pmlmepriv->to_roaming) {
2146		DBG_88E("roaming from %s(%pM length:%d\n",
2147			pnetwork->network.Ssid.Ssid, pnetwork->network.MacAddress,
2148			pnetwork->network.Ssid.SsidLength);
2149		memcpy(&pmlmepriv->assoc_ssid, &pnetwork->network.Ssid, sizeof(struct ndis_802_11_ssid));
2150
2151		pmlmepriv->assoc_by_bssid = false;
2152
2153		while (1) {
2154			do_join_r = rtw_do_join(padapter);
2155			if (_SUCCESS == do_join_r) {
2156				break;
2157			} else {
2158				DBG_88E("roaming do_join return %d\n", do_join_r);
2159				pmlmepriv->to_roaming--;
2160
2161				if (0 < pmlmepriv->to_roaming) {
2162					continue;
2163				} else {
2164					DBG_88E("%s(%d) -to roaming fail, indicate_disconnect\n", __func__, __LINE__);
2165					rtw_indicate_disconnect(padapter);
2166					break;
2167				}
2168			}
2169		}
2170	}
2171}
2172