cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rtl871x_mlme.c (52041B)


      1// SPDX-License-Identifier: GPL-2.0
      2/******************************************************************************
      3 * rtl871x_mlme.c
      4 *
      5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
      6 * Linux device driver for RTL8192SU
      7 *
      8 * Modifications for inclusion into the Linux staging tree are
      9 * Copyright(c) 2010 Larry Finger. All rights reserved.
     10 *
     11 * Contact information:
     12 * WLAN FAE <wlanfae@realtek.com>
     13 * Larry Finger <Larry.Finger@lwfinger.net>
     14 *
     15 ******************************************************************************/
     16
     17#define _RTL871X_MLME_C_
     18
     19#include <linux/etherdevice.h>
     20
     21#include "osdep_service.h"
     22#include "drv_types.h"
     23#include "recv_osdep.h"
     24#include "xmit_osdep.h"
     25#include "mlme_osdep.h"
     26#include "sta_info.h"
     27#include "wifi.h"
     28#include "wlan_bssdef.h"
     29
     30static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
     31
     32int r8712_init_mlme_priv(struct _adapter *padapter)
     33{
     34	sint	i;
     35	u8	*pbuf;
     36	struct wlan_network	*pnetwork;
     37	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
     38
     39	memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
     40	pmlmepriv->nic_hdl = (u8 *)padapter;
     41	pmlmepriv->pscanned = NULL;
     42	pmlmepriv->fw_state = 0;
     43	pmlmepriv->cur_network.network.InfrastructureMode =
     44				 Ndis802_11AutoUnknown;
     45	/* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
     46	pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
     47	spin_lock_init(&(pmlmepriv->lock));
     48	spin_lock_init(&(pmlmepriv->lock2));
     49	_init_queue(&(pmlmepriv->free_bss_pool));
     50	_init_queue(&(pmlmepriv->scanned_queue));
     51	set_scanned_network_val(pmlmepriv, 0);
     52	memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
     53	pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
     54			     GFP_ATOMIC);
     55	if (!pbuf)
     56		return -ENOMEM;
     57	pmlmepriv->free_bss_buf = pbuf;
     58	pnetwork = (struct wlan_network *)pbuf;
     59	for (i = 0; i < MAX_BSS_CNT; i++) {
     60		INIT_LIST_HEAD(&(pnetwork->list));
     61		list_add_tail(&(pnetwork->list),
     62				 &(pmlmepriv->free_bss_pool.queue));
     63		pnetwork++;
     64	}
     65	pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
     66	pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
     67	pmlmepriv->sitesurveyctrl.traffic_busy = false;
     68	/* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
     69	r8712_init_mlme_timer(padapter);
     70	return 0;
     71}
     72
     73struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
     74{
     75	unsigned long irqL;
     76	struct wlan_network *pnetwork;
     77	struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
     78
     79	spin_lock_irqsave(&free_queue->lock, irqL);
     80	pnetwork = list_first_entry_or_null(&free_queue->queue,
     81					    struct wlan_network, list);
     82	if (pnetwork) {
     83		list_del_init(&pnetwork->list);
     84		pnetwork->last_scanned = jiffies;
     85		pmlmepriv->num_of_scanned++;
     86	}
     87	spin_unlock_irqrestore(&free_queue->lock, irqL);
     88	return pnetwork;
     89}
     90
     91static void _free_network(struct mlme_priv *pmlmepriv,
     92			  struct wlan_network *pnetwork)
     93{
     94	u32 curr_time, delta_time;
     95	unsigned long irqL;
     96	struct  __queue *free_queue = &(pmlmepriv->free_bss_pool);
     97
     98	if (!pnetwork)
     99		return;
    100	if (pnetwork->fixed)
    101		return;
    102	curr_time = jiffies;
    103	delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
    104	if (delta_time < SCANQUEUE_LIFETIME)
    105		return;
    106	spin_lock_irqsave(&free_queue->lock, irqL);
    107	list_del_init(&pnetwork->list);
    108	list_add_tail(&pnetwork->list, &free_queue->queue);
    109	pmlmepriv->num_of_scanned--;
    110	spin_unlock_irqrestore(&free_queue->lock, irqL);
    111}
    112
    113static void free_network_nolock(struct mlme_priv *pmlmepriv,
    114			  struct wlan_network *pnetwork)
    115{
    116	struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
    117
    118	if (!pnetwork)
    119		return;
    120	if (pnetwork->fixed)
    121		return;
    122	list_del_init(&pnetwork->list);
    123	list_add_tail(&pnetwork->list, &free_queue->queue);
    124	pmlmepriv->num_of_scanned--;
    125}
    126
    127/* return the wlan_network with the matching addr
    128 * Shall be called under atomic context...
    129 * to avoid possible racing condition...
    130 */
    131static struct wlan_network *r8712_find_network(struct  __queue *scanned_queue,
    132					       u8 *addr)
    133{
    134	unsigned long irqL;
    135	struct list_head *phead, *plist;
    136	struct wlan_network *pnetwork = NULL;
    137
    138	if (is_zero_ether_addr(addr))
    139		return NULL;
    140	spin_lock_irqsave(&scanned_queue->lock, irqL);
    141	phead = &scanned_queue->queue;
    142	list_for_each(plist, phead) {
    143		pnetwork = list_entry(plist, struct wlan_network, list);
    144		if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
    145			break;
    146	}
    147	if (plist == phead)
    148		pnetwork = NULL;
    149	spin_unlock_irqrestore(&scanned_queue->lock, irqL);
    150	return pnetwork;
    151}
    152
    153void r8712_free_network_queue(struct _adapter *padapter)
    154{
    155	unsigned long irqL;
    156	struct list_head *phead, *plist;
    157	struct wlan_network *pnetwork;
    158	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
    159	struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
    160
    161	spin_lock_irqsave(&scanned_queue->lock, irqL);
    162	phead = &scanned_queue->queue;
    163	plist = phead->next;
    164	while (!end_of_queue_search(phead, plist)) {
    165		pnetwork = container_of(plist, struct wlan_network, list);
    166		plist = plist->next;
    167		_free_network(pmlmepriv, pnetwork);
    168	}
    169	spin_unlock_irqrestore(&scanned_queue->lock, irqL);
    170}
    171
    172sint r8712_if_up(struct _adapter *padapter)
    173{
    174	sint res;
    175
    176	if (padapter->driver_stopped || padapter->surprise_removed ||
    177	    !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
    178		res = false;
    179	} else {
    180		res = true;
    181	}
    182	return res;
    183}
    184
    185void r8712_generate_random_ibss(u8 *pibss)
    186{
    187	u32 curtime = jiffies;
    188
    189	pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
    190	pibss[1] = 0x11;
    191	pibss[2] = 0x87;
    192	pibss[3] = (u8)(curtime & 0xff);
    193	pibss[4] = (u8)((curtime >> 8) & 0xff);
    194	pibss[5] = (u8)((curtime >> 16) & 0xff);
    195}
    196
    197uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
    198{
    199	return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
    200}
    201
    202u8 *r8712_get_capability_from_ie(u8 *ie)
    203{
    204	return ie + 8 + 2;
    205}
    206
    207void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
    208{
    209	kfree(pmlmepriv->free_bss_buf);
    210}
    211
    212static struct	wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
    213{
    214	return _r8712_alloc_network(pmlmepriv);
    215}
    216
    217int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
    218{
    219	int ret = true;
    220	struct security_priv *psecuritypriv = &adapter->securitypriv;
    221
    222	if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
    223		    (pnetwork->network.Privacy == cpu_to_le32(0)))
    224		ret = false;
    225	else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
    226		 (pnetwork->network.Privacy == cpu_to_le32(1)))
    227		ret = false;
    228	else
    229		ret = true;
    230	return ret;
    231
    232}
    233
    234static int is_same_network(struct wlan_bssid_ex *src,
    235			   struct wlan_bssid_ex *dst)
    236{
    237	u16 s_cap, d_cap;
    238
    239	memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
    240	memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
    241	return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
    242			(src->Configuration.DSConfig ==
    243			dst->Configuration.DSConfig) &&
    244			((!memcmp(src->MacAddress, dst->MacAddress,
    245			ETH_ALEN))) &&
    246			((!memcmp(src->Ssid.Ssid,
    247			  dst->Ssid.Ssid,
    248			  src->Ssid.SsidLength))) &&
    249			((s_cap & WLAN_CAPABILITY_IBSS) ==
    250			(d_cap & WLAN_CAPABILITY_IBSS)) &&
    251			((s_cap & WLAN_CAPABILITY_ESS) ==
    252			(d_cap & WLAN_CAPABILITY_ESS));
    253
    254}
    255
    256struct	wlan_network *r8712_get_oldest_wlan_network(
    257				struct  __queue *scanned_queue)
    258{
    259	struct list_head *plist, *phead;
    260	struct	wlan_network	*pwlan = NULL;
    261	struct	wlan_network	*oldest = NULL;
    262
    263	phead = &scanned_queue->queue;
    264	plist = phead->next;
    265	while (1) {
    266		if (end_of_queue_search(phead, plist))
    267			break;
    268		pwlan = container_of(plist, struct wlan_network, list);
    269		if (!pwlan->fixed) {
    270			if (!oldest ||
    271			    time_after((unsigned long)oldest->last_scanned,
    272				       (unsigned long)pwlan->last_scanned))
    273				oldest = pwlan;
    274		}
    275		plist = plist->next;
    276	}
    277	return oldest;
    278}
    279
    280static void update_network(struct wlan_bssid_ex *dst,
    281			   struct wlan_bssid_ex *src,
    282			   struct _adapter *padapter)
    283{
    284	u32 last_evm = 0, tmpVal;
    285	struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
    286
    287	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
    288	    is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
    289		if (padapter->recvpriv.signal_qual_data.total_num++ >=
    290		    PHY_LINKQUALITY_SLID_WIN_MAX) {
    291			padapter->recvpriv.signal_qual_data.total_num =
    292				   PHY_LINKQUALITY_SLID_WIN_MAX;
    293			last_evm = sqd->elements[sqd->index];
    294			padapter->recvpriv.signal_qual_data.total_val -=
    295				 last_evm;
    296		}
    297		padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
    298
    299		sqd->elements[sqd->index++] = src->Rssi;
    300		if (padapter->recvpriv.signal_qual_data.index >=
    301		    PHY_LINKQUALITY_SLID_WIN_MAX)
    302			padapter->recvpriv.signal_qual_data.index = 0;
    303		/* <1> Showed on UI for user, in percentage. */
    304		tmpVal = padapter->recvpriv.signal_qual_data.total_val /
    305			 padapter->recvpriv.signal_qual_data.total_num;
    306		padapter->recvpriv.signal = (u8)tmpVal;
    307
    308		src->Rssi = padapter->recvpriv.signal;
    309	} else {
    310		src->Rssi = (src->Rssi + dst->Rssi) / 2;
    311	}
    312	memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
    313}
    314
    315static void update_current_network(struct _adapter *adapter,
    316				   struct wlan_bssid_ex *pnetwork)
    317{
    318	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    319
    320	if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
    321		update_network(&(pmlmepriv->cur_network.network),
    322			       pnetwork, adapter);
    323		r8712_update_protection(adapter,
    324			       (pmlmepriv->cur_network.network.IEs) +
    325			       sizeof(struct NDIS_802_11_FIXED_IEs),
    326			       pmlmepriv->cur_network.network.IELength);
    327	}
    328}
    329
    330/* Caller must hold pmlmepriv->lock first */
    331static void update_scanned_network(struct _adapter *adapter,
    332			    struct wlan_bssid_ex *target)
    333{
    334	struct list_head *plist, *phead;
    335
    336	u32 bssid_ex_sz;
    337	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    338	struct  __queue *queue = &pmlmepriv->scanned_queue;
    339	struct wlan_network *pnetwork = NULL;
    340	struct wlan_network *oldest = NULL;
    341
    342	phead = &queue->queue;
    343	plist = phead->next;
    344
    345	while (1) {
    346		if (end_of_queue_search(phead, plist))
    347			break;
    348
    349		pnetwork = container_of(plist, struct wlan_network, list);
    350		if (is_same_network(&pnetwork->network, target))
    351			break;
    352		if ((oldest == ((struct wlan_network *)0)) ||
    353		    time_after((unsigned long)oldest->last_scanned,
    354				(unsigned long)pnetwork->last_scanned))
    355			oldest = pnetwork;
    356
    357		plist = plist->next;
    358	}
    359
    360	/* If we didn't find a match, then get a new network slot to initialize
    361	 * with this beacon's information
    362	 */
    363	if (end_of_queue_search(phead, plist)) {
    364		if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
    365			/* If there are no more slots, expire the oldest */
    366			pnetwork = oldest;
    367			target->Rssi = (pnetwork->network.Rssi +
    368					target->Rssi) / 2;
    369			memcpy(&pnetwork->network, target,
    370				r8712_get_wlan_bssid_ex_sz(target));
    371			pnetwork->last_scanned = jiffies;
    372		} else {
    373			/* Otherwise just pull from the free list */
    374			/* update scan_time */
    375			pnetwork = alloc_network(pmlmepriv);
    376			if (!pnetwork)
    377				return;
    378			bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
    379			target->Length = bssid_ex_sz;
    380			memcpy(&pnetwork->network, target, bssid_ex_sz);
    381			list_add_tail(&pnetwork->list, &queue->queue);
    382		}
    383	} else {
    384		/* we have an entry and we are going to update it. But
    385		 * this entry may be already expired. In this case we
    386		 * do the same as we found a new net and call the new_net
    387		 * handler
    388		 */
    389		update_network(&pnetwork->network, target, adapter);
    390		pnetwork->last_scanned = jiffies;
    391	}
    392}
    393
    394static void rtl8711_add_network(struct _adapter *adapter,
    395			 struct wlan_bssid_ex *pnetwork)
    396{
    397	unsigned long irqL;
    398	struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
    399	struct  __queue *queue = &pmlmepriv->scanned_queue;
    400
    401	spin_lock_irqsave(&queue->lock, irqL);
    402	update_current_network(adapter, pnetwork);
    403	update_scanned_network(adapter, pnetwork);
    404	spin_unlock_irqrestore(&queue->lock, irqL);
    405}
    406
    407/*select the desired network based on the capability of the (i)bss.
    408 * check items:		(1) security
    409 *			(2) network_type
    410 *			(3) WMM
    411 *			(4) HT
    412 *			(5) others
    413 */
    414static int is_desired_network(struct _adapter *adapter,
    415				struct wlan_network *pnetwork)
    416{
    417	u8 wps_ie[512];
    418	uint wps_ielen;
    419	int bselected = true;
    420	struct	security_priv *psecuritypriv = &adapter->securitypriv;
    421
    422	if (psecuritypriv->wps_phase) {
    423		if (r8712_get_wps_ie(pnetwork->network.IEs,
    424		    pnetwork->network.IELength, wps_ie,
    425		    &wps_ielen))
    426			return true;
    427		return false;
    428	}
    429	if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
    430		    (pnetwork->network.Privacy == 0))
    431		bselected = false;
    432	if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
    433		if (pnetwork->network.InfrastructureMode !=
    434			adapter->mlmepriv.cur_network.network.InfrastructureMode)
    435			bselected = false;
    436	}
    437	return bselected;
    438}
    439
    440/* TODO: Perry : For Power Management */
    441void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
    442{
    443}
    444
    445void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
    446{
    447	unsigned long flags;
    448	u32 len;
    449	struct wlan_bssid_ex *pnetwork;
    450	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    451
    452	pnetwork = (struct wlan_bssid_ex *)pbuf;
    453#ifdef __BIG_ENDIAN
    454	/* endian_convert */
    455	pnetwork->Length = le32_to_cpu(pnetwork->Length);
    456	pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
    457	pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
    458	pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
    459	pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
    460	pnetwork->Configuration.ATIMWindow =
    461		 le32_to_cpu(pnetwork->Configuration.ATIMWindow);
    462	pnetwork->Configuration.BeaconPeriod =
    463		 le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
    464	pnetwork->Configuration.DSConfig =
    465		 le32_to_cpu(pnetwork->Configuration.DSConfig);
    466	pnetwork->Configuration.FHConfig.DwellTime =
    467		 le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
    468	pnetwork->Configuration.FHConfig.HopPattern =
    469		 le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
    470	pnetwork->Configuration.FHConfig.HopSet =
    471		 le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
    472	pnetwork->Configuration.FHConfig.Length =
    473		 le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
    474	pnetwork->Configuration.Length =
    475		 le32_to_cpu(pnetwork->Configuration.Length);
    476	pnetwork->InfrastructureMode =
    477		 le32_to_cpu(pnetwork->InfrastructureMode);
    478	pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
    479#endif
    480	len = r8712_get_wlan_bssid_ex_sz(pnetwork);
    481	if (len > sizeof(struct wlan_bssid_ex))
    482		return;
    483	spin_lock_irqsave(&pmlmepriv->lock2, flags);
    484	/* update IBSS_network 's timestamp */
    485	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
    486		if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
    487		    pnetwork->MacAddress, ETH_ALEN)) {
    488			struct wlan_network *ibss_wlan = NULL;
    489
    490			memcpy(pmlmepriv->cur_network.network.IEs,
    491				pnetwork->IEs, 8);
    492			ibss_wlan = r8712_find_network(
    493						&pmlmepriv->scanned_queue,
    494						pnetwork->MacAddress);
    495			if (ibss_wlan) {
    496				memcpy(ibss_wlan->network.IEs,
    497					pnetwork->IEs, 8);
    498				goto exit;
    499			}
    500		}
    501	}
    502	/* lock pmlmepriv->lock when you accessing network_q */
    503	if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
    504		if (pnetwork->Ssid.Ssid[0] != 0) {
    505			rtl8711_add_network(adapter, pnetwork);
    506		} else {
    507			pnetwork->Ssid.SsidLength = 8;
    508			memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
    509			rtl8711_add_network(adapter, pnetwork);
    510		}
    511	}
    512exit:
    513	spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
    514}
    515
    516void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
    517{
    518	unsigned long irqL;
    519	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    520
    521	spin_lock_irqsave(&pmlmepriv->lock, irqL);
    522
    523	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
    524		del_timer(&pmlmepriv->scan_to_timer);
    525
    526		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
    527	}
    528
    529	if (pmlmepriv->to_join) {
    530		if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
    531			if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
    532				set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
    533
    534				if (!r8712_select_and_join_from_scan(pmlmepriv)) {
    535					mod_timer(&pmlmepriv->assoc_timer, jiffies +
    536						  msecs_to_jiffies(MAX_JOIN_TIMEOUT));
    537				} else {
    538					struct wlan_bssid_ex *pdev_network =
    539					  &(adapter->registrypriv.dev_network);
    540					u8 *pibss =
    541						 adapter->registrypriv.dev_network.MacAddress;
    542					pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
    543					memcpy(&pdev_network->Ssid,
    544						&pmlmepriv->assoc_ssid,
    545						sizeof(struct
    546							 ndis_802_11_ssid));
    547					r8712_update_registrypriv_dev_network
    548						(adapter);
    549					r8712_generate_random_ibss(pibss);
    550					pmlmepriv->fw_state =
    551						 WIFI_ADHOC_MASTER_STATE;
    552					pmlmepriv->to_join = false;
    553				}
    554			}
    555		} else {
    556			pmlmepriv->to_join = false;
    557			set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
    558			if (!r8712_select_and_join_from_scan(pmlmepriv))
    559				mod_timer(&pmlmepriv->assoc_timer, jiffies +
    560					  msecs_to_jiffies(MAX_JOIN_TIMEOUT));
    561			else
    562				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
    563		}
    564	}
    565	spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
    566}
    567
    568/*
    569 *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
    570 */
    571void r8712_free_assoc_resources(struct _adapter *adapter)
    572{
    573	unsigned long irqL;
    574	struct wlan_network *pwlan = NULL;
    575	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    576	struct sta_priv *pstapriv = &adapter->stapriv;
    577	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
    578
    579	pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
    580				   tgt_network->network.MacAddress);
    581
    582	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
    583		struct sta_info *psta;
    584
    585		psta = r8712_get_stainfo(&adapter->stapriv,
    586					 tgt_network->network.MacAddress);
    587
    588		spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
    589		r8712_free_stainfo(adapter,  psta);
    590		spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
    591	}
    592
    593	if (check_fwstate(pmlmepriv,
    594	    WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
    595		r8712_free_all_stainfo(adapter);
    596	if (pwlan)
    597		pwlan->fixed = false;
    598
    599	if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
    600	     (adapter->stapriv.asoc_sta_count == 1)))
    601		free_network_nolock(pmlmepriv, pwlan);
    602}
    603
    604/*
    605 * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
    606 */
    607void r8712_indicate_connect(struct _adapter *padapter)
    608{
    609	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
    610
    611	pmlmepriv->to_join = false;
    612	set_fwstate(pmlmepriv, _FW_LINKED);
    613	padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
    614	r8712_os_indicate_connect(padapter);
    615	if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
    616		mod_timer(&pmlmepriv->dhcp_timer,
    617			  jiffies + msecs_to_jiffies(60000));
    618}
    619
    620/*
    621 * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
    622 */
    623void r8712_ind_disconnect(struct _adapter *padapter)
    624{
    625	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
    626
    627	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
    628		_clr_fwstate_(pmlmepriv, _FW_LINKED);
    629		padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
    630		r8712_os_indicate_disconnect(padapter);
    631	}
    632	if (padapter->pwrctrlpriv.pwr_mode !=
    633	    padapter->registrypriv.power_mgnt) {
    634		del_timer(&pmlmepriv->dhcp_timer);
    635		r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
    636				  padapter->registrypriv.smart_ps);
    637	}
    638}
    639
    640/*Notes:
    641 *pnetwork : returns from r8712_joinbss_event_callback
    642 *ptarget_wlan: found from scanned_queue
    643 *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
    644 *  "ptarget_sta" & "ptarget_wlan" exist.
    645 *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
    646 * if "ptarget_wlan" exist.
    647 *if join_res > 0, update "cur_network->network" from
    648 * "pnetwork->network" if (ptarget_wlan !=NULL).
    649 */
    650void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
    651{
    652	unsigned long irqL = 0, irqL2;
    653	struct sta_info	*ptarget_sta = NULL, *pcur_sta = NULL;
    654	struct sta_priv	*pstapriv = &adapter->stapriv;
    655	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
    656	struct wlan_network	*cur_network = &pmlmepriv->cur_network;
    657	struct wlan_network	*pcur_wlan = NULL, *ptarget_wlan = NULL;
    658	unsigned int		the_same_macaddr = false;
    659	struct wlan_network *pnetwork;
    660
    661	if (sizeof(struct list_head) == 4 * sizeof(u32)) {
    662		pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
    663		if (!pnetwork)
    664			return;
    665		memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
    666		       sizeof(struct wlan_network) - 16);
    667	} else {
    668		pnetwork = (struct wlan_network *)pbuf;
    669	}
    670
    671#ifdef __BIG_ENDIAN
    672	/* endian_convert */
    673	pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
    674	pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
    675	pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
    676	pnetwork->network.Ssid.SsidLength =
    677		 le32_to_cpu(pnetwork->network.Ssid.SsidLength);
    678	pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
    679	pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
    680	pnetwork->network.NetworkTypeInUse =
    681		 le32_to_cpu(pnetwork->network.NetworkTypeInUse);
    682	pnetwork->network.Configuration.ATIMWindow =
    683		 le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
    684	pnetwork->network.Configuration.BeaconPeriod =
    685		 le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
    686	pnetwork->network.Configuration.DSConfig =
    687		 le32_to_cpu(pnetwork->network.Configuration.DSConfig);
    688	pnetwork->network.Configuration.FHConfig.DwellTime =
    689		 le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime);
    690	pnetwork->network.Configuration.FHConfig.HopPattern =
    691		 le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern);
    692	pnetwork->network.Configuration.FHConfig.HopSet =
    693		 le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
    694	pnetwork->network.Configuration.FHConfig.Length =
    695		 le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
    696	pnetwork->network.Configuration.Length =
    697		 le32_to_cpu(pnetwork->network.Configuration.Length);
    698	pnetwork->network.InfrastructureMode =
    699		 le32_to_cpu(pnetwork->network.InfrastructureMode);
    700	pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
    701#endif
    702
    703	the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
    704				   cur_network->network.MacAddress, ETH_ALEN);
    705	pnetwork->network.Length =
    706		 r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
    707	spin_lock_irqsave(&pmlmepriv->lock, irqL);
    708	if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
    709		goto ignore_joinbss_callback;
    710	if (pnetwork->join_res > 0) {
    711		if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
    712			/*s1. find ptarget_wlan*/
    713			if (check_fwstate(pmlmepriv, _FW_LINKED)) {
    714				if (the_same_macaddr) {
    715					ptarget_wlan =
    716					    r8712_find_network(&pmlmepriv->scanned_queue,
    717					    cur_network->network.MacAddress);
    718				} else {
    719					pcur_wlan =
    720					     r8712_find_network(&pmlmepriv->scanned_queue,
    721					     cur_network->network.MacAddress);
    722					if (pcur_wlan)
    723						pcur_wlan->fixed = false;
    724
    725					pcur_sta = r8712_get_stainfo(pstapriv,
    726					     cur_network->network.MacAddress);
    727					spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL2);
    728					r8712_free_stainfo(adapter, pcur_sta);
    729					spin_unlock_irqrestore(&(pstapriv->sta_hash_lock), irqL2);
    730
    731					ptarget_wlan =
    732						 r8712_find_network(&pmlmepriv->scanned_queue,
    733						 pnetwork->network.MacAddress);
    734					if (ptarget_wlan)
    735						ptarget_wlan->fixed = true;
    736				}
    737			} else {
    738				ptarget_wlan = r8712_find_network(&pmlmepriv->scanned_queue,
    739						pnetwork->network.MacAddress);
    740				if (ptarget_wlan)
    741					ptarget_wlan->fixed = true;
    742			}
    743
    744			if (!ptarget_wlan) {
    745				if (check_fwstate(pmlmepriv,
    746					_FW_UNDER_LINKING))
    747					pmlmepriv->fw_state ^=
    748						 _FW_UNDER_LINKING;
    749				goto ignore_joinbss_callback;
    750			}
    751
    752			/*s2. find ptarget_sta & update ptarget_sta*/
    753			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
    754				if (the_same_macaddr) {
    755					ptarget_sta =
    756						 r8712_get_stainfo(pstapriv,
    757						 pnetwork->network.MacAddress);
    758					if (!ptarget_sta)
    759						ptarget_sta =
    760						 r8712_alloc_stainfo(pstapriv,
    761						 pnetwork->network.MacAddress);
    762				} else {
    763					ptarget_sta =
    764						 r8712_alloc_stainfo(pstapriv,
    765						 pnetwork->network.MacAddress);
    766				}
    767				if (ptarget_sta) /*update ptarget_sta*/ {
    768					ptarget_sta->aid = pnetwork->join_res;
    769					ptarget_sta->qos_option = 1;
    770					ptarget_sta->mac_id = 5;
    771					if (adapter->securitypriv.AuthAlgrthm == 2) {
    772						adapter->securitypriv.binstallGrpkey = false;
    773						adapter->securitypriv.busetkipkey = false;
    774						adapter->securitypriv.bgrpkey_handshake = false;
    775						ptarget_sta->ieee8021x_blocked = true;
    776						ptarget_sta->XPrivacy = adapter->
    777						securitypriv.PrivacyAlgrthm;
    778						memset((u8 *)&ptarget_sta->x_UncstKey,
    779							 0,
    780							 sizeof(union Keytype));
    781						memset((u8 *)&ptarget_sta->tkiprxmickey,
    782							 0,
    783							 sizeof(union Keytype));
    784						memset((u8 *)&ptarget_sta->tkiptxmickey,
    785							 0,
    786							 sizeof(union Keytype));
    787						memset((u8 *)&ptarget_sta->txpn, 0,
    788							 sizeof(union pn48));
    789						memset((u8 *)&ptarget_sta->rxpn, 0,
    790							 sizeof(union pn48));
    791					}
    792				} else {
    793					if (check_fwstate(pmlmepriv,
    794					    _FW_UNDER_LINKING))
    795						pmlmepriv->fw_state ^=
    796							 _FW_UNDER_LINKING;
    797					goto ignore_joinbss_callback;
    798				}
    799			}
    800
    801			/*s3. update cur_network & indicate connect*/
    802			memcpy(&cur_network->network, &pnetwork->network,
    803				pnetwork->network.Length);
    804			cur_network->aid = pnetwork->join_res;
    805			/*update fw_state will clr _FW_UNDER_LINKING*/
    806			switch (pnetwork->network.InfrastructureMode) {
    807			case Ndis802_11Infrastructure:
    808				pmlmepriv->fw_state = WIFI_STATION_STATE;
    809				break;
    810			case Ndis802_11IBSS:
    811				pmlmepriv->fw_state = WIFI_ADHOC_STATE;
    812				break;
    813			default:
    814				pmlmepriv->fw_state = WIFI_NULL_STATE;
    815				break;
    816			}
    817			r8712_update_protection(adapter,
    818					  (cur_network->network.IEs) +
    819					  sizeof(struct NDIS_802_11_FIXED_IEs),
    820					  (cur_network->network.IELength));
    821			/*TODO: update HT_Capability*/
    822			update_ht_cap(adapter, cur_network->network.IEs,
    823				      cur_network->network.IELength);
    824			/*indicate connect*/
    825			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
    826				r8712_indicate_connect(adapter);
    827			del_timer(&pmlmepriv->assoc_timer);
    828		} else {
    829			goto ignore_joinbss_callback;
    830		}
    831	} else {
    832		if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
    833			mod_timer(&pmlmepriv->assoc_timer,
    834				  jiffies + msecs_to_jiffies(1));
    835			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
    836		}
    837	}
    838ignore_joinbss_callback:
    839	spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
    840	if (sizeof(struct list_head) == 4 * sizeof(u32))
    841		kfree(pnetwork);
    842}
    843
    844void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
    845{
    846	unsigned long irqL;
    847	struct sta_info *psta;
    848	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
    849	struct stassoc_event *pstassoc	= (struct stassoc_event *)pbuf;
    850
    851	/* to do: */
    852	if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
    853		return;
    854	psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
    855	if (psta) {
    856		/*the sta have been in sta_info_queue => do nothing
    857		 *(between drv has received this event before and
    858		 * fw have not yet to set key to CAM_ENTRY)
    859		 */
    860		return;
    861	}
    862
    863	psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
    864	if (!psta)
    865		return;
    866	/* to do : init sta_info variable */
    867	psta->qos_option = 0;
    868	psta->mac_id = le32_to_cpu(pstassoc->cam_id);
    869	/* psta->aid = (uint)pstassoc->cam_id; */
    870
    871	if (adapter->securitypriv.AuthAlgrthm == 2)
    872		psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
    873	psta->ieee8021x_blocked = false;
    874	spin_lock_irqsave(&pmlmepriv->lock, irqL);
    875	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
    876	    check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
    877		if (adapter->stapriv.asoc_sta_count == 2) {
    878			/* a sta + bc/mc_stainfo (not Ibss_stainfo) */
    879			r8712_indicate_connect(adapter);
    880		}
    881	}
    882	spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
    883}
    884
    885void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
    886{
    887	unsigned long irqL, irqL2;
    888	struct sta_info *psta;
    889	struct wlan_network *pwlan = NULL;
    890	struct wlan_bssid_ex *pdev_network = NULL;
    891	u8 *pibss = NULL;
    892	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    893	struct stadel_event *pstadel = (struct stadel_event *)pbuf;
    894	struct sta_priv *pstapriv = &adapter->stapriv;
    895	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
    896
    897	spin_lock_irqsave(&pmlmepriv->lock, irqL2);
    898	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
    899		r8712_ind_disconnect(adapter);
    900		r8712_free_assoc_resources(adapter);
    901	}
    902	if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
    903	    WIFI_ADHOC_STATE)) {
    904		psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
    905		spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
    906		r8712_free_stainfo(adapter, psta);
    907		spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
    908		if (adapter->stapriv.asoc_sta_count == 1) {
    909			/*a sta + bc/mc_stainfo (not Ibss_stainfo) */
    910			pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
    911				tgt_network->network.MacAddress);
    912			if (pwlan) {
    913				pwlan->fixed = false;
    914				free_network_nolock(pmlmepriv, pwlan);
    915			}
    916			/*re-create ibss*/
    917			pdev_network = &(adapter->registrypriv.dev_network);
    918			pibss = adapter->registrypriv.dev_network.MacAddress;
    919			memcpy(pdev_network, &tgt_network->network,
    920				r8712_get_wlan_bssid_ex_sz(&tgt_network->network));
    921			memcpy(&pdev_network->Ssid,
    922				&pmlmepriv->assoc_ssid,
    923				sizeof(struct ndis_802_11_ssid));
    924			r8712_update_registrypriv_dev_network(adapter);
    925			r8712_generate_random_ibss(pibss);
    926			if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
    927				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
    928				set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
    929			}
    930		}
    931	}
    932	spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
    933}
    934
    935void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
    936{
    937	struct reportpwrstate_parm *preportpwrstate =
    938			 (struct reportpwrstate_parm *)pbuf;
    939
    940	preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
    941	r8712_cpwm_int_hdl(adapter, preportpwrstate);
    942}
    943
    944/*	When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
    945 *	 the ADDBA req frame with start seq control = 0 to wifi client after
    946 *	 the WPA handshake and the seqence number of following data packet
    947 *	will be 0. In this case, the Rx reorder sequence is not longer than 0
    948 *	 and the WiFi client will drop the data with seq number 0.
    949 *	So, the 8712 firmware has to inform driver with receiving the
    950 *	 ADDBA-Req frame so that the driver can reset the
    951 *	sequence value of Rx reorder control.
    952 */
    953void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
    954{
    955	struct	ADDBA_Req_Report_parm *pAddbareq_pram =
    956			 (struct ADDBA_Req_Report_parm *)pbuf;
    957	struct	sta_info *psta;
    958	struct	sta_priv *pstapriv = &adapter->stapriv;
    959	struct	recv_reorder_ctrl *precvreorder_ctrl = NULL;
    960
    961	psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
    962	if (psta) {
    963		precvreorder_ctrl =
    964			 &psta->recvreorder_ctrl[pAddbareq_pram->tid];
    965		/* set the indicate_seq to 0xffff so that the rx reorder
    966		 * can store any following data packet.
    967		 */
    968		precvreorder_ctrl->indicate_seq = 0xffff;
    969	}
    970}
    971
    972void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
    973{
    974	if (!adapter->securitypriv.wps_hw_pbc_pressed)
    975		adapter->securitypriv.wps_hw_pbc_pressed = true;
    976}
    977
    978void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
    979{
    980	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
    981	struct sitesurvey_ctrl	*psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
    982	struct registry_priv	*pregistrypriv = &adapter->registrypriv;
    983	u64 current_tx_pkts;
    984	uint current_rx_pkts;
    985
    986	current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
    987			  (psitesurveyctrl->last_tx_pkts);
    988	current_rx_pkts = (adapter->recvpriv.rx_pkts) -
    989			  (psitesurveyctrl->last_rx_pkts);
    990	psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
    991	psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
    992	if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
    993	    (current_rx_pkts > pregistrypriv->busy_thresh))
    994		psitesurveyctrl->traffic_busy = true;
    995	else
    996		psitesurveyctrl->traffic_busy = false;
    997}
    998
    999void _r8712_join_timeout_handler(struct _adapter *adapter)
   1000{
   1001	unsigned long irqL;
   1002	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
   1003
   1004	if (adapter->driver_stopped || adapter->surprise_removed)
   1005		return;
   1006	spin_lock_irqsave(&pmlmepriv->lock, irqL);
   1007	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
   1008	pmlmepriv->to_join = false;
   1009	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
   1010		r8712_os_indicate_disconnect(adapter);
   1011		_clr_fwstate_(pmlmepriv, _FW_LINKED);
   1012	}
   1013	if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
   1014		r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
   1015				  adapter->registrypriv.smart_ps);
   1016	}
   1017	spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
   1018}
   1019
   1020void r8712_scan_timeout_handler (struct _adapter *adapter)
   1021{
   1022	unsigned long irqL;
   1023	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
   1024
   1025	spin_lock_irqsave(&pmlmepriv->lock, irqL);
   1026	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
   1027	pmlmepriv->to_join = false;	/* scan fail, so clear to_join flag */
   1028	spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
   1029}
   1030
   1031void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
   1032{
   1033	if (adapter->driver_stopped || adapter->surprise_removed)
   1034		return;
   1035	if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
   1036		r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
   1037			    adapter->registrypriv.smart_ps);
   1038}
   1039
   1040int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
   1041{
   1042	struct list_head *phead;
   1043	unsigned char *dst_ssid, *src_ssid;
   1044	struct _adapter *adapter;
   1045	struct  __queue *queue = NULL;
   1046	struct wlan_network *pnetwork = NULL;
   1047	struct wlan_network *pnetwork_max_rssi = NULL;
   1048
   1049	adapter = (struct _adapter *)pmlmepriv->nic_hdl;
   1050	queue = &pmlmepriv->scanned_queue;
   1051	phead = &queue->queue;
   1052	pmlmepriv->pscanned = phead->next;
   1053	while (1) {
   1054		if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
   1055			if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
   1056				pnetwork = pnetwork_max_rssi;
   1057				goto ask_for_joinbss;
   1058			}
   1059			return -EINVAL;
   1060		}
   1061		pnetwork = container_of(pmlmepriv->pscanned,
   1062					struct wlan_network, list);
   1063		pmlmepriv->pscanned = pmlmepriv->pscanned->next;
   1064		if (pmlmepriv->assoc_by_bssid) {
   1065			dst_ssid = pnetwork->network.MacAddress;
   1066			src_ssid = pmlmepriv->assoc_bssid;
   1067			if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
   1068				if (check_fwstate(pmlmepriv, _FW_LINKED)) {
   1069					if (is_same_network(&pmlmepriv->cur_network.network,
   1070					    &pnetwork->network)) {
   1071						_clr_fwstate_(pmlmepriv,
   1072							_FW_UNDER_LINKING);
   1073						/*r8712_indicate_connect again*/
   1074						r8712_indicate_connect(adapter);
   1075						return 2;
   1076					}
   1077					r8712_disassoc_cmd(adapter);
   1078					r8712_ind_disconnect(adapter);
   1079					r8712_free_assoc_resources(adapter);
   1080				}
   1081				goto ask_for_joinbss;
   1082			}
   1083		} else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
   1084			goto ask_for_joinbss;
   1085		}
   1086		dst_ssid = pnetwork->network.Ssid.Ssid;
   1087		src_ssid = pmlmepriv->assoc_ssid.Ssid;
   1088		if ((pnetwork->network.Ssid.SsidLength ==
   1089		    pmlmepriv->assoc_ssid.SsidLength) &&
   1090		    (!memcmp(dst_ssid, src_ssid,
   1091		     pmlmepriv->assoc_ssid.SsidLength))) {
   1092			if (pmlmepriv->assoc_by_rssi) {
   1093				/* if the ssid is the same, select the bss
   1094				 * which has the max rssi
   1095				 */
   1096				if (pnetwork_max_rssi) {
   1097					if (pnetwork->network.Rssi >
   1098					    pnetwork_max_rssi->network.Rssi)
   1099						pnetwork_max_rssi = pnetwork;
   1100				} else {
   1101					pnetwork_max_rssi = pnetwork;
   1102				}
   1103			} else if (is_desired_network(adapter, pnetwork)) {
   1104				if (check_fwstate(pmlmepriv, _FW_LINKED)) {
   1105					r8712_disassoc_cmd(adapter);
   1106					r8712_free_assoc_resources(adapter);
   1107				}
   1108				goto ask_for_joinbss;
   1109			}
   1110		}
   1111	}
   1112
   1113ask_for_joinbss:
   1114	return r8712_joinbss_cmd(adapter, pnetwork);
   1115}
   1116
   1117int r8712_set_auth(struct _adapter *adapter,
   1118		   struct security_priv *psecuritypriv)
   1119{
   1120	struct cmd_priv	*pcmdpriv = &adapter->cmdpriv;
   1121	struct cmd_obj *pcmd;
   1122	struct setauth_parm *psetauthparm;
   1123
   1124	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
   1125	if (!pcmd)
   1126		return -ENOMEM;
   1127
   1128	psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
   1129	if (!psetauthparm) {
   1130		kfree(pcmd);
   1131		return -ENOMEM;
   1132	}
   1133	psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
   1134	pcmd->cmdcode = _SetAuth_CMD_;
   1135	pcmd->parmbuf = (unsigned char *)psetauthparm;
   1136	pcmd->cmdsz = sizeof(struct setauth_parm);
   1137	pcmd->rsp = NULL;
   1138	pcmd->rspsz = 0;
   1139	INIT_LIST_HEAD(&pcmd->list);
   1140	r8712_enqueue_cmd(pcmdpriv, pcmd);
   1141	return 0;
   1142}
   1143
   1144int r8712_set_key(struct _adapter *adapter,
   1145		  struct security_priv *psecuritypriv,
   1146		  sint keyid)
   1147{
   1148	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
   1149	struct cmd_obj *pcmd;
   1150	struct setkey_parm *psetkeyparm;
   1151	u8 keylen;
   1152	int ret;
   1153
   1154	pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
   1155	if (!pcmd)
   1156		return -ENOMEM;
   1157	psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
   1158	if (!psetkeyparm) {
   1159		ret = -ENOMEM;
   1160		goto err_free_cmd;
   1161	}
   1162	if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
   1163		psetkeyparm->algorithm =
   1164			 (u8)psecuritypriv->XGrpPrivacy;
   1165	} else { /* WEP */
   1166		psetkeyparm->algorithm =
   1167			 (u8)psecuritypriv->PrivacyAlgrthm;
   1168	}
   1169	psetkeyparm->keyid = (u8)keyid;
   1170
   1171	switch (psetkeyparm->algorithm) {
   1172	case _WEP40_:
   1173		keylen = 5;
   1174		memcpy(psetkeyparm->key,
   1175			psecuritypriv->DefKey[keyid].skey, keylen);
   1176		break;
   1177	case _WEP104_:
   1178		keylen = 13;
   1179		memcpy(psetkeyparm->key,
   1180			psecuritypriv->DefKey[keyid].skey, keylen);
   1181		break;
   1182	case _TKIP_:
   1183		if (keyid < 1 || keyid > 2) {
   1184			ret = -EINVAL;
   1185			goto err_free_parm;
   1186		}
   1187		keylen = 16;
   1188		memcpy(psetkeyparm->key,
   1189			&psecuritypriv->XGrpKey[keyid - 1], keylen);
   1190		psetkeyparm->grpkey = 1;
   1191		break;
   1192	case _AES_:
   1193		if (keyid < 1 || keyid > 2) {
   1194			ret = -EINVAL;
   1195			goto err_free_parm;
   1196		}
   1197		keylen = 16;
   1198		memcpy(psetkeyparm->key,
   1199			&psecuritypriv->XGrpKey[keyid - 1], keylen);
   1200		psetkeyparm->grpkey = 1;
   1201		break;
   1202	default:
   1203		ret = -EINVAL;
   1204		goto err_free_parm;
   1205	}
   1206	pcmd->cmdcode = _SetKey_CMD_;
   1207	pcmd->parmbuf = (u8 *)psetkeyparm;
   1208	pcmd->cmdsz =  (sizeof(struct setkey_parm));
   1209	pcmd->rsp = NULL;
   1210	pcmd->rspsz = 0;
   1211	INIT_LIST_HEAD(&pcmd->list);
   1212	r8712_enqueue_cmd(pcmdpriv, pcmd);
   1213	return 0;
   1214
   1215err_free_parm:
   1216	kfree(psetkeyparm);
   1217err_free_cmd:
   1218	kfree(pcmd);
   1219	return ret;
   1220}
   1221
   1222/* adjust IEs for r8712_joinbss_cmd in WMM */
   1223int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
   1224		    uint in_len, uint initial_out_len)
   1225{
   1226	unsigned int ielength = 0;
   1227	unsigned int i, j;
   1228
   1229	i = 12; /* after the fixed IE */
   1230	while (i < in_len) {
   1231		ielength = initial_out_len;
   1232		if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
   1233		    in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
   1234		    in_ie[i + 5] == 0x02 && i + 5 < in_len) {
   1235			/*WMM element ID and OUI*/
   1236			for (j = i; j < i + 9; j++) {
   1237				out_ie[ielength] = in_ie[j];
   1238				ielength++;
   1239			}
   1240			out_ie[initial_out_len + 1] = 0x07;
   1241			out_ie[initial_out_len + 6] = 0x00;
   1242			out_ie[initial_out_len + 8] = 0x00;
   1243			break;
   1244		}
   1245		i += (in_ie[i + 1] + 2); /* to the next IE element */
   1246	}
   1247	return ielength;
   1248}
   1249
   1250/*
   1251 * Ported from 8185: IsInPreAuthKeyList().
   1252 *
   1253 * Search by BSSID,
   1254 * Return Value:
   1255 *	-1		:if there is no pre-auth key in the  table
   1256 *	>=0		:if there is pre-auth key, and   return the entry id
   1257 */
   1258static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
   1259{
   1260	struct security_priv *p = &Adapter->securitypriv;
   1261	int i;
   1262
   1263	for (i = 0; i < NUM_PMKID_CACHE; i++)
   1264		if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN))
   1265			return i;
   1266	return -1;
   1267}
   1268
   1269sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
   1270		     u8 *out_ie, uint in_len)
   1271{
   1272	u8 authmode = 0, match;
   1273	u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
   1274	u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
   1275	uint ielength, cnt, remove_cnt;
   1276	int iEntry;
   1277	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
   1278	struct security_priv *psecuritypriv = &adapter->securitypriv;
   1279	uint ndisauthmode = psecuritypriv->ndisauthtype;
   1280	uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
   1281
   1282	if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
   1283	    (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
   1284		authmode = _WPA_IE_ID_;
   1285		uncst_oui[0] = 0x0;
   1286		uncst_oui[1] = 0x50;
   1287		uncst_oui[2] = 0xf2;
   1288	}
   1289	if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
   1290	    (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
   1291		authmode = _WPA2_IE_ID_;
   1292		uncst_oui[0] = 0x0;
   1293		uncst_oui[1] = 0x0f;
   1294		uncst_oui[2] = 0xac;
   1295	}
   1296	switch (ndissecuritytype) {
   1297	case Ndis802_11Encryption1Enabled:
   1298	case Ndis802_11Encryption1KeyAbsent:
   1299		uncst_oui[3] = 0x1;
   1300		break;
   1301	case Ndis802_11Encryption2Enabled:
   1302	case Ndis802_11Encryption2KeyAbsent:
   1303		uncst_oui[3] = 0x2;
   1304		break;
   1305	case Ndis802_11Encryption3Enabled:
   1306	case Ndis802_11Encryption3KeyAbsent:
   1307		uncst_oui[3] = 0x4;
   1308		break;
   1309	default:
   1310		break;
   1311	}
   1312	/*Search required WPA or WPA2 IE and copy to sec_ie[] */
   1313	cnt = 12;
   1314	match = false;
   1315	while (cnt < in_len) {
   1316		if (in_ie[cnt] == authmode) {
   1317			if ((authmode == _WPA_IE_ID_) &&
   1318			    (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
   1319				memcpy(&sec_ie[0], &in_ie[cnt],
   1320					in_ie[cnt + 1] + 2);
   1321				match = true;
   1322				break;
   1323			}
   1324			if (authmode == _WPA2_IE_ID_) {
   1325				memcpy(&sec_ie[0], &in_ie[cnt],
   1326					in_ie[cnt + 1] + 2);
   1327				match = true;
   1328				break;
   1329			}
   1330			if (((authmode == _WPA_IE_ID_) &&
   1331			     (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
   1332			     (authmode == _WPA2_IE_ID_))
   1333				memcpy(&bkup_ie[0], &in_ie[cnt],
   1334					in_ie[cnt + 1] + 2);
   1335		}
   1336		cnt += in_ie[cnt + 1] + 2; /*get next*/
   1337	}
   1338	/*restruct WPA IE or WPA2 IE in sec_ie[] */
   1339	if (match) {
   1340		if (sec_ie[0] == _WPA_IE_ID_) {
   1341			/* parsing SSN IE to select required encryption
   1342			 * algorithm, and set the bc/mc encryption algorithm
   1343			 */
   1344			while (true) {
   1345				/*check wpa_oui tag*/
   1346				if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
   1347					match = false;
   1348					break;
   1349				}
   1350				if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
   1351					/*IE Ver error*/
   1352					match = false;
   1353					break;
   1354				}
   1355				if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
   1356					/* get bc/mc encryption type (group
   1357					 * key type)
   1358					 */
   1359					switch (sec_ie[11]) {
   1360					case 0x0: /*none*/
   1361						psecuritypriv->XGrpPrivacy =
   1362								_NO_PRIVACY_;
   1363						break;
   1364					case 0x1: /*WEP_40*/
   1365						psecuritypriv->XGrpPrivacy =
   1366								_WEP40_;
   1367						break;
   1368					case 0x2: /*TKIP*/
   1369						psecuritypriv->XGrpPrivacy =
   1370								_TKIP_;
   1371						break;
   1372					case 0x3: /*AESCCMP*/
   1373					case 0x4:
   1374						psecuritypriv->XGrpPrivacy =
   1375								_AES_;
   1376						break;
   1377					case 0x5: /*WEP_104*/
   1378						psecuritypriv->XGrpPrivacy =
   1379								_WEP104_;
   1380						break;
   1381					}
   1382				} else {
   1383					match = false;
   1384					break;
   1385				}
   1386				if (sec_ie[12] == 0x01) {
   1387					/*check the unicast encryption type*/
   1388					if (memcmp(&sec_ie[14],
   1389					    &uncst_oui[0], 4)) {
   1390						match = false;
   1391						break;
   1392
   1393					} /*else the uncst_oui is match*/
   1394				} else { /*mixed mode, unicast_enc_type > 1*/
   1395					/*select the uncst_oui and remove
   1396					 * the other uncst_oui
   1397					 */
   1398					cnt = sec_ie[12];
   1399					remove_cnt = (cnt - 1) * 4;
   1400					sec_ie[12] = 0x01;
   1401					memcpy(&sec_ie[14], &uncst_oui[0], 4);
   1402					/*remove the other unicast suit*/
   1403					memcpy(&sec_ie[18],
   1404						&sec_ie[18 + remove_cnt],
   1405						sec_ie[1] - 18 + 2 -
   1406						remove_cnt);
   1407					sec_ie[1] = sec_ie[1] - remove_cnt;
   1408				}
   1409				break;
   1410			}
   1411		}
   1412		if (authmode == _WPA2_IE_ID_) {
   1413			/* parsing RSN IE to select required encryption
   1414			 * algorithm, and set the bc/mc encryption algorithm
   1415			 */
   1416			while (true) {
   1417				if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
   1418					/*IE Ver error*/
   1419					match = false;
   1420					break;
   1421				}
   1422				if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
   1423					/*get bc/mc encryption type*/
   1424					switch (sec_ie[7]) {
   1425					case 0x1: /*WEP_40*/
   1426						psecuritypriv->XGrpPrivacy =
   1427								_WEP40_;
   1428						break;
   1429					case 0x2: /*TKIP*/
   1430						psecuritypriv->XGrpPrivacy =
   1431								_TKIP_;
   1432						break;
   1433					case 0x4: /*AESWRAP*/
   1434						psecuritypriv->XGrpPrivacy =
   1435								_AES_;
   1436						break;
   1437					case 0x5: /*WEP_104*/
   1438						psecuritypriv->XGrpPrivacy =
   1439								_WEP104_;
   1440						break;
   1441					default: /*one*/
   1442						psecuritypriv->XGrpPrivacy =
   1443								_NO_PRIVACY_;
   1444						break;
   1445					}
   1446				} else {
   1447					match = false;
   1448					break;
   1449				}
   1450				if (sec_ie[8] == 0x01) {
   1451					/*check the unicast encryption type*/
   1452					if (memcmp(&sec_ie[10],
   1453						     &uncst_oui[0], 4)) {
   1454						match = false;
   1455						break;
   1456					} /*else the uncst_oui is match*/
   1457				} else { /*mixed mode, unicast_enc_type > 1*/
   1458					/*select the uncst_oui and remove the
   1459					 * other uncst_oui
   1460					 */
   1461					cnt = sec_ie[8];
   1462					remove_cnt = (cnt - 1) * 4;
   1463					sec_ie[8] = 0x01;
   1464					memcpy(&sec_ie[10], &uncst_oui[0], 4);
   1465					/*remove the other unicast suit*/
   1466					memcpy(&sec_ie[14],
   1467						&sec_ie[14 + remove_cnt],
   1468						(sec_ie[1] - 14 + 2 -
   1469						remove_cnt));
   1470					sec_ie[1] = sec_ie[1] - remove_cnt;
   1471				}
   1472				break;
   1473			}
   1474		}
   1475	}
   1476	if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
   1477		/*copy fixed ie*/
   1478		memcpy(out_ie, in_ie, 12);
   1479		ielength = 12;
   1480		/*copy RSN or SSN*/
   1481		if (match) {
   1482			memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
   1483			ielength += sec_ie[1] + 2;
   1484			if (authmode == _WPA2_IE_ID_) {
   1485				/*the Pre-Authentication bit should be zero*/
   1486				out_ie[ielength - 1] = 0;
   1487				out_ie[ielength - 2] = 0;
   1488			}
   1489			r8712_report_sec_ie(adapter, authmode, sec_ie);
   1490		}
   1491	} else {
   1492		/*copy fixed ie only*/
   1493		memcpy(out_ie, in_ie, 12);
   1494		ielength = 12;
   1495		if (psecuritypriv->wps_phase) {
   1496			memcpy(out_ie + ielength, psecuritypriv->wps_ie,
   1497			       psecuritypriv->wps_ie_len);
   1498			ielength += psecuritypriv->wps_ie_len;
   1499		}
   1500	}
   1501	iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
   1502	if (iEntry < 0)
   1503		return ielength;
   1504	if (authmode == _WPA2_IE_ID_) {
   1505		out_ie[ielength] = 1;
   1506		ielength++;
   1507		out_ie[ielength] = 0;	/*PMKID count = 0x0100*/
   1508		ielength++;
   1509		memcpy(&out_ie[ielength],
   1510			&psecuritypriv->PMKIDList[iEntry].PMKID, 16);
   1511		ielength += 16;
   1512		out_ie[13] += 18;/*PMKID length = 2+16*/
   1513	}
   1514	return ielength;
   1515}
   1516
   1517void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
   1518{
   1519	struct registry_priv *pregistrypriv = &adapter->registrypriv;
   1520	struct eeprom_priv *peepriv = &adapter->eeprompriv;
   1521	struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
   1522	u8 *myhwaddr = myid(peepriv);
   1523
   1524	memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
   1525	memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
   1526		sizeof(struct ndis_802_11_ssid));
   1527	pdev_network->Configuration.Length =
   1528			 sizeof(struct NDIS_802_11_CONFIGURATION);
   1529	pdev_network->Configuration.BeaconPeriod = 100;
   1530	pdev_network->Configuration.FHConfig.Length = 0;
   1531	pdev_network->Configuration.FHConfig.HopPattern = 0;
   1532	pdev_network->Configuration.FHConfig.HopSet = 0;
   1533	pdev_network->Configuration.FHConfig.DwellTime = 0;
   1534}
   1535
   1536void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
   1537{
   1538	int sz = 0;
   1539	struct registry_priv	*pregistrypriv = &adapter->registrypriv;
   1540	struct wlan_bssid_ex	*pdev_network = &pregistrypriv->dev_network;
   1541	struct security_priv	*psecuritypriv = &adapter->securitypriv;
   1542	struct wlan_network	*cur_network = &adapter->mlmepriv.cur_network;
   1543
   1544	pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
   1545					    > 0 ? 1 : 0); /* adhoc no 802.1x */
   1546	pdev_network->Rssi = 0;
   1547	switch (pregistrypriv->wireless_mode) {
   1548	case WIRELESS_11B:
   1549		pdev_network->NetworkTypeInUse = Ndis802_11DS;
   1550		break;
   1551	case WIRELESS_11G:
   1552	case WIRELESS_11BG:
   1553		pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
   1554		break;
   1555	case WIRELESS_11A:
   1556		pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
   1557		break;
   1558	default:
   1559		/* TODO */
   1560		break;
   1561	}
   1562	pdev_network->Configuration.DSConfig = pregistrypriv->channel;
   1563	if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
   1564		pdev_network->Configuration.ATIMWindow = 3;
   1565	pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
   1566	/* 1. Supported rates
   1567	 * 2. IE
   1568	 */
   1569	sz = r8712_generate_ie(pregistrypriv);
   1570	pdev_network->IELength = sz;
   1571	pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
   1572}
   1573
   1574/*the function is at passive_level*/
   1575void r8712_joinbss_reset(struct _adapter *padapter)
   1576{
   1577	int i;
   1578	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
   1579	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
   1580
   1581	/* todo: if you want to do something io/reg/hw setting before join_bss,
   1582	 * please add code here
   1583	 */
   1584	phtpriv->ampdu_enable = false;/*reset to disabled*/
   1585	for (i = 0; i < 16; i++)
   1586		phtpriv->baddbareq_issued[i] = false;/*reset it*/
   1587	if (phtpriv->ht_option) {
   1588		/* validate  usb rx aggregation */
   1589		r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
   1590	} else {
   1591		/* invalidate  usb rx aggregation */
   1592		/* TH=1 => means that invalidate usb rx aggregation */
   1593		r8712_write8(padapter, 0x102500D9, 1);
   1594	}
   1595}
   1596
   1597/*the function is >= passive_level*/
   1598unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
   1599				     u8 *out_ie, uint in_len, uint *pout_len)
   1600{
   1601	u32 ielen, out_len;
   1602	unsigned char *p;
   1603	struct ieee80211_ht_cap ht_capie;
   1604	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
   1605	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
   1606	struct qos_priv *pqospriv = &pmlmepriv->qospriv;
   1607	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
   1608
   1609	phtpriv->ht_option = 0;
   1610	p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
   1611	if (p && (ielen > 0)) {
   1612		if (pqospriv->qos_option == 0) {
   1613			out_len = *pout_len;
   1614			r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
   1615				     _WMM_IE_Length_, WMM_IE, pout_len);
   1616			pqospriv->qos_option = 1;
   1617		}
   1618		out_len = *pout_len;
   1619		memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
   1620		ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
   1621				    IEEE80211_HT_CAP_SGI_20 |
   1622				    IEEE80211_HT_CAP_SGI_40 |
   1623				    IEEE80211_HT_CAP_TX_STBC |
   1624				    IEEE80211_HT_CAP_MAX_AMSDU |
   1625				    IEEE80211_HT_CAP_DSSSCCK40);
   1626		ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
   1627				0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
   1628		r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
   1629			     sizeof(struct ieee80211_ht_cap),
   1630			     (unsigned char *)&ht_capie, pout_len);
   1631		phtpriv->ht_option = 1;
   1632	}
   1633	return phtpriv->ht_option;
   1634}
   1635
   1636/* the function is > passive_level (in critical_section) */
   1637static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
   1638{
   1639	u8 *p, max_ampdu_sz;
   1640	int i;
   1641	uint len;
   1642	struct sta_info *bmc_sta, *psta;
   1643	struct ieee80211_ht_cap *pht_capie;
   1644	struct recv_reorder_ctrl *preorder_ctrl;
   1645	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
   1646	struct ht_priv *phtpriv = &pmlmepriv->htpriv;
   1647	struct registry_priv *pregistrypriv = &padapter->registrypriv;
   1648	struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
   1649
   1650	if (!phtpriv->ht_option)
   1651		return;
   1652	/* maybe needs check if ap supports rx ampdu. */
   1653	if (!phtpriv->ampdu_enable &&
   1654	    (pregistrypriv->ampdu_enable == 1))
   1655		phtpriv->ampdu_enable = true;
   1656	/*check Max Rx A-MPDU Size*/
   1657	len = 0;
   1658	p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
   1659				WLAN_EID_HT_CAPABILITY,
   1660				&len, ie_len -
   1661				sizeof(struct NDIS_802_11_FIXED_IEs));
   1662	if (p && len > 0) {
   1663		pht_capie = (struct ieee80211_ht_cap *)(p + 2);
   1664		max_ampdu_sz = (pht_capie->ampdu_params_info &
   1665				IEEE80211_HT_AMPDU_PARM_FACTOR);
   1666		/* max_ampdu_sz (kbytes); */
   1667		max_ampdu_sz = 1 << (max_ampdu_sz + 3);
   1668		phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
   1669	}
   1670	/* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
   1671	 * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
   1672	 * wstart_b(indicate_seq) to default value=0xffff
   1673	 * todo: check if AP can send A-MPDU packets
   1674	 */
   1675	bmc_sta = r8712_get_bcmc_stainfo(padapter);
   1676	if (bmc_sta) {
   1677		for (i = 0; i < 16; i++) {
   1678			preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
   1679			preorder_ctrl->indicate_seq = 0xffff;
   1680			preorder_ctrl->wend_b = 0xffff;
   1681		}
   1682	}
   1683	psta = r8712_get_stainfo(&padapter->stapriv,
   1684				 pcur_network->network.MacAddress);
   1685	if (psta) {
   1686		for (i = 0; i < 16; i++) {
   1687			preorder_ctrl = &psta->recvreorder_ctrl[i];
   1688			preorder_ctrl->indicate_seq = 0xffff;
   1689			preorder_ctrl->wend_b = 0xffff;
   1690		}
   1691	}
   1692	len = 0;
   1693	p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
   1694		   WLAN_EID_HT_OPERATION, &len,
   1695		   ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
   1696}
   1697
   1698void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
   1699{
   1700	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
   1701	struct ht_priv	 *phtpriv = &pmlmepriv->htpriv;
   1702
   1703	if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
   1704		if (!phtpriv->baddbareq_issued[priority]) {
   1705			r8712_addbareq_cmd(padapter, (u8)priority);
   1706			phtpriv->baddbareq_issued[priority] = true;
   1707		}
   1708	}
   1709}