From 3265093b08e13c8c1cdf52a6e8c1aa0d9f27ee68 Mon Sep 17 00:00:00 2001
From: The-going <48602507+The-going@users.noreply.github.com>
Date: Mon, 7 Feb 2022 15:13:06 +0300
Subject: [PATCH 3/9] drv:net:rtl8723cs: core

---
 .../realtek/rtl8723cs/core/efuse/rtw_efuse.c  |  1728 ++
 .../wireless/realtek/rtl8723cs/core/rtw_ap.c  |  4224 +++++
 .../realtek/rtl8723cs/core/rtw_beamforming.c  |  1244 ++
 .../realtek/rtl8723cs/core/rtw_br_ext.c       |  1699 ++
 .../realtek/rtl8723cs/core/rtw_bt_mp.c        |  1753 ++
 .../realtek/rtl8723cs/core/rtw_btcoex.c       |  1724 ++
 .../wireless/realtek/rtl8723cs/core/rtw_cmd.c |  4513 +++++
 .../realtek/rtl8723cs/core/rtw_debug.c        |  3864 ++++
 .../realtek/rtl8723cs/core/rtw_eeprom.c       |   423 +
 .../realtek/rtl8723cs/core/rtw_ieee80211.c    |  2847 +++
 .../wireless/realtek/rtl8723cs/core/rtw_io.c  |   737 +
 .../realtek/rtl8723cs/core/rtw_ioctl_query.c  |   192 +
 .../realtek/rtl8723cs/core/rtw_ioctl_rtl.c    |  1021 +
 .../realtek/rtl8723cs/core/rtw_ioctl_set.c    |  1483 ++
 .../wireless/realtek/rtl8723cs/core/rtw_iol.c |   390 +
 .../wireless/realtek/rtl8723cs/core/rtw_mem.c |   122 +
 .../realtek/rtl8723cs/core/rtw_mlme.c         |  4935 +++++
 .../realtek/rtl8723cs/core/rtw_mlme_ext.c     | 15417 ++++++++++++++++
 .../wireless/realtek/rtl8723cs/core/rtw_mp.c  |  2577 +++
 .../realtek/rtl8723cs/core/rtw_mp_ioctl.c     |  2946 +++
 .../wireless/realtek/rtl8723cs/core/rtw_odm.c |   461 +
 .../wireless/realtek/rtl8723cs/core/rtw_p2p.c |  5624 ++++++
 .../realtek/rtl8723cs/core/rtw_pwrctrl.c      |  2698 +++
 .../realtek/rtl8723cs/core/rtw_recv.c         |  4966 +++++
 .../wireless/realtek/rtl8723cs/core/rtw_rf.c  |   477 +
 .../realtek/rtl8723cs/core/rtw_security.c     |  3320 ++++
 .../realtek/rtl8723cs/core/rtw_sreset.c       |   370 +
 .../realtek/rtl8723cs/core/rtw_sta_mgt.c      |  1021 +
 .../realtek/rtl8723cs/core/rtw_tdls.c         |  3162 ++++
 .../wireless/realtek/rtl8723cs/core/rtw_vht.c |   807 +
 .../realtek/rtl8723cs/core/rtw_wapi.c         |  1326 ++
 .../realtek/rtl8723cs/core/rtw_wapi_sms4.c    |   923 +
 .../realtek/rtl8723cs/core/rtw_wlan_util.c    |  4738 +++++
 .../realtek/rtl8723cs/core/rtw_xmit.c         |  5074 +++++
 34 files changed, 88806 insertions(+)
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/efuse/rtw_efuse.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_ap.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_beamforming.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_br_ext.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_bt_mp.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_btcoex.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_cmd.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_debug.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_eeprom.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_ieee80211.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_io.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_query.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_rtl.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_set.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_iol.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_mem.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme_ext.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp_ioctl.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_odm.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_p2p.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_pwrctrl.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_recv.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_rf.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_security.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_sreset.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_sta_mgt.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_tdls.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_vht.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi_sms4.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_wlan_util.c
 create mode 100644 drivers/net/wireless/realtek/rtl8723cs/core/rtw_xmit.c

diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/efuse/rtw_efuse.c b/drivers/net/wireless/realtek/rtl8723cs/core/efuse/rtw_efuse.c
new file mode 100644
index 000000000..2f9f9f25b
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/efuse/rtw_efuse.c
@@ -0,0 +1,1728 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_EFUSE_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#include "../hal/efuse/efuse_mask.h"
+
+/*------------------------Define local variable------------------------------*/
+u8	fakeEfuseBank=0;
+u32	fakeEfuseUsedBytes=0;
+u8	fakeEfuseContent[EFUSE_MAX_HW_SIZE]={0};
+u8	fakeEfuseInitMap[EFUSE_MAX_MAP_LEN]={0};
+u8	fakeEfuseModifiedMap[EFUSE_MAX_MAP_LEN]={0};
+
+u32	BTEfuseUsedBytes=0;
+u8	BTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+u8	BTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN]={0};
+u8	BTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN]={0};
+
+u32	fakeBTEfuseUsedBytes=0;
+u8	fakeBTEfuseContent[EFUSE_MAX_BT_BANK][EFUSE_MAX_HW_SIZE];
+u8	fakeBTEfuseInitMap[EFUSE_BT_MAX_MAP_LEN]={0};
+u8	fakeBTEfuseModifiedMap[EFUSE_BT_MAX_MAP_LEN]={0};
+
+u8 	maskfileBuffer[32];
+/*------------------------Define local variable------------------------------*/
+
+//------------------------------------------------------------------------------
+#define REG_EFUSE_CTRL		0x0030
+#define EFUSE_CTRL			REG_EFUSE_CTRL		// E-Fuse Control.
+//------------------------------------------------------------------------------
+
+BOOLEAN
+Efuse_Read1ByteFromFakeContent(
+	IN		PADAPTER	pAdapter,
+	IN		u16		Offset,
+	IN OUT	u8		*Value	);
+BOOLEAN
+Efuse_Read1ByteFromFakeContent(
+	IN		PADAPTER	pAdapter,
+	IN		u16		Offset,
+	IN OUT	u8		*Value	)
+{
+	if(Offset >= EFUSE_MAX_HW_SIZE)
+	{
+		return _FALSE;
+	}
+	//DbgPrint("Read fake content, offset = %d\n", Offset);
+	if(fakeEfuseBank == 0)
+		*Value = fakeEfuseContent[Offset];
+	else
+		*Value = fakeBTEfuseContent[fakeEfuseBank-1][Offset];
+	return _TRUE;
+}
+
+BOOLEAN
+Efuse_Write1ByteToFakeContent(
+	IN		PADAPTER	pAdapter,
+	IN		u16		Offset,
+	IN 		u8		Value	);
+BOOLEAN
+Efuse_Write1ByteToFakeContent(
+	IN		PADAPTER	pAdapter,
+	IN		u16		Offset,
+	IN 		u8		Value	)
+{
+	if(Offset >= EFUSE_MAX_HW_SIZE)
+	{
+		return _FALSE;
+	}
+	if(fakeEfuseBank == 0)
+		fakeEfuseContent[Offset] = Value;
+	else
+	{
+		fakeBTEfuseContent[fakeEfuseBank-1][Offset] = Value;
+	}
+	return _TRUE;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	Efuse_PowerSwitch
+ *
+ * Overview:	When we want to enable write operation, we should change to 
+ *				pwr on state. When we stop write, we should switch to 500k mode
+ *				and disable LDO 2.5V.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/17/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+VOID
+Efuse_PowerSwitch(
+	IN	PADAPTER	pAdapter,
+	IN	u8		bWrite,
+	IN	u8		PwrState)
+{
+	pAdapter->HalFunc.EfusePowerSwitch(pAdapter, bWrite, PwrState);
+}
+
+VOID
+BTEfuse_PowerSwitch(
+	IN	PADAPTER	pAdapter,
+	IN	u8		bWrite,
+	IN	u8		PwrState)
+{
+	if(pAdapter->HalFunc.BTEfusePowerSwitch)
+		pAdapter->HalFunc.BTEfusePowerSwitch(pAdapter, bWrite, PwrState);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	efuse_GetCurrentSize
+ *
+ * Overview:	Get current efuse size!!!
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/16/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+u16
+Efuse_GetCurrentSize(
+	IN PADAPTER		pAdapter,
+	IN u8			efuseType,
+	IN BOOLEAN		bPseudoTest)
+{
+	u16 ret=0;
+
+	ret = pAdapter->HalFunc.EfuseGetCurrentSize(pAdapter, efuseType, bPseudoTest);
+
+	return ret;
+}
+
+/*  11/16/2008 MH Add description. Get current efuse area enabled word!!. */
+u8
+Efuse_CalculateWordCnts(IN u8	word_en)
+{
+	u8 word_cnts = 0;
+	if(!(word_en & BIT(0)))	word_cnts++; // 0 : write enable
+	if(!(word_en & BIT(1)))	word_cnts++;
+	if(!(word_en & BIT(2)))	word_cnts++;
+	if(!(word_en & BIT(3)))	word_cnts++;
+	return word_cnts;
+}
+
+//
+//	Description:
+//		Execute E-Fuse read byte operation.
+//		Refered from SD1 Richard.
+//
+//	Assumption:
+//		1. Boot from E-Fuse and successfully auto-load.
+//		2. PASSIVE_LEVEL (USB interface)
+//
+//	Created by Roger, 2008.10.21.
+//
+VOID
+ReadEFuseByte(
+		PADAPTER	Adapter,
+		u16 			_offset, 
+		u8 			*pbuf, 
+		IN BOOLEAN	bPseudoTest) 
+{
+	u32	value32;
+	u8	readbyte;
+	u16	retry;
+	//u32 start=rtw_get_current_time();
+
+	if(bPseudoTest)
+	{
+		Efuse_Read1ByteFromFakeContent(Adapter, _offset, pbuf);
+		return;
+	}
+	if (IS_HARDWARE_TYPE_8723B(Adapter))
+	{
+		// <20130121, Kordan> For SMIC S55 EFUSE specificatoin.
+		//0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8])
+		PHY_SetMacReg(Adapter, EFUSE_TEST, BIT11, 0);
+	}
+	//Write Address
+	rtw_write8(Adapter, EFUSE_CTRL+1, (_offset & 0xff));  		
+	readbyte = rtw_read8(Adapter, EFUSE_CTRL+2);
+	rtw_write8(Adapter, EFUSE_CTRL+2, ((_offset >> 8) & 0x03) | (readbyte & 0xfc));  		
+
+	//Write bit 32 0
+	readbyte = rtw_read8(Adapter, EFUSE_CTRL+3);		
+	rtw_write8(Adapter, EFUSE_CTRL+3, (readbyte & 0x7f));  	
+	
+	//Check bit 32 read-ready
+	retry = 0;
+	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	//while(!(((value32 >> 24) & 0xff) & 0x80)  && (retry<10))
+	while(!(((value32 >> 24) & 0xff) & 0x80)  && (retry<10000))
+	{
+		value32 = rtw_read32(Adapter, EFUSE_CTRL);
+		retry++;
+	}
+
+	// 20100205 Joseph: Add delay suggested by SD1 Victor.
+	// This fix the problem that Efuse read error in high temperature condition.
+	// Designer says that there shall be some delay after ready bit is set, or the
+	// result will always stay on last data we read.
+	rtw_udelay_os(50);
+	value32 = rtw_read32(Adapter, EFUSE_CTRL);
+	
+	*pbuf = (u8)(value32 & 0xff);
+	//DBG_871X("ReadEFuseByte _offset:%08u, in %d ms\n",_offset ,rtw_get_passing_time_ms(start));
+	
+}
+
+//
+//	Description:
+//		1. Execute E-Fuse read byte operation according as map offset and 
+//		    save to E-Fuse table.
+//		2. Refered from SD1 Richard.
+//
+//	Assumption:
+//		1. Boot from E-Fuse and successfully auto-load.
+//		2. PASSIVE_LEVEL (USB interface)
+//
+//	Created by Roger, 2008.10.21.
+//
+//	2008/12/12 MH 	1. Reorganize code flow and reserve bytes. and add description.
+//					2. Add efuse utilization collect.
+//	2008/12/22 MH	Read Efuse must check if we write section 1 data again!!! Sec1
+//					write addr must be after sec5.
+//
+
+VOID
+efuse_ReadEFuse(
+	PADAPTER	Adapter,
+	u8		efuseType,
+	u16		_offset,
+	u16 		_size_byte,
+	u8      	*pbuf,
+	IN	BOOLEAN	bPseudoTest
+	);
+VOID
+efuse_ReadEFuse(
+	PADAPTER	Adapter,
+	u8		efuseType,
+	u16		_offset,
+	u16 		_size_byte,
+	u8      	*pbuf,
+	IN	BOOLEAN	bPseudoTest
+	)
+{
+	Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
+}
+
+VOID
+EFUSE_GetEfuseDefinition(
+	IN		PADAPTER	pAdapter,
+	IN		u8		efuseType,
+	IN		u8		type,
+	OUT		void		*pOut,
+	IN		BOOLEAN		bPseudoTest
+	)
+{
+	pAdapter->HalFunc.EFUSEGetEfuseDefinition(pAdapter, efuseType, type, pOut, bPseudoTest);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	EFUSE_Read1Byte
+ *
+ * Overview:	Copy from WMAC fot EFUSE read 1 byte.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 09/23/2008 	MHC		Copy from WMAC.
+ *
+ *---------------------------------------------------------------------------*/
+u8
+EFUSE_Read1Byte(	
+	IN	PADAPTER	Adapter, 
+	IN	u16		Address)
+{
+	u8	data;
+	u8	Bytetemp = {0x00};
+	u8	temp = {0x00};
+	u32	k=0;
+	u16	contentLen=0;
+
+	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (PVOID)&contentLen, _FALSE);
+
+	if (Address < contentLen)	//E-fuse 512Byte
+	{
+		//Write E-fuse Register address bit0~7
+		temp = Address & 0xFF;	
+		rtw_write8(Adapter, EFUSE_CTRL+1, temp);	
+		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);	
+		//Write E-fuse Register address bit8~9
+		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);	
+		rtw_write8(Adapter, EFUSE_CTRL+2, temp);	
+
+		//Write 0x30[31]=0
+		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+		temp = Bytetemp & 0x7F;
+		rtw_write8(Adapter, EFUSE_CTRL+3, temp);
+
+		//Wait Write-ready (0x30[31]=1)
+		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+		while(!(Bytetemp & 0x80))
+		{				
+			Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+			k++;
+			if(k==1000)
+			{
+				k=0;
+				break;
+			}
+		}
+		data=rtw_read8(Adapter, EFUSE_CTRL);
+		return data;
+	}
+	else
+		return 0xFF;
+	
+}/* EFUSE_Read1Byte */
+
+/*-----------------------------------------------------------------------------
+ * Function:	EFUSE_Write1Byte
+ *
+ * Overview:	Copy from WMAC fot EFUSE write 1 byte.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 09/23/2008 	MHC		Copy from WMAC.
+ *
+ *---------------------------------------------------------------------------*/
+
+void	
+EFUSE_Write1Byte(	
+	IN	PADAPTER	Adapter, 
+	IN	u16		Address,
+	IN	u8		Value);
+void	
+EFUSE_Write1Byte(	
+	IN	PADAPTER	Adapter, 
+	IN	u16		Address,
+	IN	u8		Value)
+{
+	u8	Bytetemp = {0x00};
+	u8	temp = {0x00};
+	u32	k=0;
+	u16	contentLen=0;
+
+	//RT_TRACE(COMP_EFUSE, DBG_LOUD, ("Addr=%x Data =%x\n", Address, Value));
+	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI , TYPE_EFUSE_REAL_CONTENT_LEN, (PVOID)&contentLen, _FALSE);
+
+	if( Address < contentLen)	//E-fuse 512Byte
+	{
+		rtw_write8(Adapter, EFUSE_CTRL, Value);
+
+		//Write E-fuse Register address bit0~7
+		temp = Address & 0xFF;	
+		rtw_write8(Adapter, EFUSE_CTRL+1, temp);	
+		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+2);	
+		
+		//Write E-fuse Register address bit8~9
+		temp = ((Address >> 8) & 0x03) | (Bytetemp & 0xFC);	
+		rtw_write8(Adapter, EFUSE_CTRL+2, temp);	
+
+		//Write 0x30[31]=1
+		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+		temp = Bytetemp | 0x80;
+		rtw_write8(Adapter, EFUSE_CTRL+3, temp);
+
+		//Wait Write-ready (0x30[31]=0)
+		Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);
+		while(Bytetemp & 0x80)
+		{
+			Bytetemp = rtw_read8(Adapter, EFUSE_CTRL+3);			
+			k++;
+			if(k==100)
+			{
+				k=0;
+				break;
+			}
+		}
+	}
+}/* EFUSE_Write1Byte */
+
+
+/*  11/16/2008 MH Read one byte from real Efuse. */
+u8
+efuse_OneByteRead(
+	IN	PADAPTER	pAdapter, 
+	IN	u16			addr,
+	IN	u8			*data,
+	IN	BOOLEAN		bPseudoTest)
+{
+	u32	tmpidx = 0;
+	u8	bResult;
+	u8	readbyte;
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(pAdapter);
+	
+	//DBG_871X("===> EFUSE_OneByteRead(), addr = %x\n", addr);
+	//DBG_871X("===> EFUSE_OneByteRead() start, 0x34 = 0x%X\n", rtw_read32(pAdapter, EFUSE_TEST));
+
+	if(bPseudoTest)
+	{
+		bResult = Efuse_Read1ByteFromFakeContent(pAdapter, addr, data);
+		return bResult;
+	}
+	
+	if(	IS_HARDWARE_TYPE_8723B(pAdapter) ||
+		(IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->VersionID))) ||
+		(IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->VersionID))
+	  )
+	{
+		// <20130121, Kordan> For SMIC EFUSE specificatoin.
+		//0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8])	
+		//PHY_SetMacReg(pAdapter, 0x34, BIT11, 0);
+		rtw_write16(pAdapter, 0x34, rtw_read16(pAdapter,0x34)& (~BIT11) ); 
+	}
+
+	// -----------------e-fuse reg ctrl ---------------------------------
+	//address			
+	rtw_write8(pAdapter, EFUSE_CTRL+1, (u8)(addr&0xff));		
+	rtw_write8(pAdapter, EFUSE_CTRL+2, ((u8)((addr>>8) &0x03) ) |
+	(rtw_read8(pAdapter, EFUSE_CTRL+2)&0xFC ));	
+
+	//rtw_write8(pAdapter, EFUSE_CTRL+3,  0x72);//read cmd	
+	//Write bit 32 0
+	readbyte = rtw_read8(pAdapter, EFUSE_CTRL+3);		
+	rtw_write8(pAdapter, EFUSE_CTRL+3, (readbyte & 0x7f));
+
+	while(!(0x80 &rtw_read8(pAdapter, EFUSE_CTRL+3))&&(tmpidx<1000))
+	{
+		rtw_mdelay_os(1);
+		tmpidx++;
+	}
+	if(tmpidx<100)
+	{			
+		*data=rtw_read8(pAdapter, EFUSE_CTRL);		
+		bResult = _TRUE;
+	}
+	else
+	{
+		*data = 0xff;	
+		bResult = _FALSE;
+		DBG_871X("%s: [ERROR] addr=0x%x bResult=%d time out 1s !!!\n", __FUNCTION__, addr, bResult);
+		DBG_871X("%s: [ERROR] EFUSE_CTRL =0x%08x !!!\n", __FUNCTION__, rtw_read32(pAdapter, EFUSE_CTRL));
+	}
+
+	return bResult;
+}
+		
+/*  11/16/2008 MH Write one byte to reald Efuse. */
+u8
+efuse_OneByteWrite(
+	IN	PADAPTER	pAdapter,  
+	IN	u16			addr, 
+	IN	u8			data,
+	IN	BOOLEAN		bPseudoTest)
+{
+	u8	tmpidx = 0;
+	u8	bResult=_FALSE;
+	u32 efuseValue = 0;
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(pAdapter);
+	
+	//DBG_871X("===> EFUSE_OneByteWrite(), addr = %x data=%x\n", addr, data);
+	//DBG_871X("===> EFUSE_OneByteWrite() start, 0x34 = 0x%X\n", rtw_read32(pAdapter, EFUSE_TEST));
+
+	if(bPseudoTest)
+	{
+		bResult = Efuse_Write1ByteToFakeContent(pAdapter, addr, data);
+		return bResult;
+	}
+
+
+	// -----------------e-fuse reg ctrl ---------------------------------	
+	//address			
+
+	
+	efuseValue = rtw_read32(pAdapter, EFUSE_CTRL);
+	efuseValue |= (BIT21|BIT31);
+	efuseValue &= ~(0x3FFFF);
+	efuseValue |= ((addr<<8 | data) & 0x3FFFF);
+
+	// <20130227, Kordan> 8192E MP chip A-cut had better not set 0x34[11] until B-Cut.
+	if (	IS_HARDWARE_TYPE_8723B(pAdapter) ||
+		(IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->VersionID))) ||
+		(IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->VersionID))
+		) {
+		// <20130121, Kordan> For SMIC EFUSE specificatoin.
+		//0x34[11]: SW force PGMEN input of efuse to high. (for the bank selected by 0x34[9:8])
+		//PHY_SetMacReg(pAdapter, 0x34, BIT11, 1);
+		rtw_write16(pAdapter, 0x34, rtw_read16(pAdapter,0x34)| (BIT11) );
+		rtw_write32(pAdapter, EFUSE_CTRL, 0x90600000|((addr<<8 | data)) );
+	}
+	else
+	{
+		rtw_write32(pAdapter, EFUSE_CTRL, efuseValue);
+	}
+
+	while((0x80 &  rtw_read8(pAdapter, EFUSE_CTRL+3)) && (tmpidx<100) ){
+		rtw_mdelay_os(1);
+		tmpidx++;
+	}
+
+	if(tmpidx<100)
+	{
+		bResult = _TRUE;
+	}
+	else
+	{
+		bResult = _FALSE;
+		DBG_871X("%s: [ERROR] addr=0x%x ,efuseValue=0x%x ,bResult=%d time out 1s !!! \n",
+					__FUNCTION__, addr, efuseValue, bResult);
+		DBG_871X("%s: [ERROR] EFUSE_CTRL =0x%08x !!!\n", __FUNCTION__, rtw_read32(pAdapter, EFUSE_CTRL));
+	}
+
+	// disable Efuse program enable
+	if (	IS_HARDWARE_TYPE_8723B(pAdapter) ||
+		(IS_HARDWARE_TYPE_8192E(pAdapter) && (!IS_A_CUT(pHalData->VersionID))) ||
+		(IS_VENDOR_8188E_I_CUT_SERIES(pAdapter)) || (IS_CHIP_VENDOR_SMIC(pHalData->VersionID))
+		) {
+		PHY_SetMacReg(pAdapter, EFUSE_TEST, BIT(11), 0);
+	}
+
+	return bResult;
+}
+
+int
+Efuse_PgPacketRead(	IN	PADAPTER	pAdapter,
+					IN	u8			offset,
+					IN	u8			*data,
+					IN	BOOLEAN		bPseudoTest)
+{
+	int	ret=0;
+
+	ret =  pAdapter->HalFunc.Efuse_PgPacketRead(pAdapter, offset, data, bPseudoTest);
+
+	return ret;
+}
+
+int 
+Efuse_PgPacketWrite(IN	PADAPTER	pAdapter, 
+					IN	u8 			offset,
+					IN	u8			word_en,
+					IN	u8			*data,
+					IN	BOOLEAN		bPseudoTest)
+{
+	int ret;
+
+	ret =  pAdapter->HalFunc.Efuse_PgPacketWrite(pAdapter, offset, word_en, data, bPseudoTest);
+
+	return ret;
+}
+
+
+int 
+Efuse_PgPacketWrite_BT(IN	PADAPTER	pAdapter, 
+					IN	u8 			offset,
+					IN	u8			word_en,
+					IN	u8			*data,
+					IN	BOOLEAN		bPseudoTest)
+{
+	int ret;
+
+	ret =  pAdapter->HalFunc.Efuse_PgPacketWrite_BT(pAdapter, offset, word_en, data, bPseudoTest);
+
+	return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	efuse_WordEnableDataRead
+ *
+ * Overview:	Read allowed word in current efuse section data.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/16/2008 	MHC		Create Version 0.
+ * 11/21/2008 	MHC		Fix Write bug when we only enable late word.
+ *
+ *---------------------------------------------------------------------------*/
+void
+efuse_WordEnableDataRead(IN	u8	word_en,
+							IN	u8	*sourdata,
+							IN	u8	*targetdata)
+{	
+	if (!(word_en&BIT(0)))
+	{
+		targetdata[0] = sourdata[0];
+		targetdata[1] = sourdata[1];
+	}
+	if (!(word_en&BIT(1)))
+	{
+		targetdata[2] = sourdata[2];
+		targetdata[3] = sourdata[3];
+	}
+	if (!(word_en&BIT(2)))
+	{
+		targetdata[4] = sourdata[4];
+		targetdata[5] = sourdata[5];
+	}
+	if (!(word_en&BIT(3)))
+	{
+		targetdata[6] = sourdata[6];
+		targetdata[7] = sourdata[7];
+	}
+}
+
+
+u8
+Efuse_WordEnableDataWrite(	IN	PADAPTER	pAdapter,
+							IN	u16		efuse_addr,
+							IN	u8		word_en, 
+							IN	u8		*data,
+							IN	BOOLEAN		bPseudoTest)
+{
+	u8	ret=0;
+
+	ret =  pAdapter->HalFunc.Efuse_WordEnableDataWrite(pAdapter, efuse_addr, word_en, data, bPseudoTest);
+	
+	return ret;
+}
+
+static u8 efuse_read8(PADAPTER padapter, u16 address, u8 *value)
+{
+	return efuse_OneByteRead(padapter,address, value, _FALSE);
+}
+
+static u8 efuse_write8(PADAPTER padapter, u16 address, u8 *value)
+{
+	return efuse_OneByteWrite(padapter,address, *value, _FALSE);
+}
+
+/*
+ * read/wirte raw efuse data
+ */
+u8 rtw_efuse_access(PADAPTER padapter, u8 bWrite, u16 start_addr, u16 cnts, u8 *data)
+{
+	int i = 0;
+	u16	real_content_len = 0, max_available_size = 0;
+	u8 res = _FAIL ;
+	u8 (*rw8)(PADAPTER, u16, u8*);
+
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_REAL_CONTENT_LEN, (PVOID)&real_content_len, _FALSE);
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
+
+	if (start_addr > real_content_len)
+		return _FAIL;
+
+	if (_TRUE == bWrite) {
+		if ((start_addr + cnts) > max_available_size)
+			return _FAIL;
+		rw8 = &efuse_write8;
+	} else
+		rw8 = &efuse_read8;
+
+	Efuse_PowerSwitch(padapter, bWrite, _TRUE);
+
+	// e-fuse one byte read / write
+	for (i = 0; i < cnts; i++) {
+		if (start_addr >= real_content_len) {
+			res = _FAIL;
+			break;
+		}
+
+		res = rw8(padapter, start_addr++, data++);
+		if (_FAIL == res) break;
+	}
+
+	Efuse_PowerSwitch(padapter, bWrite, _FALSE);
+
+	return res;
+}
+//------------------------------------------------------------------------------
+u16 efuse_GetMaxSize(PADAPTER padapter)
+{
+	u16	max_size;
+
+	max_size = 0;
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_size, _FALSE);
+	return max_size;
+}
+//------------------------------------------------------------------------------
+u8 efuse_GetCurrentSize(PADAPTER padapter, u16 *size)
+{
+	Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
+	*size = Efuse_GetCurrentSize(padapter, EFUSE_WIFI, _FALSE);
+	Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
+
+	return _SUCCESS;
+}
+//------------------------------------------------------------------------------
+u16 efuse_bt_GetMaxSize(PADAPTER padapter)
+{
+	u16	max_size;
+
+	max_size = 0;
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT , TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_size, _FALSE);
+	return max_size;
+}
+
+u8 efuse_bt_GetCurrentSize(PADAPTER padapter, u16 *size)
+{
+	Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
+	*size = Efuse_GetCurrentSize(padapter, EFUSE_BT, _FALSE);
+	Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
+
+	return _SUCCESS;
+}
+
+u8 rtw_efuse_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+{
+	u16	mapLen=0;
+
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
+
+	if ((addr + cnts) > mapLen)
+		return _FAIL;
+
+	Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
+
+	efuse_ReadEFuse(padapter, EFUSE_WIFI, addr, cnts, data, _FALSE);
+
+	Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
+
+	return _SUCCESS;
+}
+
+u8 rtw_BT_efuse_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+{
+	u16	mapLen=0;
+
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
+
+	if ((addr + cnts) > mapLen)
+		return _FAIL;
+
+	Efuse_PowerSwitch(padapter, _FALSE, _TRUE);
+
+	efuse_ReadEFuse(padapter, EFUSE_BT, addr, cnts, data, _FALSE);
+
+	Efuse_PowerSwitch(padapter, _FALSE, _FALSE);
+
+	return _SUCCESS;
+}
+
+BOOLEAN rtw_file_efuse_IsMasked(
+	PADAPTER	pAdapter,
+	u16		Offset
+	)
+{
+	int r = Offset/16;
+	int c = (Offset%16) / 2;
+	int result = 0;
+	
+	if(pAdapter->registrypriv.boffefusemask)
+		return FALSE;
+
+	//DBG_871X(" %s ,Offset=%x r= %d , c=%d , maskfileBuffer[r]= %x \n",__func__,Offset,r,c,maskfileBuffer[r]);
+	if (c < 4) // Upper double word
+	    result = (maskfileBuffer[r] & (0x10 << c));
+	else
+	    result = (maskfileBuffer[r] & (0x01 << (c-4)));
+	
+	return (result > 0) ? 0 : 1;
+
+}
+
+
+u8 rtw_efuse_file_read(PADAPTER padapter,u8 *filepatch,u8 *buf,u32 len)
+{
+	char *ptmp;
+	char *ptmpbuf=NULL;
+	u32 rtStatus;
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	ptmpbuf = rtw_zmalloc(2048);
+
+	if (ptmpbuf == NULL)
+		return _FALSE;
+
+	_rtw_memset(ptmpbuf,'\0',2048);
+	
+	rtStatus = rtw_retrieve_from_file(filepatch, ptmpbuf, 2048);
+
+	if( rtStatus > 100 )
+	{
+		u32 i,j;
+		for(i=0,j=0;j<len;i+=2,j++)
+		{
+			if (( ptmpbuf[i] == ' ' ) && (ptmpbuf[i+1] != '\n' && ptmpbuf[i+1] != '\0')) {
+				i++;
+			}
+			if( (ptmpbuf[i+1] != '\n' && ptmpbuf[i+1] != '\0'))
+			{
+					buf[j] = simple_strtoul(&ptmpbuf[i],&ptmp, 16);
+					DBG_871X(" i=%d,j=%d, %x \n",i,j,buf[j]);
+
+			} else {
+				j--;
+			}
+			
+		}
+
+	} else {
+		DBG_871X(" %s ,filepatch %s , FAIL %d\n", __func__, filepatch, rtStatus);
+		return _FALSE;
+	}
+	rtw_mfree(ptmpbuf, 2048);
+	DBG_871X(" %s ,filepatch %s , done %d\n", __func__, filepatch, rtStatus);
+	return _TRUE;
+}
+
+
+BOOLEAN 
+efuse_IsMasked(
+	PADAPTER	pAdapter,
+	u16		Offset
+	)
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(pAdapter);
+	
+
+	//if (bEfuseMaskOFF(pAdapter))
+	if(pAdapter->registrypriv.boffefusemask)
+		return FALSE;
+		
+#if DEV_BUS_TYPE == RT_USB_INTERFACE
+#if defined(CONFIG_RTL8188E)
+	if (IS_HARDWARE_TYPE_8188E(pAdapter))  
+		return (IS_MASKED(8188E,_MUSB,Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8812A)
+	if (IS_HARDWARE_TYPE_8812(pAdapter))  
+		return (IS_MASKED(8812A,_MUSB,Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8821A)
+	//if (IS_HARDWARE_TYPE_8811AU(pAdapter))  
+	//	return (IS_MASKED(8811A,_MUSB,Offset)) ? TRUE : FALSE;
+	if (IS_HARDWARE_TYPE_8821(pAdapter))  
+		return (IS_MASKED(8821A,_MUSB,Offset)) ? TRUE : FALSE;		
+#endif		
+#if defined(CONFIG_RTL8192E)
+	if (IS_HARDWARE_TYPE_8192E(pAdapter))  
+		return (IS_MASKED(8192E,_MUSB,Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8723B)
+	if (IS_HARDWARE_TYPE_8723B(pAdapter))  
+		return (IS_MASKED(8723B,_MUSB,Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8703B)
+	if (IS_HARDWARE_TYPE_8703B(pAdapter))
+		return (IS_MASKED(8703B, _MUSB, Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8814A)
+	if (IS_HARDWARE_TYPE_8814A(pAdapter))
+		return (IS_MASKED(8814A, _MUSB, Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8188F)
+	if (IS_HARDWARE_TYPE_8188F(pAdapter))
+		return (IS_MASKED(8188F, _MUSB, Offset)) ? TRUE : FALSE;
+#endif
+#elif DEV_BUS_TYPE == RT_PCI_INTERFACE
+#if defined(CONFIG_RTL8188E)
+	if (IS_HARDWARE_TYPE_8188E(pAdapter))  
+		return (IS_MASKED(8188E,_MPCIE,Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8192E)
+   	if (IS_HARDWARE_TYPE_8192E(pAdapter))	
+		return (IS_MASKED(8192E,_MPCIE,Offset)) ? TRUE : FALSE;
+#endif	
+#if defined(CONFIG_RTL8812A)
+	if (IS_HARDWARE_TYPE_8812(pAdapter))  
+		return (IS_MASKED(8812A,_MPCIE,Offset)) ? TRUE : FALSE;
+#endif	
+#if defined(CONFIG_RTL8821A)
+	if (IS_HARDWARE_TYPE_8821(pAdapter))  
+		return (IS_MASKED(8821A,_MPCIE,Offset)) ? TRUE : FALSE;
+#endif
+#if defined(CONFIG_RTL8723B)
+	if (IS_HARDWARE_TYPE_8723B(pAdapter))  
+		return (IS_MASKED(8723B,_MPCIE,Offset)) ? TRUE : FALSE; 
+#endif
+#if defined(CONFIG_RTL8814A)
+	if (IS_HARDWARE_TYPE_8814A(pAdapter))
+		return (IS_MASKED(8814A, _MPCIE, Offset)) ? TRUE : FALSE;
+#endif
+	//else if (IS_HARDWARE_TYPE_8821B(pAdapter))  
+	//	return (IS_MASKED(8821B,_MPCIE,Offset)) ? TRUE : FALSE; 
+
+#elif DEV_BUS_TYPE == RT_SDIO_INTERFACE
+#ifdef CONFIG_RTL8188E_SDIO
+	if (IS_HARDWARE_TYPE_8188E(pAdapter))  
+		return (IS_MASKED(8188E,_MSDIO,Offset)) ? TRUE : FALSE;
+#endif
+#ifdef CONFIG_RTL8188F_SDIO
+	if (IS_HARDWARE_TYPE_8188F(pAdapter))  
+		return (IS_MASKED(8188F, _MSDIO, Offset)) ? TRUE : FALSE;
+#endif
+#endif
+
+	return FALSE;	
+}
+
+//------------------------------------------------------------------------------
+u8 rtw_efuse_map_write(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+{
+#define RT_ASSERT_RET(expr)												\
+	if(!(expr)) {															\
+		printk( "Assertion failed! %s at ......\n", #expr);							\
+		printk( "      ......%s,%s,line=%d\n",__FILE__,__FUNCTION__,__LINE__);	\
+		return _FAIL;	\
+	}
+
+	u8	offset, word_en;
+	u8	*map;
+	u8	newdata[PGPKT_DATA_SIZE];
+	s32	i, j, idx;
+	u8	ret = _SUCCESS;
+	u16	mapLen=0;
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
+
+	if ((addr + cnts) > mapLen)
+		return _FAIL;
+
+	RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); // have to be 8 byte alignment
+	RT_ASSERT_RET((mapLen & 0x7) == 0); // have to be PGPKT_DATA_SIZE alignment for memcpy
+
+	map = rtw_zmalloc(mapLen);
+	if(map == NULL){
+		return _FAIL;
+	}
+	
+	_rtw_memset(map, 0xFF, mapLen);
+	
+	ret = rtw_efuse_map_read(padapter, 0, mapLen, map);
+	if (ret == _FAIL) goto exit;
+
+	if(padapter->registrypriv.boffefusemask==0)
+	{
+		for (i =0; i < cnts; i++)
+		{ 
+			if(padapter->registrypriv.bFileMaskEfuse==_TRUE)
+			{
+				if (rtw_file_efuse_IsMasked(padapter, addr+i))	/*use file efuse mask. */
+						data[i] = map[addr+i];
+			}
+			else
+			{
+				if ( efuse_IsMasked(padapter, addr+i ))
+						data[i] = map[addr+i];
+			}
+			DBG_8192C("%s , data[%d] = %x, map[addr+i]= %x\n", __func__, i, data[i], map[addr+i]);
+		}
+	}
+	Efuse_PowerSwitch(padapter, _TRUE, _TRUE);
+
+	idx = 0;
+	offset = (addr >> 3);
+	while (idx < cnts)
+	{
+		word_en = 0xF;
+		j = (addr + idx) & 0x7;
+		_rtw_memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
+		for (i = j; i<PGPKT_DATA_SIZE && idx < cnts; i++, idx++)
+		{
+			if (data[idx] != map[addr + idx])
+			{
+				word_en &= ~BIT(i >> 1);
+				newdata[i] = data[idx];
+#ifdef CONFIG_RTL8723B					
+				 if( addr + idx == 0x8)
+				 {	
+					if (IS_C_CUT(pHalData->VersionID) || IS_B_CUT(pHalData->VersionID))
+					{
+						if(pHalData->adjuseVoltageVal == 6)
+						{
+								newdata[i] = map[addr + idx];
+							 	DBG_8192C(" %s ,\n adjuseVoltageVal = %d ,newdata[%d] = %x \n",__func__,pHalData->adjuseVoltageVal,i,newdata[i]);	 
+						}
+					}
+				  }
+#endif
+			}
+		}
+
+		if (word_en != 0xF) {
+			ret = Efuse_PgPacketWrite(padapter, offset, word_en, newdata, _FALSE);
+			DBG_871X("offset=%x \n",offset);
+			DBG_871X("word_en=%x \n",word_en);
+
+			for(i=0;i<PGPKT_DATA_SIZE;i++)
+			{
+				DBG_871X("data=%x \t",newdata[i]);
+			}
+			if (ret == _FAIL) break;
+		}
+
+		offset++;
+	}
+
+	Efuse_PowerSwitch(padapter, _TRUE, _FALSE);
+
+exit:
+
+	rtw_mfree(map, mapLen);
+
+	return ret;
+}
+
+u8 rtw_efuse_mask_map_read(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+{
+	u8	ret = _SUCCESS;
+	u16	mapLen = 0, i = 0;
+	
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
+	
+	ret = rtw_efuse_map_read(padapter, addr, cnts , data);
+
+	if (padapter->registrypriv.boffefusemask == 0) {
+
+			for (i = 0; i < cnts; i++) { 
+				if (padapter->registrypriv.bFileMaskEfuse == _TRUE) {
+					if (rtw_file_efuse_IsMasked(padapter, addr+i)) /*use file efuse mask.*/ 
+							data[i] = 0xff;
+				} else {
+					/*DBG_8192C(" %s , data[%d] = %x\n", __func__, i, data[i]);*/
+					if (efuse_IsMasked(padapter, addr+i)) {
+						data[i] = 0xff;
+						/*DBG_8192C(" %s ,mask data[%d] = %x\n", __func__, i, data[i]);*/
+					}
+				}
+			}
+	
+	}
+	return ret;
+
+}
+
+u8 rtw_BT_efuse_map_write(PADAPTER padapter, u16 addr, u16 cnts, u8 *data)
+{
+#define RT_ASSERT_RET(expr)												\
+	if(!(expr)) {															\
+		printk( "Assertion failed! %s at ......\n", #expr);							\
+		printk( "      ......%s,%s,line=%d\n",__FILE__,__FUNCTION__,__LINE__);	\
+		return _FAIL;	\
+	}
+
+	u8	offset, word_en;
+	u8	*map;
+	u8	newdata[PGPKT_DATA_SIZE];
+	s32	i=0, j=0, idx;
+	u8	ret = _SUCCESS;
+	u16	mapLen=0;
+
+	EFUSE_GetEfuseDefinition(padapter, EFUSE_BT, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
+
+	if ((addr + cnts) > mapLen)
+		return _FAIL;
+
+	RT_ASSERT_RET(PGPKT_DATA_SIZE == 8); // have to be 8 byte alignment
+	RT_ASSERT_RET((mapLen & 0x7) == 0); // have to be PGPKT_DATA_SIZE alignment for memcpy
+
+	map = rtw_zmalloc(mapLen);
+	if(map == NULL){
+		return _FAIL;
+	}
+
+	ret = rtw_BT_efuse_map_read(padapter, 0, mapLen, map);
+	if (ret == _FAIL) goto exit;
+	DBG_871X("OFFSET\tVALUE(hex)\n");
+	for (i=0; i<1024; i+=16) // set 512 because the iwpriv's extra size have limit 0x7FF
+	{
+			DBG_871X("0x%03x\t", i);
+			for (j=0; j<8; j++) {
+				DBG_871X("%02X ", map[i+j]);
+			}
+			DBG_871X("\t");
+			for (; j<16; j++) {
+				DBG_871X("%02X ", map[i+j]);
+			}
+			DBG_871X("\n");
+	}
+	DBG_871X("\n");
+	Efuse_PowerSwitch(padapter, _TRUE, _TRUE);
+
+	idx = 0;
+	offset = (addr >> 3);
+	while (idx < cnts)
+	{
+		word_en = 0xF;
+		j = (addr + idx) & 0x7;
+		_rtw_memcpy(newdata, &map[offset << 3], PGPKT_DATA_SIZE);
+		for (i = j; i<PGPKT_DATA_SIZE && idx < cnts; i++, idx++)
+		{
+			if (data[idx] != map[addr + idx])
+			{
+				word_en &= ~BIT(i >> 1);
+				newdata[i] = data[idx];
+			}
+		}
+
+		if (word_en != 0xF) {
+			DBG_871X("offset=%x \n",offset);
+			DBG_871X("word_en=%x \n",word_en);
+			DBG_871X("%s: data=", __FUNCTION__);
+			for(i=0;i<PGPKT_DATA_SIZE;i++)
+			{
+				DBG_871X("0x%02X ", newdata[i]);
+			}
+			DBG_871X("\n");
+			ret = Efuse_PgPacketWrite_BT(padapter, offset, word_en, newdata, _FALSE);
+			if (ret == _FAIL) break;
+		}
+
+		offset++;
+	}
+
+	Efuse_PowerSwitch(padapter, _TRUE, _FALSE);
+
+exit:
+
+	rtw_mfree(map, mapLen);
+
+	return ret;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	Efuse_ReadAllMap
+ *
+ * Overview:	Read All Efuse content
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/11/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+VOID 
+Efuse_ReadAllMap(
+	IN		PADAPTER	pAdapter, 
+	IN		u8		efuseType,
+	IN OUT	u8		*Efuse,
+	IN		BOOLEAN		bPseudoTest);
+VOID 
+Efuse_ReadAllMap(
+	IN		PADAPTER	pAdapter, 
+	IN		u8		efuseType,
+	IN OUT	u8		*Efuse,
+	IN		BOOLEAN		bPseudoTest)
+{
+	u16	mapLen=0;
+
+	Efuse_PowerSwitch(pAdapter,_FALSE, _TRUE);
+
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, bPseudoTest);
+
+	efuse_ReadEFuse(pAdapter, efuseType, 0, mapLen, Efuse, bPseudoTest);
+
+	Efuse_PowerSwitch(pAdapter,_FALSE, _FALSE);
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	efuse_ShadowRead1Byte
+ *			efuse_ShadowRead2Byte
+ *			efuse_ShadowRead4Byte
+ *
+ * Overview:	Read from efuse init map by one/two/four bytes !!!!!
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/12/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+static VOID
+efuse_ShadowRead1Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN OUT	u8		*Value)
+{
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+
+	*Value = pHalData->efuse_eeprom_data[Offset];
+
+}	// EFUSE_ShadowRead1Byte
+
+//---------------Read Two Bytes
+static VOID
+efuse_ShadowRead2Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN OUT	u16		*Value)
+{
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+
+	*Value = pHalData->efuse_eeprom_data[Offset];
+	*Value |= pHalData->efuse_eeprom_data[Offset+1]<<8;
+
+}	// EFUSE_ShadowRead2Byte
+
+//---------------Read Four Bytes
+static VOID
+efuse_ShadowRead4Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN OUT	u32		*Value)
+{
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+
+	*Value = pHalData->efuse_eeprom_data[Offset];
+	*Value |= pHalData->efuse_eeprom_data[Offset+1]<<8;
+	*Value |= pHalData->efuse_eeprom_data[Offset+2]<<16;
+	*Value |= pHalData->efuse_eeprom_data[Offset+3]<<24;
+
+}	// efuse_ShadowRead4Byte
+
+
+/*-----------------------------------------------------------------------------
+ * Function:	efuse_ShadowWrite1Byte
+ *			efuse_ShadowWrite2Byte
+ *			efuse_ShadowWrite4Byte
+ *
+ * Overview:	Write efuse modify map by one/two/four byte.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/12/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+#ifdef PLATFORM
+static VOID
+efuse_ShadowWrite1Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN 	u8		Value);
+#endif //PLATFORM
+static VOID
+efuse_ShadowWrite1Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN 	u8		Value)
+{
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+
+	pHalData->efuse_eeprom_data[Offset] = Value;
+
+}	// efuse_ShadowWrite1Byte
+
+//---------------Write Two Bytes
+static VOID
+efuse_ShadowWrite2Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN 	u16		Value)
+{
+	
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+	
+
+	pHalData->efuse_eeprom_data[Offset] = Value&0x00FF;
+	pHalData->efuse_eeprom_data[Offset+1] = Value>>8;
+
+}	// efuse_ShadowWrite1Byte
+
+//---------------Write Four Bytes
+static VOID
+efuse_ShadowWrite4Byte(
+	IN	PADAPTER	pAdapter,
+	IN	u16		Offset,
+	IN	u32		Value)
+{
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+
+	pHalData->efuse_eeprom_data[Offset] = (u8)(Value&0x000000FF);
+	pHalData->efuse_eeprom_data[Offset+1] = (u8)((Value>>8)&0x0000FF);
+	pHalData->efuse_eeprom_data[Offset+2] = (u8)((Value>>16)&0x00FF);
+	pHalData->efuse_eeprom_data[Offset+3] = (u8)((Value>>24)&0xFF);
+
+}	// efuse_ShadowWrite1Byte
+
+/*-----------------------------------------------------------------------------
+ * Function:	EFUSE_ShadowMapUpdate
+ *
+ * Overview:	Transfer current EFUSE content to shadow init and modify map.
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/13/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void EFUSE_ShadowMapUpdate(
+	IN PADAPTER	pAdapter,
+	IN u8		efuseType,
+	IN BOOLEAN	bPseudoTest)
+{
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(pAdapter);
+	u16	mapLen=0;
+
+	EFUSE_GetEfuseDefinition(pAdapter, efuseType, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, bPseudoTest);
+
+	if (pHalData->bautoload_fail_flag == _TRUE)
+	{
+		_rtw_memset(pHalData->efuse_eeprom_data, 0xFF, mapLen);
+	}
+	else
+	{
+		#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE			
+		if(_SUCCESS != retriveAdaptorInfoFile(pAdapter->registrypriv.adaptor_info_caching_file_path, pHalData->efuse_eeprom_data)) {
+		#endif
+		
+		Efuse_ReadAllMap(pAdapter, efuseType, pHalData->efuse_eeprom_data, bPseudoTest);
+		
+		#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
+			storeAdaptorInfoFile(pAdapter->registrypriv.adaptor_info_caching_file_path, pHalData->efuse_eeprom_data);
+		}
+		#endif
+	}
+
+	//PlatformMoveMemory((PVOID)&pHalData->EfuseMap[EFUSE_MODIFY_MAP][0], 
+	//(PVOID)&pHalData->EfuseMap[EFUSE_INIT_MAP][0], mapLen);
+}// EFUSE_ShadowMapUpdate
+
+
+/*-----------------------------------------------------------------------------
+ * Function:	EFUSE_ShadowRead
+ *
+ * Overview:	Read from efuse init map !!!!!
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/12/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+void
+EFUSE_ShadowRead(
+	IN		PADAPTER	pAdapter,
+	IN		u8		Type,
+	IN		u16		Offset,
+	IN OUT	u32		*Value	)
+{
+	if (Type == 1)
+		efuse_ShadowRead1Byte(pAdapter, Offset, (u8 *)Value);
+	else if (Type == 2)
+		efuse_ShadowRead2Byte(pAdapter, Offset, (u16 *)Value);
+	else if (Type == 4)
+		efuse_ShadowRead4Byte(pAdapter, Offset, (u32 *)Value);
+	
+}	// EFUSE_ShadowRead
+
+/*-----------------------------------------------------------------------------
+ * Function:	EFUSE_ShadowWrite
+ *
+ * Overview:	Write efuse modify map for later update operation to use!!!!!
+ *
+ * Input:       NONE
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 11/12/2008 	MHC		Create Version 0.
+ *
+ *---------------------------------------------------------------------------*/
+VOID
+EFUSE_ShadowWrite(
+	IN	PADAPTER	pAdapter,
+	IN	u8		Type,
+	IN	u16		Offset,
+	IN OUT	u32		Value);
+VOID
+EFUSE_ShadowWrite(
+	IN	PADAPTER	pAdapter,
+	IN	u8		Type,
+	IN	u16		Offset,
+	IN OUT	u32		Value)
+{
+#if (MP_DRIVER == 0)
+	return;
+#endif
+	if ( pAdapter->registrypriv.mp_mode == 0)
+		return;
+
+
+	if (Type == 1)
+		efuse_ShadowWrite1Byte(pAdapter, Offset, (u8)Value);
+	else if (Type == 2)
+		efuse_ShadowWrite2Byte(pAdapter, Offset, (u16)Value);
+	else if (Type == 4)
+		efuse_ShadowWrite4Byte(pAdapter, Offset, (u32)Value);
+
+}	// EFUSE_ShadowWrite
+
+VOID
+Efuse_InitSomeVar(
+	IN		PADAPTER	pAdapter
+	);
+VOID
+Efuse_InitSomeVar(
+	IN		PADAPTER	pAdapter
+	)
+{
+	u8 i;
+	
+	_rtw_memset((PVOID)&fakeEfuseContent[0], 0xff, EFUSE_MAX_HW_SIZE);
+	_rtw_memset((PVOID)&fakeEfuseInitMap[0], 0xff, EFUSE_MAX_MAP_LEN);
+	_rtw_memset((PVOID)&fakeEfuseModifiedMap[0], 0xff, EFUSE_MAX_MAP_LEN);
+
+	for(i=0; i<EFUSE_MAX_BT_BANK; i++)
+	{
+		_rtw_memset((PVOID)&BTEfuseContent[i][0], EFUSE_MAX_HW_SIZE, 0xff);
+	}
+	_rtw_memset((PVOID)&BTEfuseInitMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
+	_rtw_memset((PVOID)&BTEfuseModifiedMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
+
+	for(i=0; i<EFUSE_MAX_BT_BANK; i++)
+	{
+		_rtw_memset((PVOID)&fakeBTEfuseContent[i][0], 0xff, EFUSE_MAX_HW_SIZE);
+	}
+	_rtw_memset((PVOID)&fakeBTEfuseInitMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
+	_rtw_memset((PVOID)&fakeBTEfuseModifiedMap[0], 0xff, EFUSE_BT_MAX_MAP_LEN);
+}
+
+const u8 _mac_hidden_max_bw_to_hal_bw_cap[MAC_HIDDEN_MAX_BW_NUM] = {
+	0,
+	0,
+	(BW_CAP_160M|BW_CAP_80M|BW_CAP_40M|BW_CAP_20M|BW_CAP_10M|BW_CAP_5M),
+	(BW_CAP_5M),
+	(BW_CAP_10M|BW_CAP_5M),
+	(BW_CAP_20M|BW_CAP_10M|BW_CAP_5M),
+	(BW_CAP_40M|BW_CAP_20M|BW_CAP_10M|BW_CAP_5M),
+	(BW_CAP_80M|BW_CAP_40M|BW_CAP_20M|BW_CAP_10M|BW_CAP_5M),
+};
+
+const u8 _mac_hidden_proto_to_hal_proto_cap[MAC_HIDDEN_PROTOCOL_NUM] = {
+	0,
+	0,
+	(PROTO_CAP_11N|PROTO_CAP_11G|PROTO_CAP_11B),
+	(PROTO_CAP_11AC|PROTO_CAP_11N|PROTO_CAP_11G|PROTO_CAP_11B),
+};
+
+u8 mac_hidden_wl_func_to_hal_wl_func(u8 func)
+{
+	u8 wl_func = 0;
+
+	if (func & BIT0)
+		wl_func |= WL_FUNC_MIRACAST;
+	if (func & BIT1)
+		wl_func |= WL_FUNC_P2P;
+	if (func & BIT2)
+		wl_func |= WL_FUNC_TDLS;
+	if (func & BIT3)
+		wl_func |= WL_FUNC_FTM;
+
+	return wl_func;
+}
+
+#ifdef PLATFORM_LINUX
+#ifdef CONFIG_ADAPTOR_INFO_CACHING_FILE
+//#include <rtw_eeprom.h>
+
+ int isAdaptorInfoFileValid(void)
+{
+	return _TRUE;
+}
+
+int storeAdaptorInfoFile(char *path, u8* efuse_data)
+{
+	int ret =_SUCCESS;
+
+	if(path && efuse_data) {
+		ret = rtw_store_to_file(path, efuse_data, EEPROM_MAX_SIZE_512);
+		if(ret == EEPROM_MAX_SIZE)
+			ret = _SUCCESS;
+		else
+			ret = _FAIL;
+	} else {
+		DBG_871X("%s NULL pointer\n",__FUNCTION__);
+		ret =  _FAIL;
+	}
+	return ret;
+}
+
+int retriveAdaptorInfoFile(char *path, u8* efuse_data)
+{
+	int ret = _SUCCESS;
+	mm_segment_t oldfs;
+	struct file *fp;
+	
+	if(path && efuse_data) {
+
+		ret = rtw_retrieve_from_file(path, efuse_data, EEPROM_MAX_SIZE);
+		
+		if(ret == EEPROM_MAX_SIZE)
+			ret = _SUCCESS;
+		else
+			ret = _FAIL;
+
+		#if 0
+		if(isAdaptorInfoFileValid()) {	
+			return 0;
+		} else {
+			return _FAIL;
+		}
+		#endif
+		
+	} else {
+		DBG_871X("%s NULL pointer\n",__FUNCTION__);
+		ret = _FAIL;
+	}
+	return ret;
+}
+#endif /* CONFIG_ADAPTOR_INFO_CACHING_FILE */
+
+#ifdef CONFIG_EFUSE_CONFIG_FILE
+u32 rtw_read_efuse_from_file(const char *path, u8 *buf)
+{
+	u32 i;
+	u8 temp[3];
+	u32 ret = _FAIL;
+
+	struct file *fp;
+	mm_segment_t fs;
+	loff_t pos = 0;
+
+	fp = filp_open(path, O_RDONLY, 0);
+	if (fp == NULL || IS_ERR(fp)) {
+		if (fp != NULL)
+			DBG_871X_LEVEL(_drv_always_, "%s open %s fail, err:%ld\n"
+				, __func__, path, PTR_ERR(fp));
+		else
+			DBG_871X_LEVEL(_drv_always_, "%s open %s fail, fp is NULL\n"
+				, __func__, path);
+
+		goto exit;
+	}
+
+	temp[2] = 0; /* add end of string '\0' */
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	for (i = 0 ; i < HWSET_MAX_SIZE ; i++) {
+		vfs_read(fp, temp, 2, &pos);
+		if (sscanf(temp, "%hhx", &buf[i]) != 1) {
+			if (0)
+				DBG_871X_LEVEL(_drv_err_, "%s sscanf fail\n", __func__);
+			buf[i] = 0xFF;
+		}
+		if ((i % EFUSE_FILE_COLUMN_NUM) == (EFUSE_FILE_COLUMN_NUM - 1)) {
+			/* Filter the lates space char. */
+			vfs_read(fp, temp, 1, &pos);
+			if (strchr(temp, ' ') == NULL) {
+				pos--;
+				vfs_read(fp, temp, 2, &pos);
+			}
+		} else {
+			pos += 1; /* Filter the space character */
+		}
+	}
+
+	set_fs(fs);
+
+	DBG_871X_LEVEL(_drv_always_, "efuse file: %s\n", path);
+#ifdef CONFIG_DEBUG
+	for (i = 0; i < HWSET_MAX_SIZE; i++) {
+		if (i % 16 == 0)
+			DBG_871X_SEL_NL(RTW_DBGDUMP, "0x%03x: ", i);
+
+		DBG_871X_SEL(RTW_DBGDUMP, "%02X%s"
+			, buf[i]
+			, ((i + 1) % 16 == 0) ? "\n" : (((i + 1) % 8 == 0) ? "    " : " ")
+		);
+	}
+	DBG_871X_SEL(RTW_DBGDUMP, "\n");
+#endif
+
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+
+u32 rtw_read_macaddr_from_file(const char *path, u8 *buf)
+{
+	struct file *fp;
+	mm_segment_t fs;
+	loff_t pos = 0;
+
+	u8 source_addr[18];
+	u8 *head, *end;
+	int i;
+	u32 ret = _FAIL;
+
+	_rtw_memset(source_addr, 0, 18);
+
+	fp = filp_open(path, O_RDONLY, 0);
+	if (fp == NULL || IS_ERR(fp)) {
+		if (fp != NULL)
+			DBG_871X_LEVEL(_drv_always_, "%s open %s fail, err:%ld\n"
+				, __func__, path, PTR_ERR(fp));
+		else
+			DBG_871X_LEVEL(_drv_always_, "%s open %s fail, fp is NULL\n"
+				, __func__, path);
+
+		goto exit;
+	}
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	vfs_read(fp, source_addr, 18, &pos);
+	source_addr[17] = ':';
+
+	head = end = source_addr;
+	for (i = 0; i < ETH_ALEN; i++) {
+		while (end && (*end != ':'))
+			end++;
+
+		if (end && (*end == ':'))
+			*end = '\0';
+
+		if (sscanf(head, "%hhx", &buf[i]) != 1) {
+			if (0)
+				DBG_871X_LEVEL(_drv_err_, "%s sscanf fail\n", __func__);
+			buf[i] = 0xFF;
+		}
+
+		if (end) {
+			end++;
+			head = end;
+		}
+	}
+
+	set_fs(fs);
+
+	DBG_871X_LEVEL(_drv_always_, "wifi_mac file: %s\n", path);
+#ifdef CONFIG_DEBUG
+	DBG_871X(MAC_FMT"\n", MAC_ARG(buf));
+#endif
+
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+#endif /* CONFIG_EFUSE_CONFIG_FILE */
+
+#endif /* PLATFORM_LINUX */
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ap.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ap.c
new file mode 100644
index 000000000..0af96bf73
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ap.c
@@ -0,0 +1,4224 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_AP_C_
+
+#include <drv_types.h>
+
+
+#ifdef CONFIG_AP_MODE
+
+extern unsigned char	RTW_WPA_OUI[];
+extern unsigned char 	WMM_OUI[];
+extern unsigned char	WPS_OUI[];
+extern unsigned char	P2P_OUI[];
+extern unsigned char	WFD_OUI[];
+
+void init_mlme_ap_info(_adapter *padapter)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;	
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+	
+
+	_rtw_spinlock_init(&pmlmepriv->bcn_update_lock);	
+
+	//for ACL 
+	_rtw_init_queue(&pacl_list->acl_node_q);
+
+	//pmlmeext->bstart_bss = _FALSE;
+
+	start_ap_mode(padapter);
+}
+
+void free_mlme_ap_info(_adapter *padapter)
+{
+	_irqL irqL;
+	struct sta_info *psta=NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	//stop_ap_mode(padapter);
+
+	pmlmepriv->update_bcn = _FALSE;
+	pmlmeext->bstart_bss = _FALSE;	
+	
+	rtw_sta_flush(padapter, _TRUE);
+
+	pmlmeinfo->state = _HW_STATE_NOLINK_;
+
+	//free_assoc_sta_resources
+	rtw_free_all_stainfo(padapter);
+
+	//free bc/mc sta_info
+	psta = rtw_get_bcmc_stainfo(padapter);	
+	//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+	rtw_free_stainfo(padapter, psta);
+	//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+	
+
+	_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
+	
+}
+
+static void update_BCNTIM(_adapter *padapter)
+{
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
+	unsigned char *pie = pnetwork_mlmeext->IEs;
+
+/*
+	//DBG_871X("%s\n", __FUNCTION__);
+	
+	//update TIM IE
+	//if(pstapriv->tim_bitmap)
+*/
+	if (_TRUE) {
+		u8 *p, *dst_ie, *premainder_ie = NULL, *pbackup_remainder_ie = NULL;
+		u16 tim_bitmap_le;
+		uint offset, tmp_len, tim_ielen, tim_ie_offset, remainder_ielen;	
+	
+		tim_bitmap_le = cpu_to_le16(pstapriv->tim_bitmap);
+
+		p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, _TIM_IE_, &tim_ielen, pnetwork_mlmeext->IELength - _FIXED_IE_LENGTH_);
+		if (p != NULL && tim_ielen > 0) {
+			tim_ielen += 2;
+			
+			premainder_ie = p + tim_ielen;
+
+			tim_ie_offset = (sint)(p -pie);
+			
+			remainder_ielen = pnetwork_mlmeext->IELength - tim_ie_offset - tim_ielen;
+
+			/*append TIM IE from dst_ie offset*/
+			dst_ie = p;
+		} else {
+			tim_ielen = 0;
+
+			/*calculate head_len*/
+			offset = _FIXED_IE_LENGTH_;
+
+			/* get ssid_ie len */
+			p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SSID_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));
+			if (p != NULL)
+				offset += tmp_len+2;
+
+			/*get supported rates len*/
+			p = rtw_get_ie(pie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &tmp_len, (pnetwork_mlmeext->IELength - _BEACON_IE_OFFSET_));	
+			if (p !=  NULL) 
+			{			
+				offset += tmp_len+2;
+			}
+
+			/*DS Parameter Set IE, len=3*/
+			offset += 3;
+
+			premainder_ie = pie + offset;
+
+			remainder_ielen = pnetwork_mlmeext->IELength - offset - tim_ielen;	
+
+			/*append TIM IE from offset*/
+			dst_ie = pie + offset;
+			
+		}
+		
+		if (remainder_ielen > 0) {
+			pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+			if(pbackup_remainder_ie && premainder_ie)
+				_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+		}		
+		
+		*dst_ie++=_TIM_IE_;
+
+		if ((pstapriv->tim_bitmap&0xff00) && (pstapriv->tim_bitmap&0x00fe))			
+			tim_ielen = 5;
+		else
+			tim_ielen = 4;
+
+		*dst_ie++ = tim_ielen;
+		
+		*dst_ie++ = 0;/*DTIM count*/
+		*dst_ie++ = 1;/*DTIM period*/
+		
+		if (pstapriv->tim_bitmap & BIT(0))/*for bc/mc frames*/
+			*dst_ie++ = BIT(0);/*bitmap ctrl */
+		else
+			*dst_ie++ = 0;
+
+		if (tim_ielen == 4) {
+			u8 pvb = 0;
+			
+			if (pstapriv->tim_bitmap & 0x00fe)
+				pvb = (u8)tim_bitmap_le;
+			else if (pstapriv->tim_bitmap & 0xff00)			
+				pvb = (u8)(tim_bitmap_le >> 8);
+			else
+				pvb = (u8)tim_bitmap_le;
+
+			*dst_ie++ = pvb;
+			
+		} else if (tim_ielen == 5) {
+			_rtw_memcpy(dst_ie, &tim_bitmap_le, 2);
+			dst_ie += 2;				
+		}	
+		
+		/*copy remainder IE*/
+		if (pbackup_remainder_ie) {
+			_rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+			rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+		}	
+
+		offset =  (uint)(dst_ie - pie);
+		pnetwork_mlmeext->IELength = offset + remainder_ielen;
+	
+	}
+}
+
+void rtw_add_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index, u8 *data, u8 len)
+{
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8	bmatch = _FALSE;
+	u8	*pie = pnetwork->IEs;
+	u8	*p=NULL, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+	u32	i, offset, ielen, ie_offset, remainder_ielen = 0;
+
+	for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pnetwork->IELength;)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
+
+		if (pIE->ElementID > index)
+		{
+			break;
+		}
+		else if(pIE->ElementID == index) // already exist the same IE
+		{
+			p = (u8 *)pIE;
+			ielen = pIE->Length;
+			bmatch = _TRUE;
+			break;
+		}
+
+		p = (u8 *)pIE;
+		ielen = pIE->Length;
+		i += (pIE->Length + 2);
+	}
+
+	if (p != NULL && ielen>0)
+	{
+		ielen += 2;
+		
+		premainder_ie = p+ielen;
+
+		ie_offset = (sint)(p -pie);
+		
+		remainder_ielen = pnetwork->IELength - ie_offset - ielen;
+
+		if(bmatch)
+			dst_ie = p;
+		else
+			dst_ie = (p+ielen);
+	}
+
+	if(dst_ie == NULL)
+		return;
+
+	if(remainder_ielen>0)
+	{
+		pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+		if(pbackup_remainder_ie && premainder_ie)
+			_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+	}
+
+	*dst_ie++=index;
+	*dst_ie++=len;
+
+	_rtw_memcpy(dst_ie, data, len);
+	dst_ie+=len;
+
+	//copy remainder IE
+	if(pbackup_remainder_ie)
+	{
+		_rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+		rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+	}
+
+	offset =  (uint)(dst_ie - pie);
+	pnetwork->IELength = offset + remainder_ielen;
+}
+
+void rtw_remove_bcn_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 index)
+{
+	u8 *p, *dst_ie=NULL, *premainder_ie=NULL, *pbackup_remainder_ie=NULL;
+	uint offset, ielen, ie_offset, remainder_ielen = 0;
+	u8	*pie = pnetwork->IEs;
+
+	p = rtw_get_ie(pie + _FIXED_IE_LENGTH_, index, &ielen, pnetwork->IELength - _FIXED_IE_LENGTH_);
+	if (p != NULL && ielen>0)
+	{
+		ielen += 2;
+		
+		premainder_ie = p+ielen;
+
+		ie_offset = (sint)(p -pie);
+		
+		remainder_ielen = pnetwork->IELength - ie_offset - ielen;
+
+		dst_ie = p;
+	}
+	else {
+		return;
+	}
+
+	if(remainder_ielen>0)
+	{
+		pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+		if(pbackup_remainder_ie && premainder_ie)
+			_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+	}
+
+	//copy remainder IE
+	if(pbackup_remainder_ie)
+	{
+		_rtw_memcpy(dst_ie, pbackup_remainder_ie, remainder_ielen);
+
+		rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+	}
+
+	offset =  (uint)(dst_ie - pie);
+	pnetwork->IELength = offset + remainder_ielen;
+}
+
+
+u8 chk_sta_is_alive(struct sta_info *psta);
+u8 chk_sta_is_alive(struct sta_info *psta)
+{
+	u8 ret = _FALSE;
+	#ifdef DBG_EXPIRATION_CHK
+	DBG_871X("sta:"MAC_FMT", rssi:%d, rx:"STA_PKTS_FMT", expire_to:%u, %s%ssq_len:%u\n"
+		, MAC_ARG(psta->hwaddr)
+		, psta->rssi_stat.UndecoratedSmoothedPWDB
+		//, STA_RX_PKTS_ARG(psta)
+		, STA_RX_PKTS_DIFF_ARG(psta)
+		, psta->expire_to
+		, psta->state&WIFI_SLEEP_STATE?"PS, ":""
+		, psta->state&WIFI_STA_ALIVE_CHK_STATE?"SAC, ":""
+		, psta->sleepq_len
+	);
+	#endif
+
+	//if(sta_last_rx_pkts(psta) == sta_rx_pkts(psta))
+	if((psta->sta_stats.last_rx_data_pkts + psta->sta_stats.last_rx_ctrl_pkts) == (psta->sta_stats.rx_data_pkts + psta->sta_stats.rx_ctrl_pkts))
+	{
+		#if 0
+		if(psta->state&WIFI_SLEEP_STATE)
+			ret = _TRUE;
+		#endif
+	}
+	else
+	{
+		ret = _TRUE;
+	}
+
+	sta_update_last_rx_pkts(psta);
+
+	return ret;
+}
+
+void	expire_timeout_chk(_adapter *padapter)
+{
+	_irqL irqL;
+	_list	*phead, *plist;
+	u8 updated = _FALSE;
+	struct sta_info *psta=NULL;	
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 chk_alive_num = 0;
+	char chk_alive_list[NUM_STA];
+	int i;
+
+
+	_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+	
+	phead = &pstapriv->auth_list;
+	plist = get_next(phead);
+	
+	//check auth_queue
+	#ifdef DBG_EXPIRATION_CHK
+	if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+		DBG_871X(FUNC_NDEV_FMT" auth_list, cnt:%u\n"
+			, FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->auth_list_cnt);
+	}
+	#endif
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)	
+	{
+		psta = LIST_CONTAINOR(plist, struct sta_info, auth_list);
+
+		plist = get_next(plist);
+
+
+#ifdef CONFIG_ATMEL_RC_PATCH
+		if (_TRUE == _rtw_memcmp((void *)(pstapriv->atmel_rc_pattern), (void *)(psta->hwaddr), ETH_ALEN))
+			continue;
+		if (psta->flag_atmel_rc)
+			continue;
+#endif
+		if(psta->expire_to>0)
+		{
+			psta->expire_to--;
+			if (psta->expire_to == 0)
+			{
+				rtw_list_delete(&psta->auth_list);
+				pstapriv->auth_list_cnt--;
+				
+				DBG_871X("auth expire %02X%02X%02X%02X%02X%02X\n",
+					psta->hwaddr[0],psta->hwaddr[1],psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]);
+				
+				_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
+				
+				//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);	
+				rtw_free_stainfo(padapter, psta);
+				//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);	
+				
+				_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+			}	
+		}	
+		
+	}
+
+	_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
+	psta = NULL;
+	
+
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+
+	//check asoc_queue
+	#ifdef DBG_EXPIRATION_CHK
+	if (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+		DBG_871X(FUNC_NDEV_FMT" asoc_list, cnt:%u\n"
+			, FUNC_NDEV_ARG(padapter->pnetdev), pstapriv->asoc_list_cnt);
+	}
+	#endif
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		plist = get_next(plist);
+#ifdef CONFIG_ATMEL_RC_PATCH
+		DBG_871X("%s:%d  psta=%p, %02x,%02x||%02x,%02x  \n\n", __func__,  __LINE__,
+			psta,pstapriv->atmel_rc_pattern[0], pstapriv->atmel_rc_pattern[5], psta->hwaddr[0], psta->hwaddr[5]);
+		if (_TRUE == _rtw_memcmp((void *)pstapriv->atmel_rc_pattern, (void *)(psta->hwaddr), ETH_ALEN))
+			continue;		
+		if (psta->flag_atmel_rc)
+			continue;
+		DBG_871X("%s: debug line:%d \n", __func__, __LINE__);
+#endif
+#ifdef CONFIG_AUTO_AP_MODE
+		if(psta->isrc)
+			continue;
+#endif
+		if (chk_sta_is_alive(psta) || !psta->expire_to) {
+			psta->expire_to = pstapriv->expire_to;
+			psta->keep_alive_trycnt = 0;
+			#ifdef CONFIG_TX_MCAST2UNI
+			psta->under_exist_checking = 0;
+			#endif	// CONFIG_TX_MCAST2UNI
+		} else {
+			psta->expire_to--;
+		}
+
+#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+#ifdef CONFIG_80211N_HT
+#ifdef CONFIG_TX_MCAST2UNI
+		if ( (psta->flags & WLAN_STA_HT) && (psta->htpriv.agg_enable_bitmap || psta->under_exist_checking) ) {
+			// check sta by delba(addba) for 11n STA 
+			// ToDo: use CCX report to check for all STAs
+			//DBG_871X("asoc check by DELBA/ADDBA! (pstapriv->expire_to=%d s)(psta->expire_to=%d s), [%02x, %d]\n", pstapriv->expire_to*2, psta->expire_to*2, psta->htpriv.agg_enable_bitmap, psta->under_exist_checking);
+			
+				if ( psta->expire_to <= (pstapriv->expire_to - 50 ) ) {
+				DBG_871X("asoc expire by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
+				psta->under_exist_checking = 0;
+				psta->expire_to = 0;
+			} else if ( psta->expire_to <= (pstapriv->expire_to - 3) && (psta->under_exist_checking==0)) {
+				DBG_871X("asoc check by DELBA/ADDBA! (%d s)\n", (pstapriv->expire_to-psta->expire_to)*2);
+				psta->under_exist_checking = 1;
+				//tear down TX AMPDU
+				send_delba(padapter, 1, psta->hwaddr);// // originator
+				psta->htpriv.agg_enable_bitmap = 0x0;//reset
+				psta->htpriv.candidate_tid_bitmap = 0x0;//reset
+			}
+		}
+#endif //CONFIG_TX_MCAST2UNI
+#endif //CONFIG_80211N_HT
+#endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+
+		if (psta->expire_to <= 0)
+		{
+			struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+			if (padapter->registrypriv.wifi_spec == 1)
+			{
+				psta->expire_to = pstapriv->expire_to;
+				continue;
+			}
+
+#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+#ifdef CONFIG_80211N_HT
+
+#define KEEP_ALIVE_TRYCNT (3)
+
+			if(psta->keep_alive_trycnt > 0 && psta->keep_alive_trycnt <= KEEP_ALIVE_TRYCNT)
+			{				
+				if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
+					psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+				else
+					psta->keep_alive_trycnt = 0;
+				
+			}
+			else if((psta->keep_alive_trycnt > KEEP_ALIVE_TRYCNT) && !(psta->state & WIFI_STA_ALIVE_CHK_STATE))
+			{
+				psta->keep_alive_trycnt = 0;
+			}			
+			if((psta->htpriv.ht_option==_TRUE) && (psta->htpriv.ampdu_enable==_TRUE)) 
+			{
+				uint priority = 1; //test using BK
+				u8 issued=0;				
+		
+				//issued = (psta->htpriv.agg_enable_bitmap>>priority)&0x1;
+				issued |= (psta->htpriv.candidate_tid_bitmap>>priority)&0x1;
+
+				if(0==issued)
+				{
+					if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE))
+					{
+						psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
+
+						if (psta->state & WIFI_SLEEP_STATE) 
+							psta->expire_to = 2; // 2x2=4 sec
+						else
+							psta->expire_to = 1; // 2 sec
+					
+						psta->state |= WIFI_STA_ALIVE_CHK_STATE;
+					
+						//add_ba_hdl(padapter, (u8*)paddbareq_parm);
+
+						DBG_871X("issue addba_req to check if sta alive, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
+
+						issue_addba_req(padapter, psta->hwaddr, (u8)priority);
+		
+						_set_timer(&psta->addba_retry_timer, ADDBA_TO);
+						
+						psta->keep_alive_trycnt++;						
+
+						continue;
+					}			
+				}					
+			}
+			if(psta->keep_alive_trycnt > 0 && psta->state & WIFI_STA_ALIVE_CHK_STATE)
+			{
+				psta->keep_alive_trycnt = 0;
+				psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+				DBG_871X("change to another methods to check alive if staion is at ps mode\n");
+			}	
+			
+#endif //CONFIG_80211N_HT
+#endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK	
+			if (psta->state & WIFI_SLEEP_STATE) {
+				if (!(psta->state & WIFI_STA_ALIVE_CHK_STATE)) {
+					//to check if alive by another methods if staion is at ps mode.					
+					psta->expire_to = pstapriv->expire_to;
+					psta->state |= WIFI_STA_ALIVE_CHK_STATE;
+
+					//DBG_871X("alive chk, sta:" MAC_FMT " is at ps mode!\n", MAC_ARG(psta->hwaddr));
+
+					//to update bcn with tim_bitmap for this station
+					pstapriv->tim_bitmap |= BIT(psta->aid);
+					update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
+
+					if(!pmlmeext->active_keep_alive_check)
+						continue;
+				}
+			}
+			#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+			if (pmlmeext->active_keep_alive_check) {
+				int stainfo_offset;
+
+				stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+				if (stainfo_offset_valid(stainfo_offset)) {
+					chk_alive_list[chk_alive_num++] = stainfo_offset;
+				}
+
+				continue;
+			}
+			#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
+			rtw_list_delete(&psta->asoc_list);
+			pstapriv->asoc_list_cnt--;
+			DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+			updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);
+		}	
+		else
+		{
+			/* TODO: Aging mechanism to digest frames in sleep_q to avoid running out of xmitframe */
+			if (psta->sleepq_len > (NR_XMITFRAME/pstapriv->asoc_list_cnt)
+				&& padapter->xmitpriv.free_xmitframe_cnt < ((NR_XMITFRAME/pstapriv->asoc_list_cnt)/2)
+			){
+				DBG_871X("%s sta:"MAC_FMT", sleepq_len:%u, free_xmitframe_cnt:%u, asoc_list_cnt:%u, clear sleep_q\n", __func__
+					, MAC_ARG(psta->hwaddr)
+					, psta->sleepq_len, padapter->xmitpriv.free_xmitframe_cnt, pstapriv->asoc_list_cnt);
+				wakeup_sta_to_xmit(padapter, psta);
+			}
+		}
+	}
+
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+if (chk_alive_num) {
+
+	u8 backup_oper_channel=0;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	/* switch to correct channel of current network  before issue keep-alive frames */
+	if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
+		backup_oper_channel = rtw_get_oper_ch(padapter);
+		SelectChannel(padapter, pmlmeext->cur_channel);
+	}
+
+	/* issue null data to check sta alive*/
+	for (i = 0; i < chk_alive_num; i++) {
+		int ret = _FAIL;
+
+		psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
+#ifdef CONFIG_ATMEL_RC_PATCH
+		if (_TRUE == _rtw_memcmp(  pstapriv->atmel_rc_pattern, psta->hwaddr, ETH_ALEN))
+			continue;
+		if (psta->flag_atmel_rc)
+			continue;
+#endif
+		if(!(psta->state &_FW_LINKED))
+			continue;		
+	
+		if (psta->state & WIFI_SLEEP_STATE)
+			ret = issue_nulldata(padapter, psta->hwaddr, 0, 1, 50);
+		else
+			ret = issue_nulldata(padapter, psta->hwaddr, 0, 3, 50);
+
+		psta->keep_alive_trycnt++;
+		if (ret == _SUCCESS)
+		{
+			DBG_871X("asoc check, sta(" MAC_FMT ") is alive\n", MAC_ARG(psta->hwaddr));
+			psta->expire_to = pstapriv->expire_to;
+			psta->keep_alive_trycnt = 0;
+			continue;
+		}
+		else if (psta->keep_alive_trycnt <= 3)
+		{
+			DBG_871X("ack check for asoc expire, keep_alive_trycnt=%d\n", psta->keep_alive_trycnt);
+			psta->expire_to = 1;
+			continue;
+		}
+
+		psta->keep_alive_trycnt = 0;
+		DBG_871X("asoc expire "MAC_FMT", state=0x%x\n", MAC_ARG(psta->hwaddr), psta->state);
+		_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+		if (rtw_is_list_empty(&psta->asoc_list)==_FALSE) {
+			rtw_list_delete(&psta->asoc_list);
+			pstapriv->asoc_list_cnt--;
+			updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_DEAUTH_LEAVING, _TRUE);
+		}
+		_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	}
+
+	if (backup_oper_channel>0) /* back to the original operation channel */
+		SelectChannel(padapter, backup_oper_channel);
+}
+#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
+
+	associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
+}
+
+void add_RATid(_adapter *padapter, struct sta_info *psta, u8 rssi_level)
+{	
+	int i;
+	u8 rf_type;
+	unsigned char sta_band = 0, shortGIrate = _FALSE;
+	u64 tx_ra_bitmap = 0;
+	struct ht_priv	*psta_ht = NULL;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+
+#ifdef CONFIG_80211N_HT
+	if(psta)
+		psta_ht = &psta->htpriv;
+	else
+		return;
+#endif //CONFIG_80211N_HT
+
+	if(!(psta->state & _FW_LINKED))
+		return;
+
+#if 0//gtest
+	if(get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)
+	{
+		//is this a 2r STA?
+		if((pstat->tx_ra_bitmap & 0x0ff00000) != 0 && !(priv->pshare->has_2r_sta & BIT(pstat->aid)))
+		{
+			priv->pshare->has_2r_sta |= BIT(pstat->aid);
+			if(rtw_read16(padapter, 0x102501f6) != 0xffff)
+			{
+				rtw_write16(padapter, 0x102501f6, 0xffff);
+				reset_1r_sta_RA(priv, 0xffff);
+				Switch_1SS_Antenna(priv, 3);
+			}
+		}
+		else// bg or 1R STA? 
+		{ 
+			if((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len && priv->pshare->has_2r_sta == 0)
+			{
+				if(rtw_read16(padapter, 0x102501f6) != 0x7777)
+				{ // MCS7 SGI
+					rtw_write16(padapter, 0x102501f6,0x7777);
+					reset_1r_sta_RA(priv, 0x7777);
+					Switch_1SS_Antenna(priv, 2);
+				}
+			}
+		}
+		
+	}
+
+	if ((pstat->rssi_level < 1) || (pstat->rssi_level > 3)) 
+	{
+		if (pstat->rssi >= priv->pshare->rf_ft_var.raGoDownUpper)
+			pstat->rssi_level = 1;
+		else if ((pstat->rssi >= priv->pshare->rf_ft_var.raGoDown20MLower) ||
+			((priv->pshare->is_40m_bw) && (pstat->ht_cap_len) &&
+			(pstat->rssi >= priv->pshare->rf_ft_var.raGoDown40MLower) &&
+			(pstat->ht_cap_buf.ht_cap_info & cpu_to_le16(_HTCAP_SUPPORT_CH_WDTH_))))
+			pstat->rssi_level = 2;
+		else
+			pstat->rssi_level = 3;
+	}
+
+	// rate adaptive by rssi
+	if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && pstat->ht_cap_len)
+	{
+		if ((get_rf_mimo_mode(priv) == MIMO_1T2R) || (get_rf_mimo_mode(priv) == MIMO_1T1R))
+		{
+			switch (pstat->rssi_level) {
+				case 1:
+					pstat->tx_ra_bitmap &= 0x100f0000;
+					break;
+				case 2:
+					pstat->tx_ra_bitmap &= 0x100ff000;
+					break;
+				case 3:
+					if (priv->pshare->is_40m_bw)
+						pstat->tx_ra_bitmap &= 0x100ff005;
+					else
+						pstat->tx_ra_bitmap &= 0x100ff001;
+
+					break;
+			}
+		}
+		else 
+		{
+			switch (pstat->rssi_level) {
+				case 1:
+					pstat->tx_ra_bitmap &= 0x1f0f0000;
+					break;
+				case 2:
+					pstat->tx_ra_bitmap &= 0x1f0ff000;
+					break;
+				case 3:
+					if (priv->pshare->is_40m_bw)
+						pstat->tx_ra_bitmap &= 0x000ff005;
+					else
+						pstat->tx_ra_bitmap &= 0x000ff001;
+
+					break;
+			}
+
+			// Don't need to mask high rates due to new rate adaptive parameters
+			//if (pstat->is_broadcom_sta)		// use MCS12 as the highest rate vs. Broadcom sta
+			//	pstat->tx_ra_bitmap &= 0x81ffffff;
+
+			// NIC driver will report not supporting MCS15 and MCS14 in asoc req
+			//if (pstat->is_rtl8190_sta && !pstat->is_2t_mimo_sta)
+			//	pstat->tx_ra_bitmap &= 0x83ffffff;		// if Realtek 1x2 sta, don't use MCS15 and MCS14
+		}
+	}
+	else if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) && isErpSta(pstat))
+	{
+		switch (pstat->rssi_level) {
+			case 1:
+				pstat->tx_ra_bitmap &= 0x00000f00;
+				break;
+			case 2:
+				pstat->tx_ra_bitmap &= 0x00000ff0;
+				break;
+			case 3:
+				pstat->tx_ra_bitmap &= 0x00000ff5;
+				break;
+		}
+	}
+	else 
+	{
+		pstat->tx_ra_bitmap &= 0x0000000d;
+	}
+
+	// disable tx short GI when station cannot rx MCS15(AP is 2T2R)
+	// disable tx short GI when station cannot rx MCS7 (AP is 1T2R or 1T1R)
+	// if there is only 1r STA and we are 2T2R, DO NOT mask SGI rate
+	if ((!(pstat->tx_ra_bitmap & 0x8000000) && (priv->pshare->has_2r_sta > 0) && (get_rf_mimo_mode(padapter) == RTL8712_RF_2T2R)) ||
+		 (!(pstat->tx_ra_bitmap & 0x80000) && (get_rf_mimo_mode(padapter) != RTL8712_RF_2T2R)))
+	{
+		pstat->tx_ra_bitmap &= ~BIT(28);	
+	}
+#endif
+
+	rtw_hal_update_sta_rate_mask(padapter, psta);
+	tx_ra_bitmap = psta->ra_mask;
+
+	shortGIrate = query_ra_short_GI(psta);
+
+	if ( pcur_network->Configuration.DSConfig > 14 ) {
+		
+		if (tx_ra_bitmap & 0xffff000)
+			sta_band |= WIRELESS_11_5N ;
+
+		if (tx_ra_bitmap & 0xff0)
+			sta_band |= WIRELESS_11A;
+
+		// 5G band
+		#ifdef CONFIG_80211AC_VHT
+		if (psta->vhtpriv.vht_option)  {
+			sta_band = WIRELESS_11_5AC;
+		}		
+		#endif
+		
+	} else {
+		if (tx_ra_bitmap & 0xffff000)
+			sta_band |= WIRELESS_11_24N;
+
+		if (tx_ra_bitmap & 0xff0)
+			sta_band |= WIRELESS_11G;
+
+		if (tx_ra_bitmap & 0x0f)
+			sta_band |= WIRELESS_11B;
+	}
+
+	psta->wireless_mode = sta_band;
+	psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
+	
+	if (psta->aid < NUM_STA)
+	{
+		u8	arg[4] = {0};
+
+		arg[0] = psta->mac_id;
+		arg[1] = psta->raid;
+		arg[2] = shortGIrate;
+		arg[3] = psta->init_rate;
+
+		DBG_871X("%s=> mac_id:%d , raid:%d , shortGIrate=%d, tx_ra_bitmap:0x%016llx, networkType:0x%02x\n", 
+			__FUNCTION__, psta->mac_id, psta->raid, shortGIrate, tx_ra_bitmap, psta->wireless_mode);
+			
+		rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, rssi_level);
+	}
+	else 
+	{
+		DBG_871X("station aid %d exceed the max number\n", psta->aid);
+	}
+
+}
+
+void update_bmc_sta(_adapter *padapter)
+{
+	_irqL	irqL;
+	unsigned char	network_type;
+	int supportRateNum = 0;
+	u64 tx_ra_bitmap = 0;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);	
+	WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;	
+	struct sta_info *psta = rtw_get_bcmc_stainfo(padapter);
+
+	if(psta)
+	{
+		psta->aid = 0;//default set to 0
+
+		pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+		psta->qos_option = 0;
+#ifdef CONFIG_80211N_HT	
+		psta->htpriv.ht_option = _FALSE;
+#endif //CONFIG_80211N_HT
+
+		psta->ieee8021x_blocked = 0;
+
+		_rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+		//psta->dot118021XPrivacy = _NO_PRIVACY_;//!!! remove it, because it has been set before this.
+
+		//prepare for add_RATid		
+		supportRateNum = rtw_get_rateset_len((u8*)&pcur_network->SupportedRates);
+		network_type = rtw_check_network_type((u8*)&pcur_network->SupportedRates, supportRateNum, pcur_network->Configuration.DSConfig);
+		if (IsSupportedTxCCK(network_type)) {
+			network_type = WIRELESS_11B;
+		}
+		else if (network_type == WIRELESS_INVALID) { // error handling
+			if ( pcur_network->Configuration.DSConfig > 14 )
+				network_type = WIRELESS_11A;
+			else
+				network_type = WIRELESS_11B;
+		}
+		update_sta_basic_rate(psta, network_type);
+		psta->wireless_mode = network_type;
+
+		rtw_hal_update_sta_rate_mask(padapter, psta);
+		tx_ra_bitmap = psta->ra_mask;
+
+		psta->raid = rtw_hal_networktype_to_raid(padapter,psta);
+
+		//ap mode
+		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
+
+		//if(pHalData->fw_ractrl == _TRUE)
+		{
+			u8	arg[4] = {0};
+
+			arg[0] = psta->mac_id;
+			arg[1] = psta->raid;
+			arg[2] = 0;
+			arg[3] = psta->init_rate;
+
+			DBG_871X("%s=> mac_id:%d , raid:%d , bitmap=0x%016llx\n", 
+				__FUNCTION__ , psta->mac_id, psta->raid , tx_ra_bitmap);
+
+			rtw_hal_add_ra_tid(padapter, tx_ra_bitmap, arg, 0);
+		}
+
+		rtw_sta_media_status_rpt(padapter, psta, 1);
+
+		_enter_critical_bh(&psta->lock, &irqL);
+		psta->state = _FW_LINKED;
+		_exit_critical_bh(&psta->lock, &irqL);
+
+	}
+	else
+	{
+		DBG_871X("add_RATid_bmc_sta error!\n");
+	}
+		
+}
+
+//notes:
+//AID: 1~MAX for sta and 0 for bc/mc in ap/adhoc mode 
+//MAC_ID = AID+1 for sta in ap/adhoc mode 
+//MAC_ID = 1 for bc/mc for sta/ap/adhoc
+//MAC_ID = 0 for bssid for sta/ap/adhoc
+//CAM_ID = //0~3 for default key, cmd_id=macid + 3, macid=aid+1;
+
+void update_sta_info_apmode(_adapter *padapter, struct sta_info *psta)
+{	
+	_irqL	irqL;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+#ifdef CONFIG_80211N_HT
+	struct ht_priv	*phtpriv_ap = &pmlmepriv->htpriv;
+	struct ht_priv	*phtpriv_sta = &psta->htpriv;
+#endif //CONFIG_80211N_HT
+	u8	cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0;
+	//set intf_tag to if1
+	//psta->intf_tag = 0;
+
+        DBG_871X("%s\n",__FUNCTION__);
+
+	//psta->mac_id = psta->aid+4;
+	//psta->mac_id = psta->aid+1;//alloc macid when call rtw_alloc_stainfo(),
+		                                       //release macid when call rtw_free_stainfo()
+
+	//ap mode
+	rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);
+	
+	if(psecuritypriv->dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
+		psta->ieee8021x_blocked = _TRUE;
+	else
+		psta->ieee8021x_blocked = _FALSE;
+	
+
+	//update sta's cap
+	
+	//ERP
+	VCS_update(padapter, psta);
+#ifdef CONFIG_80211N_HT	
+	//HT related cap
+	if(phtpriv_sta->ht_option)
+	{
+		//check if sta supports rx ampdu
+		phtpriv_sta->ampdu_enable = phtpriv_ap->ampdu_enable;
+
+		phtpriv_sta->rx_ampdu_min_spacing = (phtpriv_sta->ht_cap.ampdu_params_info&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
+	
+		// bwmode
+		if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH))
+		{			
+			psta->bw_mode = CHANNEL_WIDTH_40;
+		}
+		else
+		{			
+			psta->bw_mode = CHANNEL_WIDTH_20;
+		}
+
+		if (psta->ht_40mhz_intolerant)
+			psta->bw_mode = CHANNEL_WIDTH_20;
+		
+		if(pmlmeext->cur_bwmode < psta->bw_mode)
+		{
+			psta->bw_mode = pmlmeext->cur_bwmode;
+		}
+
+		phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;
+
+
+		//check if sta support s Short GI 20M 
+		if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
+		{
+			phtpriv_sta->sgi_20m = _TRUE;
+		}
+		
+		//check if sta support s Short GI 40M 
+		if((phtpriv_sta->ht_cap.cap_info & phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
+		{
+			if(psta->bw_mode == CHANNEL_WIDTH_40) //according to psta->bw_mode
+				phtpriv_sta->sgi_40m = _TRUE;
+			else
+				phtpriv_sta->sgi_40m = _FALSE;
+		}
+
+		psta->qos_option = _TRUE;
+
+		// B0 Config LDPC Coding Capability
+		if (TEST_FLAG(phtpriv_ap->ldpc_cap, LDPC_HT_ENABLE_TX) && 
+			GET_HT_CAP_ELE_LDPC_CAP((u8 *)(&phtpriv_sta->ht_cap)))
+		{
+			SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
+			DBG_871X("Enable HT Tx LDPC for STA(%d)\n",psta->aid);
+		}
+
+		// B7 B8 B9 Config STBC setting
+		if (TEST_FLAG(phtpriv_ap->stbc_cap, STBC_HT_ENABLE_TX) &&
+			GET_HT_CAP_ELE_RX_STBC((u8 *)(&phtpriv_sta->ht_cap)))
+		{
+			SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX) );
+			DBG_871X("Enable HT Tx STBC for STA(%d)\n",psta->aid);
+		}
+
+#ifdef CONFIG_BEAMFORMING
+		/*Config Tx beamforming setting*/
+		if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && 
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP((u8 *)(&phtpriv_sta->ht_cap)))
+		{
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
+			/*Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/
+			SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 6);
+		}
+
+		if (TEST_FLAG(phtpriv_ap->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP((u8 *)(&phtpriv_sta->ht_cap)))
+		{
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
+			/*Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/
+			SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS((u8 *)(&phtpriv_sta->ht_cap)) << 4);
+		}
+		if (cur_beamform_cap) {
+			DBG_871X("Client STA(%d) HT Beamforming Cap = 0x%02X\n", psta->aid, cur_beamform_cap);
+		}
+#endif /*CONFIG_BEAMFORMING*/
+	}
+	else
+	{
+		phtpriv_sta->ampdu_enable = _FALSE;
+		
+		phtpriv_sta->sgi_20m = _FALSE;
+		phtpriv_sta->sgi_40m = _FALSE;
+		psta->bw_mode = CHANNEL_WIDTH_20;
+		phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	}
+
+	phtpriv_sta->ldpc_cap = cur_ldpc_cap;
+	phtpriv_sta->stbc_cap = cur_stbc_cap;
+	phtpriv_sta->beamform_cap = cur_beamform_cap;
+
+	//Rx AMPDU
+	send_delba(padapter, 0, psta->hwaddr);// recipient
+	
+	//TX AMPDU
+	send_delba(padapter, 1, psta->hwaddr);// // originator
+	phtpriv_sta->agg_enable_bitmap = 0x0;//reset
+	phtpriv_sta->candidate_tid_bitmap = 0x0;//reset
+#endif //CONFIG_80211N_HT
+
+#ifdef CONFIG_80211AC_VHT
+	update_sta_vht_info_apmode(padapter, psta);
+#endif
+
+	update_ldpc_stbc_cap(psta);
+
+	//todo: init other variables
+	
+	_rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+
+	//add ratid
+	//add_RATid(padapter, psta);//move to ap_sta_info_defer_update()
+
+
+	_enter_critical_bh(&psta->lock, &irqL);
+	psta->state |= _FW_LINKED;
+	_exit_critical_bh(&psta->lock, &irqL);
+	
+
+}
+
+static void update_ap_info(_adapter *padapter, struct sta_info *psta)
+{
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+#ifdef CONFIG_80211N_HT
+	struct ht_priv	*phtpriv_ap = &pmlmepriv->htpriv;
+#endif //CONFIG_80211N_HT
+
+	psta->wireless_mode = pmlmeext->cur_wireless_mode;
+
+	psta->bssratelen = rtw_get_rateset_len(pnetwork->SupportedRates);
+	_rtw_memcpy(psta->bssrateset, pnetwork->SupportedRates, psta->bssratelen);
+
+#ifdef CONFIG_80211N_HT	
+	//HT related cap
+	if(phtpriv_ap->ht_option)
+	{
+		//check if sta supports rx ampdu
+		//phtpriv_ap->ampdu_enable = phtpriv_ap->ampdu_enable;
+
+		//check if sta support s Short GI 20M
+		if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
+		{
+			phtpriv_ap->sgi_20m = _TRUE;
+		}
+		//check if sta support s Short GI 40M
+		if((phtpriv_ap->ht_cap.cap_info) & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
+		{
+			phtpriv_ap->sgi_40m = _TRUE;
+		}
+
+		psta->qos_option = _TRUE;
+	}
+	else
+	{
+		phtpriv_ap->ampdu_enable = _FALSE;
+		
+		phtpriv_ap->sgi_20m = _FALSE;
+		phtpriv_ap->sgi_40m = _FALSE;
+	}
+
+	psta->bw_mode = pmlmeext->cur_bwmode;
+	phtpriv_ap->ch_offset = pmlmeext->cur_ch_offset;
+
+	phtpriv_ap->agg_enable_bitmap = 0x0;//reset
+	phtpriv_ap->candidate_tid_bitmap = 0x0;//reset
+
+	_rtw_memcpy(&psta->htpriv, &pmlmepriv->htpriv, sizeof(struct ht_priv));
+
+#ifdef CONFIG_80211AC_VHT
+	_rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
+#endif //CONFIG_80211AC_VHT
+
+#endif //CONFIG_80211N_HT
+
+	psta->state |= WIFI_AP_STATE; /* Aries, add,fix bug of flush_cam_entry at STOP AP mode , 0724 */
+}
+
+static void rtw_set_hw_wmm_param(_adapter *padapter)
+{
+	u8	ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
+	u8	acm_mask;
+	u16	TXOP;
+	u32	acParm, i;
+	u32	edca[4], inx[4];
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
+	struct registry_priv	 *pregpriv = &padapter->registrypriv;
+
+	acm_mask = 0;
+
+	if (IsSupported5G(pmlmeext->cur_wireless_mode) || 
+		(pmlmeext->cur_wireless_mode & WIRELESS_11_24N))
+		aSifsTime = 16;
+	else
+		aSifsTime = 10;
+
+	if (pmlmeinfo->WMM_enable == 0) {
+		padapter->mlmepriv.acm_mask = 0;
+
+		AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
+
+		if (pmlmeext->cur_wireless_mode & (WIRELESS_11G | WIRELESS_11A)) {
+			ECWMin = 4;
+			ECWMax = 10;
+		} else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
+			ECWMin = 5;
+			ECWMax = 10;
+		} else {
+			ECWMin = 4;
+			ECWMax = 10;
+		}
+
+		TXOP = 0;
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
+
+		ECWMin = 2;
+		ECWMax = 3;
+		TXOP = 0x2f;
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
+		
+	} else {
+		edca[0] = edca[1] = edca[2] = edca[3] = 0;
+
+		/*TODO:*/
+		acm_mask = 0;
+		padapter->mlmepriv.acm_mask = acm_mask;
+
+		/*
+		//BK
+		//AIFS = AIFSN * slot time + SIFS - r2t phy delay
+		*/
+		AIFS = (7 * pmlmeinfo->slotTime) + aSifsTime;
+		ECWMin = 4;
+		ECWMax = 10;
+		TXOP = 0;		
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
+		edca[XMIT_BK_QUEUE] = acParm;
+		DBG_871X("WMM(BK): %x\n", acParm);
+		
+		/* BE */
+		AIFS = (3 * pmlmeinfo->slotTime) + aSifsTime;
+		ECWMin = 4;
+		ECWMax = 6;
+		TXOP = 0;		
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
+		edca[XMIT_BE_QUEUE] = acParm;
+		DBG_871X("WMM(BE): %x\n", acParm);
+
+		/* VI */
+		AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;
+		ECWMin = 3;
+		ECWMax = 4;
+		TXOP = 94;		
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
+		edca[XMIT_VI_QUEUE] = acParm;
+		DBG_871X("WMM(VI): %x\n", acParm);
+
+		/* VO */
+		AIFS = (1 * pmlmeinfo->slotTime) + aSifsTime;
+		ECWMin = 2;
+		ECWMax = 3;
+		TXOP = 47;		
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
+		edca[XMIT_VO_QUEUE] = acParm;
+		DBG_871X("WMM(VO): %x\n", acParm);
+
+		
+		if (padapter->registrypriv.acm_method == 1)
+			rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
+		else
+			padapter->mlmepriv.acm_mask = acm_mask;
+
+		inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
+
+		if (pregpriv->wifi_spec == 1) {
+			u32	j, tmp, change_inx = _FALSE;
+
+			/* entry indx: 0->vo, 1->vi, 2->be, 3->bk. */
+			for (i = 0 ; i < 4 ; i++) {
+				for (j = i+1 ; j < 4 ; j++) {
+					/* compare CW and AIFS */
+					if ((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF)) {
+						change_inx = _TRUE;
+					} else if ((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF)) {
+						/* compare TXOP */
+						if ((edca[j] >> 16) > (edca[i] >> 16))
+							change_inx = _TRUE;
+					}
+				
+					if (change_inx) {
+						tmp = edca[i];
+						edca[i] = edca[j];
+						edca[j] = tmp;
+
+						tmp = inx[i];
+						inx[i] = inx[j];
+						inx[j] = tmp;
+
+						change_inx = _FALSE;
+					}
+				}
+			}
+		}
+
+		for (i = 0 ; i < 4 ; i++) {
+			pxmitpriv->wmm_para_seq[i] = inx[i];
+			DBG_871X("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
+		}
+		
+	}
+	
+}
+
+static void update_hw_ht_param(_adapter *padapter)
+{
+	unsigned char		max_AMPDU_len;
+	unsigned char		min_MPDU_spacing;
+	struct registry_priv	 *pregpriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	DBG_871X("%s\n", __FUNCTION__);
+	
+
+	//handle A-MPDU parameter field
+	/* 	
+		AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+		AMPDU_para [4:2]:Min MPDU Start Spacing	
+	*/
+	max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;	
+	
+	min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;	
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+
+	//
+	// Config SM Power Save setting
+	//
+	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
+	if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+	{
+		/*u8 i;
+		//update the MCS rates
+		for (i = 0; i < 16; i++)
+		{
+			pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
+		}*/
+		DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);
+	}
+
+	//
+	// Config current HT Protection mode.
+	//
+	//pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
+
+}
+
+static void rtw_ap_check_scan(_adapter *padapter)
+{
+	_irqL	irqL;
+	_list		*plist, *phead;
+	u32	delta_time, lifetime;
+	struct	wlan_network	*pnetwork = NULL;
+	WLAN_BSSID_EX *pbss = NULL;	
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);	
+	_queue	*queue	= &(pmlmepriv->scanned_queue);
+	u8 do_scan = _FALSE;
+
+	lifetime = SCANQUEUE_LIFETIME; /* 20 sec */
+
+	_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+	phead = get_list_head(queue);
+	if (rtw_end_of_queue_search(phead, get_next(phead)) == _TRUE)
+		if (padapter->registrypriv.wifi_spec)
+			do_scan = _TRUE;
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+	if (padapter->registrypriv.acs_auto_scan) {
+		do_scan = _TRUE;
+		rtw_acs_start(padapter, _TRUE);
+	}
+#endif
+		
+	if (_TRUE == do_scan) {
+		DBG_871X("%s : drv scans by itself and wait_completed\n", __func__);
+		rtw_drv_scan_by_self(padapter);
+		rtw_scan_wait_completed(padapter);
+	}
+	
+#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+	if (padapter->registrypriv.acs_auto_scan)
+		rtw_acs_start(padapter, _FALSE);
+#endif	
+	_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	phead = get_list_head(queue);
+	plist = get_next(phead);
+
+	while (1) {
+		
+		if (rtw_end_of_queue_search(phead, plist) == _TRUE)
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+		
+		if (rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, pnetwork->network.Configuration.DSConfig) >= 0
+			&& rtw_mlme_band_check(padapter, pnetwork->network.Configuration.DSConfig) == _TRUE
+			&& _TRUE == rtw_validate_ssid(&(pnetwork->network.Ssid))) {		
+			delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned);
+			
+			if (delta_time < lifetime) {
+
+				uint ie_len = 0;	
+				u8 *pbuf = NULL;
+				u8 *ie = NULL;
+		
+				pbss = &pnetwork->network;
+				ie = pbss->IEs;
+		
+				/*check if HT CAP INFO IE exists or not*/
+				pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss->IELength - _BEACON_IE_OFFSET_));
+				if (pbuf == NULL) {
+					/* HT CAP INFO IE don't exist, it is b/g mode bss.*/
+				
+					if (pmlmepriv->olbc == _FALSE)
+						pmlmepriv->olbc = _TRUE;
+
+					if (pmlmepriv->olbc_ht == _FALSE)
+						pmlmepriv->olbc_ht = _TRUE;
+				}						
+			}			
+		}
+
+		plist = get_next(plist);	
+		
+	}
+	
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	pmlmepriv->num_sta_no_ht = 0; /* reset to 0 after ap do scanning*/
+	
+}
+
+void rtw_start_bss_hdl_after_chbw_decided(_adapter *adapter)
+{
+	WLAN_BSSID_EX *pnetwork = &(adapter->mlmepriv.cur_network.network);
+	struct sta_info *sta = NULL;
+
+	/* update cur_wireless_mode */
+	update_wireless_mode(adapter);
+
+	/* update RRSR and RTS_INIT_RATE register after set channel and bandwidth */
+	UpdateBrateTbl(adapter, pnetwork->SupportedRates);
+	rtw_hal_set_hwreg(adapter, HW_VAR_BASIC_RATE, pnetwork->SupportedRates);
+
+	/* update capability after cur_wireless_mode updated */
+	update_capinfo(adapter, rtw_get_capability(pnetwork));
+
+	/* update bc/mc sta_info */
+	update_bmc_sta(adapter);
+
+	/* update AP's sta info */
+	sta = rtw_get_stainfo(&adapter->stapriv, pnetwork->MacAddress);
+	if (!sta) {
+		DBG_871X(FUNC_ADPT_FMT" !sta for macaddr="MAC_FMT"\n", FUNC_ADPT_ARG(adapter), MAC_ARG(pnetwork->MacAddress));
+		rtw_warn_on(1);
+		return;
+	}
+
+	update_ap_info(adapter, sta);
+}
+
+void start_bss_network(_adapter *padapter, struct createbss_parm *parm)
+{
+#define DUMP_ADAPTERS_STATUS 0
+
+	u8 val8;
+	u16 bcn_interval;
+	u32	acparm;
+	struct registry_priv	 *pregpriv = &padapter->registrypriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct security_priv* psecuritypriv=&(padapter->securitypriv);	
+	WLAN_BSSID_EX *pnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network; /* used as input */
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX *pnetwork_mlmeext = &(pmlmeinfo->network);
+	u8 req_ch, req_bw, req_offset;
+	bool ch_setting_changed = _FALSE;
+	u8 ch_to_set = 0, bw_to_set, offset_to_set;
+	u8 doiqk = _FALSE;
+
+	if (parm->req_ch == 0) {
+		/* change to unspecificed ch, bw, offset, get from IE */
+		goto get_cbhw_from_ie;
+	} else if (parm->req_ch > 0) {
+		/* change ch, bw, offset */
+		req_ch = parm->req_ch;
+		req_bw = parm->req_bw;
+		req_offset = parm->req_offset;
+		goto change_chbw;
+	}
+
+	bcn_interval = (u16)pnetwork->Configuration.BeaconPeriod;	
+
+	//check if there is wps ie, 
+	//if there is wpsie in beacon, the hostapd will update beacon twice when stating hostapd,
+	//and at first time the security ie ( RSN/WPA IE) will not include in beacon.
+	if(NULL == rtw_get_wps_ie(pnetwork->IEs+_FIXED_IE_LENGTH_, pnetwork->IELength-_FIXED_IE_LENGTH_, NULL, NULL))
+	{
+		pmlmeext->bstart_bss = _TRUE;
+	}
+
+	//todo: update wmm, ht cap
+	//pmlmeinfo->WMM_enable;
+	//pmlmeinfo->HT_enable;
+	if(pmlmepriv->qospriv.qos_option)
+		pmlmeinfo->WMM_enable = _TRUE;
+#ifdef CONFIG_80211N_HT
+	if(pmlmepriv->htpriv.ht_option)
+	{
+		pmlmeinfo->WMM_enable = _TRUE;
+		pmlmeinfo->HT_enable = _TRUE;
+		//pmlmeinfo->HT_info_enable = _TRUE;
+		//pmlmeinfo->HT_caps_enable = _TRUE;
+
+		update_hw_ht_param(padapter);
+	}
+#endif //#CONFIG_80211N_HT
+
+#ifdef CONFIG_80211AC_VHT
+	if(pmlmepriv->vhtpriv.vht_option) {
+		pmlmeinfo->VHT_enable = _TRUE;
+		update_hw_vht_param(padapter);
+	}
+#endif //CONFIG_80211AC_VHT
+
+	if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time
+	{
+		//WEP Key will be set before this function, do not clear CAM.
+		if ((psecuritypriv->dot11PrivacyAlgrthm != _WEP40_) && (psecuritypriv->dot11PrivacyAlgrthm != _WEP104_))
+			flush_all_cam_entry(padapter);	//clear CAM
+	}	
+
+	//set MSR to AP_Mode		
+	Set_MSR(padapter, _HW_STATE_AP_);	
+		
+	//Set BSSID REG
+	rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pnetwork->MacAddress);
+
+	//Set EDCA param reg
+#ifdef CONFIG_CONCURRENT_MODE
+	acparm = 0x005ea42b;
+#else
+	acparm = 0x002F3217; // VO
+#endif
+	rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
+	acparm = 0x005E4317; // VI
+	rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
+	//acparm = 0x00105320; // BE
+	acparm = 0x005ea42b;
+	rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+	acparm = 0x0000A444; // BK
+	rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
+
+	//Set Security
+	val8 = (psecuritypriv->dot11AuthAlgrthm == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
+	rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+	//Beacon Control related register
+	rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&bcn_interval));
+
+#if 0
+	if(pmlmepriv->cur_network.join_res != _TRUE) //setting only at  first time
+	{
+		//u32 initialgain;
+
+		//initialgain = 0x1e;
+
+
+		//disable dynamic functions, such as high power, DIG
+		/*rtw_phydm_ability_backup(padapter);*/
+		/*rtw_phydm_func_disable_all(padapter);*/
+		
+		//turn on all dynamic functions	
+		/* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE);*/
+
+		/*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/
+	
+	}
+#endif
+
+get_cbhw_from_ie:
+	rtw_ies_get_chbw(pnetwork->IEs + sizeof(NDIS_802_11_FIXED_IEs)
+		, pnetwork->IELength - sizeof(NDIS_802_11_FIXED_IEs)
+		, &req_ch, &req_bw, &req_offset);
+
+change_chbw:
+	rtw_warn_on(req_ch == 0);
+
+	ch_setting_changed = rtw_ap_chbw_decision(padapter, req_ch, req_bw, req_offset
+		, &ch_to_set, &bw_to_set, &offset_to_set);
+
+	//let pnetwork_mlmeext == pnetwork_mlme.
+	_rtw_memcpy(pnetwork_mlmeext, pnetwork, pnetwork->Length);
+
+	rtw_start_bss_hdl_after_chbw_decided(padapter);
+
+	#if defined(CONFIG_DFS_MASTER)
+	rtw_dfs_master_status_apply(padapter, MLME_AP_STARTED);
+	#endif
+
+	doiqk = _TRUE;
+	rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+	
+	if (ch_to_set != 0)
+		set_channel_bwmode(padapter, ch_to_set, offset_to_set, bw_to_set);
+
+	doiqk = _FALSE;
+	rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+	if (DUMP_ADAPTERS_STATUS) {
+		DBG_871X(FUNC_ADPT_FMT" done\n", FUNC_ADPT_ARG(padapter));
+		dump_adapters_status(RTW_DBGDUMP , adapter_to_dvobj(padapter));
+	}
+
+	if (_TRUE == pmlmeext->bstart_bss
+		&& !check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
+		&& !check_fwstate(pmlmepriv, WIFI_OP_CH_SWITCHING)
+		#ifdef CONFIG_CONCURRENT_MODE
+		&& !check_buddy_fwstate(padapter, WIFI_SITE_MONITOR)
+		#endif
+	) {
+
+	       if ((pmlmepriv->olbc == _TRUE) || (pmlmepriv->olbc_ht == _TRUE)) {
+
+			/* AP is not starting a 40 MHz BSS in presence of an 802.11g BSS. */
+
+			pmlmepriv->ht_op_mode &= (~HT_INFO_OPERATION_MODE_OP_MODE_MASK);
+			pmlmepriv->ht_op_mode |= OP_MODE_MAY_BE_LEGACY_STAS;
+			update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE);
+		}
+
+		update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
+
+		#if !defined(CONFIG_INTERRUPT_BASED_TXBCN)
+		#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		/* other case will  tx beacon when bcn interrupt coming in. */
+		if (send_beacon(padapter) == _FAIL)
+			DBG_871X("issue_beacon, fail!\n");
+		#endif 
+		#endif /* !defined(CONFIG_INTERRUPT_BASED_TXBCN) */
+	}
+
+	/*Set EDCA param reg after update cur_wireless_mode & update_capinfo*/
+	if (pregpriv->wifi_spec == 1)
+		rtw_set_hw_wmm_param(padapter);
+	
+	/*pmlmeext->bstart_bss = _TRUE;*/
+}
+
+int rtw_check_beacon_data(_adapter *padapter, u8 *pbuf,  int len)
+{
+	int ret=_SUCCESS;
+	u8 *p;
+	u8 *pHT_caps_ie=NULL;
+	u8 *pHT_info_ie=NULL;
+	u16 cap, ht_cap=_FALSE;
+	uint ie_len = 0;
+	int group_cipher, pairwise_cipher;	
+	u8	channel, network_type, supportRate[NDIS_802_11_LENGTH_RATES_EX];
+	int supportRateNum = 0;
+	u8 OUI1[] = {0x00, 0x50, 0xf2,0x01};
+	u8 wps_oui[4]={0x0,0x50,0xf2,0x04};
+	u8 WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};	
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;	
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX *pbss_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;	
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *ie = pbss_network->IEs;
+	u8 vht_cap=_FALSE;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 rf_num = 0;
+	
+	/* SSID */
+	/* Supported rates */
+	/* DS Params */
+	/* WLAN_EID_COUNTRY */
+	/* ERP Information element */
+	/* Extended supported rates */
+	/* WPA/WPA2 */
+	/* Wi-Fi Wireless Multimedia Extensions */
+	/* ht_capab, ht_oper */
+	/* WPS IE */
+
+	DBG_871X("%s, len=%d\n", __FUNCTION__, len);
+
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
+		return _FAIL;
+
+
+	if(len>MAX_IE_SZ)
+		return _FAIL;
+	
+	pbss_network->IELength = len;
+
+	_rtw_memset(ie, 0, MAX_IE_SZ);
+	
+	_rtw_memcpy(ie, pbuf, pbss_network->IELength);
+
+
+	if(pbss_network->InfrastructureMode!=Ndis802_11APMode)
+		return _FAIL;
+
+
+	rtw_ap_check_scan(padapter);
+	
+
+	pbss_network->Rssi = 0;
+
+	_rtw_memcpy(pbss_network->MacAddress, adapter_mac_addr(padapter), ETH_ALEN);
+	
+	//beacon interval
+	p = rtw_get_beacon_interval_from_ie(ie);//ie + 8;	// 8: TimeStamp, 2: Beacon Interval 2:Capability
+	//pbss_network->Configuration.BeaconPeriod = le16_to_cpu(*(unsigned short*)p);
+	pbss_network->Configuration.BeaconPeriod = RTW_GET_LE16(p);
+	
+	//capability
+	//cap = *(unsigned short *)rtw_get_capability_from_ie(ie);
+	//cap = le16_to_cpu(cap);
+	cap = RTW_GET_LE16(ie);
+
+	//SSID
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SSID_IE_, &ie_len, (pbss_network->IELength -_BEACON_IE_OFFSET_));
+	if(p && ie_len>0)
+	{
+		_rtw_memset(&pbss_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
+		_rtw_memcpy(pbss_network->Ssid.Ssid, (p + 2), ie_len);
+		pbss_network->Ssid.SsidLength = ie_len;
+		#ifdef CONFIG_P2P
+		_rtw_memcpy(padapter->wdinfo.p2p_group_ssid, pbss_network->Ssid.Ssid, pbss_network->Ssid.SsidLength);
+		padapter->wdinfo.p2p_group_ssid_len = pbss_network->Ssid.SsidLength;
+		#endif
+	}
+
+	//chnnel
+	channel = 0;
+	pbss_network->Configuration.Length = 0;
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _DSSET_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	if(p && ie_len>0)
+		channel = *(p + 2);
+
+	pbss_network->Configuration.DSConfig = channel;
+
+	
+	_rtw_memset(supportRate, 0, NDIS_802_11_LENGTH_RATES_EX);
+	// get supported rates
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _SUPPORTEDRATES_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));	
+	if (p !=  NULL) 
+	{
+		_rtw_memcpy(supportRate, p+2, ie_len);	
+		supportRateNum = ie_len;
+	}
+	
+	//get ext_supported rates
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ie_len, pbss_network->IELength - _BEACON_IE_OFFSET_);	
+	if (p !=  NULL)
+	{
+		_rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);
+		supportRateNum += ie_len;
+	
+	}
+
+	network_type = rtw_check_network_type(supportRate, supportRateNum, channel);
+
+	rtw_set_supported_rate(pbss_network->SupportedRates, network_type);
+
+
+	//parsing ERP_IE
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	if(p && ie_len>0)
+	{
+		ERP_IE_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)p);
+	}
+
+	//update privacy/security
+	if (cap & BIT(4))
+		pbss_network->Privacy = 1;
+	else
+		pbss_network->Privacy = 0;
+
+	psecuritypriv->wpa_psk = 0;
+
+	//wpa2
+	group_cipher = 0; pairwise_cipher = 0;
+	psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
+	psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;	
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));		
+	if(p && ie_len>0)
+	{
+		if(rtw_parse_wpa2_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
+		{
+			psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+			
+			psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x
+			psecuritypriv->wpa_psk |= BIT(1);
+
+			psecuritypriv->wpa2_group_cipher = group_cipher;
+			psecuritypriv->wpa2_pairwise_cipher = pairwise_cipher;
+#if 0
+			switch(group_cipher)
+			{
+				case WPA_CIPHER_NONE:				
+				psecuritypriv->wpa2_group_cipher = _NO_PRIVACY_;
+				break;
+				case WPA_CIPHER_WEP40:				
+				psecuritypriv->wpa2_group_cipher = _WEP40_;
+				break;
+				case WPA_CIPHER_TKIP:				
+				psecuritypriv->wpa2_group_cipher = _TKIP_;
+				break;
+				case WPA_CIPHER_CCMP:				
+				psecuritypriv->wpa2_group_cipher = _AES_;				
+				break;
+				case WPA_CIPHER_WEP104:					
+				psecuritypriv->wpa2_group_cipher = _WEP104_;
+				break;
+			}
+
+			switch(pairwise_cipher)
+			{
+				case WPA_CIPHER_NONE:			
+				psecuritypriv->wpa2_pairwise_cipher = _NO_PRIVACY_;
+				break;
+				case WPA_CIPHER_WEP40:			
+				psecuritypriv->wpa2_pairwise_cipher = _WEP40_;
+				break;
+				case WPA_CIPHER_TKIP:				
+				psecuritypriv->wpa2_pairwise_cipher = _TKIP_;
+				break;
+				case WPA_CIPHER_CCMP:			
+				psecuritypriv->wpa2_pairwise_cipher = _AES_;
+				break;
+				case WPA_CIPHER_WEP104:					
+				psecuritypriv->wpa2_pairwise_cipher = _WEP104_;
+				break;
+			}
+#endif			
+		}
+		
+	}
+
+	//wpa
+	ie_len = 0;
+	group_cipher = 0; pairwise_cipher = 0;
+	psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
+	psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;	
+	for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
+	{
+		p = rtw_get_ie(p, _SSN_IE_1_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));		
+		if ((p) && (_rtw_memcmp(p+2, OUI1, 4)))
+		{
+			if(rtw_parse_wpa_ie(p, ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
+			{
+				psecuritypriv->dot11AuthAlgrthm= dot11AuthAlgrthm_8021X;
+				
+				psecuritypriv->dot8021xalg = 1;//psk,  todo:802.1x
+
+				psecuritypriv->wpa_psk |= BIT(0);
+
+				psecuritypriv->wpa_group_cipher = group_cipher;
+				psecuritypriv->wpa_pairwise_cipher = pairwise_cipher;
+
+#if 0
+				switch(group_cipher)
+				{
+					case WPA_CIPHER_NONE:					
+					psecuritypriv->wpa_group_cipher = _NO_PRIVACY_;
+					break;
+					case WPA_CIPHER_WEP40:					
+					psecuritypriv->wpa_group_cipher = _WEP40_;
+					break;
+					case WPA_CIPHER_TKIP:					
+					psecuritypriv->wpa_group_cipher = _TKIP_;
+					break;
+					case WPA_CIPHER_CCMP:					
+					psecuritypriv->wpa_group_cipher = _AES_;				
+					break;
+					case WPA_CIPHER_WEP104:					
+					psecuritypriv->wpa_group_cipher = _WEP104_;
+					break;
+				}
+
+				switch(pairwise_cipher)
+				{
+					case WPA_CIPHER_NONE:					
+					psecuritypriv->wpa_pairwise_cipher = _NO_PRIVACY_;
+					break;
+					case WPA_CIPHER_WEP40:					
+					psecuritypriv->wpa_pairwise_cipher = _WEP40_;
+					break;
+					case WPA_CIPHER_TKIP:					
+					psecuritypriv->wpa_pairwise_cipher = _TKIP_;
+					break;
+					case WPA_CIPHER_CCMP:					
+					psecuritypriv->wpa_pairwise_cipher = _AES_;
+					break;
+					case WPA_CIPHER_WEP104:					
+					psecuritypriv->wpa_pairwise_cipher = _WEP104_;
+					break;
+				}
+#endif				
+			}
+
+			break;
+			
+		}
+			
+		if ((p == NULL) || (ie_len == 0))
+		{
+				break;
+		}
+		
+	}
+
+	//wmm
+	ie_len = 0;
+	pmlmepriv->qospriv.qos_option = 0;
+	if(pregistrypriv->wmm_enable)
+	{
+		for (p = ie + _BEACON_IE_OFFSET_; ;p += (ie_len + 2))
+		{			
+			p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));	
+			if((p) && _rtw_memcmp(p+2, WMM_PARA_IE, 6)) 
+			{
+				pmlmepriv->qospriv.qos_option = 1;	
+
+				*(p+8) |= BIT(7);//QoS Info, support U-APSD
+				
+				/* disable all ACM bits since the WMM admission control is not supported */
+				*(p + 10) &= ~BIT(4); /* BE */
+				*(p + 14) &= ~BIT(4); /* BK */
+				*(p + 18) &= ~BIT(4); /* VI */
+				*(p + 22) &= ~BIT(4); /* VO */
+				
+				break;				
+			}
+			
+			if ((p == NULL) || (ie_len == 0))
+			{
+				break;
+			}			
+		}		
+	}
+#ifdef CONFIG_80211N_HT
+	//parsing HT_CAP_IE
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	if(p && ie_len>0)
+	{
+		u8 rf_type=0;
+		HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor=MAX_AMPDU_FACTOR_64K;
+		struct rtw_ieee80211_ht_cap *pht_cap = (struct rtw_ieee80211_ht_cap *)(p+2);
+
+		if (0) {
+			DBG_871X(FUNC_ADPT_FMT" HT_CAP_IE from upper layer:\n", FUNC_ADPT_ARG(padapter));
+			dump_ht_cap_ie_content(RTW_DBGDUMP, p+2, ie_len);
+		}
+
+		pHT_caps_ie=p;
+
+		ht_cap = _TRUE;
+		network_type |= WIRELESS_11_24N;
+
+		rtw_ht_use_default_setting(padapter);
+
+		/* Update HT Capabilities Info field */
+		if (pmlmepriv->htpriv.sgi_20m == _FALSE)
+			pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_20);
+
+		if (pmlmepriv->htpriv.sgi_40m == _FALSE)
+			pht_cap->cap_info &= ~(IEEE80211_HT_CAP_SGI_40);
+
+		if (!TEST_FLAG(pmlmepriv->htpriv.ldpc_cap, LDPC_HT_ENABLE_RX))
+		{
+			pht_cap->cap_info &= ~(IEEE80211_HT_CAP_LDPC_CODING);
+		}
+
+		if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
+		{
+			pht_cap->cap_info &= ~(IEEE80211_HT_CAP_TX_STBC);
+		}		
+
+		if (!TEST_FLAG(pmlmepriv->htpriv.stbc_cap, STBC_HT_ENABLE_RX))
+		{
+			pht_cap->cap_info &= ~(IEEE80211_HT_CAP_RX_STBC_3R);
+		}
+
+		/* Update A-MPDU Parameters field */
+		pht_cap->ampdu_params_info &= ~(IEEE80211_HT_CAP_AMPDU_FACTOR|IEEE80211_HT_CAP_AMPDU_DENSITY);
+
+		if((psecuritypriv->wpa_pairwise_cipher & WPA_CIPHER_CCMP) ||
+			(psecuritypriv->wpa2_pairwise_cipher & WPA_CIPHER_CCMP))
+		{
+			pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&(0x07<<2));
+		}	
+		else
+		{
+			pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);	
+		}	
+
+		rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+		pht_cap->ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_FACTOR & max_rx_ampdu_factor); //set  Max Rx AMPDU size  to 64K
+		
+		_rtw_memcpy(&(pmlmeinfo->HT_caps), pht_cap, sizeof(struct HT_caps_element));
+
+		/* Update Supported MCS Set field */
+		{
+			int i;
+
+			rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+			/* RX MCS Bitmask */
+			switch(rf_type)
+			{
+				case RF_1T1R:
+				case RF_1T2R: //?
+					set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_1R);
+					break;
+				case RF_2T2R:
+					set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_2R);
+					break;
+				case RF_3T3R:
+					set_mcs_rate_by_mask(HT_CAP_ELE_RX_MCS_MAP(pht_cap), MCS_RATE_3R);
+					break;
+				default:
+					DBG_871X("[warning] rf_type %d is not expected\n", rf_type);
+			}
+			for (i = 0; i < 10; i++)
+				*(HT_CAP_ELE_RX_MCS_MAP(pht_cap)+i) &= padapter->mlmeextpriv.default_supported_mcs_set[i];
+		}
+
+#ifdef CONFIG_BEAMFORMING
+		// Use registry value to enable HT Beamforming.
+		// ToDo: use configure file to set these capability.
+		pht_cap->tx_BF_cap_info = 0;
+
+		// HT Beamformer
+		if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE))
+		{
+			// Transmit NDP Capable
+			SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(pht_cap, 1);
+			// Explicit Compressed Steering Capable
+			SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pht_cap, 1);
+			// Compressed Steering Number Antennas
+			SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, 1);
+			rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
+			SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pht_cap, rf_num);		
+		}
+
+		// HT Beamformee
+		if(TEST_FLAG(pmlmepriv->htpriv.beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
+		{
+			// Receive NDP Capable
+			SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(pht_cap, 1);
+			// Explicit Compressed Beamforming Feedback Capable
+			SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pht_cap, 2);
+			rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
+			SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pht_cap, rf_num);
+		}
+#endif //CONFIG_BEAMFORMING
+
+		_rtw_memcpy(&pmlmepriv->htpriv.ht_cap, p+2, ie_len);
+
+		if (0) {
+			DBG_871X(FUNC_ADPT_FMT" HT_CAP_IE driver masked:\n", FUNC_ADPT_ARG(padapter));
+			dump_ht_cap_ie_content(RTW_DBGDUMP, p+2, ie_len);
+		}
+	}
+
+	//parsing HT_INFO_IE
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	if(p && ie_len>0)
+	{
+		pHT_info_ie=p;
+	}
+#endif //CONFIG_80211N_HT
+	switch(network_type)
+	{
+		case WIRELESS_11B:
+			pbss_network->NetworkTypeInUse = Ndis802_11DS;
+			break;	
+		case WIRELESS_11G:
+		case WIRELESS_11BG:
+             case WIRELESS_11G_24N:
+		case WIRELESS_11BG_24N:
+			pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+			break;
+		case WIRELESS_11A:
+			pbss_network->NetworkTypeInUse = Ndis802_11OFDM5;
+			break;
+		default :
+			pbss_network->NetworkTypeInUse = Ndis802_11OFDM24;
+			break;
+	}
+	
+	pmlmepriv->cur_network.network_type = network_type;
+
+#ifdef CONFIG_80211N_HT
+	pmlmepriv->htpriv.ht_option = _FALSE;
+
+	if( (psecuritypriv->wpa2_pairwise_cipher&WPA_CIPHER_TKIP) ||
+		      (psecuritypriv->wpa_pairwise_cipher&WPA_CIPHER_TKIP))
+	{	
+		//todo:
+		//ht_cap = _FALSE;
+	}
+		      
+	//ht_cap	
+	if(pregistrypriv->ht_enable && ht_cap==_TRUE)
+	{		
+		pmlmepriv->htpriv.ht_option = _TRUE;
+		pmlmepriv->qospriv.qos_option = 1;
+
+		if(pregistrypriv->ampdu_enable==1)
+		{
+			pmlmepriv->htpriv.ampdu_enable = _TRUE;
+		}
+
+		HT_caps_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_caps_ie);
+		
+		HT_info_handler(padapter, (PNDIS_802_11_VARIABLE_IEs)pHT_info_ie);
+	}
+#endif
+
+#ifdef CONFIG_80211AC_VHT
+
+	//Parsing VHT CAP IE
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pbss_network->IELength - _BEACON_IE_OFFSET_));
+	if(p && ie_len>0)
+	{	
+		vht_cap = _TRUE; 
+	}
+	//Parsing VHT OPERATION IE
+	
+
+	pmlmepriv->vhtpriv.vht_option = _FALSE;
+	// if channel in 5G band, then add vht ie .
+	if ((pbss_network->Configuration.DSConfig > 14)
+		&& (pmlmepriv->htpriv.ht_option == _TRUE)
+		&& REGSTY_IS_11AC_ENABLE(pregistrypriv)
+		&& hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
+		&& (!pmlmepriv->country_ent || COUNTRY_CHPLAN_EN_11AC(pmlmepriv->country_ent))
+	) {
+		if (vht_cap == _TRUE)
+			pmlmepriv->vhtpriv.vht_option = _TRUE;
+		else if (REGSTY_IS_11AC_AUTO(pregistrypriv)) {
+			u8	cap_len, operation_len;
+
+			rtw_vht_use_default_setting(padapter);
+
+			{
+				/* VHT Operation mode notifiy bit in Extended IE (127) */
+				uint len = 0;
+				
+				SET_EXT_CAPABILITY_ELE_OP_MODE_NOTIF(pmlmepriv->ext_capab_ie_data, 1);
+				pmlmepriv->ext_capab_ie_len = 10;
+				rtw_set_ie(pbss_network->IEs + pbss_network->IELength, EID_EXTCapability, 8, pmlmepriv->ext_capab_ie_data, &len);
+				pbss_network->IELength += pmlmepriv->ext_capab_ie_len;
+			}
+			
+			// VHT Capabilities element
+			cap_len = rtw_build_vht_cap_ie(padapter, pbss_network->IEs + pbss_network->IELength);
+			pbss_network->IELength += cap_len;
+
+			// VHT Operation element
+			operation_len = rtw_build_vht_operation_ie(padapter, pbss_network->IEs + pbss_network->IELength, pbss_network->Configuration.DSConfig);
+			pbss_network->IELength += operation_len;
+
+			pmlmepriv->vhtpriv.vht_option = _TRUE;
+		}		
+	}
+#endif //CONFIG_80211AC_VHT
+
+	pbss_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX  *)pbss_network);
+
+	rtw_ies_get_chbw(pbss_network->IEs + _BEACON_IE_OFFSET_, pbss_network->IELength - _BEACON_IE_OFFSET_
+		, &pmlmepriv->ori_ch, &pmlmepriv->ori_bw, &pmlmepriv->ori_offset);
+	rtw_warn_on(pmlmepriv->ori_ch == 0);
+
+{
+	/* alloc sta_info for ap itself */
+
+	struct sta_info *sta;
+
+	sta = rtw_get_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+	if (!sta) {
+		sta = rtw_alloc_stainfo(&padapter->stapriv, pbss_network->MacAddress);
+		if (sta == NULL) 
+			return _FAIL;
+	}
+}
+
+	rtw_startbss_cmd(padapter, RTW_CMDF_WAIT_ACK);
+
+	rtw_indicate_connect( padapter);
+
+	pmlmepriv->cur_network.join_res = _TRUE;//for check if already set beacon
+		
+	//update bc/mc sta_info
+	//update_bmc_sta(padapter);
+
+	return ret;
+
+}
+
+void rtw_set_macaddr_acl(_adapter *padapter, int mode)
+{
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+
+	DBG_871X("%s, mode=%d\n", __func__, mode);
+
+	pacl_list->mode = mode;
+}
+
+int rtw_acl_add_sta(_adapter *padapter, u8 *addr)
+{
+	_irqL irqL;
+	_list	*plist, *phead;
+	u8 added = _FALSE;
+	int i, ret=0;
+	struct rtw_wlan_acl_node *paclnode;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+	_queue	*pacl_node_q =&pacl_list->acl_node_q;	
+
+	DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));	
+
+	if((NUM_ACL-1) < pacl_list->num)
+		return (-1);	
+
+
+	_enter_critical_bh(&(pacl_node_q->lock), &irqL);
+
+	phead = get_list_head(pacl_node_q);
+	plist = get_next(phead);
+		
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+		plist = get_next(plist);
+
+		if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN))
+		{
+			if(paclnode->valid == _TRUE)
+			{
+				added = _TRUE;
+				DBG_871X("%s, sta has been added\n", __func__);
+				break;
+			}
+		}		
+	}
+	
+	_exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+
+	if(added == _TRUE)
+		return ret;
+	
+
+	_enter_critical_bh(&(pacl_node_q->lock), &irqL);
+
+	for(i=0; i< NUM_ACL; i++)
+	{
+		paclnode = &pacl_list->aclnode[i];
+
+		if(paclnode->valid == _FALSE)
+		{
+			_rtw_init_listhead(&paclnode->list);
+	
+			_rtw_memcpy(paclnode->addr, addr, ETH_ALEN);
+		
+			paclnode->valid = _TRUE;
+
+			rtw_list_insert_tail(&paclnode->list, get_list_head(pacl_node_q));
+	
+			pacl_list->num++;
+
+			break;
+		}
+	}
+
+	DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
+	
+	_exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+	return ret;
+}
+
+int rtw_acl_remove_sta(_adapter *padapter, u8 *addr)
+{
+	_irqL irqL;
+	_list	*plist, *phead;
+	int i, ret=0;
+	struct rtw_wlan_acl_node *paclnode;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+	_queue	*pacl_node_q =&pacl_list->acl_node_q;
+	u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };	//Baddr is used for clearing acl_list
+
+	DBG_871X("%s(acl_num=%d)=" MAC_FMT "\n", __func__, pacl_list->num, MAC_ARG(addr));	
+
+	_enter_critical_bh(&(pacl_node_q->lock), &irqL);
+
+	phead = get_list_head(pacl_node_q);
+	plist = get_next(phead);
+		
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+		plist = get_next(plist);
+
+		if(_rtw_memcmp(paclnode->addr, addr, ETH_ALEN) || _rtw_memcmp(baddr, addr, ETH_ALEN))
+		{
+			if(paclnode->valid == _TRUE)
+			{
+				paclnode->valid = _FALSE;
+
+				rtw_list_delete(&paclnode->list);
+				
+				pacl_list->num--;
+			}
+		}		
+	}
+	
+	_exit_critical_bh(&(pacl_node_q->lock), &irqL);
+
+	DBG_871X("%s, acl_num=%d\n", __func__, pacl_list->num);
+	
+	return ret;
+
+}
+
+u8 rtw_ap_set_pairwise_key(_adapter *padapter, struct sta_info *psta)
+{
+	struct cmd_obj*			ph2c;
+	struct set_stakey_parm	*psetstakey_para;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;	
+	u8	res=_SUCCESS;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if ( ph2c == NULL){
+		res= _FAIL;
+		goto exit;
+	}
+
+	psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
+	if(psetstakey_para==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+		res=_FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+
+
+	psetstakey_para->algorithm = (u8)psta->dot118021XPrivacy;
+
+	_rtw_memcpy(psetstakey_para->addr, psta->hwaddr, ETH_ALEN);	
+	
+	_rtw_memcpy(psetstakey_para->key, &psta->dot118021x_UncstKey, 16);
+
+	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+
+exit:
+
+	return res;
+	
+}
+
+static int rtw_ap_set_key(_adapter *padapter, u8 *key, u8 alg, int keyid, u8 set_tx)
+{
+	u8 keylen;
+	struct cmd_obj* pcmd;
+	struct setkey_parm *psetkeyparm;
+	struct cmd_priv	*pcmdpriv=&(padapter->cmdpriv);	
+	int res=_SUCCESS;
+
+	//DBG_871X("%s\n", __FUNCTION__);
+	
+	pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(pcmd==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));
+	if(psetkeyparm==NULL){
+		rtw_mfree((unsigned char *)pcmd, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	_rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
+		
+	psetkeyparm->keyid=(u8)keyid;
+	if (is_wep_enc(alg))
+		padapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
+
+	psetkeyparm->algorithm = alg;
+
+	psetkeyparm->set_tx = set_tx;
+
+	switch(alg)
+	{
+		case _WEP40_:					
+			keylen = 5;
+			break;
+		case _WEP104_:
+			keylen = 13;			
+			break;
+		case _TKIP_:
+		case _TKIP_WTMIC_:
+		case _AES_:
+		default:
+			keylen = 16;
+	}
+
+	_rtw_memcpy(&(psetkeyparm->key[0]), key, keylen);
+	
+	pcmd->cmdcode = _SetKey_CMD_;
+	pcmd->parmbuf = (u8 *)psetkeyparm;   
+	pcmd->cmdsz =  (sizeof(struct setkey_parm));  
+	pcmd->rsp = NULL;
+	pcmd->rspsz = 0;
+
+
+	_rtw_init_listhead(&pcmd->list);
+
+	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+
+	return res;
+}
+
+int rtw_ap_set_group_key(_adapter *padapter, u8 *key, u8 alg, int keyid)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	return rtw_ap_set_key(padapter, key, alg, keyid, 1);
+}
+
+int rtw_ap_set_wep_key(_adapter *padapter, u8 *key, u8 keylen, int keyid, u8 set_tx)
+{
+	u8 alg;
+
+	switch(keylen)
+	{
+		case 5:
+			alg =_WEP40_;			
+			break;
+		case 13:
+			alg =_WEP104_;			
+			break;
+		default:
+			alg =_NO_PRIVACY_;			
+	}
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	return rtw_ap_set_key(padapter, key, alg, keyid, set_tx);
+}
+
+u8 rtw_ap_bmc_frames_hdl(_adapter *padapter)
+{
+#define HIQ_XMIT_COUNTS (6)
+	_irqL irqL;
+	struct sta_info *psta_bmc;
+	_list	*xmitframe_plist, *xmitframe_phead;
+	struct xmit_frame *pxmitframe = NULL;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct sta_priv  *pstapriv = &padapter->stapriv;
+	bool update_tim = _FALSE;
+
+
+	if (padapter->registrypriv.wifi_spec != 1)
+		return H2C_SUCCESS;
+
+	
+	psta_bmc = rtw_get_bcmc_stainfo(padapter);
+	if (!psta_bmc)
+		return H2C_SUCCESS;
+
+
+	_enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+	if ((pstapriv->tim_bitmap & BIT(0)) && (psta_bmc->sleepq_len > 0)) {
+		int tx_counts = 0;
+		
+		_update_beacon(padapter, _TIM_IE_, NULL, _FALSE, "update TIM with TIB=1");
+
+		DBG_871X("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);
+
+		xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+		xmitframe_plist = get_next(xmitframe_phead);
+
+		while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE) {
+			pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+			xmitframe_plist = get_next(xmitframe_plist);
+
+			rtw_list_delete(&pxmitframe->list);
+
+			psta_bmc->sleepq_len--;
+			tx_counts++;
+			
+			if (psta_bmc->sleepq_len > 0)
+				pxmitframe->attrib.mdata = 1;
+			else
+				pxmitframe->attrib.mdata = 0;
+
+			if (tx_counts == HIQ_XMIT_COUNTS)
+				pxmitframe->attrib.mdata = 0;
+			
+			pxmitframe->attrib.triggered = 1;
+
+			if (xmitframe_hiq_filter(pxmitframe) == _TRUE)
+				pxmitframe->attrib.qsel = QSLT_HIGH;/*HIQ*/
+
+			rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+
+			if (tx_counts == HIQ_XMIT_COUNTS)
+				break;
+			
+		}
+
+	} else {
+		if (psta_bmc->sleepq_len == 0) {
+			
+			/*DBG_871X("sleepq_len of bmc_sta = %d\n", psta_bmc->sleepq_len);*/
+			
+			if (pstapriv->tim_bitmap & BIT(0))
+				update_tim = _TRUE;
+
+			pstapriv->tim_bitmap &= ~BIT(0);
+			pstapriv->sta_dz_bitmap &= ~BIT(0);
+
+			if (update_tim == _TRUE) {
+				DBG_871X("clear TIB\n");
+				_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "bmc sleepq and HIQ empty");
+			}			
+		}
+	}
+
+	_exit_critical_bh(&pxmitpriv->lock, &irqL);
+
+/*
+	//HIQ Check
+	rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
+
+	while (_FALSE == empty && rtw_get_passing_time_ms(start) < 3000)
+	{
+		rtw_msleep_os(100);
+		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
+	}
+
+
+	printk("check if hiq empty=%d\n", empty);
+*/
+
+	return H2C_SUCCESS;
+}
+
+#ifdef CONFIG_NATIVEAP_MLME
+
+static void associated_stainfo_update(_adapter *padapter, struct sta_info *psta, u32 sta_info_type)
+{
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	DBG_871X("%s: "MAC_FMT", updated_type=0x%x\n", __func__, MAC_ARG(psta->hwaddr), sta_info_type);
+	
+	if (sta_info_type & STA_INFO_UPDATE_BW) {
+
+		if ((psta->flags & WLAN_STA_HT) && !psta->ht_20mhz_set) {
+			if (pmlmepriv->sw_to_20mhz) {
+				psta->bw_mode = CHANNEL_WIDTH_20;
+				/*psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;*/
+				psta->htpriv.sgi_40m = _FALSE;				
+			} else {
+				/*TODO: Switch back to 40MHZ?80MHZ*/
+			}
+		}		
+	}
+
+/*
+	if (sta_info_type & STA_INFO_UPDATE_RATE) {
+		
+	}
+*/	
+
+	if (sta_info_type & STA_INFO_UPDATE_PROTECTION_MODE)
+		VCS_update(padapter, psta);
+	
+/*
+	if (sta_info_type & STA_INFO_UPDATE_CAP) {
+		
+	}
+
+	if (sta_info_type & STA_INFO_UPDATE_HT_CAP) {
+		
+	}
+
+	if (sta_info_type & STA_INFO_UPDATE_VHT_CAP) {
+		
+	}	
+*/
+
+}
+
+static void update_bcn_ext_capab_ie(_adapter *padapter)
+{
+	sint ie_len = 0;
+	unsigned char	*pbuf;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+	u8 *ie = pnetwork->IEs; 
+	u8 null_extcap_data[8] = {0};
+	
+	pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+	if (pbuf && ie_len > 0)
+		rtw_remove_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_);
+
+	if ((pmlmepriv->ext_capab_ie_len > 0) && 
+		(_rtw_memcmp(pmlmepriv->ext_capab_ie_data, null_extcap_data, sizeof(null_extcap_data)) == _FALSE))
+		rtw_add_bcn_ie(padapter, pnetwork, _EXT_CAP_IE_, pmlmepriv->ext_capab_ie_data, pmlmepriv->ext_capab_ie_len);
+	
+}
+
+static void update_bcn_fixed_ie(_adapter *padapter)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_erpinfo_ie(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+	unsigned char *p, *ie = pnetwork->IEs;
+	u32 len = 0;
+
+	DBG_871X("%s, ERP_enable=%d\n", __FUNCTION__, pmlmeinfo->ERP_enable);
+
+	if(!pmlmeinfo->ERP_enable)
+		return;
+
+	//parsing ERP_IE
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _ERPINFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+	if(p && len>0)
+	{
+		PNDIS_802_11_VARIABLE_IEs pIE = (PNDIS_802_11_VARIABLE_IEs)p;
+
+		if (pmlmepriv->num_sta_non_erp == 1)
+			pIE->data[0] |= RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION;
+		else
+			pIE->data[0] &= ~(RTW_ERP_INFO_NON_ERP_PRESENT|RTW_ERP_INFO_USE_PROTECTION);
+
+		if(pmlmepriv->num_sta_no_short_preamble > 0)
+			pIE->data[0] |= RTW_ERP_INFO_BARKER_PREAMBLE_MODE;
+		else
+			pIE->data[0] &= ~(RTW_ERP_INFO_BARKER_PREAMBLE_MODE);
+	
+		ERP_IE_handler(padapter, pIE);
+	}
+	
+}
+
+static void update_bcn_htcap_ie(_adapter *padapter)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_htinfo_ie(_adapter *padapter)
+{	
+	/*
+	u8 beacon_updated = _FALSE;
+	u32 sta_info_update_type = STA_INFO_UPDATE_NONE;	
+	*/
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+	unsigned char *p, *ie = pnetwork->IEs;
+	u32 len = 0;	
+
+	if (pmlmepriv->htpriv.ht_option == _FALSE) 
+		return;
+
+	if (pmlmeinfo->HT_info_enable != 1)
+		return;
+
+
+	DBG_871X("%s current operation mode=0x%X\n",
+		   __FUNCTION__, pmlmepriv->ht_op_mode);
+
+	DBG_871X("num_sta_40mhz_intolerant(%d), 20mhz_width_req(%d), intolerant_ch_rpt(%d), olbc(%d)\n", 
+					pmlmepriv->num_sta_40mhz_intolerant, pmlmepriv->ht_20mhz_width_req, pmlmepriv->ht_intolerant_ch_reported, pmlmepriv->olbc);
+
+	/*parsing HT_INFO_IE, currently only update ht_op_mode - pht_info->infos[1] & pht_info->infos[2] for wifi logo test*/
+	p = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+	if (p && len > 0) {
+		struct HT_info_element *pht_info = NULL;
+		
+		pht_info = (struct HT_info_element *)(p + 2);		
+
+		/* for STA Channel Width/Secondary Channel Offset*/
+		if ((pmlmepriv->sw_to_20mhz == 0) && (pmlmeext->cur_channel <= 14)) {
+			if ((pmlmepriv->num_sta_40mhz_intolerant > 0) || (pmlmepriv->ht_20mhz_width_req == _TRUE) 
+				|| (pmlmepriv->ht_intolerant_ch_reported == _TRUE) || (pmlmepriv->olbc == _TRUE)) {
+				SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 0);
+				SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 0);
+
+				pmlmepriv->sw_to_20mhz = 1;
+				/*
+				sta_info_update_type |= STA_INFO_UPDATE_BW;
+				beacon_updated = _TRUE;
+				*/
+	
+				DBG_871X("%s:switching to 20Mhz\n", __FUNCTION__);	
+
+				/*TODO : cur_bwmode/cur_ch_offset switches to 20Mhz*/
+			}
+		} else {
+
+			if ((pmlmepriv->num_sta_40mhz_intolerant == 0) && (pmlmepriv->ht_20mhz_width_req == _FALSE) 
+				&& (pmlmepriv->ht_intolerant_ch_reported == _FALSE) && (pmlmepriv->olbc == _FALSE)) {
+
+				if (pmlmeext->cur_bwmode >= CHANNEL_WIDTH_40) {
+					
+					SET_HT_OP_ELE_STA_CHL_WIDTH(pht_info, 1);
+
+					SET_HT_OP_ELE_2ND_CHL_OFFSET(pht_info, 
+					(pmlmeext->cur_ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER) ? 
+						HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE : HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW);
+					
+					pmlmepriv->sw_to_20mhz = 0;
+					/*
+					sta_info_update_type |= STA_INFO_UPDATE_BW;
+					beacon_updated = _TRUE;
+					*/
+					
+					DBG_871X("%s:switching back to 40Mhz\n", __FUNCTION__);	
+				}
+			}
+		}
+
+		/* to update  ht_op_mode*/
+		*(u16 *)(pht_info->infos + 1) = cpu_to_le16(pmlmepriv->ht_op_mode);
+		
+	}	
+
+	/*associated_clients_update(padapter, beacon_updated, sta_info_update_type);*/
+
+}
+
+static void update_bcn_rsn_ie(_adapter *padapter)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_wpa_ie(_adapter *padapter)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+}
+
+static void update_bcn_wmm_ie(_adapter *padapter)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+	
+}
+
+static void update_bcn_wps_ie(_adapter *padapter)
+{
+	u8 *pwps_ie=NULL, *pwps_ie_src, *premainder_ie, *pbackup_remainder_ie=NULL;
+	uint wps_ielen=0, wps_offset, remainder_ielen;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+	unsigned char *ie = pnetwork->IEs;
+	u32 ielen = pnetwork->IELength;
+
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	pwps_ie = rtw_get_wps_ie(ie+_FIXED_IE_LENGTH_, ielen-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
+	
+	if(pwps_ie==NULL || wps_ielen==0)
+		return;
+
+	pwps_ie_src = pmlmepriv->wps_beacon_ie;
+	if(pwps_ie_src == NULL)
+		return;
+
+	wps_offset = (uint)(pwps_ie-ie);
+
+	premainder_ie = pwps_ie + wps_ielen;
+
+	remainder_ielen = ielen - wps_offset - wps_ielen;
+
+	if(remainder_ielen>0)
+	{
+		pbackup_remainder_ie = rtw_malloc(remainder_ielen);
+		if(pbackup_remainder_ie)
+			_rtw_memcpy(pbackup_remainder_ie, premainder_ie, remainder_ielen);
+	}
+
+	wps_ielen = (uint)pwps_ie_src[1];//to get ie data len
+	if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
+	{
+		_rtw_memcpy(pwps_ie, pwps_ie_src, wps_ielen+2);
+		pwps_ie += (wps_ielen+2);
+
+		if(pbackup_remainder_ie)
+			_rtw_memcpy(pwps_ie, pbackup_remainder_ie, remainder_ielen);
+
+		//update IELength
+		pnetwork->IELength = wps_offset + (wps_ielen+2) + remainder_ielen;
+	}
+
+	if(pbackup_remainder_ie)
+		rtw_mfree(pbackup_remainder_ie, remainder_ielen);
+	
+	// deal with the case without set_tx_beacon_cmd() in update_beacon() 
+#if defined( CONFIG_INTERRUPT_BASED_TXBCN ) || defined( CONFIG_PCI_HCI )
+	if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	{
+		u8 sr = 0;
+		rtw_get_wps_attr_content(pwps_ie_src,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);
+	
+		if( sr ) {
+			set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
+			DBG_871X("%s, set WIFI_UNDER_WPS\n", __func__);
+		}
+	}
+#endif
+}
+
+static void update_bcn_p2p_ie(_adapter *padapter)
+{
+
+}
+
+static void update_bcn_vendor_spec_ie(_adapter *padapter, u8*oui)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if(_rtw_memcmp(RTW_WPA_OUI, oui, 4))
+	{
+		update_bcn_wpa_ie(padapter);
+	}
+	else if(_rtw_memcmp(WMM_OUI, oui, 4))
+	{
+		update_bcn_wmm_ie(padapter);
+	}
+	else if(_rtw_memcmp(WPS_OUI, oui, 4))
+	{
+		update_bcn_wps_ie(padapter);
+	}
+	else if(_rtw_memcmp(P2P_OUI, oui, 4))
+	{
+		update_bcn_p2p_ie(padapter);
+	}
+	else
+	{
+		DBG_871X("unknown OUI type!\n");
+ 	}
+	
+	
+}
+
+void _update_beacon(_adapter *padapter, u8 ie_id, u8 *oui, u8 tx, const char *tag)
+{
+	_irqL irqL;
+	struct mlme_priv *pmlmepriv;
+	struct mlme_ext_priv	*pmlmeext;
+	//struct mlme_ext_info	*pmlmeinfo;
+	
+	//DBG_871X("%s\n", __FUNCTION__);
+
+	if(!padapter)
+		return;
+
+	pmlmepriv = &(padapter->mlmepriv);
+	pmlmeext = &(padapter->mlmeextpriv);
+	//pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if(_FALSE == pmlmeext->bstart_bss)
+		return;
+
+	_enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
+
+	switch(ie_id)
+	{
+		case 0xFF:
+
+			update_bcn_fixed_ie(padapter);//8: TimeStamp, 2: Beacon Interval 2:Capability
+			
+			break;
+	
+		case _TIM_IE_:
+			
+			update_BCNTIM(padapter);
+			
+			break;
+
+		case _ERPINFO_IE_:
+
+			update_bcn_erpinfo_ie(padapter);
+
+			break;
+
+		case _HT_CAPABILITY_IE_:
+
+			update_bcn_htcap_ie(padapter);
+			
+			break;
+
+		case _RSN_IE_2_:
+
+			update_bcn_rsn_ie(padapter);
+
+			break;
+			
+		case _HT_ADD_INFO_IE_:
+
+			update_bcn_htinfo_ie(padapter);
+			
+			break;
+	
+		case _EXT_CAP_IE_:
+
+			update_bcn_ext_capab_ie(padapter);
+
+			break;
+	
+		case _VENDOR_SPECIFIC_IE_:
+
+			update_bcn_vendor_spec_ie(padapter, oui);
+			
+			break;
+			
+		default:
+			break;
+	}
+
+	pmlmepriv->update_bcn = _TRUE;
+	
+	_exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);		
+	
+#ifndef CONFIG_INTERRUPT_BASED_TXBCN 
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+	if(tx)
+	{
+		//send_beacon(padapter);//send_beacon must execute on TSR level
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" ie_id:%u - %s\n", FUNC_ADPT_ARG(padapter), ie_id, tag);
+		set_tx_beacon_cmd(padapter);
+	}
+#else
+	{	
+		//PCI will issue beacon when BCN interrupt occurs.		
+	}
+#endif
+#endif //!CONFIG_INTERRUPT_BASED_TXBCN
+	
+}
+
+#ifdef CONFIG_80211N_HT
+
+void rtw_process_public_act_bsscoex(_adapter *padapter, u8 *pframe, uint frame_len)
+{
+	struct sta_info *psta;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 beacon_updated = _FALSE;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);	
+	uint frame_body_len = frame_len - sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 category, action;
+
+	psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+	if (psta == NULL) 
+		return;
+
+
+	category = frame_body[0];
+	action = frame_body[1];
+
+	if (frame_body_len > 0) {
+		if ((frame_body[2] == EID_BSSCoexistence) && (frame_body[3] > 0)) {			
+			u8 ie_data = frame_body[4];
+
+			if (ie_data & RTW_WLAN_20_40_BSS_COEX_40MHZ_INTOL) {
+				if (psta->ht_40mhz_intolerant == 0) {				
+					psta->ht_40mhz_intolerant = 1;
+					pmlmepriv->num_sta_40mhz_intolerant++;
+					beacon_updated = _TRUE;
+				}	
+			} else if (ie_data & RTW_WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ)	{				
+				if (pmlmepriv->ht_20mhz_width_req == _FALSE) {				
+					pmlmepriv->ht_20mhz_width_req = _TRUE;			
+					beacon_updated = _TRUE;
+				}	
+			} else
+				beacon_updated = _FALSE;
+		}		
+	}
+
+	if (frame_body_len > 8) {
+		/* if EID_BSSIntolerantChlReport ie exists */
+		if ((frame_body[5] == EID_BSSIntolerantChlReport) && (frame_body[6] > 0)) {
+			/*todo:*/
+			if (pmlmepriv->ht_intolerant_ch_reported == _FALSE) {				
+				pmlmepriv->ht_intolerant_ch_reported = _TRUE;			
+				beacon_updated = _TRUE;
+			}
+		}			
+	}
+
+	if (beacon_updated) {
+		
+		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
+	
+		associated_stainfo_update(padapter, psta, STA_INFO_UPDATE_BW);
+	}
+
+	
+	
+}
+
+void rtw_process_ht_action_smps(_adapter *padapter, u8 *ta, u8 ctrl_field)
+{
+	u8 e_field, m_field;
+	struct sta_info *psta;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	psta = rtw_get_stainfo(pstapriv, ta);
+	if (psta == NULL) 
+		return;
+
+	e_field = (ctrl_field & BIT(0)) ? 1 : 0;
+	m_field = (ctrl_field & BIT(1)) ? 1 : 0;	
+
+	if (e_field) {
+
+		/* enable */
+		/* 0:static SMPS, 1:dynamic SMPS, 3:SMPS disabled, 2:reserved*/
+		 
+		if (m_field) /*mode*/
+			psta->htpriv.smps_cap = 1;
+		else
+			psta->htpriv.smps_cap = 0;
+	} else {
+		/*disable*/
+		psta->htpriv.smps_cap = 3;
+	}
+
+	rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
+
+}
+
+/*
+op_mode
+Set to 0 (HT pure) under the followign conditions
+	- all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or
+	- all STAs in the BSS are 20 MHz HT in 20 MHz BSS
+Set to 1 (HT non-member protection) if there may be non-HT STAs
+	in both the primary and the secondary channel
+Set to 2 if only HT STAs are associated in BSS,
+	however and at least one 20 MHz HT STA is associated
+Set to 3 (HT mixed mode) when one or more non-HT STAs are associated
+	(currently non-GF HT station is considered as non-HT STA also)
+*/
+static int rtw_ht_operation_update(_adapter *padapter)
+{
+	u16 cur_op_mode, new_op_mode;
+	int op_mode_changes = 0;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct ht_priv	*phtpriv_ap = &pmlmepriv->htpriv;
+
+	if (pmlmepriv->htpriv.ht_option == _FALSE) 
+		return 0;
+	
+	/*if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed)
+		return 0;*/
+
+	DBG_871X("%s current operation mode=0x%X\n",
+		   __FUNCTION__, pmlmepriv->ht_op_mode);
+
+	if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)
+	    && pmlmepriv->num_sta_ht_no_gf) {
+		pmlmepriv->ht_op_mode |=
+			HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+		op_mode_changes++;
+	} else if ((pmlmepriv->ht_op_mode &
+		    HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT) &&
+		   pmlmepriv->num_sta_ht_no_gf == 0) {
+		pmlmepriv->ht_op_mode &=
+			~HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT;
+		op_mode_changes++;
+	}
+
+	if (!(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+	    (pmlmepriv->num_sta_no_ht || pmlmepriv->olbc_ht)) {
+		pmlmepriv->ht_op_mode |= HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+		op_mode_changes++;
+	} else if ((pmlmepriv->ht_op_mode &
+		    HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT) &&
+		   (pmlmepriv->num_sta_no_ht == 0 && !pmlmepriv->olbc_ht)) {
+		pmlmepriv->ht_op_mode &=
+			~HT_INFO_OPERATION_MODE_NON_HT_STA_PRESENT;
+		op_mode_changes++;
+	}
+
+	/* Note: currently we switch to the MIXED op mode if HT non-greenfield
+	 * station is associated. Probably it's a theoretical case, since
+	 * it looks like all known HT STAs support greenfield.
+	 */
+	new_op_mode = 0;
+	if (pmlmepriv->num_sta_no_ht /*||
+	    (pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/)
+		new_op_mode = OP_MODE_MIXED;
+	else if ((phtpriv_ap->ht_cap.cap_info & IEEE80211_HT_CAP_SUP_WIDTH)
+		 && pmlmepriv->num_sta_ht_20mhz)
+		new_op_mode = OP_MODE_20MHZ_HT_STA_ASSOCED;
+	else if (pmlmepriv->olbc_ht)
+		new_op_mode = OP_MODE_MAY_BE_LEGACY_STAS;
+	else
+		new_op_mode = OP_MODE_PURE;
+
+	cur_op_mode = pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+	if (cur_op_mode != new_op_mode) {
+		pmlmepriv->ht_op_mode &= ~HT_INFO_OPERATION_MODE_OP_MODE_MASK;
+		pmlmepriv->ht_op_mode |= new_op_mode;
+		op_mode_changes++;
+	}
+
+	DBG_871X("%s new operation mode=0x%X changes=%d\n",
+		   __FUNCTION__, pmlmepriv->ht_op_mode, op_mode_changes);
+
+	return op_mode_changes;
+	
+}
+
+#endif /* CONFIG_80211N_HT */
+
+void associated_clients_update(_adapter *padapter, u8 updated, u32 sta_info_type)
+{
+	//update associcated stations cap.
+	if(updated == _TRUE)
+	{
+		_irqL irqL;
+		_list	*phead, *plist;
+		struct sta_info *psta=NULL;	
+		struct sta_priv *pstapriv = &padapter->stapriv;
+			
+		_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+		
+		phead = &pstapriv->asoc_list;
+		plist = get_next(phead);
+		
+		//check asoc_queue
+		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)	
+		{
+			psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		
+			plist = get_next(plist);
+
+			associated_stainfo_update(padapter, psta, sta_info_type);			
+		}
+
+		_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	}		
+
+}
+
+/* called > TSR LEVEL for USB or SDIO Interface*/
+void bss_cap_update_on_sta_join(_adapter *padapter, struct sta_info *psta)
+{
+	u8 beacon_updated = _FALSE;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+	
+#if 0
+	if (!(psta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) &&
+	    !psta->no_short_preamble_set) {
+		psta->no_short_preamble_set = 1;
+		pmlmepriv->num_sta_no_short_preamble++;
+		if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && 
+		     (pmlmepriv->num_sta_no_short_preamble == 1))
+			ieee802_11_set_beacons(hapd->iface);
+	}
+#endif
+
+
+	if(!(psta->flags & WLAN_STA_SHORT_PREAMBLE))	
+	{
+		if(!psta->no_short_preamble_set)
+		{
+			psta->no_short_preamble_set = 1;
+			
+			pmlmepriv->num_sta_no_short_preamble++;
+			
+			if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && 
+		     		(pmlmepriv->num_sta_no_short_preamble == 1))
+			{
+				beacon_updated = _TRUE;
+				update_beacon(padapter, 0xFF, NULL, _TRUE);
+			}	
+			
+		}
+	}
+	else
+	{
+		if(psta->no_short_preamble_set)
+		{
+			psta->no_short_preamble_set = 0;
+			
+			pmlmepriv->num_sta_no_short_preamble--;
+			
+			if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) && 
+		     		(pmlmepriv->num_sta_no_short_preamble == 0))
+			{
+				beacon_updated = _TRUE;
+				update_beacon(padapter, 0xFF, NULL, _TRUE);
+			}	
+			
+		}
+	}
+
+#if 0
+	if (psta->flags & WLAN_STA_NONERP && !psta->nonerp_set) {
+		psta->nonerp_set = 1;
+		pmlmepriv->num_sta_non_erp++;
+		if (pmlmepriv->num_sta_non_erp == 1)
+			ieee802_11_set_beacons(hapd->iface);
+	}
+#endif
+
+	if(psta->flags & WLAN_STA_NONERP)
+	{
+		if(!psta->nonerp_set)
+		{
+			psta->nonerp_set = 1;
+			
+			pmlmepriv->num_sta_non_erp++;
+			
+			if (pmlmepriv->num_sta_non_erp == 1)
+			{
+				beacon_updated = _TRUE;
+				update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
+			}	
+		}
+		
+	}
+	else
+	{
+		if(psta->nonerp_set)
+		{
+			psta->nonerp_set = 0;
+			
+			pmlmepriv->num_sta_non_erp--;
+			
+			if (pmlmepriv->num_sta_non_erp == 0)
+			{
+				beacon_updated = _TRUE;
+				update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
+			}	
+		}
+		
+	}
+
+
+#if 0
+	if (!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT) &&
+	    !psta->no_short_slot_time_set) {
+		psta->no_short_slot_time_set = 1;
+		pmlmepriv->num_sta_no_short_slot_time++;
+		if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+		    (pmlmepriv->num_sta_no_short_slot_time == 1))
+			ieee802_11_set_beacons(hapd->iface);
+	}
+#endif
+
+	if(!(psta->capability & WLAN_CAPABILITY_SHORT_SLOT))
+	{
+		if(!psta->no_short_slot_time_set)
+		{
+			psta->no_short_slot_time_set = 1;
+			
+			pmlmepriv->num_sta_no_short_slot_time++;
+			
+			if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+		   		 (pmlmepriv->num_sta_no_short_slot_time == 1))
+			{
+				beacon_updated = _TRUE;
+				update_beacon(padapter, 0xFF, NULL, _TRUE);
+			}			
+			
+		}
+	}
+	else
+	{
+		if(psta->no_short_slot_time_set)
+		{
+			psta->no_short_slot_time_set = 0;
+			
+			pmlmepriv->num_sta_no_short_slot_time--;
+			
+			if ((pmlmeext->cur_wireless_mode > WIRELESS_11B) &&
+		   		 (pmlmepriv->num_sta_no_short_slot_time == 0))
+			{
+				beacon_updated = _TRUE;
+				update_beacon(padapter, 0xFF, NULL, _TRUE);
+			}			
+		}
+	}	
+	
+#ifdef CONFIG_80211N_HT
+
+	if (psta->flags & WLAN_STA_HT) 
+	{
+		u16 ht_capab = le16_to_cpu(psta->htpriv.ht_cap.cap_info);
+			
+		DBG_871X("HT: STA " MAC_FMT " HT Capabilities "
+			   "Info: 0x%04x\n", MAC_ARG(psta->hwaddr), ht_capab);
+
+		if (psta->no_ht_set) {
+			psta->no_ht_set = 0;
+			pmlmepriv->num_sta_no_ht--;
+		}
+		
+		if ((ht_capab & IEEE80211_HT_CAP_GRN_FLD) == 0) {
+			if (!psta->no_ht_gf_set) {
+				psta->no_ht_gf_set = 1;
+				pmlmepriv->num_sta_ht_no_gf++;
+			}
+			DBG_871X("%s STA " MAC_FMT " - no "
+				   "greenfield, num of non-gf stations %d\n",
+				   __FUNCTION__, MAC_ARG(psta->hwaddr),
+				   pmlmepriv->num_sta_ht_no_gf);
+		}
+		
+		if ((ht_capab & IEEE80211_HT_CAP_SUP_WIDTH) == 0) {
+			if (!psta->ht_20mhz_set) {
+				psta->ht_20mhz_set = 1;
+				pmlmepriv->num_sta_ht_20mhz++;
+			}
+			DBG_871X("%s STA " MAC_FMT " - 20 MHz HT, "
+				   "num of 20MHz HT STAs %d\n",
+				   __FUNCTION__, MAC_ARG(psta->hwaddr),
+				   pmlmepriv->num_sta_ht_20mhz);
+		}
+		
+
+		if (ht_capab & RTW_IEEE80211_HT_CAP_40MHZ_INTOLERANT) {
+
+			if (!psta->ht_40mhz_intolerant) {
+				psta->ht_40mhz_intolerant = 1;
+				pmlmepriv->num_sta_40mhz_intolerant++;
+				DBG_871X("%s STA " MAC_FMT " - HT_CAP_40MHZ_INTOLERANT is set\n" ,
+				   __FUNCTION__, MAC_ARG(psta->hwaddr));
+				beacon_updated = _TRUE;
+			}
+				
+/*
+			if (pmlmepriv->ht_40mhz_intolerant == _FALSE) {
+				
+				pmlmepriv->ht_40mhz_intolerant = _TRUE;				
+			
+				DBG_871X("%s STA " MAC_FMT " - HT_CAP_40MHZ_INTOLERANT is set\n" ,
+				   __FUNCTION__, MAC_ARG(psta->hwaddr));
+
+				beacon_updated = _TRUE;
+			}
+*/			
+
+			/*update ext_capab_ie_len & ext_capab_ie_data for beacon, probersp, assocrsp.*/
+			if (pmlmepriv->ext_capab_ie_len == 0)
+				pmlmepriv->ext_capab_ie_len = 1;
+			SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 1);
+
+			update_beacon(padapter, _EXT_CAP_IE_, NULL, _FALSE);
+		}		
+		
+	} 
+	else 
+	{
+		if (!psta->no_ht_set) {
+			psta->no_ht_set = 1;
+			pmlmepriv->num_sta_no_ht++;
+		}
+		if(pmlmepriv->htpriv.ht_option == _TRUE) {		
+			DBG_871X("%s STA " MAC_FMT
+				   " - no HT, num of non-HT stations %d\n",
+				   __FUNCTION__, MAC_ARG(psta->hwaddr),
+				   pmlmepriv->num_sta_no_ht);
+		}
+	}
+
+	if (rtw_ht_operation_update(padapter) > 0) {
+		update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
+		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
+		/*beacon_updated = _TRUE;*/
+	}	
+	
+#endif /* CONFIG_80211N_HT */
+
+	//update associcated stations cap.
+	associated_clients_update(padapter,  beacon_updated, STA_INFO_UPDATE_ALL);
+
+	DBG_871X("%s, updated=%d\n", __func__, beacon_updated);
+
+}
+
+u8 bss_cap_update_on_sta_leave(_adapter *padapter, struct sta_info *psta)
+{
+	u8 beacon_updated = _FALSE;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+
+	if(!psta)
+		return beacon_updated;
+
+	if (psta->no_short_preamble_set) {
+		psta->no_short_preamble_set = 0;
+		pmlmepriv->num_sta_no_short_preamble--;
+		if (pmlmeext->cur_wireless_mode > WIRELESS_11B
+		    && pmlmepriv->num_sta_no_short_preamble == 0)
+		{
+			beacon_updated = _TRUE;
+			update_beacon(padapter, 0xFF, NULL, _TRUE);
+		}	
+	}	
+
+	if (psta->nonerp_set) {
+		psta->nonerp_set = 0;		
+		pmlmepriv->num_sta_non_erp--;
+		if (pmlmepriv->num_sta_non_erp == 0)
+		{
+			beacon_updated = _TRUE;
+			update_beacon(padapter, _ERPINFO_IE_, NULL, _TRUE);
+		}	
+	}
+
+	if (psta->no_short_slot_time_set) {
+		psta->no_short_slot_time_set = 0;
+		pmlmepriv->num_sta_no_short_slot_time--;
+		if (pmlmeext->cur_wireless_mode > WIRELESS_11B
+		    && pmlmepriv->num_sta_no_short_slot_time == 0)
+		{
+			beacon_updated = _TRUE;
+			update_beacon(padapter, 0xFF, NULL, _TRUE);
+		}	
+	}
+	
+#ifdef CONFIG_80211N_HT
+
+	if (psta->no_ht_gf_set) {
+		psta->no_ht_gf_set = 0;
+		pmlmepriv->num_sta_ht_no_gf--;
+	}
+
+	if (psta->no_ht_set) {
+		psta->no_ht_set = 0;
+		pmlmepriv->num_sta_no_ht--;
+	}
+
+	if (psta->ht_20mhz_set) {
+		psta->ht_20mhz_set = 0;
+		pmlmepriv->num_sta_ht_20mhz--;
+	}
+
+	if (psta->ht_40mhz_intolerant) {
+		psta->ht_40mhz_intolerant = 0;
+		pmlmepriv->num_sta_40mhz_intolerant--;
+
+		/*update ext_capab_ie_len & ext_capab_ie_data for beacon, probersp, assocrsp.*/
+		if ((pmlmepriv->ext_capab_ie_len > 0) && (pmlmepriv->num_sta_40mhz_intolerant == 0)) {
+			SET_EXT_CAPABILITY_ELE_BSS_COEXIST(pmlmepriv->ext_capab_ie_data, 0);
+			update_beacon(padapter, _EXT_CAP_IE_, NULL, _FALSE);
+		}
+		
+		beacon_updated = _TRUE;
+
+		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _FALSE);
+	}
+
+	if (rtw_ht_operation_update(padapter) > 0) {
+		update_beacon(padapter, _HT_CAPABILITY_IE_, NULL, _FALSE);
+		update_beacon(padapter, _HT_ADD_INFO_IE_, NULL, _TRUE);
+	}
+	
+#endif /* CONFIG_80211N_HT */
+
+	/* update associated stations cap.
+	associated_clients_update(padapter,  beacon_updated, STA_INFO_UPDATE_ALL); //move it to avoid deadlock
+	*/
+	
+	DBG_871X("%s, updated=%d\n", __func__, beacon_updated);
+
+	return beacon_updated;
+
+}
+
+u8 ap_free_sta(_adapter *padapter, struct sta_info *psta, bool active, u16 reason, bool enqueue)
+{
+	_irqL irqL;
+	u8 beacon_updated = _FALSE;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	if(!psta)
+		return beacon_updated;
+
+	if (active == _TRUE)
+	{
+#ifdef CONFIG_80211N_HT
+		//tear down Rx AMPDU
+		send_delba(padapter, 0, psta->hwaddr);// recipient
+	
+		//tear down TX AMPDU
+		send_delba(padapter, 1, psta->hwaddr);// // originator
+		
+#endif //CONFIG_80211N_HT
+
+		issue_deauth(padapter, psta->hwaddr, reason);
+	}
+
+#ifdef CONFIG_BEAMFORMING
+	beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, psta->hwaddr, ETH_ALEN, 1);
+#endif
+
+	psta->htpriv.agg_enable_bitmap = 0x0;//reset
+	psta->htpriv.candidate_tid_bitmap = 0x0;//reset
+
+	//clear cam entry / key
+	rtw_clearstakey_cmd(padapter, psta, enqueue);
+
+
+	_enter_critical_bh(&psta->lock, &irqL);
+	psta->state &= ~_FW_LINKED;
+	_exit_critical_bh(&psta->lock, &irqL);
+
+	#ifdef CONFIG_IOCTL_CFG80211
+	if (1) {
+		#ifdef COMPAT_KERNEL_RELEASE
+		rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
+		#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+		rtw_cfg80211_indicate_sta_disassoc(padapter, psta->hwaddr, reason);
+		#else //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+		/* will call rtw_cfg80211_indicate_sta_disassoc() in cmd_thread for old API context */
+		#endif //(LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37)) && !defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+	} else
+	#endif //CONFIG_IOCTL_CFG80211
+	{
+		rtw_indicate_sta_disassoc_event(padapter, psta);
+	}
+
+	report_del_sta_event(padapter, psta->hwaddr, reason, enqueue);
+
+	beacon_updated = bss_cap_update_on_sta_leave(padapter, psta);
+
+	//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);					
+	rtw_free_stainfo(padapter, psta);
+	//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+	
+
+	return beacon_updated;
+
+}
+
+int rtw_ap_inform_ch_switch(_adapter *padapter, u8 new_ch, u8 ch_offset)
+{
+	_irqL irqL;
+	_list	*phead, *plist;
+	int ret=0;	
+	struct sta_info *psta = NULL;	
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+	if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+		return ret;
+
+	DBG_871X(FUNC_NDEV_FMT" with ch:%u, offset:%u\n",
+		FUNC_NDEV_ARG(padapter->pnetdev), new_ch, ch_offset);
+
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+	
+	/* for each sta in asoc_queue */
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)	
+	{		
+		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		plist = get_next(plist);
+
+		issue_action_spct_ch_switch(padapter, psta->hwaddr, new_ch, ch_offset);
+		psta->expire_to = ((pstapriv->expire_to * 2) > 5) ? 5 : (pstapriv->expire_to * 2);
+	}
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	issue_action_spct_ch_switch(padapter, bc_addr, new_ch, ch_offset);
+
+	return ret;
+}
+
+int rtw_sta_flush(_adapter *padapter, bool enqueue)
+{
+	_irqL irqL;
+	_list	*phead, *plist;
+	int ret = 0;
+	struct sta_info *psta = NULL;	
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 flush_num = 0;
+	char flush_list[NUM_STA];
+	int i;
+
+	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+		return ret;
+
+	DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
+	/* pick sta from sta asoc_queue */
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+		int stainfo_offset;
+
+		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		plist = get_next(plist);
+
+		rtw_list_delete(&psta->asoc_list);
+		pstapriv->asoc_list_cnt--;
+
+		stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+		if (stainfo_offset_valid(stainfo_offset))
+			flush_list[flush_num++] = stainfo_offset;
+		else
+			rtw_warn_on(1);
+	}
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	/* call ap_free_sta() for each sta picked */
+	for (i = 0; i < flush_num; i++) {
+		psta = rtw_get_stainfo_by_offset(pstapriv, flush_list[i]);
+		ap_free_sta(padapter, psta, _TRUE, WLAN_REASON_DEAUTH_LEAVING, enqueue);
+	}
+
+	issue_deauth(padapter, bc_addr, WLAN_REASON_DEAUTH_LEAVING);
+
+	associated_clients_update(padapter, _TRUE, STA_INFO_UPDATE_ALL);
+
+	return ret;
+}
+
+/* called > TSR LEVEL for USB or SDIO Interface*/
+void sta_info_update(_adapter *padapter, struct sta_info *psta)
+{	
+	int flags = psta->flags;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	
+				
+	//update wmm cap.
+	if(WLAN_STA_WME&flags)
+		psta->qos_option = 1;
+	else
+		psta->qos_option = 0;
+
+	if(pmlmepriv->qospriv.qos_option == 0)	
+		psta->qos_option = 0;
+
+		
+#ifdef CONFIG_80211N_HT		
+	//update 802.11n ht cap.
+	if(WLAN_STA_HT&flags)
+	{
+		psta->htpriv.ht_option = _TRUE;
+		psta->qos_option = 1;	
+
+		psta->htpriv.smps_cap = (psta->htpriv.ht_cap.cap_info & IEEE80211_HT_CAP_SM_PS)>>2;
+	}
+	else		
+	{
+		psta->htpriv.ht_option = _FALSE;
+	}
+		
+	if(pmlmepriv->htpriv.ht_option == _FALSE)	
+		psta->htpriv.ht_option = _FALSE;
+#endif
+
+#ifdef CONFIG_80211AC_VHT
+	//update 802.11AC vht cap.
+	if(WLAN_STA_VHT&flags)
+	{
+		psta->vhtpriv.vht_option = _TRUE;
+	}
+	else		
+	{
+		psta->vhtpriv.vht_option = _FALSE;
+	}
+
+	if(pmlmepriv->vhtpriv.vht_option == _FALSE)
+		psta->vhtpriv.vht_option = _FALSE;
+#endif	
+
+
+	update_sta_info_apmode(padapter, psta);
+		
+
+}
+
+/* called >= TSR LEVEL for USB or SDIO Interface*/
+void ap_sta_info_defer_update(_adapter *padapter, struct sta_info *psta)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if(psta->state & _FW_LINKED)
+	{
+		pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+	
+		//add ratid
+		add_RATid(padapter, psta, 0);//DM_RATR_STA_INIT
+	}	
+}
+/* restore hw setting from sw data structures */
+void rtw_ap_restore_network(_adapter *padapter)
+{
+	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_priv * pstapriv = &padapter->stapriv;
+	struct sta_info *psta;
+	struct security_priv* psecuritypriv=&(padapter->securitypriv);
+	_irqL irqL;
+	_list	*phead, *plist;
+	u8 chk_alive_num = 0;
+	char chk_alive_list[NUM_STA];
+	int i;
+
+	rtw_setopmode_cmd(padapter, Ndis802_11APMode,_FALSE);
+
+	set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+	rtw_startbss_cmd(padapter, RTW_CMDF_DIRECTLY);
+
+	if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
+		(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
+	{
+		/* restore group key, WEP keys is restored in ips_leave() */
+		rtw_set_key(padapter, psecuritypriv, psecuritypriv->dot118021XGrpKeyid, 0,_FALSE);
+	}
+
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+		int stainfo_offset;
+
+		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		plist = get_next(plist);
+
+		stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+		if (stainfo_offset_valid(stainfo_offset)) {
+			chk_alive_list[chk_alive_num++] = stainfo_offset;
+		}
+	}
+
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	for (i = 0; i < chk_alive_num; i++) {
+		psta = rtw_get_stainfo_by_offset(pstapriv, chk_alive_list[i]);
+
+		if (psta == NULL) {
+			DBG_871X(FUNC_ADPT_FMT" sta_info is null\n", FUNC_ADPT_ARG(padapter));
+		} else if (psta->state &_FW_LINKED) {
+			rtw_sta_media_status_rpt(padapter, psta, 1);
+			Update_RA_Entry(padapter, psta);
+			//pairwise key
+			/* per sta pairwise key and settings */
+			if(	(padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
+				(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
+			{
+				rtw_setstakey_cmd(padapter, psta, UNICAST_KEY,_FALSE);
+			}			
+		}
+	}
+
+}
+
+void start_ap_mode(_adapter *padapter)
+{
+	int i;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+	
+	pmlmepriv->update_bcn = _FALSE;
+	
+	/*init_mlme_ap_info(padapter);*/
+	
+	pmlmeext->bstart_bss = _FALSE;
+
+	pmlmepriv->num_sta_non_erp = 0;
+
+	pmlmepriv->num_sta_no_short_slot_time = 0;
+
+	pmlmepriv->num_sta_no_short_preamble = 0;
+
+	pmlmepriv->num_sta_ht_no_gf = 0;
+#ifdef CONFIG_80211N_HT
+	pmlmepriv->num_sta_no_ht = 0;
+#endif //CONFIG_80211N_HT
+	pmlmeinfo->HT_info_enable = 0;
+	pmlmeinfo->HT_caps_enable = 0;
+	pmlmeinfo->HT_enable = 0;
+	
+	pmlmepriv->num_sta_ht_20mhz = 0;
+	pmlmepriv->num_sta_40mhz_intolerant = 0;
+	pmlmepriv->olbc = _FALSE;
+	pmlmepriv->olbc_ht = _FALSE;
+	
+#ifdef CONFIG_80211N_HT
+	pmlmepriv->ht_20mhz_width_req = _FALSE;
+	pmlmepriv->ht_intolerant_ch_reported = _FALSE;
+	pmlmepriv->ht_op_mode = 0;
+	pmlmepriv->sw_to_20mhz = 0;
+#endif
+
+	_rtw_memset(pmlmepriv->ext_capab_ie_data, 0, sizeof(pmlmepriv->ext_capab_ie_data));
+	pmlmepriv->ext_capab_ie_len = 0;
+
+	for (i = 0 ;  i < NUM_STA ; i++)
+		pstapriv->sta_aid[i] = NULL;
+	
+	//for ACL 
+	_rtw_init_listhead(&(pacl_list->acl_node_q.queue));
+	pacl_list->num = 0;
+	pacl_list->mode = 0;
+	for(i = 0; i < NUM_ACL; i++)
+	{		
+		_rtw_init_listhead(&pacl_list->aclnode[i].list);
+		pacl_list->aclnode[i].valid = _FALSE;
+	}
+
+}
+
+void stop_ap_mode(_adapter *padapter)
+{
+	_irqL irqL;
+	_list	*phead, *plist;
+	struct rtw_wlan_acl_node *paclnode;
+	struct sta_info *psta=NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;	
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+	_queue	*pacl_node_q =&pacl_list->acl_node_q;	
+
+	pmlmepriv->update_bcn = _FALSE;
+	pmlmeext->bstart_bss = _FALSE;
+	padapter->netif_up = _FALSE;
+	//_rtw_spinlock_free(&pmlmepriv->bcn_update_lock);
+	
+	//reset and init security priv , this can refine with rtw_reset_securitypriv
+	_rtw_memset((unsigned char *)&padapter->securitypriv, 0, sizeof (struct security_priv));
+	padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeOpen;
+	padapter->securitypriv.ndisencryptstatus = Ndis802_11WEPDisabled;
+
+	#ifdef CONFIG_DFS_MASTER
+	rtw_dfs_master_status_apply(padapter, MLME_AP_STOPPED);
+	#endif
+
+	/* free scan queue */
+	rtw_free_network_queue(padapter, _TRUE);
+
+	//for ACL
+	_enter_critical_bh(&(pacl_node_q->lock), &irqL);
+	phead = get_list_head(pacl_node_q);
+	plist = get_next(phead);		
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+		plist = get_next(plist);
+
+		if(paclnode->valid == _TRUE)
+		{
+			paclnode->valid = _FALSE;
+
+			rtw_list_delete(&paclnode->list);
+				
+			pacl_list->num--;		
+		}		
+	}	
+	_exit_critical_bh(&(pacl_node_q->lock), &irqL);
+	
+	DBG_871X("%s, free acl_node_queue, num=%d\n", __func__, pacl_list->num);
+	
+	rtw_sta_flush(padapter, _TRUE);
+
+	//free_assoc_sta_resources	
+	rtw_free_all_stainfo(padapter);
+	
+	psta = rtw_get_bcmc_stainfo(padapter);
+	//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+	rtw_free_stainfo(padapter, psta);
+	//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+	
+	rtw_init_bcmc_stainfo(padapter);	
+
+	rtw_free_mlme_priv_ie_data(pmlmepriv);
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_MediaStatusNotify(padapter, 0); //disconnect 
+#endif	
+
+}
+
+#endif //CONFIG_NATIVEAP_MLME
+
+void rtw_ap_update_bss_chbw(_adapter *adapter, WLAN_BSSID_EX *bss, u8 ch, u8 bw, u8 offset)
+{
+#define UPDATE_VHT_CAP 1
+#define UPDATE_HT_CAP 1
+
+#ifdef CONFIG_80211AC_VHT
+	{
+		struct vht_priv	*vhtpriv = &adapter->mlmepriv.vhtpriv;
+		u8 *vht_cap_ie, *vht_op_ie;
+		int vht_cap_ielen, vht_op_ielen;
+		u8	center_freq;
+
+		vht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTCapability, &vht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+		vht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_VHTOperation, &vht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+		center_freq = rtw_get_center_ch(ch, bw, offset);
+
+		/* update vht cap ie */
+		if (vht_cap_ie && vht_cap_ielen) {
+			#if UPDATE_VHT_CAP
+			/* if ((bw == CHANNEL_WIDTH_160 || bw == CHANNEL_WIDTH_80_80) && pvhtpriv->sgi_160m)
+				SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvht_cap_ie + 2, 1);
+			else */
+				SET_VHT_CAPABILITY_ELE_SHORT_GI160M(vht_cap_ie + 2, 0);
+
+			if (bw >= CHANNEL_WIDTH_80 && vhtpriv->sgi_80m)
+				SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 1);
+			else
+				SET_VHT_CAPABILITY_ELE_SHORT_GI80M(vht_cap_ie + 2, 0);
+			#endif
+		}
+
+		/* update vht op ie */
+		if (vht_op_ie && vht_op_ielen) {
+			if (bw < CHANNEL_WIDTH_80) {
+				SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 0);
+				SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, 0);
+				SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
+			} else if (bw == CHANNEL_WIDTH_80) {
+				SET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2, 1);
+				SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(vht_op_ie + 2, center_freq);
+				SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(vht_op_ie + 2, 0);
+			} else {
+				DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" unsupported BW:%u\n", FUNC_ADPT_ARG(adapter), bw);
+				rtw_warn_on(1);
+			}
+		}
+	}
+#endif /* CONFIG_80211AC_VHT */
+#ifdef CONFIG_80211N_HT
+	{
+		struct ht_priv	*htpriv = &adapter->mlmepriv.htpriv;
+		u8 *ht_cap_ie, *ht_op_ie;
+		int ht_cap_ielen, ht_op_ielen;
+
+		ht_cap_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTCapability, &ht_cap_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+		ht_op_ie = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), EID_HTInfo, &ht_op_ielen, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+
+		/* update ht cap ie */
+		if (ht_cap_ie && ht_cap_ielen) {
+			#if UPDATE_HT_CAP
+			if (bw >= CHANNEL_WIDTH_40)
+				SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 1);
+			else
+				SET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2, 0);
+
+			if (bw >= CHANNEL_WIDTH_40 && htpriv->sgi_40m)
+				SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 1);
+			else
+				SET_HT_CAP_ELE_SHORT_GI40M(ht_cap_ie + 2, 0);
+
+			if (htpriv->sgi_20m)
+				SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 1);
+			else
+				SET_HT_CAP_ELE_SHORT_GI20M(ht_cap_ie + 2, 0);
+			#endif
+		}
+
+		/* update ht op ie */
+		if (ht_op_ie && ht_op_ielen) {
+			SET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2, ch);
+			switch (offset) {
+			case HAL_PRIME_CHNL_OFFSET_LOWER:
+				SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCA);
+				break;
+			case HAL_PRIME_CHNL_OFFSET_UPPER:
+				SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCB);
+				break;
+			case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
+			default:
+				SET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2, SCN);
+				break;
+			}
+
+			if (bw >= CHANNEL_WIDTH_40)
+				SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 1);
+			else
+				SET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2, 0);
+		}
+	}
+#endif /* CONFIG_80211N_HT */
+
+{
+	u8 *p;
+	int ie_len;
+	u8 old_ch = bss->Configuration.DSConfig;
+	bool change_band = _FALSE;
+
+	if ((ch <= 14 && old_ch >= 36) || (ch >= 36 && old_ch <= 14))
+		change_band = _TRUE;
+
+	/* update channel in IE */
+	p = rtw_get_ie((bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)), _DSSET_IE_, &ie_len, (bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)));
+	if (p && ie_len > 0)
+		*(p + 2) = ch;
+
+	bss->Configuration.DSConfig = ch;
+
+	/* band is changed, update ERP, support rate, ext support rate IE */
+	if (change_band == _TRUE)
+		change_band_update_ie(adapter, bss, ch);
+}
+
+}
+
+bool rtw_ap_chbw_decision(_adapter *adapter, u8 req_ch, u8 req_bw, u8 req_offset
+	, u8 *ch, u8 *bw, u8 *offset)
+{
+	u8 dec_ch, dec_bw, dec_offset;
+	u8 u_ch = 0, u_offset, u_bw;
+	bool changed = _FALSE;
+	struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
+	u8 sta_num;
+	u8 ld_sta_num;
+	u8 lg_sta_num;
+	u8 ap_num;
+	u8 ld_ap_num;
+	bool set_u_ch = _FALSE, set_dec_ch = _FALSE;
+
+	dec_ch = req_ch;
+	dec_bw = req_bw;
+	dec_offset = req_offset;
+	
+	rtw_dev_iface_status_no_self(adapter, &sta_num, &ld_sta_num, &lg_sta_num, &ap_num, &ld_ap_num);
+	DBG_871X(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num%u, ap_num:%u\n"
+		, FUNC_ADPT_ARG(adapter), ld_sta_num, lg_sta_num, ap_num);
+
+	if (ld_sta_num || ap_num) {
+		/* has linked STA or AP mode, follow */
+
+		rtw_warn_on(!rtw_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset));
+
+		DBG_871X(FUNC_ADPT_FMT" union no self: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
+		DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), req_ch, req_bw, req_offset);
+
+		rtw_adjust_chbw(adapter, u_ch, &dec_bw, &dec_offset);
+
+		rtw_sync_chbw(&dec_ch, &dec_bw, &dec_offset
+			, &u_ch, &u_bw, &u_offset);
+
+		rtw_ap_update_bss_chbw(adapter, &(adapter->mlmepriv.cur_network.network)
+			, dec_ch, dec_bw, dec_offset);
+
+		set_u_ch = _TRUE;
+	} else if (lg_sta_num) {
+		/* has linking STA */
+
+		rtw_warn_on(!rtw_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset));
+
+		DBG_871X(FUNC_ADPT_FMT" union no self: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
+		DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), req_ch, req_bw, req_offset);
+
+		rtw_adjust_chbw(adapter, dec_ch, &dec_bw, &dec_offset);
+		
+		if (rtw_is_chbw_grouped(u_ch, u_bw, u_offset, dec_ch, dec_bw, dec_offset)) {
+
+			rtw_sync_chbw(&dec_ch, &dec_bw, &dec_offset
+					, &u_ch, &u_bw, &u_offset);
+
+			rtw_ap_update_bss_chbw(adapter, &(adapter->mlmepriv.cur_network.network)
+				, dec_ch, dec_bw, dec_offset);
+
+			set_u_ch = _TRUE;
+		} else {
+			/* set this for possible ch change when join down*/
+			set_fwstate(&adapter->mlmepriv, WIFI_OP_CH_SWITCHING);
+		}
+	} else {
+		/* single AP mode */
+
+		DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), req_ch, req_bw, req_offset);
+		rtw_adjust_chbw(adapter, dec_ch, &dec_bw, &dec_offset);
+
+		#if defined(CONFIG_DFS_MASTER)
+		/* check NOL */
+		if (rtw_chset_is_ch_non_ocp(mlmeext->channel_set, dec_ch, dec_bw, dec_offset)) {
+			/* choose 5G DFS channel for debug */
+			if (adapter_to_rfctl(adapter)->dbg_dfs_master_choose_dfs_ch_first
+				&& rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G|RTW_CHF_NON_DFS) == _TRUE) {
+				DBG_871X(FUNC_ADPT_FMT" choose 5G DFS channel for debug\n", FUNC_ADPT_ARG(adapter));
+			} else 
+			/* choose from 5G no DFS */
+			if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G|RTW_CHF_DFS) == _FALSE) {
+				/* including 5G DFS, not long CAC */
+				if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G|RTW_CHF_LONG_CAC) == _FALSE) {
+					/* including 5G DFS, long CAC */
+					if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_2G) == _FALSE) {
+						/* including 2.4G channel */
+						if (rtw_choose_available_chbw(adapter, req_bw, &dec_ch, &dec_bw, &dec_offset, RTW_CHF_5G) == _FALSE) {
+							DBG_871X(FUNC_ADPT_FMT" no available ch\n", FUNC_ADPT_ARG(adapter));
+							rtw_warn_on(1);
+						}
+					}
+				}
+			}
+		}
+		#endif /* defined(CONFIG_DFS_MASTER) */
+
+		rtw_ap_update_bss_chbw(adapter, &(adapter->mlmepriv.cur_network.network)
+				, dec_ch, dec_bw, dec_offset);
+
+		set_dec_ch = _TRUE;
+	}
+
+	if (check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY)
+		#ifdef CONFIG_CONCURRENT_MODE
+		|| check_buddy_fwstate(adapter, _FW_UNDER_SURVEY)
+		#endif
+	) {
+		/* scanning, leave ch setting to scan state machine */
+		set_u_ch = set_dec_ch = _FALSE;
+	}
+
+	if (mlmeext->cur_channel != dec_ch
+		|| mlmeext->cur_bwmode != dec_bw
+		|| mlmeext->cur_ch_offset != dec_offset)
+		changed = _TRUE;
+
+	if (changed == _TRUE && rtw_linked_check(adapter) == _TRUE) {
+		#ifdef CONFIG_SPCT_CH_SWITCH
+		if (1)
+			rtw_ap_inform_ch_switch(adapter, dec_ch, dec_offset);
+		else
+		#endif
+			rtw_sta_flush(adapter, _FALSE);
+	}
+
+	mlmeext->cur_channel = dec_ch;
+	mlmeext->cur_bwmode = dec_bw;
+	mlmeext->cur_ch_offset = dec_offset;
+
+	if (u_ch != 0)
+		DBG_871X(FUNC_ADPT_FMT" union: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
+
+	DBG_871X(FUNC_ADPT_FMT" dec: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), dec_ch, dec_bw, dec_offset);
+
+	if (set_u_ch == _TRUE) {
+		*ch = u_ch;
+		*bw = u_bw;
+		*offset = u_offset;
+	} else if (set_dec_ch == _TRUE) {
+		*ch = dec_ch;
+		*bw = dec_bw;
+		*offset = dec_offset;
+	}	
+
+	return changed;
+}
+
+#endif //CONFIG_AP_MODE
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_beamforming.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_beamforming.c
new file mode 100644
index 000000000..854f8ef08
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_beamforming.c
@@ -0,0 +1,1244 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_BEAMFORMING_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#ifdef CONFIG_BEAMFORMING
+
+#if (BEAMFORMING_SUPPORT == 0) /*for diver defined beamforming*/
+struct beamforming_entry	*beamforming_get_entry_by_addr(struct mlme_priv *pmlmepriv, u8* ra,u8* idx)
+{
+	u8	i = 0;
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	
+	for(i = 0; i < BEAMFORMING_ENTRY_NUM; i++)
+	{
+		if(	pBeamInfo->beamforming_entry[i].bUsed && 
+			(_rtw_memcmp(ra,pBeamInfo->beamforming_entry[i].mac_addr, ETH_ALEN)))
+		{
+			*idx = i;
+			return &(pBeamInfo->beamforming_entry[i]);
+		}
+	}
+
+	return NULL;
+}
+
+BEAMFORMING_CAP beamforming_get_entry_beam_cap_by_mac_id(PVOID pmlmepriv ,u8 mac_id)
+{
+	u8	i = 0;
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO((struct mlme_priv *)pmlmepriv);
+	BEAMFORMING_CAP		BeamformEntryCap = BEAMFORMING_CAP_NONE;
+	
+	for(i = 0; i < BEAMFORMING_ENTRY_NUM; i++)
+	{
+		if(	pBeamInfo->beamforming_entry[i].bUsed && 
+			(mac_id == pBeamInfo->beamforming_entry[i].mac_id))
+		{
+			BeamformEntryCap =  pBeamInfo->beamforming_entry[i].beamforming_entry_cap;
+			i = BEAMFORMING_ENTRY_NUM;
+		}
+	}
+
+	return BeamformEntryCap;
+}
+
+struct beamforming_entry	*beamforming_get_free_entry(struct mlme_priv *pmlmepriv, u8* idx)
+{
+	u8	i = 0;
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+
+	for(i = 0; i < BEAMFORMING_ENTRY_NUM; i++)
+	{
+		if(pBeamInfo->beamforming_entry[i].bUsed == _FALSE)
+		{
+			*idx = i;
+			return &(pBeamInfo->beamforming_entry[i]);
+		}	
+	}
+	return NULL;
+}
+
+
+struct beamforming_entry	*beamforming_add_entry(PADAPTER adapter, u8* ra, u16 aid,
+	u16 mac_id, CHANNEL_WIDTH bw, BEAMFORMING_CAP beamfrom_cap, u8* idx)
+{
+	struct mlme_priv			*pmlmepriv = &(adapter->mlmepriv);
+	struct beamforming_entry	*pEntry = beamforming_get_free_entry(pmlmepriv, idx);
+
+	if(pEntry != NULL)
+	{	
+		pEntry->bUsed = _TRUE;
+		pEntry->aid = aid;
+		pEntry->mac_id = mac_id;
+		pEntry->sound_bw = bw;
+		if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+		{
+			u16	BSSID = ((*(adapter_mac_addr(adapter) + 5) & 0xf0) >> 4) ^ 
+				(*(adapter_mac_addr(adapter) + 5) & 0xf); /* BSSID[44:47] xor BSSID[40:43] */
+			pEntry->p_aid = (aid + BSSID * 32) & 0x1ff;		// (dec(A) + dec(B)*32) mod 512
+			pEntry->g_id = 63;
+		}		
+		else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+		{
+			pEntry->p_aid = 0;
+			pEntry->g_id = 63;
+		}
+		else
+		{
+			pEntry->p_aid =  ra[5];						// BSSID[39:47]
+			pEntry->p_aid = (pEntry->p_aid << 1) | (ra[4] >> 7 );
+			pEntry->g_id = 0;
+		}
+		_rtw_memcpy(pEntry->mac_addr, ra, ETH_ALEN);
+		pEntry->bSound = _FALSE;
+
+		//3 TODO SW/FW sound period
+		pEntry->sound_period = 200;
+		pEntry->beamforming_entry_cap = beamfrom_cap;
+		pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
+
+
+		pEntry->PreLogSeq = 0;	/*Modified by Jeffery @2015-04-13*/
+		pEntry->LogSeq = 0;		/*Modified by Jeffery @2014-10-29*/
+		pEntry->LogRetryCnt = 0;	/*Modified by Jeffery @2014-10-29*/
+		pEntry->LogSuccess = 0;	/*LogSuccess is NOT needed to be accumulated, so  LogSuccessCnt->LogSuccess, 2015-04-13, Jeffery*/
+		pEntry->ClockResetTimes = 0;	/*Modified by Jeffery @2015-04-13*/
+		pEntry->LogStatusFailCnt = 0;
+
+		return pEntry;
+	}
+	else
+		return NULL;
+}
+
+BOOLEAN	beamforming_remove_entry(struct mlme_priv *pmlmepriv, u8* ra, u8* idx)
+{
+	struct beamforming_entry	*pEntry = beamforming_get_entry_by_addr(pmlmepriv, ra, idx);
+
+	if(pEntry != NULL)
+	{	
+		pEntry->bUsed = _FALSE;
+		pEntry->beamforming_entry_cap = BEAMFORMING_CAP_NONE;
+		pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
+		return _TRUE;
+	}
+	else
+		return _FALSE;
+}
+
+/* Used for BeamformingStart_V1  */
+void	beamforming_dym_ndpa_rate(PADAPTER adapter)
+{
+	u16	NDPARate = MGN_6M;
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(adapter);
+	
+	if(pHalData->MinUndecoratedPWDBForDM > 30) // link RSSI > 30%
+		NDPARate = MGN_24M;
+	else
+		NDPARate = MGN_6M;
+
+	//BW = CHANNEL_WIDTH_20;
+	NDPARate = NDPARate << 8;
+	rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_RATE, (u8 *)&NDPARate);
+}
+
+void beamforming_dym_period(PADAPTER Adapter)
+{
+	u8	Idx;
+	BOOLEAN	bChangePeriod = _FALSE;
+	u16	SoundPeriod_SW, SoundPeriod_FW;
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(Adapter);
+	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(Adapter);
+	struct beamforming_entry	*pBeamformEntry;
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(( &Adapter->mlmepriv));
+	struct sounding_info		*pSoundInfo = &(pBeamInfo->sounding_info);
+	
+	//3 TODO  per-client throughput caculation.
+
+	if(pdvobjpriv->traffic_stat.cur_tx_tp + pdvobjpriv->traffic_stat.cur_rx_tp > 2)
+	{
+		SoundPeriod_SW = 32*20;
+		SoundPeriod_FW = 2;
+	}	
+	else
+	{
+		SoundPeriod_SW = 32*2000;
+		SoundPeriod_FW = 200;
+	}	
+
+	for(Idx = 0; Idx < BEAMFORMING_ENTRY_NUM; Idx++)
+	{
+		pBeamformEntry = pBeamInfo->beamforming_entry+Idx;
+		if(pBeamformEntry->bDefaultCSI)
+		{
+			SoundPeriod_SW = 32*2000;
+			SoundPeriod_FW = 200;
+		}
+
+		if(pBeamformEntry->beamforming_entry_cap & (BEAMFORMER_CAP_HT_EXPLICIT |BEAMFORMER_CAP_VHT_SU))
+		{
+			if(pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
+			{				
+				if(pBeamformEntry->sound_period != SoundPeriod_FW)
+				{
+					pBeamformEntry->sound_period = SoundPeriod_FW;
+					bChangePeriod = _TRUE;	// Only FW sounding need to send H2C packet to change sound period. 
+				}
+			}
+			else if(pBeamformEntry->sound_period != SoundPeriod_SW)
+			{
+				pBeamformEntry->sound_period = SoundPeriod_SW;
+			}
+		}
+	}
+
+	if(bChangePeriod)
+		rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&Idx);
+}
+
+BOOLEAN	issue_ht_sw_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
+{
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	struct xmit_priv		*pxmitpriv = &(Adapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
+	u8	*pframe;
+	u16	*fctrl;
+	u16	duration = 0;
+	u8	aSifsTime = 0;
+	u8	NDPTxRate = 0;
+
+	DBG_871X("%s: issue_ht_sw_ndpa_packet!\n", __func__);
+
+	NDPTxRate = MGN_MCS8;
+	DBG_871X("%s: NDPTxRate =%d\n", __func__, NDPTxRate);
+	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+	
+	if (pmgntframe == NULL)
+		return _FALSE;
+
+	/*update attribute*/
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(Adapter, pattrib);
+	pattrib->qsel = QSLT_MGNT;
+	pattrib->rate = NDPTxRate;
+	pattrib->bwmode = bw;
+	pattrib->order = 1;
+	pattrib->subtype = WIFI_ACTION_NOACK;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &pwlanhdr->frame_ctl;
+	*(fctrl) = 0;
+
+	SetOrderBit(pframe);
+	SetFrameSubType(pframe, WIFI_ACTION_NOACK);
+
+	_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	if (pmlmeext->cur_wireless_mode == WIRELESS_11B)
+		aSifsTime = 10;
+	else
+		aSifsTime = 16;
+
+	duration = 2*aSifsTime + 40;
+	
+	if (bw == CHANNEL_WIDTH_40)
+		duration += 87;
+	else	
+		duration += 180;
+
+	SetDuration(pframe, duration);
+
+	/*HT control field*/
+	SET_HT_CTRL_CSI_STEERING(pframe+24, 3);
+	SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe+24, 1);
+
+	_rtw_memcpy(pframe+28, ActionHdr, 4);
+
+	pattrib->pktlen = 32;
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(Adapter, pmgntframe);
+
+	return _TRUE;
+
+
+}
+BOOLEAN	issue_ht_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
+{
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	struct xmit_priv		*pxmitpriv = &(Adapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
+	u8	*pframe;
+	u16	*fctrl;
+	u16	duration = 0;
+	u8	aSifsTime = 0;
+
+	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+
+	if (pmgntframe == NULL)
+		return _FALSE;
+
+	/*update attribute*/
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(Adapter, pattrib);
+
+	if (qidx == BCN_QUEUE_INX)
+		pattrib->qsel = QSLT_BEACON;
+	pattrib->rate = MGN_MCS8;
+	pattrib->bwmode = bw;
+	pattrib->order = 1;
+	pattrib->subtype = WIFI_ACTION_NOACK;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+	pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;
+
+	fctrl = &pwlanhdr->frame_ctl;
+	*(fctrl) = 0;
+
+	SetOrderBit(pframe);
+	SetFrameSubType(pframe, WIFI_ACTION_NOACK);
+
+	_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	if( pmlmeext->cur_wireless_mode == WIRELESS_11B)
+		aSifsTime = 10;
+	else
+		aSifsTime = 16;
+
+	duration = 2*aSifsTime + 40;
+	
+	if(bw == CHANNEL_WIDTH_40)
+		duration+= 87;
+	else	
+		duration+= 180;
+
+	SetDuration(pframe, duration);
+
+	//HT control field
+	SET_HT_CTRL_CSI_STEERING(pframe+24, 3);
+	SET_HT_CTRL_NDP_ANNOUNCEMENT(pframe+24, 1);
+
+	_rtw_memcpy(pframe+28, ActionHdr, 4);
+
+	pattrib->pktlen = 32;
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(Adapter, pmgntframe);
+
+	return _TRUE;
+}
+
+BOOLEAN	beamforming_send_ht_ndpa_packet(PADAPTER Adapter, u8 *ra, CHANNEL_WIDTH bw, u8 qidx)
+{
+	return issue_ht_ndpa_packet(Adapter, ra, bw, qidx);
+}
+BOOLEAN	issue_vht_sw_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
+{
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	struct xmit_priv		*pxmitpriv = &(Adapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv		*pmlmepriv = &(Adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	struct rtw_ndpa_sta_info	sta_info;
+	u8		 NDPTxRate = 0;
+	
+	u8	*pframe;
+	u16	*fctrl;
+	u16	duration = 0;
+	u8	sequence = 0, aSifsTime = 0;
+
+	DBG_871X("%s: issue_vht_sw_ndpa_packet!\n", __func__);
+
+	
+	NDPTxRate = MGN_VHT2SS_MCS0;
+	DBG_871X("%s: NDPTxRate =%d\n", __func__, NDPTxRate);
+	pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+
+	if (pmgntframe == NULL) {
+		DBG_871X("%s, alloc mgnt frame fail\n", __func__);
+		return _FALSE;
+	}
+
+	/*update attribute*/
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(Adapter, pattrib);
+	pattrib->qsel = QSLT_MGNT;
+	pattrib->rate = NDPTxRate;
+	pattrib->bwmode = bw;
+	pattrib->subtype = WIFI_NDPA;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &pwlanhdr->frame_ctl;
+	*(fctrl) = 0;
+
+	SetFrameSubType(pframe, WIFI_NDPA);
+
+	_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
+
+	if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))
+		aSifsTime = 16;
+	else
+		aSifsTime = 10;
+
+	duration = 2*aSifsTime + 44;
+	
+	if (bw == CHANNEL_WIDTH_80)
+		duration += 40;
+	else if (bw == CHANNEL_WIDTH_40)
+		duration += 87;
+	else	
+		duration += 180;
+
+	SetDuration(pframe, duration);
+	
+	sequence = pBeamInfo->sounding_sequence << 2;
+	if (pBeamInfo->sounding_sequence >= 0x3f)
+		pBeamInfo->sounding_sequence = 0;
+	else
+		pBeamInfo->sounding_sequence++;
+
+	_rtw_memcpy(pframe+16, &sequence, 1);
+	if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
+		aid = 0;		
+
+	sta_info.aid = aid;
+	sta_info.feedback_type = 0;
+	sta_info.nc_index = 0;
+	
+	_rtw_memcpy(pframe+17, (u8 *)&sta_info, 2);
+
+	pattrib->pktlen = 19;
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(Adapter, pmgntframe);
+	
+
+	return _TRUE;
+
+}
+BOOLEAN	issue_vht_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
+{
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	struct xmit_priv		*pxmitpriv = &(Adapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv		*pmlmepriv = &(Adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	struct rtw_ndpa_sta_info	sta_info;
+	u8	*pframe;
+	u16	*fctrl;
+	u16	duration = 0;
+	u8	sequence = 0, aSifsTime = 0;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		return _FALSE;
+
+	/*update attribute*/
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(Adapter, pattrib);
+
+	if (qidx == BCN_QUEUE_INX)
+		pattrib->qsel = QSLT_BEACON;
+	pattrib->rate = MGN_VHT2SS_MCS0;
+	pattrib->bwmode = bw;
+	pattrib->subtype = WIFI_NDPA;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+	pwlanhdr = (struct rtw_ieee80211_hdr*)pframe;
+
+	fctrl = &pwlanhdr->frame_ctl;
+	*(fctrl) = 0;
+
+	SetFrameSubType(pframe, WIFI_NDPA);
+
+	_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(Adapter), ETH_ALEN);
+
+	if (IsSupported5G(pmlmeext->cur_wireless_mode) || IsSupportedHT(pmlmeext->cur_wireless_mode))
+		aSifsTime = 16;
+	else
+		aSifsTime = 10;
+
+	duration = 2*aSifsTime + 44;
+	
+	if(bw == CHANNEL_WIDTH_80)
+		duration += 40;
+	else if(bw == CHANNEL_WIDTH_40)
+		duration+= 87;
+	else	
+		duration+= 180;
+
+	SetDuration(pframe, duration);
+
+	sequence = pBeamInfo->sounding_sequence<< 2;
+	if (pBeamInfo->sounding_sequence >= 0x3f)
+		pBeamInfo->sounding_sequence = 0;
+	else
+		pBeamInfo->sounding_sequence++;
+
+	_rtw_memcpy(pframe+16, &sequence,1);
+
+	if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
+		aid = 0;		
+
+	sta_info.aid = aid;
+	sta_info.feedback_type = 0;
+	sta_info.nc_index= 0;
+	
+	_rtw_memcpy(pframe+17, (u8 *)&sta_info, 2);
+
+	pattrib->pktlen = 19;
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(Adapter, pmgntframe);
+
+	return _TRUE;
+}
+
+BOOLEAN	beamforming_send_vht_ndpa_packet(PADAPTER Adapter, u8 *ra, u16 aid, CHANNEL_WIDTH bw, u8 qidx)
+{
+	return issue_vht_ndpa_packet(Adapter, ra, aid, bw, qidx);
+}
+
+BOOLEAN	beamfomring_bSounding(struct beamforming_info *pBeamInfo)
+{
+	BOOLEAN		bSounding = _FALSE;
+
+	if(( beamforming_get_beamform_cap(pBeamInfo) & BEAMFORMER_CAP) == 0)
+		bSounding = _FALSE;
+	else 
+		bSounding = _TRUE;
+
+	return bSounding;
+}
+
+u8	beamforming_sounding_idx(struct beamforming_info *pBeamInfo)
+{
+	u8	idx = 0;
+	u8	i;
+
+	for(i = 0; i < BEAMFORMING_ENTRY_NUM; i++)
+	{
+		if (pBeamInfo->beamforming_entry[i].bUsed &&
+			(_FALSE == pBeamInfo->beamforming_entry[i].bSound))
+		{
+			idx = i;
+			break;
+		}
+	}
+
+	return idx;
+}
+
+SOUNDING_MODE	beamforming_sounding_mode(struct beamforming_info *pBeamInfo, u8 idx)
+{
+	struct beamforming_entry	BeamEntry = pBeamInfo->beamforming_entry[idx];
+	SOUNDING_MODE	mode;
+
+	if(BeamEntry.beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU)
+	{
+		mode = SOUNDING_FW_VHT_TIMER;
+	}
+	else if(BeamEntry.beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
+	{
+		mode = SOUNDING_FW_HT_TIMER;
+	}
+	else
+	{
+		mode = SOUNDING_STOP_All_TIMER;
+	}
+
+	return mode;
+}
+
+u16	beamforming_sounding_time(struct beamforming_info *pBeamInfo, SOUNDING_MODE mode, u8 idx)
+{
+	u16						sounding_time = 0xffff;
+	struct beamforming_entry	BeamEntry = pBeamInfo->beamforming_entry[idx];
+
+	sounding_time = BeamEntry.sound_period;
+
+	return sounding_time;
+}
+
+CHANNEL_WIDTH	beamforming_sounding_bw(struct beamforming_info *pBeamInfo, SOUNDING_MODE mode, u8 idx)
+{
+	CHANNEL_WIDTH				sounding_bw = CHANNEL_WIDTH_20;
+	struct beamforming_entry		BeamEntry = pBeamInfo->beamforming_entry[idx];
+
+	sounding_bw = BeamEntry.sound_bw;
+
+	return sounding_bw;
+}
+
+BOOLEAN	beamforming_select_beam_entry(struct beamforming_info *pBeamInfo)
+{
+	struct sounding_info		*pSoundInfo = &(pBeamInfo->sounding_info);
+
+	pSoundInfo->sound_idx = beamforming_sounding_idx(pBeamInfo);
+
+	if(pSoundInfo->sound_idx < BEAMFORMING_ENTRY_NUM)
+		pSoundInfo->sound_mode = beamforming_sounding_mode(pBeamInfo, pSoundInfo->sound_idx);
+	else
+		pSoundInfo->sound_mode = SOUNDING_STOP_All_TIMER;
+	
+	if(SOUNDING_STOP_All_TIMER == pSoundInfo->sound_mode)
+	{
+		return _FALSE;
+	}
+	else
+	{
+		pSoundInfo->sound_bw = beamforming_sounding_bw(pBeamInfo, pSoundInfo->sound_mode, pSoundInfo->sound_idx );
+		pSoundInfo->sound_period = beamforming_sounding_time(pBeamInfo, pSoundInfo->sound_mode, pSoundInfo->sound_idx );
+		return _TRUE;
+	}
+}
+
+BOOLEAN	beamforming_start_fw(PADAPTER adapter, u8 idx)
+{
+	u8						*RA = NULL;
+	struct beamforming_entry	*pEntry;
+	BOOLEAN					ret = _TRUE;
+	struct mlme_priv			*pmlmepriv = &(adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+
+	pEntry = &(pBeamInfo->beamforming_entry[idx]);
+	if(pEntry->bUsed == _FALSE)
+	{
+		DBG_871X("Skip Beamforming, no entry for Idx =%d\n", idx);
+		return _FALSE;
+	}
+
+	pEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING;
+	pEntry->bSound = _TRUE;
+	rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&idx);
+
+	return _TRUE;
+}
+
+void	beamforming_end_fw(PADAPTER adapter)
+{
+	u8	idx = 0;
+
+	rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&idx);
+
+	DBG_871X("%s\n", __FUNCTION__);
+}
+
+BOOLEAN	beamforming_start_period(PADAPTER adapter)
+{
+	BOOLEAN	ret = _TRUE;
+	struct mlme_priv			*pmlmepriv = &(adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	struct sounding_info		*pSoundInfo = &(pBeamInfo->sounding_info);
+
+	beamforming_dym_ndpa_rate(adapter);
+
+	beamforming_select_beam_entry(pBeamInfo);
+
+	if(pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
+	{
+		ret = beamforming_start_fw(adapter, pSoundInfo->sound_idx);
+	}
+	else
+	{
+		ret = _FALSE;
+	}
+
+	DBG_871X("%s Idx %d Mode %d BW %d Period %d\n", __FUNCTION__, 
+			pSoundInfo->sound_idx, pSoundInfo->sound_mode, pSoundInfo->sound_bw, pSoundInfo->sound_period);
+
+	return ret;
+}
+
+void	beamforming_end_period(PADAPTER adapter)
+{
+	u8						idx = 0;
+	struct beamforming_entry	*pBeamformEntry;
+	struct mlme_priv			*pmlmepriv = &(adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	struct sounding_info		*pSoundInfo = &(pBeamInfo->sounding_info);
+
+
+	if(pSoundInfo->sound_mode == SOUNDING_FW_VHT_TIMER || pSoundInfo->sound_mode == SOUNDING_FW_HT_TIMER)
+	{		
+		beamforming_end_fw(adapter);
+	}
+}
+
+void	beamforming_notify(PADAPTER adapter)
+{
+	BOOLEAN		bSounding = _FALSE;
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(&(adapter->mlmepriv));
+
+	bSounding = beamfomring_bSounding(pBeamInfo);
+	
+	if(pBeamInfo->beamforming_state == BEAMFORMING_STATE_IDLE)
+	{
+		if(bSounding)
+		{			
+			if(beamforming_start_period(adapter) == _TRUE)
+				pBeamInfo->beamforming_state = BEAMFORMING_STATE_START;
+		}
+	}
+	else if(pBeamInfo->beamforming_state == BEAMFORMING_STATE_START)
+	{
+		if(bSounding)
+		{
+			if(beamforming_start_period(adapter) == _FALSE)
+				pBeamInfo->beamforming_state = BEAMFORMING_STATE_END;
+		}
+		else
+		{
+			beamforming_end_period(adapter);
+			pBeamInfo->beamforming_state = BEAMFORMING_STATE_END;
+		}
+	}
+	else if(pBeamInfo->beamforming_state == BEAMFORMING_STATE_END)
+	{
+		if(bSounding)
+		{
+			if(beamforming_start_period(adapter) == _TRUE)
+				pBeamInfo->beamforming_state = BEAMFORMING_STATE_START;
+		}
+	}
+	else
+	{
+		DBG_871X("%s BeamformState %d\n", __FUNCTION__, pBeamInfo->beamforming_state);
+	}
+
+	DBG_871X("%s BeamformState %d bSounding %d\n", __FUNCTION__, pBeamInfo->beamforming_state, bSounding);
+}
+
+BOOLEAN	beamforming_init_entry(PADAPTER	adapter, struct sta_info *psta, u8* idx)
+{
+	struct mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+	struct ht_priv		*phtpriv = &(pmlmepriv->htpriv);
+#ifdef CONFIG_80211AC_VHT	
+	struct vht_priv		*pvhtpriv = &(pmlmepriv->vhtpriv);
+#endif
+	struct mlme_ext_priv	*pmlmeext = &(adapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct beamforming_entry	*pBeamformEntry = NULL;
+	u8	*ra; 
+	u16	aid, mac_id;
+	u8	wireless_mode;
+	CHANNEL_WIDTH	bw = CHANNEL_WIDTH_20;
+	BEAMFORMING_CAP	beamform_cap = BEAMFORMING_CAP_NONE;
+
+	// The current setting does not support Beaforming
+	if (0 == phtpriv->beamform_cap 
+#ifdef CONFIG_80211AC_VHT
+		&& 0 == pvhtpriv->beamform_cap
+#endif
+		) {
+		DBG_871X("The configuration disabled Beamforming! Skip...\n");
+		return _FALSE;
+	}
+
+	aid = psta->aid;
+	ra = psta->hwaddr;
+	mac_id = psta->mac_id;
+	wireless_mode = psta->wireless_mode;
+	bw = psta->bw_mode;
+
+	if (IsSupportedHT(wireless_mode) || IsSupportedVHT(wireless_mode)) {
+		//3 // HT
+		u8	cur_beamform;
+
+		cur_beamform = psta->htpriv.beamform_cap;
+
+		// We are Beamformee because the STA is Beamformer
+		if(TEST_FLAG(cur_beamform, BEAMFORMING_HT_BEAMFORMER_ENABLE))
+			beamform_cap =(BEAMFORMING_CAP)(beamform_cap |BEAMFORMEE_CAP_HT_EXPLICIT);
+
+		// We are Beamformer because the STA is Beamformee
+		if(TEST_FLAG(cur_beamform, BEAMFORMING_HT_BEAMFORMEE_ENABLE))
+			beamform_cap =(BEAMFORMING_CAP)(beamform_cap | BEAMFORMER_CAP_HT_EXPLICIT);
+#ifdef CONFIG_80211AC_VHT
+		if (IsSupportedVHT(wireless_mode)) {
+			//3 // VHT
+			cur_beamform = psta->vhtpriv.beamform_cap;
+
+			// We are Beamformee because the STA is Beamformer
+			if(TEST_FLAG(cur_beamform, BEAMFORMING_VHT_BEAMFORMER_ENABLE))
+				beamform_cap =(BEAMFORMING_CAP)(beamform_cap |BEAMFORMEE_CAP_VHT_SU);
+			// We are Beamformer because the STA is Beamformee
+			if(TEST_FLAG(cur_beamform, BEAMFORMING_VHT_BEAMFORMEE_ENABLE))
+				beamform_cap =(BEAMFORMING_CAP)(beamform_cap |BEAMFORMER_CAP_VHT_SU);
+		}
+#endif //CONFIG_80211AC_VHT
+
+		if(beamform_cap == BEAMFORMING_CAP_NONE)
+			return _FALSE;
+		
+		DBG_871X("Beamforming Config Capability = 0x%02X\n", beamform_cap);
+
+		pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ra, idx);
+		if (pBeamformEntry == NULL) {
+			pBeamformEntry = beamforming_add_entry(adapter, ra, aid, mac_id, bw, beamform_cap, idx);
+			if(pBeamformEntry == NULL)
+				return _FALSE;
+			else
+				pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
+		} else {
+			// Entry has been created. If entry is initialing or progressing then errors occur.
+			if (pBeamformEntry->beamforming_entry_state != BEAMFORMING_ENTRY_STATE_INITIALIZED && 
+				pBeamformEntry->beamforming_entry_state != BEAMFORMING_ENTRY_STATE_PROGRESSED) {
+				DBG_871X("Error State of Beamforming");
+				return _FALSE;
+			} else {
+				pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
+			}
+		}
+
+		pBeamformEntry->beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED;
+		psta->txbf_paid = pBeamformEntry->p_aid;
+		psta->txbf_gid = pBeamformEntry->g_id;
+
+		DBG_871X("%s Idx %d\n", __FUNCTION__, *idx);
+	} else {
+		return _FALSE;
+	}
+
+	return _SUCCESS;
+}
+
+void	beamforming_deinit_entry(PADAPTER adapter, u8* ra)
+{
+	u8	idx = 0;
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+	
+	if(beamforming_remove_entry(pmlmepriv, ra, &idx) == _TRUE)
+	{
+		rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, (u8 *)&idx);
+	}
+
+	DBG_871X("%s Idx %d\n", __FUNCTION__, idx);
+}
+
+void	beamforming_reset(PADAPTER adapter)
+{
+	u8	idx = 0;
+	struct mlme_priv			*pmlmepriv = &(adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+
+	for(idx = 0; idx < BEAMFORMING_ENTRY_NUM; idx++)
+	{
+		if(pBeamInfo->beamforming_entry[idx].bUsed == _TRUE)
+		{
+			pBeamInfo->beamforming_entry[idx].bUsed = _FALSE;
+			pBeamInfo->beamforming_entry[idx].beamforming_entry_cap = BEAMFORMING_CAP_NONE;
+			pBeamInfo->beamforming_entry[idx].beamforming_entry_state= BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
+			rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_LEAVE, (u8 *)&idx);
+		}
+	}
+
+	DBG_871X("%s\n", __FUNCTION__);
+}
+
+void beamforming_sounding_fail(PADAPTER Adapter)
+{
+	struct mlme_priv			*pmlmepriv = &(Adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	struct beamforming_entry	*pEntry = &(pBeamInfo->beamforming_entry[pBeamInfo->beamforming_cur_idx]);
+
+	pEntry->bSound = _FALSE;
+	rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx);
+	beamforming_deinit_entry(Adapter, pEntry->mac_addr);
+}
+
+void	beamforming_check_sounding_success(PADAPTER Adapter,BOOLEAN status)
+{
+	struct mlme_priv			*pmlmepriv = &(Adapter->mlmepriv);
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(pmlmepriv);
+	struct beamforming_entry	*pEntry = &(pBeamInfo->beamforming_entry[pBeamInfo->beamforming_cur_idx]);
+
+	if(status == 1)
+	{
+		pEntry->LogStatusFailCnt = 0;
+	}	
+	else
+	{
+		pEntry->LogStatusFailCnt++;
+		DBG_871X("%s LogStatusFailCnt %d\n", __FUNCTION__, pEntry->LogStatusFailCnt);
+	}
+	if(pEntry->LogStatusFailCnt > 20)
+	{
+		DBG_871X("%s LogStatusFailCnt > 20, Stop SOUNDING\n", __FUNCTION__);
+		//pEntry->bSound = _FALSE;
+		//rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx);
+		//beamforming_deinit_entry(Adapter, pEntry->mac_addr);
+		beamforming_wk_cmd(Adapter, BEAMFORMING_CTRL_SOUNDING_FAIL, NULL, 0, 1);
+	}
+}
+
+void	beamforming_enter(PADAPTER adapter, PVOID psta)
+{
+	u8	idx = 0xff;
+
+	if(beamforming_init_entry(adapter, (struct sta_info *)psta, &idx))
+		rtw_hal_set_hwreg(adapter, HW_VAR_SOUNDING_ENTER, (u8 *)&idx);
+
+	//DBG_871X("%s Idx %d\n", __FUNCTION__, idx);
+}
+
+void	beamforming_leave(PADAPTER adapter,u8* ra)
+{
+	if(ra == NULL)
+		beamforming_reset(adapter);
+	else
+		beamforming_deinit_entry(adapter, ra);
+
+	beamforming_notify(adapter);
+}
+
+BEAMFORMING_CAP beamforming_get_beamform_cap(struct beamforming_info	*pBeamInfo)
+{
+	u8	i;
+	BOOLEAN 				bSelfBeamformer = _FALSE;
+	BOOLEAN 				bSelfBeamformee = _FALSE;
+	struct beamforming_entry	beamforming_entry;
+	BEAMFORMING_CAP 		beamform_cap = BEAMFORMING_CAP_NONE;
+
+	for(i = 0; i < BEAMFORMING_ENTRY_NUM; i++)
+	{
+		beamforming_entry = pBeamInfo->beamforming_entry[i];
+
+		if(beamforming_entry.bUsed)
+		{
+			if( (beamforming_entry.beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU) ||
+				(beamforming_entry.beamforming_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT))
+				bSelfBeamformee = _TRUE;
+			if( (beamforming_entry.beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU) ||
+				(beamforming_entry.beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT))
+				bSelfBeamformer = _TRUE;
+		}
+
+		if(bSelfBeamformer && bSelfBeamformee)
+			i = BEAMFORMING_ENTRY_NUM;
+	}
+
+	if(bSelfBeamformer)
+		beamform_cap |= BEAMFORMER_CAP;
+	if(bSelfBeamformee)
+		beamform_cap |= BEAMFORMEE_CAP;
+
+	return beamform_cap;
+}
+
+void	beamforming_watchdog(PADAPTER Adapter)
+{
+	struct beamforming_info	*pBeamInfo = GET_BEAMFORM_INFO(( &(Adapter->mlmepriv)));
+
+	if(pBeamInfo->beamforming_state != BEAMFORMING_STATE_START)
+		return;
+
+	beamforming_dym_period(Adapter);
+	beamforming_dym_ndpa_rate(Adapter);
+}
+#endif/* #if (BEAMFORMING_SUPPORT ==0) - for diver defined beamforming*/
+
+u32	beamforming_get_report_frame(PADAPTER	 Adapter, union recv_frame *precv_frame)
+{
+	u32	ret = _SUCCESS;
+#if (BEAMFORMING_SUPPORT == 1)
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(Adapter);
+	PDM_ODM_T		pDM_Odm = &(pHalData->odmpriv);
+
+	ret = Beamforming_GetReportFrame(pDM_Odm, precv_frame);
+	
+#else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
+	struct beamforming_entry	*pBeamformEntry = NULL;
+	struct mlme_priv			*pmlmepriv = &(Adapter->mlmepriv);
+	u8	*pframe = precv_frame->u.hdr.rx_data;
+	u32	frame_len = precv_frame->u.hdr.len;
+	u8	*ta;
+	u8	idx, offset;
+	
+	/*DBG_871X("beamforming_get_report_frame\n");*/
+
+	/*Memory comparison to see if CSI report is the same with previous one*/
+	ta = GetAddr2Ptr(pframe);
+	pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ta, &idx);
+	if (pBeamformEntry->beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU)
+		offset = 31;	/*24+(1+1+3)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
+	else if (pBeamformEntry->beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT)
+		offset = 34;	/*24+(1+1+6)+2  MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
+	else
+		return ret;
+
+	/*DBG_871X("%s MacId %d offset=%d\n", __FUNCTION__, pBeamformEntry->mac_id, offset);*/
+
+	if (_rtw_memcmp(pBeamformEntry->PreCsiReport + offset, pframe+offset, frame_len-offset) == _FALSE)
+		pBeamformEntry->DefaultCsiCnt = 0;
+	else 
+		pBeamformEntry->DefaultCsiCnt++;
+	
+	_rtw_memcpy(&pBeamformEntry->PreCsiReport, pframe, frame_len);
+
+	pBeamformEntry->bDefaultCSI = _FALSE;
+
+	if (pBeamformEntry->DefaultCsiCnt > 20)
+		pBeamformEntry->bDefaultCSI = _TRUE;
+	else
+		pBeamformEntry->bDefaultCSI = _FALSE;
+#endif
+	return ret;
+}
+
+void	beamforming_get_ndpa_frame(PADAPTER	 Adapter, union recv_frame *precv_frame)
+{
+#if (BEAMFORMING_SUPPORT == 1)
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(Adapter);
+	PDM_ODM_T		pDM_Odm = &(pHalData->odmpriv);
+
+	Beamforming_GetNDPAFrame(pDM_Odm, precv_frame);
+
+#else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
+	u8	*ta;
+	u8	idx, Sequence;
+	u8	*pframe = precv_frame->u.hdr.rx_data;
+	struct mlme_priv			*pmlmepriv = &(Adapter->mlmepriv);
+	struct beamforming_entry	*pBeamformEntry = NULL;
+
+	/*DBG_871X("beamforming_get_ndpa_frame\n");*/
+
+	if (IS_HARDWARE_TYPE_8812(Adapter) == _FALSE)
+		return;
+	else if (GetFrameSubType(pframe) != WIFI_NDPA)
+		return;
+
+	ta = GetAddr2Ptr(pframe);
+	/*Remove signaling TA. */
+	ta[0] = ta[0] & 0xFE; 
+	
+	pBeamformEntry = beamforming_get_entry_by_addr(pmlmepriv, ta, &idx);
+
+	if (pBeamformEntry == NULL)
+		return;
+	else if (!(pBeamformEntry->beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU))
+		return;
+	/*LogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/
+	/*ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery*/
+	else if ((pBeamformEntry->LogSuccess == 1) || (pBeamformEntry->ClockResetTimes == 5)) {
+		DBG_871X("[%s] LogSeq=%d, PreLogSeq=%d\n", __func__, pBeamformEntry->LogSeq, pBeamformEntry->PreLogSeq);
+		return;
+	}
+
+	Sequence = (pframe[16]) >> 2;
+	DBG_871X("[%s] Start, Sequence=%d, LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, ClockResetTimes=%d, LogSuccess=%d\n", 
+		__func__, Sequence, pBeamformEntry->LogSeq, pBeamformEntry->PreLogSeq, pBeamformEntry->LogRetryCnt, pBeamformEntry->ClockResetTimes, pBeamformEntry->LogSuccess);
+
+	if ((pBeamformEntry->LogSeq != 0) && (pBeamformEntry->PreLogSeq != 0)) {
+		/*Success condition*/
+		if ((pBeamformEntry->LogSeq != Sequence) && (pBeamformEntry->PreLogSeq != pBeamformEntry->LogSeq)) {
+			/* break option for clcok reset, 2015-03-30, Jeffery */
+			pBeamformEntry->LogRetryCnt = 0;
+			/*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/
+			/*That is, LogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/
+			pBeamformEntry->LogSuccess = 1;
+		
+		} else {/*Fail condition*/
+
+			if (pBeamformEntry->LogRetryCnt == 5) {
+				pBeamformEntry->ClockResetTimes++;
+		pBeamformEntry->LogRetryCnt = 0;
+
+				DBG_871X("[%s] Clock Reset!!! ClockResetTimes=%d\n",  __func__, pBeamformEntry->ClockResetTimes);
+			beamforming_wk_cmd(Adapter, BEAMFORMING_CTRL_SOUNDING_CLK, NULL, 0, 1);
+
+			} else
+		pBeamformEntry->LogRetryCnt++;
+	}
+	}
+
+	/*Update LogSeq & PreLogSeq*/
+	pBeamformEntry->PreLogSeq = pBeamformEntry->LogSeq;
+	pBeamformEntry->LogSeq = Sequence;
+
+#endif
+	
+}
+
+
+
+
+void	beamforming_wk_hdl(_adapter *padapter, u8 type, u8 *pbuf)
+{
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(padapter);
+	PDM_ODM_T		pDM_Odm = &(pHalData->odmpriv);
+_func_enter_;
+
+#if (BEAMFORMING_SUPPORT == 1) /*(BEAMFORMING_SUPPORT == 1)- for PHYDM beamfoming*/
+	switch (type) {
+	case BEAMFORMING_CTRL_ENTER:
+	{
+		struct sta_info	*psta = (PVOID)pbuf;
+		u16			staIdx = psta->mac_id;
+
+		Beamforming_Enter(pDM_Odm, staIdx);		
+		break;
+	}
+	case BEAMFORMING_CTRL_LEAVE:
+		Beamforming_Leave(pDM_Odm, pbuf);
+		break;
+	default:
+		break;
+
+	}
+#else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
+	switch (type) {	
+		case BEAMFORMING_CTRL_ENTER:
+			beamforming_enter(padapter, (PVOID)pbuf);
+			break;
+
+		case BEAMFORMING_CTRL_LEAVE:
+			beamforming_leave(padapter, pbuf);
+			break;
+
+		case BEAMFORMING_CTRL_SOUNDING_FAIL:
+			beamforming_sounding_fail(padapter);
+			break;
+
+		case BEAMFORMING_CTRL_SOUNDING_CLK:
+			rtw_hal_set_hwreg(padapter, HW_VAR_SOUNDING_CLK, NULL);
+			break;
+	
+		default:
+			break;
+	}
+#endif
+_func_exit_;
+}
+
+u8	beamforming_wk_cmd(_adapter*padapter, s32 type, u8 *pbuf, s32 size, u8 enqueue)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+	
+_func_enter_;
+
+	if(enqueue)
+	{
+		u8	*wk_buf;
+	
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+		if(ph2c==NULL){
+			res= _FAIL;
+			goto exit;
+		}
+		
+		pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+		if(pdrvextra_cmd_parm==NULL){
+			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+			res= _FAIL;
+			goto exit;
+		}
+
+		if (pbuf != NULL) {
+			wk_buf = rtw_zmalloc(size);
+			if(wk_buf==NULL){
+				rtw_mfree((u8 *)ph2c, sizeof(struct cmd_obj));
+				rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
+				res= _FAIL;
+				goto exit;
+			}
+
+			_rtw_memcpy(wk_buf, pbuf, size);
+		} else {
+			wk_buf = NULL;
+			size = 0;
+		}
+
+		pdrvextra_cmd_parm->ec_id = BEAMFORMING_WK_CID;
+		pdrvextra_cmd_parm->type = type;
+		pdrvextra_cmd_parm->size = size;
+		pdrvextra_cmd_parm->pbuf = wk_buf;
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	}
+	else
+	{
+		beamforming_wk_hdl(padapter, type, pbuf);
+	}
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+}
+
+void update_attrib_txbf_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
+{
+	if (psta) {
+		pattrib->txbf_g_id = psta->txbf_gid;
+		pattrib->txbf_p_aid = psta->txbf_paid;
+	}
+}
+
+#endif
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_br_ext.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_br_ext.c
new file mode 100644
index 000000000..024049cfb
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_br_ext.c
@@ -0,0 +1,1699 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_BR_EXT_C_
+
+#ifdef __KERNEL__
+#include <linux/if_arp.h>
+#include <net/ip.h>
+#include <net/ipx.h>
+#include <linux/atalk.h>
+#include <linux/udp.h>
+#include <linux/if_pppox.h>
+#endif
+
+#if 1	// rtw_wifi_driver
+#include <drv_types.h>
+#else	// rtw_wifi_driver
+#include "./8192cd_cfg.h"
+
+#ifndef __KERNEL__
+#include "./sys-support.h"
+#endif
+
+#include "./8192cd.h"
+#include "./8192cd_headers.h"
+#include "./8192cd_br_ext.h"
+#include "./8192cd_debug.h"
+#endif	// rtw_wifi_driver
+
+#ifdef CL_IPV6_PASS
+#ifdef __KERNEL__
+#include <linux/ipv6.h>
+#include <linux/icmpv6.h>
+#include <net/ndisc.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24))
+#include <net/ip6_checksum.h>
+#else
+#include <net/checksum.h>
+#endif
+#endif
+#endif
+
+#ifdef CONFIG_BR_EXT
+
+//#define BR_EXT_DEBUG
+
+#define NAT25_IPV4		01
+#define NAT25_IPV6		02
+#define NAT25_IPX		03
+#define NAT25_APPLE		04
+#define NAT25_PPPOE		05
+
+#define RTL_RELAY_TAG_LEN (ETH_ALEN)
+#define TAG_HDR_LEN		4
+
+#define MAGIC_CODE		0x8186
+#define MAGIC_CODE_LEN	2
+#define WAIT_TIME_PPPOE	5	// waiting time for pppoe server in sec
+
+/*-----------------------------------------------------------------
+  How database records network address:
+           0    1    2    3    4    5    6    7    8    9   10
+        |----|----|----|----|----|----|----|----|----|----|----|
+  IPv4  |type|                             |      IP addr      |
+  IPX   |type|      Net addr     |          Node addr          |
+  IPX   |type|      Net addr     |Sckt addr|
+  Apple |type| Network |node|
+  PPPoE |type|   SID   |           AC MAC            |
+-----------------------------------------------------------------*/
+
+
+//Find a tag in pppoe frame and return the pointer
+static __inline__ unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
+{
+	unsigned char *cur_ptr, *start_ptr;
+	unsigned short tagLen, tagType;
+
+	start_ptr = cur_ptr = (unsigned char *)ph->tag;
+	while((cur_ptr - start_ptr) < ntohs(ph->length)) {
+		// prevent un-alignment access
+		tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
+		tagLen  = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
+		if(tagType == type)
+			return cur_ptr;
+		cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
+	}
+	return 0;
+}
+
+
+static __inline__ int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
+{
+	struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
+	int data_len;
+
+	data_len = tag->tag_len + TAG_HDR_LEN;
+	if (skb_tailroom(skb) < data_len) {
+		_DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
+		return -1;
+	}
+
+	skb_put(skb, data_len);
+	// have a room for new tag
+	memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
+	ph->length = htons(ntohs(ph->length) + data_len);
+	memcpy((unsigned char *)ph->tag, tag, data_len);
+	return data_len;
+}
+
+static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
+{
+	int tail_len;
+	unsigned long end, tail;
+
+	if ((src+len) > skb_tail_pointer(skb) || skb->len < len)
+		return -1;
+
+	tail = (unsigned long)skb_tail_pointer(skb);
+	end = (unsigned long)src+len;
+	if (tail < end)
+		return -1;
+
+	tail_len = (int)(tail-end);
+	if (tail_len > 0)
+		memmove(src, src+len, tail_len);
+
+	skb_trim(skb, skb->len-len);
+	return 0;
+}
+
+static __inline__ unsigned long __nat25_timeout(_adapter *priv)
+{
+	unsigned long timeout;
+
+	timeout = jiffies - NAT25_AGEING_TIME*HZ;
+
+	return timeout;
+}
+
+
+static __inline__ int  __nat25_has_expired(_adapter *priv,
+				struct nat25_network_db_entry *fdb)
+{
+	if(time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
+		return 1;
+
+	return 0;
+}
+
+
+static __inline__ void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
+				unsigned int *ipAddr)
+{
+	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+	networkAddr[0] = NAT25_IPV4;
+	memcpy(networkAddr+7, (unsigned char *)ipAddr, 4);
+}
+
+
+static __inline__ void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr,
+				unsigned int *ipxNetAddr, unsigned char *ipxNodeAddr)
+{
+	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+	networkAddr[0] = NAT25_IPX;
+	memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
+	memcpy(networkAddr+5, ipxNodeAddr, 6);
+}
+
+
+static __inline__ void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr,
+				unsigned int *ipxNetAddr, unsigned short *ipxSocketAddr)
+{
+	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+	networkAddr[0] = NAT25_IPX;
+	memcpy(networkAddr+1, (unsigned char *)ipxNetAddr, 4);
+	memcpy(networkAddr+5, (unsigned char *)ipxSocketAddr, 2);
+}
+
+
+static __inline__ void __nat25_generate_apple_network_addr(unsigned char *networkAddr,
+				unsigned short *network, unsigned char *node)
+{
+	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+	networkAddr[0] = NAT25_APPLE;
+	memcpy(networkAddr+1, (unsigned char *)network, 2);
+	networkAddr[3] = *node;
+}
+
+
+static __inline__ void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
+				unsigned char *ac_mac, unsigned short *sid)
+{
+	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+	networkAddr[0] = NAT25_PPPOE;
+	memcpy(networkAddr+1, (unsigned char *)sid, 2);
+	memcpy(networkAddr+3, (unsigned char *)ac_mac, 6);
+}
+
+
+#ifdef CL_IPV6_PASS
+static  void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
+				unsigned int *ipAddr)
+{
+	memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
+
+	networkAddr[0] = NAT25_IPV6;
+	memcpy(networkAddr+1, (unsigned char *)ipAddr, 16);
+}
+
+
+static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
+{
+	while (len > 0) {
+		if (*data == tag && *(data+1) == len8b && len >= len8b*8)
+			return data+2;	
+		
+		len -= (*(data+1))*8;		
+		data += (*(data+1))*8;		
+	}
+	return NULL;
+}
+
+
+static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
+{
+	struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
+	unsigned char *mac;
+	
+	if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) { 
+		if (len >= 8) {
+			mac = scan_tlv(&data[8], len-8, 1, 1);
+			if (mac) {
+				DBG_871X("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],					
+					replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
+				memcpy(mac, replace_mac, 6);	
+				return 1;				
+			}
+		}
+	}
+	else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
+		if (len >= 16) {
+			mac = scan_tlv(&data[16], len-16, 1, 1);
+			if (mac) {
+				DBG_871X("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],					
+					replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
+				memcpy(mac, replace_mac, 6);			
+				return 1;				
+			}
+		}		
+	}
+	else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
+		if (len >= 24) {
+			mac = scan_tlv(&data[24], len-24, 1, 1);
+			if (mac) {		
+				DBG_871X("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],					
+					replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
+				memcpy(mac, replace_mac, 6);	
+				return 1;								
+			}
+		}		
+	}
+	else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
+		if (len >= 24) {
+			mac = scan_tlv(&data[24], len-24, 2, 1);
+			if (mac) {
+				DBG_871X("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],					
+					replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
+				memcpy(mac, replace_mac, 6);		
+				return 1;				
+			}
+		}		
+	}
+	else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
+		if (len >= 40) {
+			mac = scan_tlv(&data[40], len-40, 2, 1);
+			if (mac) {				
+				DBG_871X("Redirect,  replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
+					mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],					
+					replace_mac[0],replace_mac[1],replace_mac[2],replace_mac[3],replace_mac[4],replace_mac[5]);
+				memcpy(mac, replace_mac, 6);	
+				return 1;				
+			}
+		}		
+	}	
+	return 0;
+}
+
+
+static void convert_ipv6_mac_to_mc(struct sk_buff *skb)
+{	
+	struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
+	unsigned char *dst_mac = skb->data;
+
+	//dst_mac[0] = 0xff;
+	//dst_mac[1] = 0xff;
+	/*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/
+	dst_mac[0] = 0x33;
+	dst_mac[1] = 0x33;
+	memcpy(&dst_mac[2], &iph->daddr.s6_addr32[3], 4);
+	#if defined(__LINUX_2_6__) 
+	/*modified by qinjunjie,warning:should not remove next line*/
+	skb->pkt_type = PACKET_MULTICAST;
+	#endif
+}
+#endif /* CL_IPV6_PASS */
+
+
+static __inline__ int __nat25_network_hash(unsigned char *networkAddr)
+{
+	if(networkAddr[0] == NAT25_IPV4)
+	{
+		unsigned long x;
+
+		x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+	else if(networkAddr[0] == NAT25_IPX)
+	{
+		unsigned long x;
+
+		x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
+			networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+	else if(networkAddr[0] == NAT25_APPLE)
+	{
+		unsigned long x;
+
+		x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+	else if(networkAddr[0] == NAT25_PPPOE)
+	{
+		unsigned long x;
+
+		x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+#ifdef CL_IPV6_PASS
+	else if(networkAddr[0] == NAT25_IPV6)
+	{
+		unsigned long x;
+
+		x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
+			networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
+			networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
+			networkAddr[16];
+	
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+#endif	
+	else
+	{
+		unsigned long x = 0;
+		int i;
+
+		for (i=0; i<MAX_NETWORK_ADDR_LEN; i++)
+			x ^= networkAddr[i];
+
+		return x & (NAT25_HASH_SIZE - 1);
+	}
+}
+
+
+static __inline__ void __network_hash_link(_adapter *priv,
+				struct nat25_network_db_entry *ent, int hash)
+{
+	// Caller must _enter_critical_bh already!
+	//_irqL irqL;
+	//_enter_critical_bh(&priv->br_ext_lock, &irqL);
+
+	ent->next_hash = priv->nethash[hash];
+	if(ent->next_hash != NULL)
+		ent->next_hash->pprev_hash = &ent->next_hash;
+	priv->nethash[hash] = ent;
+	ent->pprev_hash = &priv->nethash[hash];
+
+	//_exit_critical_bh(&priv->br_ext_lock, &irqL);
+}
+
+
+static __inline__ void __network_hash_unlink(struct nat25_network_db_entry *ent)
+{
+	// Caller must _enter_critical_bh already!
+	//_irqL irqL;
+	//_enter_critical_bh(&priv->br_ext_lock, &irqL);
+
+	*(ent->pprev_hash) = ent->next_hash;
+	if(ent->next_hash != NULL)
+		ent->next_hash->pprev_hash = ent->pprev_hash;
+	ent->next_hash = NULL;
+	ent->pprev_hash = NULL;
+
+	//_exit_critical_bh(&priv->br_ext_lock, &irqL);
+}
+
+
+static int __nat25_db_network_lookup_and_replace(_adapter *priv,
+				struct sk_buff *skb, unsigned char *networkAddr)
+{
+	struct nat25_network_db_entry *db;
+	_irqL irqL;
+	_enter_critical_bh(&priv->br_ext_lock, &irqL);
+
+	db = priv->nethash[__nat25_network_hash(networkAddr)];
+	while (db != NULL)
+	{
+		if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN))
+		{
+			if(!__nat25_has_expired(priv, db))
+			{
+				// replace the destination mac address
+				memcpy(skb->data, db->macAddr, ETH_ALEN);
+				atomic_inc(&db->use_count);
+
+#ifdef CL_IPV6_PASS
+				DBG_871X("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"	
+							"%02x%02x%02x%02x%02x%02x\n",				
+					db->macAddr[0],
+					db->macAddr[1],
+					db->macAddr[2],
+					db->macAddr[3],
+					db->macAddr[4],
+					db->macAddr[5],
+					db->networkAddr[0],
+					db->networkAddr[1],
+					db->networkAddr[2],
+					db->networkAddr[3],
+					db->networkAddr[4],
+					db->networkAddr[5],
+					db->networkAddr[6],
+					db->networkAddr[7],
+					db->networkAddr[8],
+					db->networkAddr[9],
+					db->networkAddr[10],
+					db->networkAddr[11],
+					db->networkAddr[12],
+					db->networkAddr[13],
+					db->networkAddr[14],
+					db->networkAddr[15],
+					db->networkAddr[16]);
+#else				
+				DBG_871X("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+					db->macAddr[0],
+					db->macAddr[1],
+					db->macAddr[2],
+					db->macAddr[3],
+					db->macAddr[4],
+					db->macAddr[5],
+					db->networkAddr[0],
+					db->networkAddr[1],
+					db->networkAddr[2],
+					db->networkAddr[3],
+					db->networkAddr[4],
+					db->networkAddr[5],
+					db->networkAddr[6],
+					db->networkAddr[7],
+					db->networkAddr[8],
+					db->networkAddr[9],
+					db->networkAddr[10]);
+#endif
+			}
+			_exit_critical_bh(&priv->br_ext_lock, &irqL);
+			return 1;
+		}
+
+		db = db->next_hash;
+	}
+
+	_exit_critical_bh(&priv->br_ext_lock, &irqL);
+	return 0;
+}
+
+
+static void __nat25_db_network_insert(_adapter *priv,
+				unsigned char *macAddr, unsigned char *networkAddr)
+{
+	struct nat25_network_db_entry *db;
+	int hash;
+	_irqL irqL;
+	_enter_critical_bh(&priv->br_ext_lock, &irqL);
+
+	hash = __nat25_network_hash(networkAddr);
+	db = priv->nethash[hash];
+	while (db != NULL)
+	{
+		if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN))
+		{
+			memcpy(db->macAddr, macAddr, ETH_ALEN);
+			db->ageing_timer = jiffies;
+			_exit_critical_bh(&priv->br_ext_lock, &irqL);
+			return;
+		}
+
+		db = db->next_hash;
+	}
+
+	db = (struct nat25_network_db_entry *) rtw_malloc(sizeof(*db));
+	if(db == NULL) {
+		_exit_critical_bh(&priv->br_ext_lock, &irqL);
+		return;
+	}
+
+	memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
+	memcpy(db->macAddr, macAddr, ETH_ALEN);
+	atomic_set(&db->use_count, 1);
+	db->ageing_timer = jiffies;
+
+	__network_hash_link(priv, db, hash);
+
+	_exit_critical_bh(&priv->br_ext_lock, &irqL);
+}
+
+
+static void __nat25_db_print(_adapter *priv)
+{
+	_irqL irqL;
+	_enter_critical_bh(&priv->br_ext_lock, &irqL);
+
+#ifdef BR_EXT_DEBUG
+	static int counter = 0;
+	int i, j;
+	struct nat25_network_db_entry *db;
+
+	counter++;
+	if((counter % 16) != 0)
+		return;
+
+	for(i=0, j=0; i<NAT25_HASH_SIZE; i++)
+	{
+		db = priv->nethash[i];
+
+		while (db != NULL)
+		{
+#ifdef CL_IPV6_PASS
+			panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+					"%02x%02x%02x%02x%02x%02x\n",
+				j,
+				i,
+				atomic_read(&db->use_count),
+				db->macAddr[0],
+				db->macAddr[1],
+				db->macAddr[2],
+				db->macAddr[3],
+				db->macAddr[4],
+				db->macAddr[5],
+				db->networkAddr[0],
+				db->networkAddr[1],
+				db->networkAddr[2],
+				db->networkAddr[3],
+				db->networkAddr[4],
+				db->networkAddr[5],
+				db->networkAddr[6],
+				db->networkAddr[7],
+				db->networkAddr[8],
+				db->networkAddr[9],
+				db->networkAddr[10],
+				db->networkAddr[11],
+				db->networkAddr[12],
+				db->networkAddr[13],
+				db->networkAddr[14],
+				db->networkAddr[15],
+				db->networkAddr[16]);
+#else
+			panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+				j,
+				i,
+				atomic_read(&db->use_count),
+				db->macAddr[0],
+				db->macAddr[1],
+				db->macAddr[2],
+				db->macAddr[3],
+				db->macAddr[4],
+				db->macAddr[5],
+				db->networkAddr[0],
+				db->networkAddr[1],
+				db->networkAddr[2],
+				db->networkAddr[3],
+				db->networkAddr[4],
+				db->networkAddr[5],
+				db->networkAddr[6],
+				db->networkAddr[7],
+				db->networkAddr[8],
+				db->networkAddr[9],
+				db->networkAddr[10]);
+#endif
+			j++;
+
+			db = db->next_hash;
+		}
+	}
+#endif
+
+	_exit_critical_bh(&priv->br_ext_lock, &irqL);
+}
+
+
+
+
+/*
+ *	NAT2.5 interface
+ */
+
+void nat25_db_cleanup(_adapter *priv)
+{
+	int i;
+	_irqL irqL;
+	_enter_critical_bh(&priv->br_ext_lock, &irqL);
+	
+	for(i=0; i<NAT25_HASH_SIZE; i++)
+	{
+		struct nat25_network_db_entry *f;
+		f = priv->nethash[i];
+		while (f != NULL) {
+			struct nat25_network_db_entry *g;
+
+			g = f->next_hash;
+			if(priv->scdb_entry == f)
+			{
+				memset(priv->scdb_mac, 0, ETH_ALEN);
+				memset(priv->scdb_ip, 0, 4);
+				priv->scdb_entry = NULL;
+			}
+			__network_hash_unlink(f);
+			rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry));
+
+			f = g;
+		}
+	}
+
+	_exit_critical_bh(&priv->br_ext_lock, &irqL);
+}
+
+
+void nat25_db_expire(_adapter *priv)
+{
+	int i;
+	_irqL irqL;
+	_enter_critical_bh(&priv->br_ext_lock, &irqL);
+	
+	//if(!priv->ethBrExtInfo.nat25_disable)
+	{
+		for (i=0; i<NAT25_HASH_SIZE; i++)
+		{
+			struct nat25_network_db_entry *f;
+			f = priv->nethash[i];
+
+			while (f != NULL)
+			{
+				struct nat25_network_db_entry *g;
+				g = f->next_hash;
+
+				if(__nat25_has_expired(priv, f))
+				{
+					if(atomic_dec_and_test(&f->use_count))
+					{
+#ifdef BR_EXT_DEBUG
+#ifdef CL_IPV6_PASS
+						panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
+								"%02x%02x%02x%02x%02x%02x\n",
+							i,
+							f->macAddr[0],
+							f->macAddr[1],
+							f->macAddr[2],
+							f->macAddr[3],
+							f->macAddr[4],
+							f->macAddr[5],
+							f->networkAddr[0],
+							f->networkAddr[1],
+							f->networkAddr[2],
+							f->networkAddr[3],
+							f->networkAddr[4],
+							f->networkAddr[5],
+							f->networkAddr[6],
+							f->networkAddr[7],
+							f->networkAddr[8],
+							f->networkAddr[9],
+							f->networkAddr[10],
+							f->networkAddr[11],
+							f->networkAddr[12],
+							f->networkAddr[13],
+							f->networkAddr[14],
+							f->networkAddr[15],
+							f->networkAddr[16]);
+#else
+
+						panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
+							i,
+							f->macAddr[0],
+							f->macAddr[1],
+							f->macAddr[2],
+							f->macAddr[3],
+							f->macAddr[4],
+							f->macAddr[5],
+							f->networkAddr[0],
+							f->networkAddr[1],
+							f->networkAddr[2],
+							f->networkAddr[3],
+							f->networkAddr[4],
+							f->networkAddr[5],
+							f->networkAddr[6],
+							f->networkAddr[7],
+							f->networkAddr[8],
+							f->networkAddr[9],
+							f->networkAddr[10]);
+#endif
+#endif
+						if(priv->scdb_entry == f)
+						{
+							memset(priv->scdb_mac, 0, ETH_ALEN);
+							memset(priv->scdb_ip, 0, 4);
+							priv->scdb_entry = NULL;
+						}
+						__network_hash_unlink(f);
+						rtw_mfree((u8 *) f, sizeof(struct nat25_network_db_entry));
+					}
+				}
+
+				f = g;
+			}
+		}
+	}
+
+	_exit_critical_bh(&priv->br_ext_lock, &irqL);
+}
+
+
+#ifdef SUPPORT_TX_MCAST2UNI
+static int checkIPMcAndReplace(_adapter *priv, struct sk_buff *skb, unsigned int *dst_ip)
+{
+	struct stat_info	*pstat;
+	struct list_head	*phead, *plist;
+	int i;
+
+	phead = &priv->asoc_list;
+	plist = phead->next;
+
+	while (plist != phead) {
+		pstat = list_entry(plist, struct stat_info, asoc_list);
+		plist = plist->next;
+
+		if (pstat->ipmc_num == 0)
+			continue;
+
+		for (i=0; i<MAX_IP_MC_ENTRY; i++) {
+			if (pstat->ipmc[i].used && !memcmp(&pstat->ipmc[i].mcmac[3], ((unsigned char *)dst_ip)+1, 3)) {
+				memcpy(skb->data, pstat->ipmc[i].mcmac, ETH_ALEN);
+				return 1;
+			}
+		}
+	}
+	return 0;
+}
+#endif
+
+int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method)
+{
+	unsigned short protocol;
+	unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
+
+	if(skb == NULL)
+		return -1;
+
+	if((method <= NAT25_MIN) || (method >= NAT25_MAX))
+		return -1;
+
+	protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
+
+	/*---------------------------------------------------*/
+	/*                 Handle IP frame                   */
+	/*---------------------------------------------------*/
+	if(protocol == __constant_htons(ETH_P_IP))
+	{
+		struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN);
+
+		if(((unsigned char*)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len))
+		{
+			DEBUG_WARN("NAT25: malformed IP packet !\n");
+			return -1;
+		}
+
+		switch(method)
+		{
+			case NAT25_CHECK:
+				return -1;
+
+			case NAT25_INSERT:
+				{
+					//some muticast with source IP is all zero, maybe other case is illegal
+					//in class A, B, C, host address is all zero or all one is illegal
+					if (iph->saddr == 0)
+						return 0;
+					DBG_871X("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
+					__nat25_generate_ipv4_network_addr(networkAddr, &iph->saddr);
+					//record source IP address and , source mac address into db
+					__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+					__nat25_db_print(priv);
+				}
+				return 0;
+
+			case NAT25_LOOKUP:
+				{
+					DBG_871X("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph->saddr, iph->daddr);
+#ifdef SUPPORT_TX_MCAST2UNI
+					if (priv->pshare->rf_ft_var.mc2u_disable ||
+							((((OPMODE & (WIFI_STATION_STATE|WIFI_ASOC_STATE))
+							== (WIFI_STATION_STATE|WIFI_ASOC_STATE)) &&
+							!checkIPMcAndReplace(priv, skb, &iph->daddr)) ||
+							(OPMODE & WIFI_ADHOC_STATE)))
+#endif
+					{
+						__nat25_generate_ipv4_network_addr(networkAddr, &iph->daddr);
+
+						if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
+							if (*((unsigned char *)&iph->daddr + 3) == 0xff) {
+								// L2 is unicast but L3 is broadcast, make L2 bacome broadcast
+								DBG_871X("NAT25: Set DA as boardcast\n");
+								memset(skb->data, 0xff, ETH_ALEN);
+							}
+							else {
+								// forward unknow IP packet to upper TCP/IP
+								DBG_871X("NAT25: Replace DA with BR's MAC\n");
+								if ( (*(u32 *)priv->br_mac) == 0 && (*(u16 *)(priv->br_mac+4)) == 0 ) {
+									void netdev_br_init(struct net_device *netdev);
+									printk("Re-init netdev_br_init() due to br_mac==0!\n");
+									netdev_br_init(priv->pnetdev);
+								}
+								memcpy(skb->data, priv->br_mac, ETH_ALEN);
+							}
+						}
+					}
+				}
+				return 0;
+
+			default:
+				return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*                 Handle ARP frame                  */
+	/*---------------------------------------------------*/
+	else if(protocol == __constant_htons(ETH_P_ARP))
+	{
+		struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
+		unsigned char *arp_ptr = (unsigned char *)(arp + 1);
+		unsigned int *sender, *target;
+
+		if(arp->ar_pro != __constant_htons(ETH_P_IP))
+		{
+			DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp->ar_pro));
+			return -1;
+		}
+
+		switch(method)
+		{
+			case NAT25_CHECK:
+				return 0;	// skb_copy for all ARP frame
+
+			case NAT25_INSERT:
+				{
+					DBG_871X("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
+						arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
+
+					// change to ARP sender mac address to wlan STA address
+                                        memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
+
+					arp_ptr += arp->ar_hln;
+					sender = (unsigned int *)arp_ptr;
+
+					__nat25_generate_ipv4_network_addr(networkAddr, sender);
+
+					__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+					__nat25_db_print(priv);
+				}
+				return 0;
+
+			case NAT25_LOOKUP:
+				{
+					DBG_871X("NAT25: Lookup ARP\n");
+
+					arp_ptr += arp->ar_hln;
+					sender = (unsigned int *)arp_ptr;
+					arp_ptr += (arp->ar_hln + arp->ar_pln);
+					target = (unsigned int *)arp_ptr;
+
+					__nat25_generate_ipv4_network_addr(networkAddr, target);
+
+					__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
+
+					// change to ARP target mac address to Lookup result
+					arp_ptr = (unsigned char *)(arp + 1);
+					arp_ptr += (arp->ar_hln + arp->ar_pln);
+					memcpy(arp_ptr, skb->data, ETH_ALEN);
+				}
+				return 0;
+
+			default:
+				return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*         Handle IPX and Apple Talk frame           */
+	/*---------------------------------------------------*/
+	else if((protocol == __constant_htons(ETH_P_IPX)) || 
+		(protocol == __constant_htons(ETH_P_ATALK)) ||
+		(protocol == __constant_htons(ETH_P_AARP)))
+	{
+		unsigned char ipx_header[2] = {0xFF, 0xFF};
+		struct ipxhdr	*ipx = NULL;
+		struct elapaarp	*ea = NULL;
+		struct ddpehdr	*ddp = NULL;
+		unsigned char *framePtr = skb->data + ETH_HLEN;
+
+		if(protocol == __constant_htons(ETH_P_IPX))
+		{
+			DBG_871X("NAT25: Protocol=IPX (Ethernet II)\n");
+			ipx = (struct ipxhdr *)framePtr;
+		}
+		else //if(protocol <= __constant_htons(ETH_FRAME_LEN))
+		{
+			if(!memcmp(ipx_header, framePtr, 2))
+			{
+				DBG_871X("NAT25: Protocol=IPX (Ethernet 802.3)\n");
+				ipx = (struct ipxhdr *)framePtr;
+			}
+			else
+			{
+				unsigned char ipx_8022_type =  0xE0;
+				unsigned char snap_8022_type = 0xAA;
+
+				if(*framePtr == snap_8022_type)
+				{
+					unsigned char ipx_snap_id[5] = {0x0, 0x0, 0x0, 0x81, 0x37};		// IPX SNAP ID
+					unsigned char aarp_snap_id[5] = {0x00, 0x00, 0x00, 0x80, 0xF3};	// Apple Talk AARP SNAP ID
+					unsigned char ddp_snap_id[5] = {0x08, 0x00, 0x07, 0x80, 0x9B};	// Apple Talk DDP SNAP ID
+
+					framePtr += 3;	// eliminate the 802.2 header
+
+					if(!memcmp(ipx_snap_id, framePtr, 5))
+					{
+						framePtr += 5;	// eliminate the SNAP header
+
+						DBG_871X("NAT25: Protocol=IPX (Ethernet SNAP)\n");
+						ipx = (struct ipxhdr *)framePtr;
+					}
+					else if(!memcmp(aarp_snap_id, framePtr, 5))
+					{
+						framePtr += 5;	// eliminate the SNAP header
+
+						ea = (struct elapaarp *)framePtr;
+					}
+					else if(!memcmp(ddp_snap_id, framePtr, 5))
+					{
+						framePtr += 5;	// eliminate the SNAP header
+
+						ddp = (struct ddpehdr *)framePtr;
+					}
+					else
+					{
+						DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr[0],
+							framePtr[1], framePtr[2], framePtr[3], framePtr[4]);
+						return -1;
+					}
+				}
+				else if(*framePtr == ipx_8022_type)
+				{
+					framePtr += 3;	// eliminate the 802.2 header
+
+					if(!memcmp(ipx_header, framePtr, 2))
+					{
+						DBG_871X("NAT25: Protocol=IPX (Ethernet 802.2)\n");
+						ipx = (struct ipxhdr *)framePtr;
+					}
+					else
+						return -1;
+				}
+			}
+		}
+
+		/*   IPX   */
+		if(ipx != NULL)
+		{
+			switch(method)
+			{
+				case NAT25_CHECK:
+					if(!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
+					{
+						DBG_871X("NAT25: Check IPX skb_copy\n");
+						return 0;
+					}
+					return -1;
+
+				case NAT25_INSERT:
+					{
+						DBG_871X("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
+							ipx->ipx_dest.net,
+							ipx->ipx_dest.node[0],
+							ipx->ipx_dest.node[1],
+							ipx->ipx_dest.node[2],
+							ipx->ipx_dest.node[3],
+							ipx->ipx_dest.node[4],
+							ipx->ipx_dest.node[5],
+							ipx->ipx_dest.sock,
+							ipx->ipx_source.net,
+							ipx->ipx_source.node[0],
+							ipx->ipx_source.node[1],
+							ipx->ipx_source.node[2],
+							ipx->ipx_source.node[3],
+							ipx->ipx_source.node[4],
+							ipx->ipx_source.node[5],
+							ipx->ipx_source.sock);
+
+						if(!memcmp(skb->data+ETH_ALEN, ipx->ipx_source.node, ETH_ALEN))
+						{
+							DBG_871X("NAT25: Use IPX Net, and Socket as network addr\n");
+
+							__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_source.net, &ipx->ipx_source.sock);
+
+							// change IPX source node addr to wlan STA address
+                                                        memcpy(ipx->ipx_source.node, GET_MY_HWADDR(priv), ETH_ALEN);
+						}
+						else
+						{
+							__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_source.net, ipx->ipx_source.node);
+						}
+
+						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+						__nat25_db_print(priv);
+					}
+					return 0;
+
+				case NAT25_LOOKUP:
+					{
+                                                if(!memcmp(GET_MY_HWADDR(priv), ipx->ipx_dest.node, ETH_ALEN))
+						{
+							DBG_871X("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
+
+							__nat25_generate_ipx_network_addr_with_socket(networkAddr, &ipx->ipx_dest.net, &ipx->ipx_dest.sock);
+
+							__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
+
+							// replace IPX destination node addr with Lookup destination MAC addr
+							memcpy(ipx->ipx_dest.node, skb->data, ETH_ALEN);
+						}
+						else
+						{
+							__nat25_generate_ipx_network_addr_with_node(networkAddr, &ipx->ipx_dest.net, ipx->ipx_dest.node);
+
+							__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
+						}
+					}
+					return 0;
+
+				default:
+					return -1;
+			}
+		}
+
+		/*   AARP   */
+		else if(ea != NULL)
+		{
+			/* Sanity check fields. */
+			if(ea->hw_len != ETH_ALEN || ea->pa_len != AARP_PA_ALEN)
+			{
+				DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
+				return -1;
+			}
+
+			switch(method)
+			{
+				case NAT25_CHECK:
+					return 0;
+
+				case NAT25_INSERT:
+					{
+						// change to AARP source mac address to wlan STA address
+                                                memcpy(ea->hw_src, GET_MY_HWADDR(priv), ETH_ALEN);
+
+						DBG_871X("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
+							ea->pa_src_net,
+							ea->pa_src_node,
+							ea->pa_dst_net,
+							ea->pa_dst_node);
+
+						__nat25_generate_apple_network_addr(networkAddr, &ea->pa_src_net, &ea->pa_src_node);
+
+						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+						__nat25_db_print(priv);
+					}
+					return 0;
+
+				case NAT25_LOOKUP:
+					{
+						DBG_871X("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
+							ea->pa_src_net,
+							ea->pa_src_node,
+							ea->pa_dst_net,
+							ea->pa_dst_node);
+
+						__nat25_generate_apple_network_addr(networkAddr, &ea->pa_dst_net, &ea->pa_dst_node);
+
+						__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
+
+						// change to AARP destination mac address to Lookup result
+						memcpy(ea->hw_dst, skb->data, ETH_ALEN);
+					}
+					return 0;
+
+				default:
+					return -1;
+			}
+		}
+
+		/*   DDP   */
+		else if(ddp != NULL)
+		{
+			switch(method)
+			{
+				case NAT25_CHECK:
+					return -1;
+
+				case NAT25_INSERT:
+					{
+						DBG_871X("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
+							ddp->deh_snet,
+							ddp->deh_snode,
+							ddp->deh_dnet,
+							ddp->deh_dnode);
+
+						__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_snet, &ddp->deh_snode);
+
+						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+						__nat25_db_print(priv);
+					}
+					return 0;
+
+				case NAT25_LOOKUP:
+					{
+						DBG_871X("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
+							ddp->deh_snet,
+							ddp->deh_snode,
+							ddp->deh_dnet,
+							ddp->deh_dnode);
+
+						__nat25_generate_apple_network_addr(networkAddr, &ddp->deh_dnet, &ddp->deh_dnode);
+
+						__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
+					}
+					return 0;
+
+				default:
+					return -1;
+			}
+		}
+
+		return -1;
+	}
+
+	/*---------------------------------------------------*/
+	/*                Handle PPPoE frame                 */
+	/*---------------------------------------------------*/
+	else if((protocol == __constant_htons(ETH_P_PPP_DISC)) ||
+		(protocol == __constant_htons(ETH_P_PPP_SES)))
+	{
+		struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
+		unsigned short *pMagic;
+
+		switch(method)
+		{
+			case NAT25_CHECK:
+				if (ph->sid == 0)
+					return 0;
+				return 1;
+
+			case NAT25_INSERT:
+				if(ph->sid == 0)	// Discovery phase according to tag
+				{
+					if(ph->code == PADI_CODE || ph->code == PADR_CODE)
+					{
+						if (priv->ethBrExtInfo.addPPPoETag) {
+							struct pppoe_tag *tag, *pOldTag;
+							unsigned char tag_buf[40];
+							int old_tag_len=0;
+
+							tag = (struct pppoe_tag *)tag_buf;
+							pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
+							if (pOldTag) { // if SID existed, copy old value and delete it
+								old_tag_len = ntohs(pOldTag->tag_len);
+								if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
+									DEBUG_ERR("SID tag length too long!\n");
+									return -1;
+								}
+
+								memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
+									pOldTag->tag_data, old_tag_len);
+
+								if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
+									DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
+									return -1;
+								}
+								ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
+							}
+
+							tag->tag_type = PTT_RELAY_SID;
+							tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
+
+							// insert the magic_code+client mac in relay tag
+							pMagic = (unsigned short *)tag->tag_data;
+							*pMagic = htons(MAGIC_CODE);
+							memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
+
+							//Add relay tag
+							if(__nat25_add_pppoe_tag(skb, tag) < 0)
+								return -1;
+
+							DBG_871X("NAT25: Insert PPPoE, forward %s packet\n",
+											(ph->code == PADI_CODE ? "PADI" : "PADR"));
+						}
+						else { // not add relay tag
+							if (priv->pppoe_connection_in_progress &&
+									memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))	 {
+								DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
+								return -2;
+							}
+
+							if (priv->pppoe_connection_in_progress == 0)
+								memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
+
+							priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
+						}
+					}
+					else
+						return -1;
+				}
+				else	// session phase
+				{
+						DBG_871X("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
+
+						__nat25_generate_pppoe_network_addr(networkAddr, skb->data, &(ph->sid));
+
+						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+
+						__nat25_db_print(priv);
+
+						if (!priv->ethBrExtInfo.addPPPoETag &&
+								priv->pppoe_connection_in_progress &&
+									!memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
+							priv->pppoe_connection_in_progress = 0;
+				}
+				return 0;
+
+			case NAT25_LOOKUP:
+				if(ph->code == PADO_CODE || ph->code == PADS_CODE)
+				{
+					if (priv->ethBrExtInfo.addPPPoETag) {
+						struct pppoe_tag *tag;
+						unsigned char *ptr;
+						unsigned short tagType, tagLen;
+						int offset=0;
+
+						if((ptr = __nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID))) == 0) {
+							DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
+							return -1;
+						}
+
+						tag = (struct pppoe_tag *)ptr;
+						tagType = (unsigned short)((ptr[0] << 8) + ptr[1]);
+						tagLen = (unsigned short)((ptr[2] << 8) + ptr[3]);
+
+						if((tagType != ntohs(PTT_RELAY_SID)) || (tagLen < (MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN))) {
+							DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen);
+							return -1;
+						}
+
+						pMagic = (unsigned short *)tag->tag_data;
+						if (ntohs(*pMagic) != MAGIC_CODE) {
+							DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
+								(ph->code == PADO_CODE ? "PADO" : "PADS"));
+							return -1;
+						}
+
+						memcpy(skb->data, tag->tag_data+MAGIC_CODE_LEN, ETH_ALEN);
+
+						if (tagLen > MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN)
+							offset = TAG_HDR_LEN;
+
+						if (skb_pull_and_merge(skb, ptr+offset, TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset) < 0) {
+							DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
+							return -1;
+						}
+						ph->length = htons(ntohs(ph->length)-(TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN-offset));
+						if (offset > 0)
+							tag->tag_len = htons(tagLen-MAGIC_CODE_LEN-RTL_RELAY_TAG_LEN);
+
+						DBG_871X("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
+							(ph->code == PADO_CODE ? "PADO" : "PADS"),	skb->dev->name);
+					}
+					else { // not add relay tag
+						if (!priv->pppoe_connection_in_progress) {
+							DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
+							return -1;
+						}
+						memcpy(skb->data, priv->pppoe_addr, ETH_ALEN);
+						priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
+					}
+				}
+				else {
+					if(ph->sid != 0)
+					{
+						DBG_871X("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb->dev->name);
+						__nat25_generate_pppoe_network_addr(networkAddr, skb->data+ETH_ALEN, &(ph->sid));
+
+						__nat25_db_network_lookup_and_replace(priv, skb, networkAddr);
+
+						__nat25_db_print(priv);
+					}
+					else
+						return -1;
+
+				}
+				return 0;
+
+			default:
+				return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*                 Handle EAP frame                  */
+	/*---------------------------------------------------*/
+	else if(protocol == __constant_htons(0x888e))
+	{
+		switch(method)
+		{
+			case NAT25_CHECK:
+				return -1;
+
+			case NAT25_INSERT:
+				return 0;
+
+			case NAT25_LOOKUP:
+				return 0;
+
+			default:
+				return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*         Handle C-Media proprietary frame          */
+	/*---------------------------------------------------*/
+	else if((protocol == __constant_htons(0xe2ae)) ||
+		(protocol == __constant_htons(0xe2af)))
+	{
+		switch(method)
+		{
+			case NAT25_CHECK:
+				return -1;
+
+			case NAT25_INSERT:
+				return 0;
+
+			case NAT25_LOOKUP:
+				return 0;
+
+			default:
+				return -1;
+		}
+	}
+
+	/*---------------------------------------------------*/
+	/*         Handle IPV6 frame      							  */
+	/*---------------------------------------------------*/
+#ifdef CL_IPV6_PASS
+	else if(protocol == __constant_htons(ETH_P_IPV6))
+	{
+		struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
+
+		if (sizeof(*iph) >= (skb->len - ETH_HLEN))
+		{
+			DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
+			return -1;
+		}
+
+		switch(method)
+		{
+			case NAT25_CHECK:
+				if (skb->data[0] & 1)
+					return 0;				
+				return -1;
+
+			case NAT25_INSERT:
+				{
+					DBG_871X("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
+									" DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", 
+						iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3],
+						iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7],
+						iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3],
+						iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]);
+
+					if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
+						__nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr);
+						__nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
+						__nat25_db_print(priv);
+
+						if (iph->nexthdr == IPPROTO_ICMPV6 && 
+								skb->len > (ETH_HLEN +  sizeof(*iph) + 4)) {
+							if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph), 
+                                                                skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {                                                   
+								struct icmp6hdr  *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
+								hdr->icmp6_cksum = 0;
+								hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
+												iph->payload_len,
+												IPPROTO_ICMPV6,
+												csum_partial((__u8 *)hdr, iph->payload_len, 0));
+							}
+						}						
+					}
+				}
+				return 0;
+
+			case NAT25_LOOKUP:
+				DBG_871X("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
+								" DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n", 
+						iph->saddr.s6_addr16[0],iph->saddr.s6_addr16[1],iph->saddr.s6_addr16[2],iph->saddr.s6_addr16[3],
+						iph->saddr.s6_addr16[4],iph->saddr.s6_addr16[5],iph->saddr.s6_addr16[6],iph->saddr.s6_addr16[7],
+						iph->daddr.s6_addr16[0],iph->daddr.s6_addr16[1],iph->daddr.s6_addr16[2],iph->daddr.s6_addr16[3],
+						iph->daddr.s6_addr16[4],iph->daddr.s6_addr16[5],iph->daddr.s6_addr16[6],iph->daddr.s6_addr16[7]);
+			
+
+				__nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->daddr);
+				if (!__nat25_db_network_lookup_and_replace(priv, skb, networkAddr)) {
+#ifdef SUPPORT_RX_UNI2MCAST							
+					if (iph->daddr.s6_addr[0] == 0xff)
+						convert_ipv6_mac_to_mc(skb);	
+#endif											
+				}
+				return 0;
+
+			default:
+				return -1;
+		}
+	}
+#endif	// CL_IPV6_PASS
+
+	return -1;
+}
+
+
+int nat25_handle_frame(_adapter *priv, struct sk_buff *skb)
+{
+#ifdef BR_EXT_DEBUG
+	if((!priv->ethBrExtInfo.nat25_disable) && (!(skb->data[0] & 1)))
+	{
+		panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n",
+			skb->data[0],
+			skb->data[1],
+			skb->data[2],
+			skb->data[3],
+			skb->data[4],
+			skb->data[5],
+			skb->data[6],
+			skb->data[7],
+			skb->data[8],
+			skb->data[9],
+			skb->data[10],
+			skb->data[11]);
+	}
+#endif
+
+	if(!(skb->data[0] & 1))
+	{
+		int is_vlan_tag=0, i, retval=0;
+		unsigned short vlan_hdr=0;
+
+		if (*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_8021Q)) {
+			is_vlan_tag = 1;
+			vlan_hdr = *((unsigned short *)(skb->data+ETH_ALEN*2+2));
+			for (i=0; i<6; i++)
+				*((unsigned short *)(skb->data+ETH_ALEN*2+2-i*2)) = *((unsigned short *)(skb->data+ETH_ALEN*2-2-i*2));
+			skb_pull(skb, 4);
+		}
+
+		if (!priv->ethBrExtInfo.nat25_disable)
+		{
+			_irqL irqL;
+			_enter_critical_bh(&priv->br_ext_lock, &irqL);
+			/*
+			 *	This function look up the destination network address from
+			 *	the NAT2.5 database. Return value = -1 means that the
+			 *	corresponding network protocol is NOT support.
+			 */
+			if (!priv->ethBrExtInfo.nat25sc_disable &&
+				(*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP)) &&
+				!memcmp(priv->scdb_ip, skb->data+ETH_HLEN+16, 4)) {
+				memcpy(skb->data, priv->scdb_mac, ETH_ALEN);
+				
+				_exit_critical_bh(&priv->br_ext_lock, &irqL);
+			}
+			else {
+				_exit_critical_bh(&priv->br_ext_lock, &irqL);
+				
+				retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
+			}
+		}
+		else {
+			if (((*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_IP)) &&
+					!memcmp(priv->br_ip, skb->data+ETH_HLEN+16, 4)) ||
+				((*((unsigned short *)(skb->data+ETH_ALEN*2)) == __constant_htons(ETH_P_ARP)) &&
+					!memcmp(priv->br_ip, skb->data+ETH_HLEN+24, 4))) {
+				// for traffic to upper TCP/IP
+				retval = nat25_db_handle(priv, skb, NAT25_LOOKUP);
+			}
+		}
+
+		if (is_vlan_tag) {
+			skb_push(skb, 4);
+			for (i=0; i<6; i++)
+				*((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
+			*((unsigned short *)(skb->data+ETH_ALEN*2)) = __constant_htons(ETH_P_8021Q);
+			*((unsigned short *)(skb->data+ETH_ALEN*2+2)) = vlan_hdr;
+		}
+
+		if(retval == -1) {
+			//DEBUG_ERR("NAT25: Lookup fail!\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+#if 0
+void mac_clone(_adapter *priv, unsigned char *addr)
+{
+	struct sockaddr sa;
+
+	memcpy(sa.sa_data, addr, ETH_ALEN);
+	DBG_871X("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n",
+		addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
+	rtl8192cd_set_hwaddr(priv->dev, &sa);
+}
+
+
+int mac_clone_handle_frame(_adapter *priv, struct sk_buff *skb)
+{
+	if(priv->ethBrExtInfo.macclone_enable && !priv->macclone_completed)
+	{
+		if(!(skb->data[ETH_ALEN] & 1))	//// check any other particular MAC add
+		{
+                        if(memcmp(skb->data+ETH_ALEN, GET_MY_HWADDR(priv), ETH_ALEN) &&
+				((priv->dev->br_port) &&
+				 memcmp(skb->data+ETH_ALEN, priv->br_mac, ETH_ALEN)))
+			{
+				mac_clone(priv, skb->data+ETH_ALEN);
+				priv->macclone_completed = 1;
+			}
+		}
+	}
+
+	return 0;
+}
+#endif // 0
+
+#define SERVER_PORT			67
+#define CLIENT_PORT			68
+#define DHCP_MAGIC			0x63825363
+#define BROADCAST_FLAG		0x8000
+
+struct dhcpMessage {
+	u_int8_t op;
+	u_int8_t htype;
+	u_int8_t hlen;
+	u_int8_t hops;
+	u_int32_t xid;
+	u_int16_t secs;
+	u_int16_t flags;
+	u_int32_t ciaddr;
+	u_int32_t yiaddr;
+	u_int32_t siaddr;
+	u_int32_t giaddr;
+	u_int8_t chaddr[16];
+	u_int8_t sname[64];
+	u_int8_t file[128];
+	u_int32_t cookie;
+	u_int8_t options[308]; /* 312 - cookie */
+};
+
+void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb)
+{
+	if(skb == NULL)
+		return;
+
+	if(!priv->ethBrExtInfo.dhcp_bcst_disable)
+	{
+		unsigned short protocol = *((unsigned short *)(skb->data + 2 * ETH_ALEN));
+
+		if(protocol == __constant_htons(ETH_P_IP)) // IP
+		{
+			struct iphdr* iph = (struct iphdr *)(skb->data + ETH_HLEN);
+
+			if(iph->protocol == IPPROTO_UDP) // UDP
+			{
+				struct udphdr *udph = (struct udphdr *)((SIZE_PTR)iph + (iph->ihl << 2));
+
+				if((udph->source == __constant_htons(CLIENT_PORT))
+					&& (udph->dest == __constant_htons(SERVER_PORT))) // DHCP request
+				{
+					struct dhcpMessage *dhcph =
+						(struct dhcpMessage *)((SIZE_PTR)udph + sizeof(struct udphdr));
+
+					if(dhcph->cookie == __constant_htonl(DHCP_MAGIC)) // match magic word
+					{
+						if(!(dhcph->flags & htons(BROADCAST_FLAG))) // if not broadcast
+						{
+							register int sum = 0;
+
+							DBG_871X("DHCP: change flag of DHCP request to broadcast.\n");
+							// or BROADCAST flag
+							dhcph->flags |= htons(BROADCAST_FLAG);
+							// recalculate checksum
+							sum = ~(udph->check) & 0xffff;
+							sum += dhcph->flags;
+							while(sum >> 16)
+								sum = (sum & 0xffff) + (sum >> 16);
+							udph->check = ~sum;
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+
+void *scdb_findEntry(_adapter *priv, unsigned char *macAddr,
+				unsigned char *ipAddr)
+{
+	unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
+	struct nat25_network_db_entry *db;
+	int hash;
+	//_irqL irqL;
+	//_enter_critical_bh(&priv->br_ext_lock, &irqL);
+
+	__nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
+	hash = __nat25_network_hash(networkAddr);
+	db = priv->nethash[hash];
+	while (db != NULL)
+	{
+		if(!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
+			//_exit_critical_bh(&priv->br_ext_lock, &irqL);
+			return (void *)db;
+		}
+
+		db = db->next_hash;
+	}
+
+	//_exit_critical_bh(&priv->br_ext_lock, &irqL);
+	return NULL;
+}
+
+#endif	// CONFIG_BR_EXT
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_bt_mp.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_bt_mp.c
new file mode 100644
index 000000000..338a5b315
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_bt_mp.c
@@ -0,0 +1,1753 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *										  
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+
+
+#include <drv_types.h>
+#include <rtw_bt_mp.h>
+
+#if defined(CONFIG_RTL8723B)
+#include <rtl8723b_hal.h>
+#endif
+
+#if defined(CONFIG_RTL8723B) || defined(CONFIG_RTL8821A)
+void MPh2c_timeout_handle(void *FunctionContext)
+{
+	PADAPTER pAdapter;
+	PMPT_CONTEXT pMptCtx;
+
+
+	DBG_8192C("[MPT], MPh2c_timeout_handle \n");
+
+	pAdapter = (PADAPTER)FunctionContext;
+	pMptCtx = &pAdapter->mppriv.MptCtx;
+
+	pMptCtx->bMPh2c_timeout = _TRUE;
+
+	if ((_FALSE == pMptCtx->MptH2cRspEvent)
+		|| ((_TRUE == pMptCtx->MptH2cRspEvent)
+			&& (_FALSE == pMptCtx->MptBtC2hEvent)))
+	{
+		_rtw_up_sema(&pMptCtx->MPh2c_Sema);
+	}
+}
+
+u32 WaitC2Hevent(PADAPTER pAdapter, u8 *C2H_event, u32 delay_time)
+{
+	PMPT_CONTEXT		pMptCtx=&(pAdapter->mppriv.MptCtx);
+	pMptCtx->bMPh2c_timeout=_FALSE;
+	
+	if( pAdapter->registrypriv.mp_mode == 0 )
+	{
+		DBG_8192C("[MPT], Error!! WaitC2Hevent mp_mode == 0!!\n");
+		return _FALSE;
+	}
+
+	_set_timer( &pMptCtx->MPh2c_timeout_timer, delay_time );
+	
+	_rtw_down_sema(&pMptCtx->MPh2c_Sema);
+
+	if (pMptCtx->bMPh2c_timeout == _TRUE)
+	{
+		*C2H_event = _FALSE;
+		
+		return _FALSE;
+	}
+
+	// for safty, cancel timer here again
+	_cancel_timer_ex(&pMptCtx->MPh2c_timeout_timer);
+	
+	return _TRUE;
+}
+
+BT_CTRL_STATUS
+mptbt_CheckC2hFrame(
+	PADAPTER		Adapter,
+	PBT_H2C			pH2c,
+	PBT_EXT_C2H		pExtC2h
+	)
+{
+	BT_CTRL_STATUS	c2hStatus = BT_STATUS_C2H_SUCCESS;
+		
+	//DBG_8192C("[MPT], MPT rsp C2H hex: %x %x %x  %x %x %x \n"), pExtC2h , pExtC2h+1 ,pExtC2h+2 ,pExtC2h+3 ,pExtC2h+4 ,pExtC2h+5);
+
+	DBG_8192C("[MPT], statusCode = 0x%x\n", pExtC2h->statusCode);
+	DBG_8192C("[MPT], retLen = %d\n", pExtC2h->retLen);
+	DBG_8192C("[MPT], opCodeVer : req/rsp=%d/%d\n", pH2c->opCodeVer, pExtC2h->opCodeVer);
+	DBG_8192C("[MPT], reqNum : req/rsp=%d/%d\n", pH2c->reqNum, pExtC2h->reqNum);
+	if(pExtC2h->reqNum != pH2c->reqNum)
+	{
+		c2hStatus = BT_STATUS_C2H_REQNUM_MISMATCH;
+		DBG_8192C("[MPT], Error!! C2H reqNum Mismatch!!\n");
+	}
+	else if(pExtC2h->opCodeVer != pH2c->opCodeVer)
+	{
+		c2hStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH;
+		DBG_8192C("[MPT], Error!! OPCode version L mismatch!!\n");
+	}
+
+	return c2hStatus;
+}
+
+BT_CTRL_STATUS
+mptbt_SendH2c(
+	PADAPTER	Adapter,
+	PBT_H2C	pH2c,
+	u2Byte		h2cCmdLen
+	)
+{
+	//KIRQL				OldIrql = KeGetCurrentIrql();
+	BT_CTRL_STATUS	h2cStatus=BT_STATUS_H2C_SUCCESS;
+	PMPT_CONTEXT		pMptCtx=&(Adapter->mppriv.MptCtx);
+	u1Byte				i;
+
+	DBG_8192C("[MPT], mptbt_SendH2c()=========>\n");
+
+	//PlatformResetEvent(&pMptCtx->MptH2cRspEvent);
+	//PlatformResetEvent(&pMptCtx->MptBtC2hEvent);
+	
+//	if(OldIrql == PASSIVE_LEVEL)
+//	{
+		//RTPRINT_DATA(FMPBT, FMPBT_H2C_CONTENT, ("[MPT], MPT H2C hex: \n"), pH2c, h2cCmdLen);
+
+		for(i=0; i<BT_H2C_MAX_RETRY; i++)
+		{
+			DBG_8192C("[MPT], Send H2C command to wifi!!!\n");
+
+			pMptCtx->MptH2cRspEvent = _FALSE;
+			pMptCtx->MptBtC2hEvent = _FALSE;
+
+#if defined(CONFIG_RTL8723B)
+			rtl8723b_set_FwBtMpOper_cmd(Adapter, pH2c->opCode, pH2c->opCodeVer, pH2c->reqNum, pH2c->buf);
+#endif
+			pMptCtx->h2cReqNum++;
+			pMptCtx->h2cReqNum %= 16;
+
+			if(WaitC2Hevent(Adapter, &pMptCtx->MptH2cRspEvent, 100))
+			{
+				DBG_8192C("[MPT], Received WiFi MptH2cRspEvent!!!\n");
+				if(WaitC2Hevent(Adapter, &pMptCtx->MptBtC2hEvent, 400))
+				{
+					DBG_8192C("[MPT], Received MptBtC2hEvent!!!\n");
+					break;
+				}
+				else
+				{
+					DBG_8192C("[MPT], Error!!BT MptBtC2hEvent timeout!!\n");
+					h2cStatus = BT_STATUS_H2C_BT_NO_RSP;
+				}
+			}
+			else
+			{
+				DBG_8192C("[MPT], Error!!WiFi  MptH2cRspEvent timeout!!\n");
+				h2cStatus = BT_STATUS_H2C_TIMTOUT;
+			}
+		}
+//	}
+//	else
+//	{
+//		RT_ASSERT(FALSE, ("[MPT],  mptbt_SendH2c() can only run under PASSIVE_LEVEL!!\n"));
+//		h2cStatus = BT_STATUS_WRONG_LEVEL;
+//	}
+
+	DBG_8192C("[MPT], mptbt_SendH2c()<=========\n");
+	return h2cStatus;
+}
+
+
+
+BT_CTRL_STATUS
+mptbt_CheckBtRspStatus(
+	PADAPTER			Adapter,
+	PBT_EXT_C2H			pExtC2h
+	)
+{
+	BT_CTRL_STATUS	retStatus=BT_OP_STATUS_SUCCESS;
+
+	switch(pExtC2h->statusCode)
+	{
+		case BT_OP_STATUS_SUCCESS:
+			retStatus = BT_STATUS_BT_OP_SUCCESS;
+			DBG_8192C("[MPT], BT status : BT_STATUS_SUCCESS\n");
+			break;
+		case BT_OP_STATUS_VERSION_MISMATCH:
+			retStatus = BT_STATUS_OPCODE_L_VERSION_MISMATCH;
+			DBG_8192C("[MPT], BT status : BT_STATUS_OPCODE_L_VERSION_MISMATCH\n");
+			break;
+		case BT_OP_STATUS_UNKNOWN_OPCODE:
+			retStatus = BT_STATUS_UNKNOWN_OPCODE_L;
+			DBG_8192C("[MPT], BT status : BT_STATUS_UNKNOWN_OPCODE_L\n");
+			break;
+		case BT_OP_STATUS_ERROR_PARAMETER:
+			retStatus = BT_STATUS_PARAMETER_FORMAT_ERROR_L;
+			DBG_8192C("[MPT], BT status : BT_STATUS_PARAMETER_FORMAT_ERROR_L\n");
+			break;
+		default:
+			retStatus = BT_STATUS_UNKNOWN_STATUS_L;
+			DBG_8192C("[MPT], BT status : BT_STATUS_UNKNOWN_STATUS_L\n");
+			break;
+	}
+	
+	return retStatus;
+}	
+
+
+
+BT_CTRL_STATUS
+mptbt_BtFwOpCodeProcess(
+	PADAPTER		Adapter,
+	u1Byte			btFwOpCode,
+	u1Byte			opCodeVer,
+	pu1Byte			pH2cPar,
+	u1Byte			h2cParaLen
+	)
+{
+	u1Byte				H2C_Parameter[6] ={0};
+	PBT_H2C				pH2c=(PBT_H2C)&H2C_Parameter[0];
+	PMPT_CONTEXT		pMptCtx=&(Adapter->mppriv.MptCtx);
+	PBT_EXT_C2H			pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
+	u2Byte				paraLen=0,i;
+	BT_CTRL_STATUS	h2cStatus=BT_STATUS_H2C_SUCCESS, c2hStatus=BT_STATUS_C2H_SUCCESS;
+	BT_CTRL_STATUS	retStatus=BT_STATUS_H2C_BT_NO_RSP;
+
+	if( Adapter->registrypriv.mp_mode == 0 )
+	{
+		DBG_8192C("[MPT], Error!! mptbt_BtFwOpCodeProces mp_mode == 0!!\n");
+		return _FALSE;
+	}
+
+	pH2c->opCode = btFwOpCode;
+	pH2c->opCodeVer = opCodeVer;
+	pH2c->reqNum = pMptCtx->h2cReqNum;
+	//PlatformMoveMemory(&pH2c->buf[0], pH2cPar, h2cParaLen);
+	//_rtw_memcpy(&pH2c->buf[0], pH2cPar, h2cParaLen);
+	_rtw_memcpy(pH2c->buf, pH2cPar, h2cParaLen);
+
+	DBG_8192C("[MPT], pH2c->opCode=%d\n", pH2c->opCode);
+	DBG_8192C("[MPT], pH2c->opCodeVer=%d\n", pH2c->opCodeVer);
+	DBG_8192C("[MPT], pH2c->reqNum=%d\n", pH2c->reqNum);
+	DBG_8192C("[MPT], h2c parameter length=%d\n", h2cParaLen);
+	for (i=0; i<h2cParaLen; i++)
+	{
+		DBG_8192C("[MPT], parameter[%d]=0x%02x\n", i, pH2c->buf[i]);
+	}
+
+	h2cStatus = mptbt_SendH2c(Adapter, pH2c, h2cParaLen+2);
+	if(BT_STATUS_H2C_SUCCESS == h2cStatus)
+	{
+		// if reach here, it means H2C get the correct c2h response, 
+		c2hStatus = mptbt_CheckC2hFrame(Adapter, pH2c, pExtC2h);
+		if(BT_STATUS_C2H_SUCCESS == c2hStatus)
+		{
+			retStatus = mptbt_CheckBtRspStatus(Adapter, pExtC2h);
+		}
+		else
+		{
+			DBG_8192C("[MPT], Error!! C2H failed for pH2c->opCode=%d\n", pH2c->opCode);
+			// check c2h status error, return error status code to upper layer.
+			retStatus = c2hStatus;
+		}
+	}
+	else
+	{
+		DBG_8192C("[MPT], Error!! H2C failed for pH2c->opCode=%d\n", pH2c->opCode);
+		// check h2c status error, return error status code to upper layer.
+		retStatus = h2cStatus;
+	}
+
+	return retStatus;
+}
+
+
+
+
+u2Byte
+mptbt_BtReady(
+	PADAPTER		Adapter,
+	PBT_REQ_CMD 	pBtReq,
+	PBT_RSP_CMD 	pBtRsp
+	)
+{
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode;
+	u1Byte				btOpcodeVer=0;
+	PMPT_CONTEXT		pMptCtx=&(Adapter->mppriv.MptCtx);
+	PBT_EXT_C2H			pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
+	u1Byte				i;
+	u1Byte				btFwVer=0, bdAddr[6]={0};
+	u2Byte				btRealFwVer=0;
+	pu2Byte 			pu2Tmp=NULL;
+
+	//
+	// check upper layer parameters
+	//
+
+	// 1. check upper layer opcode version
+	if(pBtReq->opCodeVer != 1)
+	{
+		DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+		pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+		return paraLen;
+	}
+
+	pBtRsp->pParamStart[0] = MP_BT_NOT_READY;
+	paraLen = 10;
+	//
+	// execute lower layer opcodes
+	//
+
+	// Get BT FW version
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_GET_BT_VERSION;
+	// execute h2c and check respond c2h from bt fw is correct or not
+	retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+	else
+	{
+		pu2Tmp = (pu2Byte)&pExtC2h->buf[0];
+		btRealFwVer = *pu2Tmp;
+		btFwVer = pExtC2h->buf[1];
+		DBG_8192C("[MPT], btRealFwVer=0x%x, btFwVer=0x%x\n", btRealFwVer, btFwVer);
+	}
+
+	// Get BD Address
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_GET_BD_ADDR_L;
+	// execute h2c and check respond c2h from bt fw is correct or not
+	retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+	else
+	{
+		bdAddr[5] = pExtC2h->buf[0];
+		bdAddr[4] = pExtC2h->buf[1];
+		bdAddr[3] = pExtC2h->buf[2];
+	}
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_GET_BD_ADDR_H;
+	// execute h2c and check respond c2h from bt fw is correct or not
+	retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+	else
+	{
+		bdAddr[2] = pExtC2h->buf[0];
+		bdAddr[1] = pExtC2h->buf[1];
+		bdAddr[0] = pExtC2h->buf[2];
+	}
+	DBG_8192C("[MPT], Local BDAddr:");
+	for(i=0; i<6; i++)
+	{
+		DBG_8192C(" 0x%x ", bdAddr[i]);
+	}
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	pBtRsp->pParamStart[0] = MP_BT_READY;
+	pu2Tmp = (pu2Byte)&pBtRsp->pParamStart[1];
+	*pu2Tmp = btRealFwVer;
+	pBtRsp->pParamStart[3] = btFwVer;
+	for(i=0; i<6; i++)
+	{
+		pBtRsp->pParamStart[4+i] = bdAddr[5-i];
+	}
+
+	return paraLen;
+}
+
+void mptbt_close_WiFiRF(PADAPTER Adapter)
+{
+	PHY_SetBBReg(Adapter, 0x824, 0xF, 0x0);
+	PHY_SetBBReg(Adapter, 0x824, 0x700000, 0x0);
+	PHY_SetRFReg(Adapter, RF_PATH_A, 0x0, 0xF0000, 0x0);
+}
+
+void mptbt_open_WiFiRF(PADAPTER	Adapter)
+{
+	PHY_SetBBReg(Adapter, 0x824, 0x700000, 0x3);
+	PHY_SetBBReg(Adapter, 0x824, 0xF, 0x2);
+	PHY_SetRFReg(Adapter, RF_PATH_A, 0x0, 0xF0000, 0x3);
+}
+
+u4Byte mptbt_switch_RF(PADAPTER	Adapter, u1Byte	Enter)
+{
+	u2Byte	tmp_2byte = 0;
+
+	//Enter test mode
+	if (Enter) {
+		////1>. close WiFi RF
+		mptbt_close_WiFiRF(Adapter);
+		
+		////2>. change ant switch to BT
+		tmp_2byte = rtw_read16(Adapter, 0x860);
+		tmp_2byte = tmp_2byte | BIT(9);
+		tmp_2byte = tmp_2byte & (~BIT(8));
+		rtw_write16(Adapter, 0x860, tmp_2byte);
+		rtw_write16(Adapter, 0x870, 0x300);
+	} else {
+		////1>. Open WiFi RF
+		mptbt_open_WiFiRF(Adapter);
+		
+		////2>. change ant switch back
+		tmp_2byte = rtw_read16(Adapter, 0x860);
+		tmp_2byte = tmp_2byte | BIT(8);
+		tmp_2byte = tmp_2byte & (~BIT(9));
+		rtw_write16(Adapter, 0x860, tmp_2byte);
+		rtw_write16(Adapter, 0x870, 0x300);
+	}
+
+	return 0;
+}
+
+u2Byte
+mptbt_BtSetMode(
+	PADAPTER		Adapter,
+	PBT_REQ_CMD 	pBtReq,
+	PBT_RSP_CMD 	pBtRsp
+	)
+{
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode;
+	u1Byte				btOpcodeVer=0;
+	u1Byte				btModeToSet=0;
+
+	//
+	// check upper layer parameters
+	//
+	// 1. check upper layer opcode version
+	if(pBtReq->opCodeVer != 1)
+	{
+		DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+		pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+		return paraLen;
+	}
+	// 2. check upper layer parameter length
+	if(1 == pBtReq->paraLength)
+	{
+		btModeToSet = pBtReq->pParamStart[0];
+		DBG_8192C("[MPT], BtTestMode=%d \n", btModeToSet);
+	}
+	else
+	{
+		DBG_8192C("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+	
+	//
+	// execute lower layer opcodes
+	//
+	
+	// 1. fill h2c parameters	
+	// check bt mode
+	btOpcode = BT_LO_OP_SET_BT_MODE;
+	if(btModeToSet >= MP_BT_MODE_MAX)
+	{
+		pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	else
+	{
+		mptbt_switch_RF(Adapter, 1);
+
+		h2cParaBuf[0] = btModeToSet;
+		h2cParaLen = 1;
+		// 2. execute h2c and check respond c2h from bt fw is correct or not
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// 3. construct respond status code and data.
+	if(BT_STATUS_BT_OP_SUCCESS == retStatus)
+	{
+		pBtRsp->status = BT_STATUS_SUCCESS;
+	}
+	else
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+	}
+	
+	return paraLen;
+}
+
+
+VOID
+MPTBT_FwC2hBtMpCtrl(
+	PADAPTER	Adapter,
+	pu1Byte 	tmpBuf,
+	u1Byte		length
+	)
+{
+	u32 i;
+	PMPT_CONTEXT	pMptCtx=&(Adapter->mppriv.MptCtx);
+	PBT_EXT_C2H pExtC2h=(PBT_EXT_C2H)tmpBuf;
+	
+	if(Adapter->bBTFWReady == _FALSE || Adapter->registrypriv.mp_mode == 0 )
+	{	
+		//DBG_8192C("Ignore C2H BT MP Info since not in MP mode \n");
+		return;
+	}
+	if( length > 32 || length < 3 )
+	{
+		DBG_8192C("\n [MPT], pExtC2h->buf hex: length=%d > 32 || < 3\n",length);
+		return;
+	}
+
+	//cancel_timeout for h2c handle
+	_cancel_timer_ex(&pMptCtx->MPh2c_timeout_timer);
+
+	for (i=0; i<length; i++)
+	{
+		DBG_8192C("[MPT], %s, buf[%d]=0x%02x ", __FUNCTION__, i, tmpBuf[i]);
+	}
+	DBG_8192C("[MPT], pExtC2h->extendId=0x%x\n", pExtC2h->extendId);
+	
+	switch(pExtC2h->extendId)
+	{
+		case EXT_C2H_WIFI_FW_ACTIVE_RSP:
+			DBG_8192C("[MPT], EXT_C2H_WIFI_FW_ACTIVE_RSP\n");
+#if 0
+			DBG_8192C("[MPT], pExtC2h->buf hex: \n");
+			for (i=0; i<(length-3); i++)
+			{
+				DBG_8192C(" 0x%x ", pExtC2h->buf[i]);
+			}
+#endif
+			if ((_FALSE == pMptCtx->bMPh2c_timeout)
+				&& (_FALSE == pMptCtx->MptH2cRspEvent))
+			{
+				pMptCtx->MptH2cRspEvent = _TRUE;
+				_rtw_up_sema(&pMptCtx->MPh2c_Sema);
+			}
+			break;
+
+		case EXT_C2H_TRIG_BY_BT_FW:
+			DBG_8192C("[MPT], EXT_C2H_TRIG_BY_BT_FW\n");
+			_rtw_memcpy(&pMptCtx->c2hBuf[0], tmpBuf, length);
+			DBG_8192C("[MPT], pExtC2h->statusCode=0x%x\n", pExtC2h->statusCode);
+			DBG_8192C("[MPT], pExtC2h->retLen=0x%x\n", pExtC2h->retLen);
+			DBG_8192C("[MPT], pExtC2h->opCodeVer=0x%x\n", pExtC2h->opCodeVer);
+			DBG_8192C("[MPT], pExtC2h->reqNum=0x%x\n", pExtC2h->reqNum);
+			for (i=0; i<(length-3); i++)
+			{
+				DBG_8192C("[MPT], pExtC2h->buf[%d]=0x%02x\n", i, pExtC2h->buf[i]);
+			}
+
+			if ((_FALSE == pMptCtx->bMPh2c_timeout)
+				&& (_TRUE == pMptCtx->MptH2cRspEvent)
+				&& (_FALSE == pMptCtx->MptBtC2hEvent))
+			{
+				pMptCtx->MptBtC2hEvent = _TRUE;
+				_rtw_up_sema(&pMptCtx->MPh2c_Sema);
+			}
+			break;
+
+		default:
+			DBG_8192C("[MPT], EXT_C2H Target not found,pExtC2h->extendId =%d ,pExtC2h->reqNum=%d\n",pExtC2h->extendId,pExtC2h->reqNum);
+			break;
+	}
+	
+
+	
+}
+
+
+u2Byte
+mptbt_BtGetGeneral(
+	IN	PADAPTER		Adapter,
+	IN	PBT_REQ_CMD 	pBtReq,
+	IN	PBT_RSP_CMD 	pBtRsp
+	)
+{
+	PMPT_CONTEXT		pMptCtx=&(Adapter->mppriv.MptCtx);
+	PBT_EXT_C2H 		pExtC2h=(PBT_EXT_C2H)&pMptCtx->c2hBuf[0];
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode, bdAddr[6]={0};
+	u1Byte				btOpcodeVer=0;
+	u1Byte				getType=0, i;
+	u2Byte				getParaLen=0, validParaLen=0;
+	u1Byte				regType=0, reportType=0;
+	u4Byte				regAddr=0, regValue=0;
+	pu4Byte 			pu4Tmp;
+	pu2Byte 			pu2Tmp;
+	pu1Byte 			pu1Tmp;
+
+	//
+	// check upper layer parameters
+	//
+	
+	// check upper layer opcode version
+	if(pBtReq->opCodeVer != 1)
+	{
+		DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+		pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+		return paraLen;
+	}
+	// check upper layer parameter length
+	if(pBtReq->paraLength < 1)
+	{
+		DBG_8192C("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+	getParaLen = pBtReq->paraLength - 1;
+	getType = pBtReq->pParamStart[0];
+	
+	DBG_8192C("[MPT], getType=%d, getParaLen=%d\n", getType, getParaLen);
+
+	// check parameter first
+	switch(getType)
+	{
+		case BT_GGET_REG:
+			DBG_8192C("[MPT], [BT_GGET_REG]\n");
+			validParaLen = 5;
+			if(getParaLen == validParaLen)
+			{
+				btOpcode = BT_LO_OP_READ_REG;
+				regType = pBtReq->pParamStart[1];
+				pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2];
+				regAddr = *pu4Tmp;
+				DBG_8192C("[MPT], BT_GGET_REG regType=0x%02x, regAddr=0x%08x!!\n",
+					regType, regAddr);
+				if(regType >= BT_REG_MAX)
+				{
+					pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+				else
+				{
+					if( ((BT_REG_RF==regType)&&(regAddr>0x7f)) ||
+						((BT_REG_MODEM==regType)&&(regAddr>0x1ff)) ||
+						((BT_REG_BLUEWIZE==regType)&&(regAddr>0xfff)) ||
+						((BT_REG_VENDOR==regType)&&(regAddr>0xfff)) ||
+						((BT_REG_LE==regType)&&(regAddr>0xfff)) )
+					{				
+						pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+						return paraLen;
+					}
+				}
+			}
+			break;
+		case BT_GGET_STATUS:
+			DBG_8192C("[MPT], [BT_GGET_STATUS]\n");
+			validParaLen = 0;
+			break;
+		case BT_GGET_REPORT:
+			DBG_8192C("[MPT], [BT_GGET_REPORT]\n");
+			validParaLen = 1;
+			if(getParaLen == validParaLen)
+			{
+				reportType = pBtReq->pParamStart[1];
+				DBG_8192C("[MPT], BT_GGET_REPORT reportType=0x%x!!\n", reportType);
+				if(reportType >= BT_REPORT_MAX)
+				{
+					pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+			}
+			break;
+		default:
+			{
+				DBG_8192C("[MPT], Error!! getType=%d, out of range\n", getType);
+				pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+				return paraLen;
+			}
+			break;
+	}
+	if(getParaLen != validParaLen)
+	{
+		DBG_8192C("[MPT], Error!! wrong parameter length=%d for BT_GET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n",
+			getParaLen, getType, validParaLen);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+	
+	//
+	// execute lower layer opcodes
+	//
+	if(BT_GGET_REG == getType)
+	{
+		// fill h2c parameters
+		// here we should write reg value first then write the address, adviced by Austin
+		btOpcode = BT_LO_OP_READ_REG;
+		h2cParaBuf[0] = regType;
+		h2cParaBuf[1] = pBtReq->pParamStart[2];
+		h2cParaBuf[2] = pBtReq->pParamStart[3];
+		h2cParaLen = 3;
+		// execute h2c and check respond c2h from bt fw is correct or not
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		// construct respond status code and data.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+
+		pu2Tmp = (pu2Byte)&pExtC2h->buf[0];
+		regValue = *pu2Tmp;
+		DBG_8192C("[MPT], read reg regType=0x%02x, regAddr=0x%08x, regValue=0x%04x\n", 
+			regType, regAddr, regValue);
+		
+		pu4Tmp = (pu4Byte)&pBtRsp->pParamStart[0];
+		*pu4Tmp = regValue;
+		paraLen = 4;
+	}
+	else if(BT_GGET_STATUS == getType)
+	{
+		btOpcode = BT_LO_OP_GET_BT_STATUS;
+		h2cParaLen = 0;
+		// execute h2c and check respond c2h from bt fw is correct or not
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		// construct respond status code and data.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+
+		pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+		pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+		DBG_8192C("[MPT], read bt status, testMode=0x%x, testStatus=0x%x\n", 
+			pBtRsp->pParamStart[0], pBtRsp->pParamStart[1]);		
+		paraLen = 2;
+	}
+	else if(BT_GGET_REPORT == getType)
+	{
+		switch(reportType)
+		{
+			case BT_REPORT_RX_PACKET_CNT:
+				{
+					DBG_8192C("[MPT], [Rx Packet Counts]\n");
+					btOpcode = BT_LO_OP_GET_RX_PKT_CNT_L;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+
+					btOpcode = BT_LO_OP_GET_RX_PKT_CNT_H;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[2] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[3] = pExtC2h->buf[1];
+					paraLen = 4;
+				}
+				break;
+			case BT_REPORT_RX_ERROR_BITS:
+				{
+					DBG_8192C("[MPT], [Rx Error Bits]\n");
+					btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_L;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+
+					btOpcode = BT_LO_OP_GET_RX_ERROR_BITS_H;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[2] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[3] = pExtC2h->buf[1];
+					paraLen = 4;
+				}
+				break;
+			case BT_REPORT_RSSI:
+				{
+					DBG_8192C("[MPT], [RSSI]\n");
+					btOpcode = BT_LO_OP_GET_RSSI;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+					paraLen = 2;
+				}
+				break;
+			case BT_REPORT_CFO_HDR_QUALITY:
+				{
+					DBG_8192C("[MPT], [CFO & Header Quality]\n");
+					btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_L;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[0] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[1] = pExtC2h->buf[1];
+
+					btOpcode = BT_LO_OP_GET_CFO_HDR_QUALITY_H;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					pBtRsp->pParamStart[2] = pExtC2h->buf[0];
+					pBtRsp->pParamStart[3] = pExtC2h->buf[1];
+					paraLen = 4;
+				}
+				break;
+			case BT_REPORT_CONNECT_TARGET_BD_ADDR:
+				{
+					DBG_8192C("[MPT], [Connected Target BD ADDR]\n");
+					btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_L;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					bdAddr[5] = pExtC2h->buf[0];
+					bdAddr[4] = pExtC2h->buf[1];
+					bdAddr[3] = pExtC2h->buf[2];
+
+					btOpcode = BT_LO_OP_GET_TARGET_BD_ADDR_H;
+					h2cParaLen = 0;
+					// execute h2c and check respond c2h from bt fw is correct or not
+					retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+					// construct respond status code and data.
+					if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+					{
+						pBtRsp->status = ((btOpcode<<8)|retStatus);
+						DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+						return paraLen;
+					}
+					bdAddr[2] = pExtC2h->buf[0];
+					bdAddr[1] = pExtC2h->buf[1];
+					bdAddr[0] = pExtC2h->buf[2];
+						
+					DBG_8192C("[MPT], Connected Target BDAddr:%s", bdAddr);
+					for(i=0; i<6; i++)
+					{
+						pBtRsp->pParamStart[i] = bdAddr[5-i];
+					}
+					paraLen = 6;
+				}
+				break;
+			default:
+				pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+				return paraLen;
+				break;
+		}
+	}
+
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	return paraLen;
+}
+
+
+
+u2Byte
+mptbt_BtSetGeneral(
+	IN	PADAPTER		Adapter,
+	IN	PBT_REQ_CMD 	pBtReq,
+	IN	PBT_RSP_CMD 	pBtRsp
+	)
+{
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode;
+	u1Byte				btOpcodeVer=0;
+	u1Byte				setType=0;
+	u2Byte				setParaLen=0, validParaLen=0;
+	u1Byte				regType=0, bdAddr[6]={0}, calVal=0;
+	u4Byte				regAddr=0, regValue=0;
+	pu4Byte 			pu4Tmp;
+	pu2Byte 			pu2Tmp;
+	pu1Byte 			pu1Tmp;
+
+	//
+	// check upper layer parameters
+	//
+	
+	// check upper layer opcode version
+	if(pBtReq->opCodeVer != 1)
+	{
+		DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+		pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+		return paraLen;
+	}
+	// check upper layer parameter length
+	if(pBtReq->paraLength < 1)
+	{
+		DBG_8192C("[MPT], Error!! wrong parameter length=%d (should larger than 1)\n", pBtReq->paraLength);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+	setParaLen = pBtReq->paraLength - 1;
+	setType = pBtReq->pParamStart[0];
+	
+	DBG_8192C("[MPT], setType=%d, setParaLen=%d\n", setType, setParaLen);
+
+	// check parameter first
+	switch(setType)
+	{
+		case BT_GSET_REG:
+			DBG_8192C ("[MPT], [BT_GSET_REG]\n");
+			validParaLen = 9;
+			if(setParaLen == validParaLen)
+			{
+				btOpcode = BT_LO_OP_WRITE_REG_VALUE;
+				regType = pBtReq->pParamStart[1];
+				pu4Tmp = (pu4Byte)&pBtReq->pParamStart[2];
+				regAddr = *pu4Tmp;
+				pu4Tmp = (pu4Byte)&pBtReq->pParamStart[6];
+				regValue = *pu4Tmp;
+				DBG_8192C("[MPT], BT_GSET_REG regType=0x%x, regAddr=0x%x, regValue=0x%x!!\n", 
+					regType, regAddr, regValue);
+				if(regType >= BT_REG_MAX)
+				{
+					pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+				else
+				{
+					if( ((BT_REG_RF==regType)&&(regAddr>0x7f)) ||
+						((BT_REG_MODEM==regType)&&(regAddr>0x1ff)) ||
+						((BT_REG_BLUEWIZE==regType)&&(regAddr>0xfff)) ||
+						((BT_REG_VENDOR==regType)&&(regAddr>0xfff)) ||
+						((BT_REG_LE==regType)&&(regAddr>0xfff)) )
+					{				
+						pBtRsp->status = (btOpcode<<8)| BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+						return paraLen;
+					}
+				}
+			}
+			break;
+		case BT_GSET_RESET:
+			DBG_8192C("[MPT], [BT_GSET_RESET]\n");
+			validParaLen = 0;
+			break;
+		case BT_GSET_TARGET_BD_ADDR:
+			DBG_8192C("[MPT], [BT_GSET_TARGET_BD_ADDR]\n");
+			validParaLen = 6;
+			if(setParaLen == validParaLen)
+			{
+				btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H;
+				if( (pBtReq->pParamStart[1]==0) &&
+					(pBtReq->pParamStart[2]==0) &&
+					(pBtReq->pParamStart[3]==0) &&
+					(pBtReq->pParamStart[4]==0) &&
+					(pBtReq->pParamStart[5]==0) &&
+					(pBtReq->pParamStart[6]==0) )
+				{
+					DBG_8192C("[MPT], Error!! targetBDAddr=all zero\n");
+					pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+				if( (pBtReq->pParamStart[1]==0xff) &&
+					(pBtReq->pParamStart[2]==0xff) &&
+					(pBtReq->pParamStart[3]==0xff) &&
+					(pBtReq->pParamStart[4]==0xff) &&
+					(pBtReq->pParamStart[5]==0xff) &&
+					(pBtReq->pParamStart[6]==0xff) )
+				{
+					DBG_8192C("[MPT], Error!! targetBDAddr=all 0xf\n");
+					pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+				bdAddr[0] = pBtReq->pParamStart[6];
+				bdAddr[1] = pBtReq->pParamStart[5];
+				bdAddr[2] = pBtReq->pParamStart[4];
+				bdAddr[3] = pBtReq->pParamStart[3];
+				bdAddr[4] = pBtReq->pParamStart[2];
+				bdAddr[5] = pBtReq->pParamStart[1];
+				DBG_8192C ("[MPT], target BDAddr:%x,%x,%x,%x,%x,%x\n", 
+							bdAddr[0],bdAddr[1],bdAddr[2],bdAddr[3],bdAddr[4],bdAddr[5]);
+			}
+			break;
+		case BT_GSET_TX_PWR_FINETUNE:
+			DBG_8192C("[MPT], [BT_GSET_TX_PWR_FINETUNE]\n");
+			validParaLen = 1;
+			if(setParaLen == validParaLen)
+			{
+				btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION;
+				calVal = pBtReq->pParamStart[1];
+				if( (calVal<1) || (calVal>9) )
+				{
+					pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+				DBG_8192C ("[MPT], calVal=%d\n", calVal);
+			}
+			break;
+		case BT_SET_TRACKING_INTERVAL:
+			DBG_871X("[MPT], [BT_SET_TRACKING_INTERVAL] setParaLen =%d \n",setParaLen);
+			
+			validParaLen = 1;	
+			if(setParaLen == validParaLen)	
+				calVal = pBtReq->pParamStart[1];
+			break;
+		case BT_SET_THERMAL_METER:
+			DBG_871X("[MPT], [BT_SET_THERMAL_METER] setParaLen =%d \n",setParaLen);
+			validParaLen = 1;	
+			if(setParaLen == validParaLen)	
+				calVal = pBtReq->pParamStart[1];
+			break;
+		case BT_ENABLE_CFO_TRACKING:
+			DBG_871X("[MPT], [BT_ENABLE_CFO_TRACKING] setParaLen =%d \n",setParaLen);
+			validParaLen = 1;	
+			if(setParaLen == validParaLen)	
+				calVal = pBtReq->pParamStart[1];
+			break;
+		case BT_GSET_UPDATE_BT_PATCH:
+			
+			break;
+		default:
+			{
+				DBG_8192C ("[MPT], Error!! setType=%d, out of range\n", setType);
+				pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+				return paraLen;
+			}
+			break;
+	}
+	if(setParaLen != validParaLen)
+	{
+		DBG_8192C("[MPT], Error!! wrong parameter length=%d for BT_SET_GEN_CMD cmd id=0x%x, paraLen should=0x%x\n",
+			setParaLen, setType, validParaLen);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+	
+	//
+	// execute lower layer opcodes
+	//
+	if(BT_GSET_REG == setType)
+	{
+		// fill h2c parameters
+		// here we should write reg value first then write the address, adviced by Austin
+		btOpcode = BT_LO_OP_WRITE_REG_VALUE;
+		h2cParaBuf[0] = pBtReq->pParamStart[6];
+		h2cParaBuf[1] = pBtReq->pParamStart[7];
+		h2cParaBuf[2] = pBtReq->pParamStart[8];
+		h2cParaLen = 3;
+		// execute h2c and check respond c2h from bt fw is correct or not
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		// construct respond status code and data.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+		
+		// write reg address
+		btOpcode = BT_LO_OP_WRITE_REG_ADDR;
+		h2cParaBuf[0] = regType;
+		h2cParaBuf[1] = pBtReq->pParamStart[2];
+		h2cParaBuf[2] = pBtReq->pParamStart[3];
+		h2cParaLen = 3;
+		// execute h2c and check respond c2h from bt fw is correct or not
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		// construct respond status code and data.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}		
+	}
+	else if(BT_GSET_RESET == setType)
+	{
+		btOpcode = BT_LO_OP_RESET;
+		h2cParaLen = 0;
+		// execute h2c and check respond c2h from bt fw is correct or not
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		// construct respond status code and data.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+	}
+	else if(BT_GSET_TARGET_BD_ADDR == setType)
+	{
+		// fill h2c parameters
+		btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_L;
+		h2cParaBuf[0] = pBtReq->pParamStart[1];
+		h2cParaBuf[1] = pBtReq->pParamStart[2];
+		h2cParaBuf[2] = pBtReq->pParamStart[3];
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);		
+		// ckeck bt return status.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+
+		btOpcode = BT_LO_OP_SET_TARGET_BD_ADDR_H;
+		h2cParaBuf[0] = pBtReq->pParamStart[4];
+		h2cParaBuf[1] = pBtReq->pParamStart[5];
+		h2cParaBuf[2] = pBtReq->pParamStart[6];
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);		
+		// ckeck bt return status.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+	}
+	else if(BT_GSET_TX_PWR_FINETUNE == setType)
+	{
+		// fill h2c parameters
+		btOpcode = BT_LO_OP_SET_TX_POWER_CALIBRATION;
+		h2cParaBuf[0] = calVal;
+		h2cParaLen = 1;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		// ckeck bt return status.
+		if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+		{
+			pBtRsp->status = ((btOpcode<<8)|retStatus);
+			DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+	}
+	else if(BT_SET_TRACKING_INTERVAL == setType)
+	{
+		//	BT_LO_OP_SET_TRACKING_INTERVAL								= 0x22,
+		//	BT_LO_OP_SET_THERMAL_METER									= 0x23,
+		//	BT_LO_OP_ENABLE_CFO_TRACKING									= 0x24,
+				btOpcode = BT_LO_OP_SET_TRACKING_INTERVAL;
+				h2cParaBuf[0] = calVal;
+				h2cParaLen = 1;
+				retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);		
+				// ckeck bt return status.
+				if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+				{
+					pBtRsp->status = ((btOpcode<<8)|retStatus);
+					DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+					return paraLen;
+				}
+	}
+	else if(BT_SET_THERMAL_METER == setType)
+	{
+				btOpcode = BT_LO_OP_SET_THERMAL_METER;
+				h2cParaBuf[0] = calVal;
+				h2cParaLen = 1;
+				retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);		
+				// ckeck bt return status.
+				if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+				{
+					pBtRsp->status = ((btOpcode<<8)|retStatus);
+					DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+					return paraLen;
+				}
+	}
+	else if(BT_ENABLE_CFO_TRACKING == setType)
+	{
+				btOpcode = BT_LO_OP_ENABLE_CFO_TRACKING;
+				h2cParaBuf[0] = calVal;
+				h2cParaLen = 1;
+				retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);		
+				// ckeck bt return status.
+				if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+				{
+					pBtRsp->status = ((btOpcode<<8)|retStatus);
+					DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+			return paraLen;
+		}
+	}
+	
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	return paraLen;
+}
+
+
+
+u2Byte
+mptbt_BtSetTxRxPars(
+	IN	PADAPTER		Adapter,
+	IN	PBT_REQ_CMD 	pBtReq,
+	IN	PBT_RSP_CMD 	pBtRsp
+	)
+{
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode;
+	u1Byte				btOpcodeVer=0;
+	PBT_TXRX_PARAMETERS pTxRxPars=(PBT_TXRX_PARAMETERS)&pBtReq->pParamStart[0];
+	u2Byte				lenTxRx=sizeof(BT_TXRX_PARAMETERS);
+	u1Byte				i;
+	u1Byte				bdAddr[6]={0};
+
+	//
+	// check upper layer parameters
+	//
+	
+	// 1. check upper layer opcode version
+	if(pBtReq->opCodeVer != 1)
+	{
+		DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+		pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+		return paraLen;
+	}
+	// 2. check upper layer parameter length
+	if(pBtReq->paraLength == sizeof(BT_TXRX_PARAMETERS))
+	{	
+		DBG_8192C ("[MPT], pTxRxPars->txrxChannel=0x%x \n", pTxRxPars->txrxChannel);
+		DBG_8192C ("[MPT], pTxRxPars->txrxTxPktCnt=0x%8x \n", pTxRxPars->txrxTxPktCnt);
+		DBG_8192C  ("[MPT], pTxRxPars->txrxTxPktInterval=0x%x \n", pTxRxPars->txrxTxPktInterval);
+		DBG_8192C  ("[MPT], pTxRxPars->txrxPayloadType=0x%x \n", pTxRxPars->txrxPayloadType);
+		DBG_8192C  ("[MPT], pTxRxPars->txrxPktType=0x%x \n", pTxRxPars->txrxPktType);
+		DBG_8192C  ("[MPT], pTxRxPars->txrxPayloadLen=0x%x \n", pTxRxPars->txrxPayloadLen);
+		DBG_8192C  ("[MPT], pTxRxPars->txrxPktHeader=0x%x \n", pTxRxPars->txrxPktHeader);
+		DBG_8192C  ("[MPT], pTxRxPars->txrxWhitenCoeff=0x%x \n", pTxRxPars->txrxWhitenCoeff); 	
+		bdAddr[0] = pTxRxPars->txrxBdaddr[5];
+		bdAddr[1] = pTxRxPars->txrxBdaddr[4];
+		bdAddr[2] = pTxRxPars->txrxBdaddr[3];
+		bdAddr[3] = pTxRxPars->txrxBdaddr[2];
+		bdAddr[4] = pTxRxPars->txrxBdaddr[1];
+		bdAddr[5] = pTxRxPars->txrxBdaddr[0];
+		DBG_8192C  ("[MPT], pTxRxPars->txrxBdaddr: %s", &bdAddr[0]);
+		DBG_8192C ("[MPT], pTxRxPars->txrxTxGainIndex=0x%x \n", pTxRxPars->txrxTxGainIndex);
+	}
+	else
+	{
+		DBG_8192C  ("[MPT], Error!! pBtReq->paraLength=%d, correct Len=%d\n", pBtReq->paraLength, lenTxRx);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+
+	//
+	// execute lower layer opcodes
+	//
+	
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_PKT_HEADER;
+	if(pTxRxPars->txrxPktHeader > 0x3ffff)
+	{
+		DBG_8192C  ("[MPT], Error!! pTxRxPars->txrxPktHeader=0x%x is out of range, (should be between 0x0~0x3ffff)\n", pTxRxPars->txrxPktHeader);
+		pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	else
+	{
+		h2cParaBuf[0] = (u1Byte)(pTxRxPars->txrxPktHeader&0xff);
+		h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPktHeader&0xff00)>>8);
+		h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPktHeader&0xff0000)>>16);
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C  ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}	
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_PKT_TYPE_LEN;
+	{
+		u2Byte	payloadLenLimit=0;
+		switch(pTxRxPars->txrxPktType)
+		{
+			case MP_BT_PKT_DH1:
+				payloadLenLimit = 27*8;
+				break;
+			case MP_BT_PKT_DH3:
+				payloadLenLimit = 183*8;
+				break;
+			case MP_BT_PKT_DH5:
+				payloadLenLimit = 339*8;
+				break;
+			case MP_BT_PKT_2DH1:
+				payloadLenLimit = 54*8;
+				break;
+			case MP_BT_PKT_2DH3:
+				payloadLenLimit = 367*8;
+				break;
+			case MP_BT_PKT_2DH5:
+				payloadLenLimit = 679*8;
+				break;
+			case MP_BT_PKT_3DH1:
+				payloadLenLimit = 83*8;
+				break;
+			case MP_BT_PKT_3DH3:
+				payloadLenLimit = 552*8;
+				break;
+			case MP_BT_PKT_3DH5:
+				payloadLenLimit = 1021*8;
+				break;
+			case MP_BT_PKT_LE:
+				payloadLenLimit = 39*8;
+				break;
+			default:
+				{
+					DBG_8192C  ("[MPT], Error!! Unknown pTxRxPars->txrxPktType=0x%x\n", pTxRxPars->txrxPktType);
+					pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+					return paraLen;
+				}
+				break;
+		}
+
+		if(pTxRxPars->txrxPayloadLen > payloadLenLimit)
+		{
+			DBG_8192C ("[MPT], Error!! pTxRxPars->txrxPayloadLen=0x%x, (should smaller than %d)\n", 
+				pTxRxPars->txrxPayloadLen, payloadLenLimit);
+			pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+			return paraLen;
+		}
+
+		h2cParaBuf[0] = pTxRxPars->txrxPktType;
+		h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxPayloadLen&0xff));
+		h2cParaBuf[2] = (u1Byte)((pTxRxPars->txrxPayloadLen&0xff00)>>8);
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_PKT_CNT_L_PL_TYPE;
+	if(pTxRxPars->txrxPayloadType > MP_BT_PAYLOAD_MAX)
+	{
+		DBG_8192C  ("[MPT], Error!! pTxRxPars->txrxPayloadType=0x%x, (should be between 0~4)\n", pTxRxPars->txrxPayloadType);
+		pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	else
+	{
+		h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff));
+		h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff00)>>8);
+		h2cParaBuf[2] = pTxRxPars->txrxPayloadType;
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}	
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_PKT_CNT_H_PKT_INTV;
+	if(pTxRxPars->txrxTxPktInterval > 15)
+	{
+	DBG_8192C  ("[MPT], Error!! pTxRxPars->txrxTxPktInterval=0x%x, (should be between 0~15)\n", pTxRxPars->txrxTxPktInterval);
+	pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	else
+	{
+		h2cParaBuf[0] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff0000)>>16);
+		h2cParaBuf[1] = (u1Byte)((pTxRxPars->txrxTxPktCnt&0xff000000)>>24);
+		h2cParaBuf[2] = pTxRxPars->txrxTxPktInterval;
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}	
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_WHITENCOEFF;
+	{
+		h2cParaBuf[0] = pTxRxPars->txrxWhitenCoeff;
+		h2cParaLen = 1;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C  ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_CHNL_TX_GAIN;
+	if( (pTxRxPars->txrxChannel > 78) ||
+		(pTxRxPars->txrxTxGainIndex > 7) )
+	{
+		DBG_8192C ("[MPT], Error!! pTxRxPars->txrxChannel=0x%x, (should be between 0~78)\n", pTxRxPars->txrxChannel);
+		DBG_8192C ("[MPT], Error!! pTxRxPars->txrxTxGainIndex=0x%x, (should be between 0~7)\n", pTxRxPars->txrxTxGainIndex);
+		pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	else
+	{
+		h2cParaBuf[0] = pTxRxPars->txrxChannel;
+		h2cParaBuf[1] = pTxRxPars->txrxTxGainIndex;
+		h2cParaLen = 2;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+
+	// fill h2c parameters
+	btOpcode = BT_LO_OP_SET_BD_ADDR_L;
+	if( (pTxRxPars->txrxBdaddr[0]==0) &&
+		(pTxRxPars->txrxBdaddr[1]==0) &&
+		(pTxRxPars->txrxBdaddr[2]==0) &&
+		(pTxRxPars->txrxBdaddr[3]==0) &&
+		(pTxRxPars->txrxBdaddr[4]==0) &&
+		(pTxRxPars->txrxBdaddr[5]==0) )
+	{
+		DBG_8192C ("[MPT], Error!! pTxRxPars->txrxBdaddr=all zero\n");
+		pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	if( (pTxRxPars->txrxBdaddr[0]==0xff) &&
+		(pTxRxPars->txrxBdaddr[1]==0xff) &&
+		(pTxRxPars->txrxBdaddr[2]==0xff) &&
+		(pTxRxPars->txrxBdaddr[3]==0xff) &&
+		(pTxRxPars->txrxBdaddr[4]==0xff) &&
+		(pTxRxPars->txrxBdaddr[5]==0xff) )
+	{
+		DBG_8192C ("[MPT], Error!! pTxRxPars->txrxBdaddr=all 0xf\n");
+		pBtRsp->status = (btOpcode<<8)|BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	
+	{
+		h2cParaBuf[0] = pTxRxPars->txrxBdaddr[0];
+		h2cParaBuf[1] = pTxRxPars->txrxBdaddr[1];
+		h2cParaBuf[2] = pTxRxPars->txrxBdaddr[2];
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}	
+
+	btOpcode = BT_LO_OP_SET_BD_ADDR_H;
+	{
+		h2cParaBuf[0] = pTxRxPars->txrxBdaddr[3];
+		h2cParaBuf[1] = pTxRxPars->txrxBdaddr[4];
+		h2cParaBuf[2] = pTxRxPars->txrxBdaddr[5];
+		h2cParaLen = 3;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	// ckeck bt return status.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C  ("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	return paraLen;
+}
+
+
+
+u2Byte
+mptbt_BtTestCtrl(
+	IN	PADAPTER		Adapter,
+	IN	PBT_REQ_CMD 	pBtReq,
+	IN	PBT_RSP_CMD 	pBtRsp
+	)
+{
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode;
+	u1Byte				btOpcodeVer=0;
+	u1Byte				testCtrl=0;
+
+	//
+	// check upper layer parameters
+	//
+	
+	// 1. check upper layer opcode version
+	if(pBtReq->opCodeVer != 1)
+	{
+		DBG_8192C("[MPT], Error!! Upper OP code version not match!!!\n");
+		pBtRsp->status = BT_STATUS_OPCODE_U_VERSION_MISMATCH;
+		return paraLen;
+	}
+	// 2. check upper layer parameter length
+	if(1 == pBtReq->paraLength)
+	{
+		testCtrl = pBtReq->pParamStart[0];
+		DBG_8192C("[MPT], testCtrl=%d \n", testCtrl);
+	}
+	else
+	{
+		DBG_8192C("[MPT], Error!! wrong parameter length=%d (should be 1)\n", pBtReq->paraLength);
+		pBtRsp->status = BT_STATUS_PARAMETER_FORMAT_ERROR_U;
+		return paraLen;
+	}
+	
+	//
+	// execute lower layer opcodes
+	//
+	
+	// 1. fill h2c parameters	
+	// check bt mode
+	btOpcode = BT_LO_OP_TEST_CTRL;
+	if(testCtrl >= MP_BT_TEST_MAX)
+	{
+		DBG_8192C("[MPT], Error!! testCtrl=0x%x, (should be between smaller or equal to 0x%x)\n", 
+			testCtrl, MP_BT_TEST_MAX-1);
+		pBtRsp->status = BT_STATUS_PARAMETER_OUT_OF_RANGE_U;
+		return paraLen;
+	}
+	else
+	{
+		h2cParaBuf[0] = testCtrl;
+		h2cParaLen = 1;
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+	}
+	
+	// 3. construct respond status code and data.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	return paraLen;
+}
+
+
+u2Byte
+mptbt_TestBT(
+	IN	PADAPTER		Adapter,
+	IN	PBT_REQ_CMD 	pBtReq,
+	IN	PBT_RSP_CMD 	pBtRsp
+	)
+{
+
+	u1Byte				h2cParaBuf[6] ={0};
+	u1Byte				h2cParaLen=0;
+	u2Byte				paraLen=0;
+	u1Byte				retStatus=BT_STATUS_BT_OP_SUCCESS;
+	u1Byte				btOpcode;
+	u1Byte				btOpcodeVer=0;
+	u1Byte				testCtrl=0;
+
+	// 1. fill h2c parameters	
+		btOpcode =  0x11;
+		h2cParaBuf[0] = 0x11;
+		h2cParaBuf[1] = 0x0;
+		h2cParaBuf[2] = 0x0;
+		h2cParaBuf[3] = 0x0;
+		h2cParaBuf[4] = 0x0;
+		h2cParaLen = 1;
+	//	retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, &h2cParaBuf[0], h2cParaLen);
+		retStatus = mptbt_BtFwOpCodeProcess(Adapter, btOpcode, btOpcodeVer, h2cParaBuf, h2cParaLen);
+	
+	
+	// 3. construct respond status code and data.
+	if(BT_STATUS_BT_OP_SUCCESS != retStatus)
+	{
+		pBtRsp->status = ((btOpcode<<8)|retStatus);
+		DBG_8192C("[MPT], Error!! status code=0x%x \n", pBtRsp->status);
+		return paraLen;
+	}
+
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	return paraLen;
+}
+
+VOID
+mptbt_BtControlProcess(
+	PADAPTER	Adapter,
+	PVOID		pInBuf
+	)
+{
+	u1Byte			H2C_Parameter[6] ={0};
+	PBT_H2C 		pH2c=(PBT_H2C)&H2C_Parameter[0];
+	PMPT_CONTEXT	pMptCtx=&(Adapter->mppriv.MptCtx);
+	PBT_REQ_CMD 	pBtReq=(PBT_REQ_CMD)pInBuf;
+	PBT_RSP_CMD 	pBtRsp;
+	u1Byte			i;
+
+
+	DBG_8192C("[MPT], mptbt_BtControlProcess()=========>\n");
+
+	DBG_8192C("[MPT], input opCodeVer=%d\n", pBtReq->opCodeVer);
+	DBG_8192C("[MPT], input OpCode=%d\n", pBtReq->OpCode);
+	DBG_8192C("[MPT], paraLength=%d \n", pBtReq->paraLength);
+	if(pBtReq->paraLength)
+	{
+		//DBG_8192C("[MPT], parameters(hex):0x%x %d \n",&pBtReq->pParamStart[0], pBtReq->paraLength);
+	}
+
+	_rtw_memset((void*)pMptCtx->mptOutBuf, 0, 100);
+	pMptCtx->mptOutLen = 4; //length of (BT_RSP_CMD.status+BT_RSP_CMD.paraLength)
+
+	pBtRsp = (PBT_RSP_CMD)pMptCtx->mptOutBuf;
+	pBtRsp->status = BT_STATUS_SUCCESS;
+	pBtRsp->paraLength = 0x0;
+
+	// The following we should maintain the User OP codes sent by upper layer
+	switch(pBtReq->OpCode)
+	{
+		case BT_UP_OP_BT_READY:
+			DBG_8192C("[MPT], OPcode : [BT_READY]\n");
+			pBtRsp->paraLength = mptbt_BtReady(Adapter, pBtReq, pBtRsp);
+			break;
+		case BT_UP_OP_BT_SET_MODE:
+			DBG_8192C("[MPT], OPcode : [BT_SET_MODE]\n");
+			pBtRsp->paraLength = mptbt_BtSetMode(Adapter, pBtReq, pBtRsp);
+			break;
+		case BT_UP_OP_BT_SET_TX_RX_PARAMETER:
+			DBG_8192C("[MPT], OPcode : [BT_SET_TXRX_PARAMETER]\n");
+			pBtRsp->paraLength = mptbt_BtSetTxRxPars(Adapter, pBtReq, pBtRsp);
+			break;
+		case BT_UP_OP_BT_SET_GENERAL:
+			DBG_8192C("[MPT], OPcode : [BT_SET_GENERAL]\n");
+			pBtRsp->paraLength = mptbt_BtSetGeneral(Adapter, pBtReq, pBtRsp);
+			break;
+		case BT_UP_OP_BT_GET_GENERAL:
+			DBG_8192C("[MPT], OPcode : [BT_GET_GENERAL]\n");
+			pBtRsp->paraLength = mptbt_BtGetGeneral(Adapter, pBtReq, pBtRsp);
+			break;
+		case BT_UP_OP_BT_TEST_CTRL:
+			DBG_8192C("[MPT], OPcode : [BT_TEST_CTRL]\n");
+			pBtRsp->paraLength = mptbt_BtTestCtrl(Adapter, pBtReq, pBtRsp);
+			break;
+		case BT_UP_OP_TEST_BT:
+			DBG_8192C("[MPT], OPcode : [TEST_BT]\n");
+			pBtRsp->paraLength = mptbt_TestBT(Adapter, pBtReq, pBtRsp);
+			break;
+		default:
+			DBG_8192C("[MPT], Error!! OPcode : UNDEFINED!!!!\n");
+			pBtRsp->status = BT_STATUS_UNKNOWN_OPCODE_U;
+			pBtRsp->paraLength = 0x0;
+			break;
+	}
+
+	pMptCtx->mptOutLen += pBtRsp->paraLength;
+
+	DBG_8192C("[MPT], pMptCtx->mptOutLen=%d, pBtRsp->paraLength=%d\n", pMptCtx->mptOutLen, pBtRsp->paraLength);
+	DBG_8192C("[MPT], mptbt_BtControlProcess()<=========\n");
+}
+
+#endif
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_btcoex.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_btcoex.c
new file mode 100644
index 000000000..791353bf5
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_btcoex.c
@@ -0,0 +1,1724 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#ifdef CONFIG_BT_COEXIST
+
+#include <drv_types.h>
+#include <hal_btcoex.h>
+#include <hal_data.h>
+
+
+void rtw_btcoex_Initialize(PADAPTER padapter)
+{
+	hal_btcoex_Initialize(padapter);
+}
+
+void rtw_btcoex_PowerOnSetting(PADAPTER padapter)
+{
+	hal_btcoex_PowerOnSetting(padapter);
+}
+
+void rtw_btcoex_PreLoadFirmware(PADAPTER padapter)
+{
+	hal_btcoex_PreLoadFirmware(padapter);
+}
+
+void rtw_btcoex_HAL_Initialize(PADAPTER padapter, u8 bWifiOnly)
+{
+	hal_btcoex_InitHwConfig(padapter, bWifiOnly);
+}
+
+void rtw_btcoex_IpsNotify(PADAPTER padapter, u8 type)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_IpsNotify(padapter, type);
+}
+
+void rtw_btcoex_LpsNotify(PADAPTER padapter, u8 type)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_LpsNotify(padapter, type);
+}
+
+void rtw_btcoex_ScanNotify(PADAPTER padapter, u8 type)
+{
+	PHAL_DATA_TYPE	pHalData;
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	PBT_MGNT	pBtMgnt=&pcoex_info->BtMgnt;
+#endif //CONFIG_BT_COEXIST_SOCKET_TRX
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ((_FALSE == type) && (padapter->pbuddy_adapter))
+	{
+		PADAPTER pbuddy = padapter->pbuddy_adapter;
+		if (check_fwstate(&pbuddy->mlmepriv, WIFI_SITE_MONITOR) == _TRUE)
+			return;
+	}
+#endif
+
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	if(pBtMgnt->ExtConfig.bEnableWifiScanNotify)
+		rtw_btcoex_SendScanNotify(padapter, type);
+#endif //CONFIG_BT_COEXIST_SOCKET_TRX	
+
+	hal_btcoex_ScanNotify(padapter, type);
+}
+
+void rtw_btcoex_ConnectNotify(PADAPTER padapter, u8 action)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+#ifdef DBG_CONFIG_ERROR_RESET
+	if (_TRUE == rtw_hal_sreset_inprogress(padapter))
+	{
+		DBG_8192C(FUNC_ADPT_FMT ": [BTCoex] under reset, skip notify!\n",
+			FUNC_ADPT_ARG(padapter));
+		return;
+	}
+#endif // DBG_CONFIG_ERROR_RESET
+		
+#ifdef CONFIG_CONCURRENT_MODE
+	if ((_FALSE == action) && (padapter->pbuddy_adapter))
+	{
+		PADAPTER pbuddy = padapter->pbuddy_adapter;
+		if (check_fwstate(&pbuddy->mlmepriv, WIFI_UNDER_LINKING) == _TRUE)
+			return;
+	}
+#endif
+
+	hal_btcoex_ConnectNotify(padapter, action);
+}
+
+void rtw_btcoex_MediaStatusNotify(PADAPTER padapter, u8 mediaStatus)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+#ifdef DBG_CONFIG_ERROR_RESET
+	if (_TRUE == rtw_hal_sreset_inprogress(padapter))
+	{
+		DBG_8192C(FUNC_ADPT_FMT ": [BTCoex] under reset, skip notify!\n",
+			FUNC_ADPT_ARG(padapter));
+		return;
+	}
+#endif // DBG_CONFIG_ERROR_RESET
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ((RT_MEDIA_DISCONNECT == mediaStatus) && (padapter->pbuddy_adapter))
+	{
+		PADAPTER pbuddy = padapter->pbuddy_adapter;
+		if (check_fwstate(&pbuddy->mlmepriv, WIFI_ASOC_STATE) == _TRUE)
+			return;
+	}
+#endif // CONFIG_CONCURRENT_MODE
+
+	if ((RT_MEDIA_CONNECT == mediaStatus)
+		&& (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE))
+	{
+		rtw_hal_set_hwreg(padapter, HW_VAR_DL_RSVD_PAGE, NULL);
+	}
+
+	hal_btcoex_MediaStatusNotify(padapter, mediaStatus);
+}
+
+void rtw_btcoex_SpecialPacketNotify(PADAPTER padapter, u8 pktType)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_SpecialPacketNotify(padapter, pktType);
+}
+
+void rtw_btcoex_IQKNotify(PADAPTER padapter, u8 state)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_IQKNotify(padapter, state);
+}
+
+void rtw_btcoex_BtInfoNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_BtInfoNotify(padapter, length, tmpBuf);
+}
+
+void rtw_btcoex_BtMpRptNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	if (padapter->registrypriv.mp_mode == 1)
+		return;
+
+	hal_btcoex_BtMpRptNotify(padapter, length, tmpBuf);
+}
+
+void rtw_btcoex_SuspendNotify(PADAPTER padapter, u8 state)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_SuspendNotify(padapter, state);
+}
+
+void rtw_btcoex_HaltNotify(PADAPTER padapter)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	if (_FALSE == padapter->bup)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": bup=%d Skip!\n",
+			FUNC_ADPT_ARG(padapter), padapter->bup);
+
+		return;
+	}
+
+	if (rtw_is_surprise_removed(padapter)) {
+		DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=%s Skip!\n",
+			FUNC_ADPT_ARG(padapter), rtw_is_surprise_removed(padapter)?"True":"False");
+
+		return;
+	}
+
+	hal_btcoex_HaltNotify(padapter);
+}
+
+void rtw_btcoex_ScoreBoardStatusNotify(PADAPTER padapter, u8 length, u8 *tmpBuf)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+	hal_btcoex_ScoreBoardStatusNotify(padapter, length, tmpBuf);
+}
+
+void rtw_btcoex_SwitchBtTRxMask(PADAPTER padapter)
+{
+	hal_btcoex_SwitchBtTRxMask(padapter);	
+}
+
+void rtw_btcoex_Switch(PADAPTER padapter, u8 enable)
+{
+	hal_btcoex_SetBTCoexist(padapter, enable);
+}
+
+u8 rtw_btcoex_IsBtDisabled(PADAPTER padapter)
+{
+	return hal_btcoex_IsBtDisabled(padapter);
+}
+
+void rtw_btcoex_Handler(PADAPTER padapter)
+{
+	PHAL_DATA_TYPE	pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+
+	if (_FALSE == pHalData->EEPROMBluetoothCoexist)
+		return;
+
+#if defined(CONFIG_CONCURRENT_MODE)
+	if (padapter->adapter_type != PRIMARY_ADAPTER)
+		return;
+#endif
+
+
+
+	hal_btcoex_Hanlder(padapter);
+}
+
+s32 rtw_btcoex_IsBTCoexRejectAMPDU(PADAPTER padapter)
+{
+	s32 coexctrl;
+
+	coexctrl = hal_btcoex_IsBTCoexRejectAMPDU(padapter);
+
+	return coexctrl;
+}
+
+s32 rtw_btcoex_IsBTCoexCtrlAMPDUSize(PADAPTER padapter)
+{
+	s32 coexctrl;
+
+	coexctrl = hal_btcoex_IsBTCoexCtrlAMPDUSize(padapter);
+
+	return coexctrl;
+}
+
+u32 rtw_btcoex_GetAMPDUSize(PADAPTER padapter)
+{
+	u32 size;
+
+	size = hal_btcoex_GetAMPDUSize(padapter);
+
+	return size;
+}
+
+void rtw_btcoex_SetManualControl(PADAPTER padapter, u8 manual)
+{
+	if (_TRUE == manual)
+	{
+		hal_btcoex_SetManualControl(padapter, _TRUE);
+	}
+	else
+	{
+		hal_btcoex_SetManualControl(padapter, _FALSE);
+	}
+}
+
+u8 rtw_btcoex_1Ant(PADAPTER padapter)
+{
+	return hal_btcoex_1Ant(padapter);
+}
+
+u8 rtw_btcoex_IsBtControlLps(PADAPTER padapter)
+{
+	return hal_btcoex_IsBtControlLps(padapter);
+}
+
+u8 rtw_btcoex_IsLpsOn(PADAPTER padapter)
+{
+	return hal_btcoex_IsLpsOn(padapter);
+}
+
+u8 rtw_btcoex_RpwmVal(PADAPTER padapter)
+{
+	return hal_btcoex_RpwmVal(padapter);
+}
+
+u8 rtw_btcoex_LpsVal(PADAPTER padapter)
+{
+	return hal_btcoex_LpsVal(padapter);
+}
+
+void rtw_btcoex_SetBTCoexist(PADAPTER padapter, u8 bBtExist)
+{
+	hal_btcoex_SetBTCoexist(padapter, bBtExist);
+}
+
+void rtw_btcoex_SetChipType(PADAPTER padapter, u8 chipType)
+{
+	hal_btcoex_SetChipType(padapter, chipType);
+}
+
+void rtw_btcoex_SetPGAntNum(PADAPTER padapter, u8 antNum)
+{
+	hal_btcoex_SetPgAntNum(padapter, antNum);
+}
+
+u8 rtw_btcoex_GetPGAntNum(PADAPTER padapter)
+{
+	return hal_btcoex_GetPgAntNum(padapter);
+}
+
+void rtw_btcoex_SetSingleAntPath(PADAPTER padapter, u8 singleAntPath)
+{
+	hal_btcoex_SetSingleAntPath(padapter, singleAntPath);
+}
+
+u32 rtw_btcoex_GetRaMask(PADAPTER padapter)
+{
+	return hal_btcoex_GetRaMask(padapter);
+}
+
+void rtw_btcoex_RecordPwrMode(PADAPTER padapter, u8 *pCmdBuf, u8 cmdLen)
+{
+	hal_btcoex_RecordPwrMode(padapter, pCmdBuf, cmdLen);
+}
+
+void rtw_btcoex_DisplayBtCoexInfo(PADAPTER padapter, u8 *pbuf, u32 bufsize)
+{
+	hal_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize);
+}
+
+void rtw_btcoex_SetDBG(PADAPTER padapter, u32 *pDbgModule)
+{
+	hal_btcoex_SetDBG(padapter, pDbgModule);
+}
+
+u32 rtw_btcoex_GetDBG(PADAPTER padapter, u8 *pStrBuf, u32 bufSize)
+{
+	return hal_btcoex_GetDBG(padapter, pStrBuf, bufSize);
+}
+
+u8 rtw_btcoex_IncreaseScanDeviceNum(PADAPTER padapter)
+{
+	return hal_btcoex_IncreaseScanDeviceNum(padapter);
+}
+
+u8 rtw_btcoex_IsBtLinkExist(PADAPTER padapter)
+{
+	return hal_btcoex_IsBtLinkExist(padapter);
+}
+
+void rtw_btcoex_SetBtPatchVersion(PADAPTER padapter,u16 btHciVer, u16 btPatchVer)
+{
+	hal_btcoex_SetBtPatchVersion(padapter,btHciVer,btPatchVer);
+}
+
+void rtw_btcoex_SetHciVersion(PADAPTER  padapter, u16 hciVersion)
+{
+	hal_btcoex_SetHciVersion(padapter, hciVersion);
+}
+
+void rtw_btcoex_StackUpdateProfileInfo(void) 
+{
+	hal_btcoex_StackUpdateProfileInfo();
+}
+
+void rtw_btcoex_BTOffOnNotify(PADAPTER padapter, u8 bBTON)
+{
+	hal_btcoex_BTOffOnNotify(padapter, bBTON);
+}
+
+// ==================================================
+// Below Functions are called by BT-Coex
+// ==================================================
+void rtw_btcoex_rx_ampdu_apply(PADAPTER padapter)
+{
+	rtw_rx_ampdu_apply(padapter);
+}
+
+void rtw_btcoex_LPS_Enter(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrpriv;
+	u8 lpsVal;
+
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+
+	pwrpriv->bpower_saving = _TRUE;
+	lpsVal = rtw_btcoex_LpsVal(padapter);
+	rtw_set_ps_mode(padapter, PS_MODE_MIN, 0, lpsVal, "BTCOEX");
+}
+
+void rtw_btcoex_LPS_Leave(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrpriv;
+
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+
+	if (pwrpriv->pwr_mode != PS_MODE_ACTIVE)
+	{
+		rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "BTCOEX");
+		LPS_RF_ON_check(padapter, 100);
+		pwrpriv->bpower_saving = _FALSE;
+	}
+}
+
+u16 rtw_btcoex_btreg_read(PADAPTER padapter, u8 type, u16 addr, u32 *data)
+{
+	return hal_btcoex_btreg_read(padapter, type, addr, data);
+}
+
+u16 rtw_btcoex_btreg_write(PADAPTER padapter, u8 type, u16 addr, u16 val)
+{
+	return hal_btcoex_btreg_write(padapter, type, addr, val);
+}
+
+
+// ==================================================
+// Below Functions are BT-Coex socket related function
+// ==================================================
+
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+_adapter *pbtcoexadapter = NULL;
+u8 rtw_btcoex_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
+{
+	struct cmd_obj *ph2c;
+	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+	u8 *btinfo;
+	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if (pdrvextra_cmd_parm == NULL) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	btinfo = rtw_zmalloc(len);
+	if (btinfo == NULL) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		rtw_mfree((u8*)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = len;
+	pdrvextra_cmd_parm->pbuf = btinfo;
+
+	_rtw_memcpy(btinfo, buf, len);
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+	return res;
+}
+
+u8 rtw_btcoex_send_event_to_BT(_adapter *padapter, u8 status,  u8 event_code, u8 opcode_low, u8 opcode_high,u8 *dbg_msg)
+{
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0,tx_event_length = 0;
+	rtw_HCI_event *pEvent;
+	
+	pEvent = (rtw_HCI_event*)(&localBuf[0]);
+
+	pEvent->EventCode = event_code;
+	pEvent->Data[0] = 0x1;	//packet #
+	pEvent->Data[1] = opcode_low;
+	pEvent->Data[2] = opcode_high;
+	len = len + 3;
+
+		// Return parameters starts from here
+	pRetPar = &pEvent->Data[len];		
+	pRetPar[0] = status;		//status
+
+	len++;
+	pEvent->Length = len;
+
+	//total tx event length + EventCode length + sizeof(length)
+	tx_event_length = pEvent->Length + 2;
+#if 0
+	rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, dbg_msg);
+#endif		
+	status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		
+	return status;
+}
+
+/* 
+Ref: 
+Realtek Wi-Fi Driver
+Host Controller Interface for
+Bluetooth 3.0 + HS V1.4 2013/02/07
+
+Window team code & BT team code
+ */
+
+
+u8 rtw_btcoex_parse_BT_info_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	#define BT_INFO_LENGTH 8
+	
+	u8 curPollEnable = pcmd[0];
+	u8 curPollTime = pcmd[1];
+	u8 btInfoReason = pcmd[2];
+	u8 btInfoLen = pcmd[3];
+	u8 btinfo[BT_INFO_LENGTH];
+
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0,tx_event_length = 0;
+	RTW_HCI_STATUS status = HCI_STATUS_SUCCESS;
+	rtw_HCI_event *pEvent;
+
+	DBG_871X("%s\n",__func__);
+	DBG_871X("current Poll Enable: %d, currrent Poll Time: %d\n",curPollEnable,curPollTime);
+	DBG_871X("BT Info reason: %d, BT Info length: %d\n",btInfoReason,btInfoLen);
+	/*DBG_871X("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n"
+		,pcmd[4],pcmd[5],pcmd[6],pcmd[7],pcmd[8],pcmd[9],pcmd[10],pcmd[11]);*/
+
+	_rtw_memset(btinfo, 0, BT_INFO_LENGTH);
+	
+#if 1
+	if(BT_INFO_LENGTH != btInfoLen)
+	{
+		status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
+		DBG_871X("Error BT Info Length: %d\n",btInfoLen);
+		//return _FAIL;
+	}
+	else
+#endif
+	{
+		if(0x1 == btInfoReason || 0x2 == btInfoReason)
+		{
+			_rtw_memcpy(btinfo, &pcmd[4], btInfoLen);
+			btinfo[0] = btInfoReason;
+			rtw_btcoex_btinfo_cmd(padapter,btinfo,btInfoLen);
+		}
+		else
+		{
+			DBG_871X("Other BT info reason\n");
+		}
+	}
+
+	//send complete event to BT
+	{
+
+		pEvent = (rtw_HCI_event*)(&localBuf[0]);
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_INFO_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_INFO_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+			// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+			//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+#if 0
+		rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length,"BT_info_event");
+#endif		
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		
+		return status;
+			//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_BT_patch_ver_info_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	RTW_HCI_STATUS status=HCI_STATUS_SUCCESS;
+	u16		btPatchVer=0x0, btHciVer=0x0;
+	//u16		*pU2tmp;
+	
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+
+	btHciVer = pcmd[0] | pcmd[1]<<8;
+	btPatchVer = pcmd[2] | pcmd[3]<<8;
+
+
+	DBG_871X("%s, cmd:%02x %02x %02x %02x\n",__func__, pcmd[0] ,pcmd[1] ,pcmd[2] ,pcmd[3]);
+	DBG_871X("%s, HCI Ver:%d, Patch Ver:%d\n",__func__, btHciVer,btPatchVer);
+	
+	rtw_btcoex_SetBtPatchVersion(padapter,btHciVer,btPatchVer);
+
+
+	//send complete event to BT
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_PATCH_VERSION_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_PATCH_VERSION_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+#if 0
+		rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length,"BT_patch_event");
+#endif
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_HCI_Ver_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	RTW_HCI_STATUS status=HCI_STATUS_SUCCESS;
+	u16 hciver = pcmd[0] | pcmd[1] <<8;
+	
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	PBT_MGNT	pBtMgnt=&pcoex_info->BtMgnt;
+	pBtMgnt->ExtConfig.HCIExtensionVer = hciver;
+	DBG_871X("%s, HCI Version: %d\n",__func__,pBtMgnt->ExtConfig.HCIExtensionVer);
+	if(pBtMgnt->ExtConfig.HCIExtensionVer  < 4)
+	{
+		status = HCI_STATUS_INVALID_HCI_CMD_PARA_VALUE;
+		DBG_871X("%s, Version = %d, HCI Version < 4\n",__func__,pBtMgnt->ExtConfig.HCIExtensionVer );
+	}
+	else
+	{
+		rtw_btcoex_SetHciVersion(padapter,hciver);
+	}
+	//send complete event to BT
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_EXTENSION_VERSION_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_EXTENSION_VERSION_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+	
+}
+
+u8 rtw_btcoex_parse_WIFI_scan_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	RTW_HCI_STATUS status=HCI_STATUS_SUCCESS;
+
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	PBT_MGNT	pBtMgnt=&pcoex_info->BtMgnt;
+	pBtMgnt->ExtConfig.bEnableWifiScanNotify= pcmd[0];
+	DBG_871X("%s, bEnableWifiScanNotify: %d\n",__func__,pBtMgnt->ExtConfig.bEnableWifiScanNotify);
+	
+	//send complete event to BT
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_ENABLE_WIFI_SCAN_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_ENABLE_WIFI_SCAN_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_HCI_link_status_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+	struct bt_coex_info	*pcoex_info=&padapter->coex_info;
+	PBT_MGNT	pBtMgnt=&pcoex_info->BtMgnt;
+	//PBT_DBG		pBtDbg=&padapter->MgntInfo.BtInfo.BtDbg;
+	u8		i, numOfHandle=0, numOfAcl=0;
+	u16		conHandle;
+	u8		btProfile, btCoreSpec, linkRole;
+	u8		*pTriple;
+
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	
+	//pBtDbg->dbgHciInfo.hciCmdCntLinkStatusNotify++;
+	//RT_DISP_DATA(FIOCTL, IOCTL_BT_HCICMD_EXT, "LinkStatusNotify, Hex Data :\n", 
+	//		&pHciCmd->Data[0], pHciCmd->Length);
+
+	DBG_871X("BTLinkStatusNotify\n");
+
+	// Current only RTL8723 support this command.
+	//pBtMgnt->bSupportProfile = TRUE;
+	pBtMgnt->bSupportProfile = _FALSE;
+
+	pBtMgnt->ExtConfig.NumberOfACL = 0;
+	pBtMgnt->ExtConfig.NumberOfSCO = 0;
+	
+	numOfHandle = pcmd[0];
+	//RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, ("numOfHandle = 0x%x\n", numOfHandle));
+	//RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, ("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer));
+	DBG_871X("numOfHandle = 0x%x\n", numOfHandle);
+	DBG_871X("HCIExtensionVer = %d\n", pBtMgnt->ExtConfig.HCIExtensionVer);
+	
+	pTriple = &pcmd[1];
+	for(i=0; i<numOfHandle; i++)
+	{	
+		if(pBtMgnt->ExtConfig.HCIExtensionVer < 1)
+		{
+			conHandle = *((u8 *)&pTriple[0]);
+			btProfile = pTriple[2];
+			btCoreSpec = pTriple[3];
+			if(BT_PROFILE_SCO == btProfile)
+			{
+				pBtMgnt->ExtConfig.NumberOfSCO++;
+			}
+			else
+			{
+				pBtMgnt->ExtConfig.NumberOfACL++;			
+				pBtMgnt->ExtConfig.aclLink[i].ConnectHandle = conHandle;
+				pBtMgnt->ExtConfig.aclLink[i].BTProfile = btProfile;
+				pBtMgnt->ExtConfig.aclLink[i].BTCoreSpec = btCoreSpec;
+			}
+			//RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, 
+			//	("Connection_Handle=0x%x, BTProfile=%d, BTSpec=%d\n",
+			//		conHandle, btProfile, btCoreSpec));
+			DBG_871X("Connection_Handle=0x%x, BTProfile=%d, BTSpec=%d\n", conHandle, btProfile, btCoreSpec);
+			pTriple += 4;
+		}
+		else if(pBtMgnt->ExtConfig.HCIExtensionVer >= 1)
+		{
+			conHandle = *((pu2Byte)&pTriple[0]);
+			btProfile = pTriple[2];
+			btCoreSpec = pTriple[3];
+			linkRole = pTriple[4];
+			if(BT_PROFILE_SCO == btProfile)
+			{
+				pBtMgnt->ExtConfig.NumberOfSCO++;
+			}
+			else
+			{
+				pBtMgnt->ExtConfig.NumberOfACL++;			
+				pBtMgnt->ExtConfig.aclLink[i].ConnectHandle = conHandle;
+				pBtMgnt->ExtConfig.aclLink[i].BTProfile = btProfile;
+				pBtMgnt->ExtConfig.aclLink[i].BTCoreSpec = btCoreSpec;
+				pBtMgnt->ExtConfig.aclLink[i].linkRole = linkRole;
+			}
+			//RT_DISP(FIOCTL, IOCTL_BT_HCICMD_EXT, 
+			DBG_871X("Connection_Handle=0x%x, BTProfile=%d, BTSpec=%d, LinkRole=%d\n",
+				conHandle, btProfile, btCoreSpec, linkRole);
+			pTriple += 5;
+		}	
+	}
+	rtw_btcoex_StackUpdateProfileInfo();
+
+		//send complete event to BT
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_LINK_STATUS_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_LINK_STATUS_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+	
+	
+}
+
+u8 rtw_btcoex_parse_HCI_BT_coex_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_COEX_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_COEX_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_HCI_BT_operation_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+
+	DBG_871X("%s, OP code: %d\n",__func__,pcmd[0]);
+
+	switch(pcmd[0])
+	{
+		case HCI_BT_OP_NONE:
+			DBG_871X("[bt operation] : Operation None!!\n");
+			break;
+		case HCI_BT_OP_INQUIRY_START:
+			DBG_871X("[bt operation] : Inquiry start!!\n");
+			break;
+		case HCI_BT_OP_INQUIRY_FINISH:
+			DBG_871X("[bt operation] : Inquiry finished!!\n");
+			break;
+		case HCI_BT_OP_PAGING_START:
+			DBG_871X("[bt operation] : Paging is started!!\n");
+			break;
+		case HCI_BT_OP_PAGING_SUCCESS:
+			DBG_871X("[bt operation] : Paging complete successfully!!\n");
+			break;
+		case HCI_BT_OP_PAGING_UNSUCCESS:
+			DBG_871X("[bt operation] : Paging complete unsuccessfully!!\n");
+			break;
+		case HCI_BT_OP_PAIRING_START:
+			DBG_871X("[bt operation] : Pairing start!!\n");
+			break;
+		case HCI_BT_OP_PAIRING_FINISH:
+			DBG_871X("[bt operation] : Pairing finished!!\n");
+			break;
+		case HCI_BT_OP_BT_DEV_ENABLE:
+			DBG_871X("[bt operation] : BT Device is enabled!!\n");
+			break;
+		case HCI_BT_OP_BT_DEV_DISABLE:
+			DBG_871X("[bt operation] : BT Device is disabled!!\n");
+			break;
+		default:
+			DBG_871X("[bt operation] : Unknown, error!!\n");
+			break;
+	}
+
+			//send complete event to BT
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_OPERATION_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_OPERATION_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_BT_AFH_MAP_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_AFH_MAP_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_AFH_MAP_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_BT_register_val_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_REGISTER_VALUE_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_REGISTER_VALUE_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_HCI_BT_abnormal_notify_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_BT_ABNORMAL_NOTIFY, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_BT_ABNORMAL_NOTIFY, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+u8 rtw_btcoex_parse_HCI_query_RF_status_cmd(_adapter *padapter, u8 *pcmd, u16 cmdlen)
+{
+	u8 localBuf[6] = "";
+	u8 *pRetPar;
+	u8	len=0, tx_event_length =0;
+	rtw_HCI_event *pEvent;
+	RTW_HCI_STATUS	status=HCI_STATUS_SUCCESS;
+
+	{
+		pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+
+		pEvent->EventCode = HCI_EVENT_COMMAND_COMPLETE;
+		pEvent->Data[0] = 0x1;	//packet #
+		pEvent->Data[1] = HCIOPCODELOW(HCI_QUERY_RF_STATUS, OGF_EXTENSION);
+		pEvent->Data[2] = HCIOPCODEHIGHT(HCI_QUERY_RF_STATUS, OGF_EXTENSION);
+		len = len + 3;
+
+		// Return parameters starts from here
+		pRetPar = &pEvent->Data[len];		
+		pRetPar[0] = status;		//status
+
+		len++;
+		pEvent->Length = len;
+
+		//total tx event length + EventCode length + sizeof(length)
+		tx_event_length = pEvent->Length + 2;
+
+		status = rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+		return status;
+		//bthci_IndicateEvent(Adapter, PPacketIrpEvent, len+2);
+	}
+}
+
+/*****************************************
+* HCI cmd format :
+*| 15 - 0						|	
+*| OPcode (OCF|OGF<<10)		|
+*| 15 - 8		|7 - 0			|
+*|Cmd para 	|Cmd para Length	|
+*|Cmd para......				|
+******************************************/
+
+//bit 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
+//	 |	OCF			             |	   OGF       |
+void rtw_btcoex_parse_hci_extend_cmd(_adapter *padapter, u8 *pcmd, u16 len,const u16 hci_OCF)
+{
+
+	DBG_871X("%s: OCF: %x\n",__func__,hci_OCF);
+	switch(hci_OCF)
+	{
+		case HCI_EXTENSION_VERSION_NOTIFY:
+			DBG_871X("HCI_EXTENSION_VERSION_NOTIFY\n");
+			rtw_btcoex_parse_HCI_Ver_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_LINK_STATUS_NOTIFY:
+			DBG_871X("HCI_LINK_STATUS_NOTIFY\n");
+			rtw_btcoex_parse_HCI_link_status_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_OPERATION_NOTIFY:
+			// only for 8723a 2ant
+			DBG_871X("HCI_BT_OPERATION_NOTIFY\n");
+			rtw_btcoex_parse_HCI_BT_operation_notify_cmd(padapter,pcmd, len);
+			//
+			break;
+		case HCI_ENABLE_WIFI_SCAN_NOTIFY:
+			DBG_871X("HCI_ENABLE_WIFI_SCAN_NOTIFY\n");
+			rtw_btcoex_parse_WIFI_scan_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_QUERY_RF_STATUS:
+			// only for 8723b 2ant
+			DBG_871X("HCI_QUERY_RF_STATUS\n");
+			rtw_btcoex_parse_HCI_query_RF_status_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_ABNORMAL_NOTIFY:
+			DBG_871X("HCI_BT_ABNORMAL_NOTIFY\n");
+			rtw_btcoex_parse_HCI_BT_abnormal_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_INFO_NOTIFY:
+			DBG_871X("HCI_BT_INFO_NOTIFY\n");
+			rtw_btcoex_parse_BT_info_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_COEX_NOTIFY:
+			DBG_871X("HCI_BT_COEX_NOTIFY\n");
+			rtw_btcoex_parse_HCI_BT_coex_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_PATCH_VERSION_NOTIFY:
+			DBG_871X("HCI_BT_PATCH_VERSION_NOTIFY\n");
+			rtw_btcoex_parse_BT_patch_ver_info_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_AFH_MAP_NOTIFY:
+			DBG_871X("HCI_BT_AFH_MAP_NOTIFY\n");
+			rtw_btcoex_parse_BT_AFH_MAP_notify_cmd(padapter,pcmd, len);
+			break;
+		case HCI_BT_REGISTER_VALUE_NOTIFY:
+			DBG_871X("HCI_BT_REGISTER_VALUE_NOTIFY\n");
+			rtw_btcoex_parse_BT_register_val_notify_cmd(padapter,pcmd, len);
+			break;
+		default:
+			DBG_871X("ERROR!!! Unknown OCF: %x\n",hci_OCF);
+			break;
+			
+	}
+}
+
+void rtw_btcoex_parse_hci_cmd(_adapter *padapter, u8 *pcmd, u16 len)
+{
+	u16 opcode = pcmd[0] | pcmd[1]<<8;
+	u16 hci_OGF = HCI_OGF(opcode);
+	u16 hci_OCF = HCI_OCF(opcode);
+	u8 cmdlen = len -3;
+	u8 pare_len = pcmd[2];
+
+	DBG_871X("%s\n",__func__);
+	DBG_871X("OGF: %x,OCF: %x\n",hci_OGF,hci_OCF);
+	switch(hci_OGF)
+	{
+		case OGF_EXTENSION:
+			DBG_871X("HCI_EXTENSION_CMD_OGF\n");
+			rtw_btcoex_parse_hci_extend_cmd(padapter, &pcmd[3], cmdlen, hci_OCF);
+			break;
+		default:
+			DBG_871X("Other OGF: %x\n",hci_OGF);
+			break;
+	}
+}
+
+u16 rtw_btcoex_parse_recv_data(u8 *msg, u8 msg_size)
+{
+	u8 cmp_msg1[32] = attend_ack;
+	u8 cmp_msg2[32] = leave_ack;
+	u8 cmp_msg3[32] = bt_leave;
+	u8 cmp_msg4[32] = invite_req;
+	u8 cmp_msg5[32] = attend_req;
+	u8 cmp_msg6[32] = invite_rsp;
+	u8 res = OTHER;
+	
+	if (_rtw_memcmp(cmp_msg1, msg, msg_size) == _TRUE) {
+		/*DBG_871X("%s, msg:%s\n",__func__,msg);*/
+		res = RX_ATTEND_ACK;
+	} else if (_rtw_memcmp(cmp_msg2, msg, msg_size) == _TRUE) {
+		/*DBG_871X("%s, msg:%s\n",__func__,msg);*/
+		res = RX_LEAVE_ACK;
+	} else if (_rtw_memcmp(cmp_msg3, msg, msg_size) == _TRUE) {
+		/*DBG_871X("%s, msg:%s\n",__func__,msg);*/
+		res = RX_BT_LEAVE;
+	} else if (_rtw_memcmp(cmp_msg4, msg, msg_size) == _TRUE) {
+		/*DBG_871X("%s, msg:%s\n",__func__,msg);*/
+		res = RX_INVITE_REQ;
+	} else if (_rtw_memcmp(cmp_msg5, msg, msg_size) == _TRUE) {
+		res = RX_ATTEND_REQ;
+	} else if (_rtw_memcmp(cmp_msg6, msg, msg_size) == _TRUE) {
+		res = RX_INVITE_RSP;
+	} else {
+		DBG_871X("%s, %s\n", __func__, msg);
+		res = OTHER;
+	}
+	
+	DBG_871X("%s, res:%d\n", __func__, res);
+	
+	return res;
+}
+
+void rtw_btcoex_recvmsgbysocket(void *data)
+{
+	u8 recv_data[255];
+	u8 tx_msg[255] = leave_ack;
+	u32 len = 0;
+	u16 recv_length = 0;
+	u16 parse_res = 0;
+#if 0
+	u8 para_len = 0, polling_enable = 0, poling_interval = 0, reason = 0, btinfo_len = 0;
+	u8 btinfo[BT_INFO_LEN] = {0};
+#endif
+
+	struct bt_coex_info *pcoex_info = NULL;
+	struct sock *sk = NULL;
+	struct sk_buff *skb = NULL;
+	
+	DBG_871X("%s\n",__func__);
+
+	if (pbtcoexadapter == NULL) {
+		DBG_871X("%s: btcoexadapter NULL!\n", __func__);
+		return;
+	}
+
+	pcoex_info = &pbtcoexadapter->coex_info;
+	sk = pcoex_info->sk_store;
+
+	if (sk == NULL) {
+		DBG_871X("%s: critical error when receive socket data!\n", __func__);
+		return;
+	}
+	
+	len = skb_queue_len(&sk->sk_receive_queue);
+	while (len > 0) {
+		skb = skb_dequeue(&sk->sk_receive_queue);
+
+		/*important: cut the udp header from skb->data! header length is 8 byte*/
+		recv_length = skb->len-8;
+		_rtw_memset(recv_data, 0, sizeof(recv_data));
+		_rtw_memcpy(recv_data, skb->data+8, recv_length);
+		
+		parse_res = rtw_btcoex_parse_recv_data(recv_data, recv_length);
+/*
+		if (RX_ATTEND_ACK == parse_res) {
+			//attend ack 
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_ATTEND_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+		} else if (RX_ATTEND_REQ == parse_res) {
+			//attend req from BT 
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_BT_ATTEND_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_sendmsgbysocket(pbtcoexadapter, attend_ack, sizeof(attend_ack), _FALSE);
+		} else if (RX_INVITE_REQ == parse_res) {
+			//invite req from BT
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_INVITE_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_sendmsgbysocket(pbtcoexadapter, invite_rsp, sizeof(invite_rsp), _FALSE);
+		} else if (RX_INVITE_RSP == parse_res) {
+			//invite rsp
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_INVITE_RSP!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+		} else if (RX_LEAVE_ACK == parse_res) {
+			//mean BT know wifi  will leave
+			pcoex_info->BT_attend = _FALSE;
+			DBG_871X("RX_LEAVE_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);			
+		} else if (RX_BT_LEAVE == parse_res) {
+			//BT leave
+			rtw_btcoex_sendmsgbysocket(pbtcoexadapter, leave_ack, sizeof(leave_ack), _FALSE); // no ack
+			pcoex_info->BT_attend = _FALSE;
+			DBG_871X("RX_BT_LEAVE!sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);			
+		} else {
+			//todo: check if recv data are really hci cmds
+			if (_TRUE == pcoex_info->BT_attend)
+				rtw_btcoex_parse_hci_cmd(pbtcoexadapter, recv_data, recv_length);
+		}
+*/
+		switch (parse_res) {
+		case RX_ATTEND_ACK:
+			/* attend ack */
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_ATTEND_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_BTOffOnNotify(pbtcoexadapter, pcoex_info->BT_attend);
+			break;
+
+		case RX_ATTEND_REQ:
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_BT_ATTEND_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_sendmsgbysocket(pbtcoexadapter, attend_ack, sizeof(attend_ack), _FALSE);
+			rtw_btcoex_BTOffOnNotify(pbtcoexadapter, pcoex_info->BT_attend);
+			break;
+
+		case RX_INVITE_REQ:
+			/* invite req from BT */
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_INVITE_REQ!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_sendmsgbysocket(pbtcoexadapter, invite_rsp, sizeof(invite_rsp), _FALSE);
+			rtw_btcoex_BTOffOnNotify(pbtcoexadapter, pcoex_info->BT_attend);
+			break;
+
+		case RX_INVITE_RSP:
+			 /*invite rsp*/
+			pcoex_info->BT_attend = _TRUE;
+			DBG_871X("RX_INVITE_RSP!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_BTOffOnNotify(pbtcoexadapter, pcoex_info->BT_attend);
+			break;
+
+		case RX_LEAVE_ACK:
+			/* mean BT know wifi  will leave */
+			pcoex_info->BT_attend = _FALSE;
+			DBG_871X("RX_LEAVE_ACK!,sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+			rtw_btcoex_BTOffOnNotify(pbtcoexadapter, pcoex_info->BT_attend);
+			break;
+
+		case RX_BT_LEAVE:
+			/* BT leave */
+			rtw_btcoex_sendmsgbysocket(pbtcoexadapter, leave_ack, sizeof(leave_ack), _FALSE); /* no ack */
+			pcoex_info->BT_attend = _FALSE;
+			DBG_871X("RX_BT_LEAVE!sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);	
+			rtw_btcoex_BTOffOnNotify(pbtcoexadapter, pcoex_info->BT_attend);
+			break;
+
+		default:
+			if (_TRUE == pcoex_info->BT_attend)
+				rtw_btcoex_parse_hci_cmd(pbtcoexadapter, recv_data, recv_length);
+			else
+				DBG_871X("ERROR!! BT is UP\n");
+			break;
+
+		}
+		
+		len--;
+		kfree_skb(skb);
+	}
+}
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 15, 0))
+void rtw_btcoex_recvmsg_init(struct sock *sk_in, s32 bytes)
+#else
+void rtw_btcoex_recvmsg_init(struct sock *sk_in)
+#endif
+{
+	struct bt_coex_info *pcoex_info = NULL;
+	
+	if (pbtcoexadapter == NULL) {
+		DBG_871X("%s: btcoexadapter NULL\n", __func__);
+		return;
+	}
+	pcoex_info = &pbtcoexadapter->coex_info;
+	pcoex_info->sk_store = sk_in;
+	if (pcoex_info->btcoex_wq != NULL)
+		queue_delayed_work(pcoex_info->btcoex_wq, &pcoex_info->recvmsg_work, 0);
+	else
+		DBG_871X("%s: BTCOEX workqueue NULL\n", __func__);
+}
+
+u8 rtw_btcoex_sendmsgbysocket(_adapter *padapter, u8 *msg, u8 msg_size, bool force)
+{
+	u8 error; 
+	struct msghdr	udpmsg; 
+	mm_segment_t	oldfs; 
+	struct iovec	iov; 
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+
+	DBG_871X("%s: msg:%s, force:%s\n", __func__, msg, force == _TRUE?"TRUE":"FALSE");
+	if (_FALSE == force) {
+		if (_FALSE == pcoex_info->BT_attend) {
+			DBG_871X("TX Blocked: WiFi-BT disconnected\n");			
+			return _FAIL;
+		}
+	}
+		
+	iov.iov_base	 = (void *)msg; 
+	iov.iov_len	 = msg_size; 
+	udpmsg.msg_name	 = &pcoex_info->bt_sockaddr; 
+	udpmsg.msg_namelen	= sizeof(struct sockaddr_in); 
+	udpmsg.msg_iov	 = &iov; 
+	udpmsg.msg_iovlen	= 1; 
+	udpmsg.msg_control	= NULL; 
+	udpmsg.msg_controllen = 0; 
+	udpmsg.msg_flags	= MSG_DONTWAIT | MSG_NOSIGNAL; 
+	oldfs = get_fs(); 
+	set_fs(KERNEL_DS); 
+	error = sock_sendmsg(pcoex_info->udpsock, &udpmsg, msg_size); 
+	set_fs(oldfs); 
+	if (error < 0) {
+		DBG_871X("Error when sendimg msg, error:%d\n", error); 
+		return _FAIL;
+	} else
+		return _SUCCESS;
+}
+
+u8 rtw_btcoex_create_kernel_socket(_adapter *padapter)
+{
+	s8 kernel_socket_err; 
+	u8 tx_msg[255] = attend_req;
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	s32 sock_reuse = 1;
+	u8 status = _FAIL;
+	
+	DBG_871X("%s CONNECT_PORT %d\n", __func__, CONNECT_PORT);
+
+	if (NULL == pcoex_info) {
+		DBG_871X("coex_info: NULL\n"); 
+		status =  _FAIL;
+	}
+	
+	kernel_socket_err = sock_create(PF_INET, SOCK_DGRAM, 0, &pcoex_info->udpsock); 
+    
+	if (kernel_socket_err < 0) { 
+		DBG_871X("Error during creation of socket error:%d\n", kernel_socket_err); 
+		status = _FAIL;	
+	} else {
+		_rtw_memset(&(pcoex_info->wifi_sockaddr), 0, sizeof(pcoex_info->wifi_sockaddr)); 
+		pcoex_info->wifi_sockaddr.sin_family = AF_INET; 
+		pcoex_info->wifi_sockaddr.sin_port = htons(CONNECT_PORT); 
+		pcoex_info->wifi_sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+		_rtw_memset(&(pcoex_info->bt_sockaddr), 0, sizeof(pcoex_info->bt_sockaddr)); 
+		pcoex_info->bt_sockaddr.sin_family = AF_INET; 
+		pcoex_info->bt_sockaddr.sin_port = htons(CONNECT_PORT_BT); 
+		pcoex_info->bt_sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+		pcoex_info->sk_store = NULL;
+		kernel_socket_err = pcoex_info->udpsock->ops->bind(pcoex_info->udpsock, (struct sockaddr *)&pcoex_info->wifi_sockaddr, 
+			sizeof(pcoex_info->wifi_sockaddr)); 
+		if (kernel_socket_err == 0) {	
+			DBG_871X("binding socket success\n"); 
+			pcoex_info->udpsock->sk->sk_data_ready = rtw_btcoex_recvmsg_init;
+			pcoex_info->sock_open |=  KERNEL_SOCKET_OK;
+			pcoex_info->BT_attend = _FALSE;
+			DBG_871X("WIFI sending attend_req\n"); 
+			rtw_btcoex_sendmsgbysocket(padapter, attend_req, sizeof(attend_req), _TRUE);
+			status = _SUCCESS;
+		} else { 
+			pcoex_info->BT_attend = _FALSE;
+			sock_release(pcoex_info->udpsock); /* bind fail release socket */
+			DBG_871X("Error binding socket: %d\n", kernel_socket_err); 
+			status = _FAIL;
+		} 
+			
+	}
+
+	return status;
+}
+
+void rtw_btcoex_close_kernel_socket(_adapter *padapter)
+{
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	if (pcoex_info->sock_open & KERNEL_SOCKET_OK) {
+		DBG_871X("release kernel socket\n");
+		sock_release(pcoex_info->udpsock);
+		pcoex_info->sock_open &= ~(KERNEL_SOCKET_OK);	
+		if (_TRUE == pcoex_info->BT_attend)
+			pcoex_info->BT_attend = _FALSE;
+		
+		DBG_871X("sock_open:%d, BT_attend:%d\n", pcoex_info->sock_open, pcoex_info->BT_attend);
+	}
+}
+
+void rtw_btcoex_init_socket(_adapter *padapter)
+{
+		
+	u8 is_invite = _FALSE;
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	DBG_871X("%s\n", __func__);
+	if (_FALSE == pcoex_info->is_exist) {
+		_rtw_memset(pcoex_info,0,sizeof(struct bt_coex_info));
+		pcoex_info->btcoex_wq = create_workqueue("BTCOEX");
+		INIT_DELAYED_WORK(&pcoex_info->recvmsg_work,
+			  (void *)rtw_btcoex_recvmsgbysocket);
+		pbtcoexadapter = padapter;
+		/* We expect BT is off if BT don't send ack to wifi */
+		DBG_871X("We expect BT is off if BT send ack to wifi\n");
+		rtw_btcoex_BTOffOnNotify(pbtcoexadapter, _FALSE);
+		if (rtw_btcoex_create_kernel_socket(padapter) == _SUCCESS) {
+			pcoex_info->is_exist = _TRUE;
+		} else {
+			pcoex_info->is_exist = _FALSE;
+			pbtcoexadapter = NULL;
+		}
+		
+		DBG_871X("%s: pbtcoexadapter:%p, coex_info->is_exist: %s\n"
+			, __func__, pbtcoexadapter, pcoex_info->is_exist == _TRUE?"TRUE":"FALSE");
+	}
+}
+
+void rtw_btcoex_close_socket(_adapter *padapter)
+{
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+
+	DBG_871X("%s--coex_info->is_exist: %s, pcoex_info->BT_attend:%s\n"
+		, __func__, pcoex_info->is_exist == _TRUE?"TRUE":"FALSE", pcoex_info->BT_attend == _TRUE?"TRUE":"FALSE");
+	
+	if (_TRUE == pcoex_info->is_exist) {
+		if (_TRUE == pcoex_info->BT_attend) {
+			/*inform BT wifi leave*/
+			rtw_btcoex_sendmsgbysocket(padapter, wifi_leave, sizeof(wifi_leave), _FALSE);
+			msleep(50);
+		}
+		rtw_btcoex_close_kernel_socket(padapter);
+		pbtcoexadapter = NULL;
+		pcoex_info->is_exist = _FALSE;
+	}
+	if (pcoex_info->btcoex_wq != NULL) {
+		flush_workqueue(pcoex_info->btcoex_wq);
+		destroy_workqueue(pcoex_info->btcoex_wq);
+	}
+}
+
+void rtw_btcoex_dump_tx_msg(u8 *tx_msg, u8 len, u8 *msg_name)
+{
+	u8 	i = 0;
+	DBG_871X("======> Msg name: %s\n", msg_name);
+	for(i=0;i<len;i++)
+	{
+		printk("%02x ", tx_msg[i]);
+	}
+	printk("\n");
+	DBG_871X("Msg name: %s <======\n", msg_name);
+}
+
+/* Porting from Windows team */
+void rtw_btcoex_SendEventExtBtCoexControl(PADAPTER padapter, u8 bNeedDbgRsp, u8 dataLen, void *pData)
+{
+	u8			len=0, tx_event_length = 0;
+	u8 			localBuf[32] = "";
+	u8			*pRetPar;
+	u8			opCode=0;
+	u8			*pInBuf=(pu1Byte)pData;
+	u8			*pOpCodeContent;
+	rtw_HCI_event *pEvent;
+
+	opCode = pInBuf[0];	
+
+	DBG_871X("%s, OPCode:%02x\n",__func__,opCode);
+
+	pEvent = (rtw_HCI_event*)(&localBuf[0]);
+
+	//len += bthci_ExtensionEventHeaderRtk(&localBuf[0], 
+	//	HCI_EVENT_EXT_BT_COEX_CONTROL);
+	pEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
+	pEvent->Data[0] = HCI_EVENT_EXT_BT_COEX_CONTROL;	//extension event code
+	len ++;
+	
+	// Return parameters starts from here
+	pRetPar = &pEvent->Data[len];
+	_rtw_memcpy(&pRetPar[0], pData, dataLen);
+
+	len += dataLen;
+
+	pEvent->Length = len;
+
+	//total tx event length + EventCode length + sizeof(length)
+	tx_event_length = pEvent->Length + 2;
+#if 0
+	rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "BT COEX CONTROL", _FALSE);
+#endif
+	rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+
+}
+
+/* Porting from Windows team */
+void rtw_btcoex_SendEventExtBtInfoControl(PADAPTER padapter, u8 dataLen, void *pData)
+{
+	rtw_HCI_event *pEvent;
+	u8			*pRetPar;
+	u8			len=0, tx_event_length = 0;
+	u8 			localBuf[32] = "";
+
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	PBT_MGNT		pBtMgnt = &pcoex_info->BtMgnt;
+	
+	DBG_871X("%s\n",__func__);
+	if(pBtMgnt->ExtConfig.HCIExtensionVer < 4) //not support
+	{
+		DBG_871X("ERROR: HCIExtensionVer = %d, HCIExtensionVer<4 !!!!\n",pBtMgnt->ExtConfig.HCIExtensionVer);
+		return;
+	}
+
+	pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+	//len += bthci_ExtensionEventHeaderRtk(&localBuf[0], 
+	//		HCI_EVENT_EXT_BT_INFO_CONTROL);
+	pEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
+	pEvent->Data[0] = HCI_EVENT_EXT_BT_INFO_CONTROL;		//extension event code
+	len ++;
+
+	// Return parameters starts from here
+	pRetPar = &pEvent->Data[len];
+	_rtw_memcpy(&pRetPar[0], pData, dataLen);
+
+	len += dataLen;
+
+	pEvent->Length = len;
+
+	//total tx event length + EventCode length + sizeof(length)
+	tx_event_length = pEvent->Length + 2;
+#if 0
+	rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "BT INFO CONTROL");
+#endif
+	rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+	
+}
+
+void rtw_btcoex_SendScanNotify(PADAPTER padapter, u8 scanType)
+{
+	u8	len=0, tx_event_length=0;
+	u8 	localBuf[7] = "";
+	u8	*pRetPar;
+	u8	*pu1Temp;
+	rtw_HCI_event *pEvent;
+	struct bt_coex_info *pcoex_info = &padapter->coex_info;
+	PBT_MGNT		pBtMgnt = &pcoex_info->BtMgnt;
+
+//	if(!pBtMgnt->BtOperationOn)
+//		return;
+		
+	pEvent = (rtw_HCI_event *)(&localBuf[0]);
+
+//	len += bthci_ExtensionEventHeaderRtk(&localBuf[0], 
+//			HCI_EVENT_EXT_WIFI_SCAN_NOTIFY);
+
+	pEvent->EventCode = HCI_EVENT_EXTENSION_RTK;
+	pEvent->Data[0] = HCI_EVENT_EXT_WIFI_SCAN_NOTIFY;		//extension event code
+	len ++;
+
+	// Return parameters starts from here
+	//pRetPar = &PPacketIrpEvent->Data[len];
+	//pu1Temp = (u8 *)&pRetPar[0];
+	//*pu1Temp = scanType;
+	pEvent->Data[len] = scanType;
+	len += 1;
+
+	pEvent->Length = len;
+
+	//total tx event length + EventCode length + sizeof(length)
+	tx_event_length = pEvent->Length + 2;
+#if 0
+	rtw_btcoex_dump_tx_msg((u8 *)pEvent, tx_event_length, "WIFI SCAN OPERATION");
+#endif	
+	rtw_btcoex_sendmsgbysocket(padapter, (u8 *)pEvent, tx_event_length, _FALSE);
+}
+#endif //CONFIG_BT_COEXIST_SOCKET_TRX
+#endif // CONFIG_BT_COEXIST
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_cmd.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_cmd.c
new file mode 100644
index 000000000..3c2aede2b
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_cmd.c
@@ -0,0 +1,4513 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_CMD_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#ifndef DBG_CMD_EXECUTE
+	#define DBG_CMD_EXECUTE 0
+#endif
+
+/*
+Caller and the rtw_cmd_thread can protect cmd_q by spin_lock.
+No irqsave is necessary.
+*/
+
+sint	_rtw_init_cmd_priv (struct	cmd_priv *pcmdpriv)
+{
+	sint res=_SUCCESS;
+	
+_func_enter_;	
+
+	_rtw_init_sema(&(pcmdpriv->cmd_queue_sema), 0);
+	//_rtw_init_sema(&(pcmdpriv->cmd_done_sema), 0);
+	_rtw_init_sema(&(pcmdpriv->terminate_cmdthread_sema), 0);
+	
+	
+	_rtw_init_queue(&(pcmdpriv->cmd_queue));
+	
+	//allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf
+	
+	pcmdpriv->cmd_seq = 1;
+	
+	pcmdpriv->cmd_allocated_buf = rtw_zmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
+	
+	if (pcmdpriv->cmd_allocated_buf == NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	
+	pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ - ( (SIZE_PTR)(pcmdpriv->cmd_allocated_buf) & (CMDBUFF_ALIGN_SZ-1));
+		
+	pcmdpriv->rsp_allocated_buf = rtw_zmalloc(MAX_RSPSZ + 4);
+	
+	if (pcmdpriv->rsp_allocated_buf == NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	
+	pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 - ( (SIZE_PTR)(pcmdpriv->rsp_allocated_buf) & 3);
+
+	pcmdpriv->cmd_issued_cnt = pcmdpriv->cmd_done_cnt = pcmdpriv->rsp_cnt = 0;
+
+	_rtw_mutex_init(&pcmdpriv->sctx_mutex);
+exit:
+	
+_func_exit_;	  
+
+	return res;
+	
+}	
+
+#ifdef CONFIG_C2H_WK
+static void c2h_wk_callback(_workitem *work);
+#endif
+sint _rtw_init_evt_priv(struct evt_priv *pevtpriv)
+{
+	sint res=_SUCCESS;
+
+_func_enter_;	
+
+#ifdef CONFIG_H2CLBK
+	_rtw_init_sema(&(pevtpriv->lbkevt_done), 0);
+	pevtpriv->lbkevt_limit = 0;
+	pevtpriv->lbkevt_num = 0;
+	pevtpriv->cmdevt_parm = NULL;		
+#endif		
+	
+	//allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf
+	ATOMIC_SET(&pevtpriv->event_seq, 0);
+	pevtpriv->evt_done_cnt = 0;
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+
+	_rtw_init_sema(&(pevtpriv->evt_notify), 0);
+	_rtw_init_sema(&(pevtpriv->terminate_evtthread_sema), 0);
+
+	pevtpriv->evt_allocated_buf = rtw_zmalloc(MAX_EVTSZ + 4);	
+	if (pevtpriv->evt_allocated_buf == NULL){
+		res= _FAIL;
+		goto exit;
+		}
+	pevtpriv->evt_buf = pevtpriv->evt_allocated_buf  +  4 - ((unsigned int)(pevtpriv->evt_allocated_buf) & 3);
+	
+		
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+	pevtpriv->allocated_c2h_mem = rtw_zmalloc(C2H_MEM_SZ +4); 
+	
+	if (pevtpriv->allocated_c2h_mem == NULL){
+		res= _FAIL;
+		goto exit;
+	}
+
+	pevtpriv->c2h_mem = pevtpriv->allocated_c2h_mem +  4\
+	- ( (u32)(pevtpriv->allocated_c2h_mem) & 3);
+#ifdef PLATFORM_OS_XP
+	pevtpriv->pc2h_mdl= IoAllocateMdl((u8 *)pevtpriv->c2h_mem, C2H_MEM_SZ , FALSE, FALSE, NULL);
+	
+	if(pevtpriv->pc2h_mdl == NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	MmBuildMdlForNonPagedPool(pevtpriv->pc2h_mdl);
+#endif
+#endif //end of CONFIG_SDIO_HCI
+
+	_rtw_init_queue(&(pevtpriv->evt_queue));
+
+exit:	
+
+#endif //end of CONFIG_EVENT_THREAD_MODE
+
+#ifdef CONFIG_C2H_WK
+	_init_workitem(&pevtpriv->c2h_wk, c2h_wk_callback, NULL);
+	pevtpriv->c2h_wk_alive = _FALSE;
+	pevtpriv->c2h_queue = rtw_cbuf_alloc(C2H_QUEUE_MAX_LEN+1);
+#endif
+
+_func_exit_;		 
+
+	return res;
+}
+
+void _rtw_free_evt_priv (struct	evt_priv *pevtpriv)
+{
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("+_rtw_free_evt_priv \n"));
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+	_rtw_free_sema(&(pevtpriv->evt_notify));
+	_rtw_free_sema(&(pevtpriv->terminate_evtthread_sema));
+
+
+	if (pevtpriv->evt_allocated_buf)
+		rtw_mfree(pevtpriv->evt_allocated_buf, MAX_EVTSZ + 4);
+#endif
+
+#ifdef CONFIG_C2H_WK
+	_cancel_workitem_sync(&pevtpriv->c2h_wk);
+	while(pevtpriv->c2h_wk_alive)
+		rtw_msleep_os(10);
+
+	while (!rtw_cbuf_empty(pevtpriv->c2h_queue)) {
+		void *c2h;
+		if ((c2h = rtw_cbuf_pop(pevtpriv->c2h_queue)) != NULL
+			&& c2h != (void *)pevtpriv) {
+			rtw_mfree(c2h, 16);
+		}
+	}
+	rtw_cbuf_free(pevtpriv->c2h_queue);
+#endif
+
+	RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("-_rtw_free_evt_priv \n"));
+
+_func_exit_;	  	
+
+}
+
+void _rtw_free_cmd_priv (struct	cmd_priv *pcmdpriv)
+{
+_func_enter_;
+
+	if(pcmdpriv){
+		_rtw_spinlock_free(&(pcmdpriv->cmd_queue.lock));
+		_rtw_free_sema(&(pcmdpriv->cmd_queue_sema));
+		//_rtw_free_sema(&(pcmdpriv->cmd_done_sema));
+		_rtw_free_sema(&(pcmdpriv->terminate_cmdthread_sema));
+
+		if (pcmdpriv->cmd_allocated_buf)
+			rtw_mfree(pcmdpriv->cmd_allocated_buf, MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
+		
+		if (pcmdpriv->rsp_allocated_buf)
+			rtw_mfree(pcmdpriv->rsp_allocated_buf, MAX_RSPSZ + 4);
+
+		_rtw_mutex_free(&pcmdpriv->sctx_mutex);
+	}
+_func_exit_;		
+}
+
+/*
+Calling Context:
+
+rtw_enqueue_cmd can only be called between kernel thread, 
+since only spin_lock is used.
+
+ISR/Call-Back functions can't call this sub-function.
+
+*/
+#ifdef DBG_CMD_QUEUE
+extern u8 dump_cmd_id;
+#endif
+
+sint _rtw_enqueue_cmd(_queue *queue, struct cmd_obj *obj, bool to_head)
+{
+	_irqL irqL;
+
+_func_enter_;
+
+	if (obj == NULL)
+		goto exit;
+
+	if(obj->cmdsz > MAX_CMDSZ ){
+		DBG_871X("%s failed due to obj->cmdsz(%d) > MAX_CMDSZ(%d) \n",__FUNCTION__, obj->cmdsz,MAX_CMDSZ);
+		goto exit;
+	}
+	//_enter_critical_bh(&queue->lock, &irqL);
+	_enter_critical(&queue->lock, &irqL);	
+
+	if (to_head)
+		rtw_list_insert_head(&obj->list, &queue->queue);
+	else
+		rtw_list_insert_tail(&obj->list, &queue->queue);
+
+	#ifdef DBG_CMD_QUEUE
+	if(dump_cmd_id){
+		printk("%s===> cmdcode:0x%02x\n",__FUNCTION__,obj->cmdcode);
+		if(obj->cmdcode == GEN_CMD_CODE(_Set_MLME_EVT)){
+			if(obj->parmbuf){
+				struct C2HEvent_Header *pc2h_evt_hdr = (struct C2HEvent_Header *)(obj->parmbuf);
+				printk("pc2h_evt_hdr->ID:0x%02x(%d)\n",pc2h_evt_hdr->ID,pc2h_evt_hdr->ID);
+			}
+		}
+		if(obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)){
+			if(obj->parmbuf){
+				struct drvextra_cmd_parm *pdrvextra_cmd_parm =(struct drvextra_cmd_parm*)(obj->parmbuf);
+				printk("pdrvextra_cmd_parm->ec_id:0x%02x\n",pdrvextra_cmd_parm->ec_id);
+			}
+		}
+	}	
+	
+	if (queue->queue.prev->next != &queue->queue)
+	{
+		DBG_871X("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
+            &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
+		
+		DBG_871X("==========%s============\n",__FUNCTION__);
+		DBG_871X("head:%p,obj_addr:%p\n",&queue->queue,obj);
+		DBG_871X("padapter: %p\n",obj->padapter);
+		DBG_871X("cmdcode: 0x%02x\n",obj->cmdcode);
+		DBG_871X("res: %d\n",obj->res);
+		DBG_871X("parmbuf: %p\n",obj->parmbuf);
+		DBG_871X("cmdsz: %d\n",obj->cmdsz);
+		DBG_871X("rsp: %p\n",obj->rsp);
+		DBG_871X("rspsz: %d\n",obj->rspsz);
+		DBG_871X("sctx: %p\n",obj->sctx);
+		DBG_871X("list->next: %p\n",obj->list.next);
+		DBG_871X("list->prev: %p\n",obj->list.prev);
+	}
+	#endif //DBG_CMD_QUEUE
+	
+	//_exit_critical_bh(&queue->lock, &irqL);	
+	_exit_critical(&queue->lock, &irqL);
+
+exit:	
+
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+struct	cmd_obj	*_rtw_dequeue_cmd(_queue *queue)
+{
+	_irqL irqL;
+	struct cmd_obj *obj;
+
+_func_enter_;
+
+	//_enter_critical_bh(&(queue->lock), &irqL);
+	_enter_critical(&queue->lock, &irqL);
+	
+	#ifdef DBG_CMD_QUEUE
+	if (queue->queue.prev->next != &queue->queue)
+	{
+   		 DBG_871X("[%d] head %p, tail %p, tail->prev->next %p[tail], tail->next %p[head]\n", __LINE__,
+            &queue->queue, queue->queue.prev, queue->queue.prev->prev->next, queue->queue.prev->next);
+	}
+	#endif //DBG_CMD_QUEUE
+
+
+	if (rtw_is_list_empty(&(queue->queue))){
+		obj = NULL;
+	}
+	else
+	{
+		obj = LIST_CONTAINOR(get_next(&(queue->queue)), struct cmd_obj, list);
+
+		#ifdef DBG_CMD_QUEUE
+		if (queue->queue.prev->next != &queue->queue){
+				DBG_871X("==========%s============\n",__FUNCTION__);
+                          DBG_871X("head:%p,obj_addr:%p\n",&queue->queue,obj);
+				DBG_871X("padapter: %p\n",obj->padapter);
+				DBG_871X("cmdcode: 0x%02x\n",obj->cmdcode);
+				DBG_871X("res: %d\n",obj->res);
+				DBG_871X("parmbuf: %p\n",obj->parmbuf);
+				DBG_871X("cmdsz: %d\n",obj->cmdsz);
+				DBG_871X("rsp: %p\n",obj->rsp);
+				DBG_871X("rspsz: %d\n",obj->rspsz);
+				DBG_871X("sctx: %p\n",obj->sctx);                        	
+				DBG_871X("list->next: %p\n",obj->list.next);
+				DBG_871X("list->prev: %p\n",obj->list.prev);
+		}
+		
+		if(dump_cmd_id){
+			DBG_871X("%s===> cmdcode:0x%02x\n",__FUNCTION__,obj->cmdcode);
+		 	if(obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)){
+				if(obj->parmbuf){
+                                struct drvextra_cmd_parm *pdrvextra_cmd_parm =(struct drvextra_cmd_parm*)(obj->parmbuf);
+                                printk("pdrvextra_cmd_parm->ec_id:0x%02x\n",pdrvextra_cmd_parm->ec_id);
+                        }
+                	}
+
+		}	
+		#endif //DBG_CMD_QUEUE
+		
+		rtw_list_delete(&obj->list);
+	}
+
+	//_exit_critical_bh(&(queue->lock), &irqL);
+	_exit_critical(&queue->lock, &irqL);
+
+_func_exit_;	
+
+	return obj;
+}
+
+u32	rtw_init_cmd_priv(struct cmd_priv *pcmdpriv)
+{
+	u32	res;
+_func_enter_;	
+	res = _rtw_init_cmd_priv (pcmdpriv);
+_func_exit_;	
+	return res;	
+}
+
+u32	rtw_init_evt_priv (struct	evt_priv *pevtpriv)
+{
+	int	res;
+_func_enter_;		
+	res = _rtw_init_evt_priv(pevtpriv);
+_func_exit_;		
+	return res;
+}
+
+void rtw_free_evt_priv (struct	evt_priv *pevtpriv)
+{
+_func_enter_;
+	RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("rtw_free_evt_priv\n"));
+	_rtw_free_evt_priv(pevtpriv);
+_func_exit_;		
+}	
+
+void rtw_free_cmd_priv (struct	cmd_priv *pcmdpriv)
+{
+_func_enter_;
+	RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("rtw_free_cmd_priv\n"));
+	_rtw_free_cmd_priv(pcmdpriv);
+_func_exit_;	
+}	
+
+int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj);
+int rtw_cmd_filter(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+{
+	u8 bAllow = _FALSE; //set to _TRUE to allow enqueuing cmd when hw_init_completed is _FALSE
+	
+	#ifdef SUPPORT_HW_RFOFF_DETECTED
+	//To decide allow or not
+	if( (adapter_to_pwrctl(pcmdpriv->padapter)->bHWPwrPindetect)
+		&&(!pcmdpriv->padapter->registrypriv.usbss_enable)
+	)		
+	{
+		if(cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra) ) 
+		{
+			struct drvextra_cmd_parm	*pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf; 
+			if(pdrvextra_cmd_parm->ec_id == POWER_SAVING_CTRL_WK_CID)
+			{	
+				//DBG_871X("==>enqueue POWER_SAVING_CTRL_WK_CID\n");
+				bAllow = _TRUE; 
+			}
+		}
+	}
+	#endif
+
+#ifndef CONFIG_C2H_PACKET_EN
+	/* C2H should be always allowed */
+	if(cmd_obj->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
+		struct drvextra_cmd_parm *pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)cmd_obj->parmbuf;
+		if(pdrvextra_cmd_parm->ec_id == C2H_WK_CID) {
+			bAllow = _TRUE;
+		}
+	}
+#endif
+
+	if(cmd_obj->cmdcode == GEN_CMD_CODE(_SetChannelPlan))
+		bAllow = _TRUE;
+
+	if (cmd_obj->no_io)
+		bAllow = _TRUE;
+
+	if ((!rtw_is_hw_init_completed(pcmdpriv->padapter) && (bAllow == _FALSE))
+		|| ATOMIC_READ(&(pcmdpriv->cmdthd_running)) == _FALSE	//com_thread not running
+	) {
+		if (DBG_CMD_EXECUTE)
+			DBG_871X(ADPT_FMT" drop "CMD_FMT" hw_init_completed:%u, cmdthd_running:%u\n", ADPT_ARG(cmd_obj->padapter)
+				, CMD_ARG(cmd_obj), rtw_get_hw_init_completed(cmd_obj->padapter), ATOMIC_READ(&pcmdpriv->cmdthd_running));
+		if (0)
+			rtw_warn_on(1);
+
+		return _FAIL;
+	}
+	return _SUCCESS;
+}
+
+
+
+u32 rtw_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *cmd_obj)
+{
+	int res = _FAIL;
+	PADAPTER padapter = pcmdpriv->padapter;
+	
+_func_enter_;	
+	
+	if (cmd_obj == NULL) {
+		goto exit;
+	}
+
+	cmd_obj->padapter = padapter;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	//change pcmdpriv to primary's pcmdpriv
+	if (padapter->adapter_type != PRIMARY_ADAPTER && padapter->pbuddy_adapter)
+		pcmdpriv = &(padapter->pbuddy_adapter->cmdpriv);
+#endif	
+
+	if( _FAIL == (res=rtw_cmd_filter(pcmdpriv, cmd_obj)) ) {
+		rtw_free_cmd_obj(cmd_obj);
+		goto exit;
+	}
+
+	res = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, cmd_obj, 0);
+
+	if(res == _SUCCESS)
+		_rtw_up_sema(&pcmdpriv->cmd_queue_sema);
+	
+exit:	
+	
+_func_exit_;
+
+	return res;
+}
+
+struct	cmd_obj	*rtw_dequeue_cmd(struct cmd_priv *pcmdpriv)
+{
+	struct cmd_obj *cmd_obj;
+	
+_func_enter_;		
+
+	cmd_obj = _rtw_dequeue_cmd(&pcmdpriv->cmd_queue);
+		
+_func_exit_;			
+	return cmd_obj;
+}
+
+void rtw_cmd_clr_isr(struct	cmd_priv *pcmdpriv)
+{
+_func_enter_;
+	pcmdpriv->cmd_done_cnt++;
+	//_rtw_up_sema(&(pcmdpriv->cmd_done_sema));
+_func_exit_;		
+}
+
+void rtw_free_cmd_obj(struct cmd_obj *pcmd)
+{
+	struct drvextra_cmd_parm *extra_parm = NULL;
+_func_enter_;
+
+	if (pcmd->parmbuf != NULL) {
+		/* free parmbuf in cmd_obj */
+		rtw_mfree((unsigned char *)pcmd->parmbuf, pcmd->cmdsz);
+	}
+	if(pcmd->rsp!=NULL)
+	{
+		if(pcmd->rspsz!= 0)
+		{
+			//free rsp in cmd_obj
+			rtw_mfree((unsigned char*)pcmd->rsp, pcmd->rspsz);
+		}	
+	}	
+
+	//free cmd_obj
+	rtw_mfree((unsigned char*)pcmd, sizeof(struct cmd_obj));
+	
+_func_exit_;		
+}
+
+
+void rtw_stop_cmd_thread(_adapter *adapter)
+{
+	if(adapter->cmdThread &&
+		ATOMIC_READ(&(adapter->cmdpriv.cmdthd_running)) == _TRUE &&
+		adapter->cmdpriv.stop_req == 0)
+	{
+		adapter->cmdpriv.stop_req = 1;
+		_rtw_up_sema(&adapter->cmdpriv.cmd_queue_sema);
+		_rtw_down_sema(&adapter->cmdpriv.terminate_cmdthread_sema);
+	}
+}
+
+thread_return rtw_cmd_thread(thread_context context)
+{
+	u8 ret;
+	struct cmd_obj *pcmd;
+	u8 *pcmdbuf, *prspbuf;
+	u32 cmd_start_time;
+	u32 cmd_process_time;
+	u8 (*cmd_hdl)(_adapter *padapter, u8* pbuf);
+	void (*pcmd_callback)(_adapter *dev, struct cmd_obj *pcmd);
+	PADAPTER padapter = (PADAPTER)context;
+	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
+	struct drvextra_cmd_parm *extra_parm = NULL;
+	_irqL irqL;
+_func_enter_;
+
+	thread_enter("RTW_CMD_THREAD");
+
+	pcmdbuf = pcmdpriv->cmd_buf;
+	prspbuf = pcmdpriv->rsp_buf;
+
+	pcmdpriv->stop_req = 0;
+	ATOMIC_SET(&(pcmdpriv->cmdthd_running), _TRUE);
+	_rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema);
+
+	RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("start r871x rtw_cmd_thread !!!!\n"));
+
+	while (1) {
+		if (_rtw_down_sema(&pcmdpriv->cmd_queue_sema) == _FAIL) {
+			DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" _rtw_down_sema(&pcmdpriv->cmd_queue_sema) return _FAIL, break\n", FUNC_ADPT_ARG(padapter));
+			break;
+		}
+
+		if (RTW_CANNOT_RUN(padapter)) {
+			DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",
+				__func__
+				, rtw_is_drv_stopped(padapter)?"True":"False"
+				, rtw_is_surprise_removed(padapter)?"True":"False"
+				, __LINE__);
+			break;
+		}
+
+		if (pcmdpriv->stop_req) {
+			DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" stop_req:%u, break\n", FUNC_ADPT_ARG(padapter), pcmdpriv->stop_req);
+			break;
+		}
+		
+		_enter_critical(&pcmdpriv->cmd_queue.lock, &irqL);
+		if (rtw_is_list_empty(&(pcmdpriv->cmd_queue.queue))) {
+			//DBG_871X("%s: cmd queue is empty!\n", __func__);
+			_exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);
+			continue;
+		}
+		_exit_critical(&pcmdpriv->cmd_queue.lock, &irqL);
+
+_next:
+		if (RTW_CANNOT_RUN(padapter)) {
+			DBG_871X_LEVEL(_drv_always_, "%s: DriverStopped(%s) SurpriseRemoved(%s) break at line %d\n",
+				__func__
+				, rtw_is_drv_stopped(padapter)?"True":"False"
+				, rtw_is_surprise_removed(padapter)?"True":"False"
+				, __LINE__);
+			break;
+		}
+
+		pcmd = rtw_dequeue_cmd(pcmdpriv);
+		if (!pcmd) {
+			#ifdef CONFIG_LPS_LCLK
+			rtw_unregister_cmd_alive(padapter);
+			#endif
+			continue;
+		}
+
+		cmd_start_time = rtw_get_current_time();
+		pcmdpriv->cmd_issued_cnt++;
+
+		if (pcmd->cmdsz > MAX_CMDSZ) {
+			DBG_871X_LEVEL(_drv_err_, "%s cmdsz:%d > MAX_CMDSZ:%d\n", __func__, pcmd->cmdsz, MAX_CMDSZ);
+			pcmd->res = H2C_PARAMETERS_ERROR;
+			goto post_process;
+		}
+
+		if (pcmd->cmdcode >= (sizeof(wlancmds) / sizeof(struct cmd_hdl))) {
+			DBG_871X_LEVEL(_drv_err_, "%s undefined cmdcode:%d\n", __func__, pcmd->cmdcode);
+			pcmd->res = H2C_PARAMETERS_ERROR;
+			goto post_process;
+		}
+
+		cmd_hdl = wlancmds[pcmd->cmdcode].h2cfuns;
+		if (!cmd_hdl) {
+			DBG_871X_LEVEL(_drv_err_, "%s no cmd_hdl for cmdcode:%d\n", __func__, pcmd->cmdcode);
+			pcmd->res = H2C_PARAMETERS_ERROR;
+			goto post_process;
+		}
+
+		if (_FAIL == rtw_cmd_filter(pcmdpriv, pcmd)) {
+			pcmd->res = H2C_DROPPED;
+			if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
+				extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
+				if (extra_parm && extra_parm->pbuf && extra_parm->size > 0)
+					rtw_mfree(extra_parm->pbuf, extra_parm->size);
+			}
+			goto post_process;
+		}
+
+		#ifdef CONFIG_LPS_LCLK
+		if (pcmd->no_io) {
+			rtw_unregister_cmd_alive(padapter);
+		} else {
+			if (rtw_register_cmd_alive(padapter) != _SUCCESS) {
+				if (DBG_CMD_EXECUTE)
+					DBG_871X_LEVEL(_drv_always_, "%s: wait to leave LPS_LCLK\n", __func__);
+
+				pcmd->res = H2C_ENQ_HEAD;
+				ret = _rtw_enqueue_cmd(&pcmdpriv->cmd_queue, pcmd, 1);
+				if (ret == _SUCCESS) {
+					if (DBG_CMD_EXECUTE)
+						DBG_871X(ADPT_FMT" "CMD_FMT" ENQ_HEAD\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
+					continue;
+				}
+
+				DBG_871X(ADPT_FMT" "CMD_FMT" ENQ_HEAD_FAIL\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd));
+				pcmd->res = H2C_ENQ_HEAD_FAIL;
+				rtw_warn_on(1);
+			}
+		}
+		#endif /* CONFIG_LPS_LCLK */
+
+		if (DBG_CMD_EXECUTE)
+			DBG_871X(ADPT_FMT" "CMD_FMT" %sexecute\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd)
+				, pcmd->res == H2C_ENQ_HEAD ? "ENQ_HEAD " : (pcmd->res == H2C_ENQ_HEAD_FAIL ? "ENQ_HEAD_FAIL " : ""));
+
+		_rtw_memcpy(pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
+		ret = cmd_hdl(pcmd->padapter, pcmdbuf);
+		pcmd->res = ret;
+
+		pcmdpriv->cmd_seq++;
+
+post_process:
+
+		_enter_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
+		if (pcmd->sctx) {
+			if (0)
+				DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pcmd->sctx\n",
+					FUNC_ADPT_ARG(pcmd->padapter));
+			if (pcmd->res == H2C_SUCCESS)
+				rtw_sctx_done(&pcmd->sctx);
+			else
+				rtw_sctx_done_err(&pcmd->sctx, RTW_SCTX_DONE_CMD_ERROR);
+		}
+		_exit_critical_mutex(&(pcmd->padapter->cmdpriv.sctx_mutex), NULL);
+
+		cmd_process_time = rtw_get_passing_time_ms(cmd_start_time);
+		if (cmd_process_time > 1000) {
+			DBG_871X(ADPT_FMT" "CMD_FMT" process_time=%d\n", ADPT_ARG(pcmd->padapter), CMD_ARG(pcmd), cmd_process_time);
+			if (0)
+				rtw_warn_on(1);
+		}
+
+		//call callback function for post-processed
+		if(pcmd->cmdcode < (sizeof(rtw_cmd_callback) /sizeof(struct _cmd_callback)))
+		{
+			pcmd_callback = rtw_cmd_callback[pcmd->cmdcode].callback;
+			if(pcmd_callback == NULL)
+			{
+				RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("mlme_cmd_hdl(): pcmd_callback=0x%p, cmdcode=0x%x\n", pcmd_callback, pcmd->cmdcode));
+				rtw_free_cmd_obj(pcmd);
+			}
+			else
+			{
+				//todo: !!! fill rsp_buf to pcmd->rsp if (pcmd->rsp!=NULL)
+				pcmd_callback(pcmd->padapter, pcmd);//need conider that free cmd_obj in rtw_cmd_callback
+			}
+		}
+		else
+		{
+			RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("%s: cmdcode=0x%x callback not defined!\n", __FUNCTION__, pcmd->cmdcode));
+			rtw_free_cmd_obj(pcmd);
+		}
+
+		flush_signals_thread();
+
+		goto _next;
+
+	}
+
+#ifdef CONFIG_LPS_LCLK
+	rtw_unregister_cmd_alive(padapter);
+#endif
+
+	/* free all cmd_obj resources */
+	do {
+		pcmd = rtw_dequeue_cmd(pcmdpriv);
+		if (pcmd == NULL)
+			break;
+
+		if (0)
+			DBG_871X("%s: leaving... drop "CMD_FMT"\n", __func__, CMD_ARG(pcmd));
+
+		if (pcmd->cmdcode == GEN_CMD_CODE(_Set_Drv_Extra)) {
+			extra_parm = (struct drvextra_cmd_parm *)pcmd->parmbuf;
+			if(extra_parm->pbuf && extra_parm->size > 0) {
+				rtw_mfree(extra_parm->pbuf, extra_parm->size);
+			}
+		}
+
+		rtw_free_cmd_obj(pcmd);	
+	} while (1);
+
+	_rtw_up_sema(&pcmdpriv->terminate_cmdthread_sema);
+	ATOMIC_SET(&(pcmdpriv->cmdthd_running), _FALSE);
+
+_func_exit_;
+
+	thread_exit();
+
+}
+
+
+#ifdef CONFIG_EVENT_THREAD_MODE
+u32 rtw_enqueue_evt(struct evt_priv *pevtpriv, struct evt_obj *obj)
+{
+	_irqL irqL;
+	int	res;
+	_queue *queue = &pevtpriv->evt_queue;
+	
+_func_enter_;	
+
+	res = _SUCCESS; 		
+
+	if (obj == NULL) {
+		res = _FAIL;
+		goto exit;
+	}	
+
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	rtw_list_insert_tail(&obj->list, &queue->queue);
+	
+	_exit_critical_bh(&queue->lock, &irqL);
+
+	//rtw_evt_notify_isr(pevtpriv);
+
+exit:
+	
+_func_exit_;		
+
+	return res;	
+}
+
+struct evt_obj *rtw_dequeue_evt(_queue *queue)
+{
+	_irqL irqL;
+	struct	evt_obj	*pevtobj;
+	
+_func_enter_;		
+
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	if (rtw_is_list_empty(&(queue->queue)))
+		pevtobj = NULL;
+	else
+	{
+		pevtobj = LIST_CONTAINOR(get_next(&(queue->queue)), struct evt_obj, list);
+		rtw_list_delete(&pevtobj->list);
+	}
+
+	_exit_critical_bh(&queue->lock, &irqL);
+	
+_func_exit_;			
+
+	return pevtobj;	
+}
+
+void rtw_free_evt_obj(struct evt_obj *pevtobj)
+{
+_func_enter_;
+
+	if(pevtobj->parmbuf)
+		rtw_mfree((unsigned char*)pevtobj->parmbuf, pevtobj->evtsz);
+	
+	rtw_mfree((unsigned char*)pevtobj, sizeof(struct evt_obj));
+	
+_func_exit_;		
+}
+
+void rtw_evt_notify_isr(struct evt_priv *pevtpriv)
+{
+_func_enter_;
+	pevtpriv->evt_done_cnt++;
+	_rtw_up_sema(&(pevtpriv->evt_notify));
+_func_exit_;	
+}
+#endif
+
+
+/*
+u8 rtw_setstandby_cmd(unsigned char  *adapter) 
+*/
+u8 rtw_setstandby_cmd(_adapter *padapter, uint action)
+{
+	struct cmd_obj*			ph2c;
+	struct usb_suspend_parm*	psetusbsuspend;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+
+	u8 ret = _SUCCESS;
+	
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		ret = _FAIL;
+		goto exit;
+	}
+	
+	psetusbsuspend = (struct usb_suspend_parm*)rtw_zmalloc(sizeof(struct usb_suspend_parm)); 
+	if (psetusbsuspend == NULL) {
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		ret = _FAIL;
+		goto exit;
+	}
+
+	psetusbsuspend->action = action;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, psetusbsuspend, GEN_CMD_CODE(_SetUsbSuspend));
+
+	ret = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+	
+exit:	
+	
+_func_exit_;		
+
+	return ret;
+}
+
+/*
+rtw_sitesurvey_cmd(~)
+	### NOTE:#### (!!!!)
+	MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
+*/
+u8 rtw_sitesurvey_cmd(_adapter  *padapter, NDIS_802_11_SSID *ssid, int ssid_num,
+	struct rtw_ieee80211_channel *ch, int ch_num)
+{
+	u8 res = _FAIL;
+	struct cmd_obj		*ph2c;
+	struct sitesurvey_parm	*psurveyPara;
+	struct cmd_priv 	*pcmdpriv = &padapter->cmdpriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif //CONFIG_P2P
+
+_func_enter_;
+
+#ifdef CONFIG_LPS
+	if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE){
+		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 1);
+	}
+#endif
+
+#ifdef CONFIG_P2P_PS
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
+		p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
+	}
+#endif //CONFIG_P2P_PS
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL)
+		return _FAIL;
+
+	psurveyPara = (struct sitesurvey_parm*)rtw_zmalloc(sizeof(struct sitesurvey_parm)); 
+	if (psurveyPara == NULL) {
+		rtw_mfree((unsigned char*) ph2c, sizeof(struct cmd_obj));
+		return _FAIL;
+	}
+
+	rtw_free_network_queue(padapter, _FALSE);
+
+	RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("%s: flush network queue\n", __FUNCTION__));
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
+
+	/* psurveyPara->bsslimit = 48; */
+	psurveyPara->scan_mode = pmlmepriv->scan_mode;
+
+	/* prepare ssid list */
+	if (ssid) {
+		int i;
+		for (i=0; i<ssid_num && i< RTW_SSID_SCAN_AMOUNT; i++) {
+			if (ssid[i].SsidLength) {
+				_rtw_memcpy(&psurveyPara->ssid[i], &ssid[i], sizeof(NDIS_802_11_SSID));
+				psurveyPara->ssid_num++;
+				if (0)
+					DBG_871X(FUNC_ADPT_FMT" ssid:(%s, %d)\n", FUNC_ADPT_ARG(padapter),
+						psurveyPara->ssid[i].Ssid, psurveyPara->ssid[i].SsidLength);
+			}
+		}
+	}
+
+	/* prepare channel list */
+	if (ch) {
+		int i;
+		for (i=0; i<ch_num && i< RTW_CHANNEL_SCAN_AMOUNT; i++) {
+			if (ch[i].hw_value && !(ch[i].flags & RTW_IEEE80211_CHAN_DISABLED)) {
+				_rtw_memcpy(&psurveyPara->ch[i], &ch[i], sizeof(struct rtw_ieee80211_channel));
+				psurveyPara->ch_num++;
+				if (0)
+					DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter),
+						psurveyPara->ch[i].hw_value);
+			}
+		}
+	}
+
+	set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+	if(res == _SUCCESS) {
+
+		pmlmepriv->scan_start_time = rtw_get_current_time();
+
+#ifdef CONFIG_SCAN_BACKOP
+		if((padapter->pbuddy_adapter->mlmeextpriv.mlmext_info.state&0x03) == WIFI_FW_AP_STATE)
+		{
+			if(IsSupported5G(padapter->registrypriv.wireless_mode) 
+				&& IsSupported24G(padapter->registrypriv.wireless_mode)) //dual band
+				mlme_set_scan_to_timer(pmlmepriv, CONC_SCANNING_TIMEOUT_DUAL_BAND);
+			else //single band
+				mlme_set_scan_to_timer(pmlmepriv, CONC_SCANNING_TIMEOUT_SINGLE_BAND);
+		}		
+		else
+#endif /* CONFIG_SCAN_BACKOP */
+			mlme_set_scan_to_timer(pmlmepriv, SCANNING_TIMEOUT);
+
+		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
+	} else {
+		_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+	}
+
+_func_exit_;		
+
+	return res;
+}
+
+u8 rtw_setdatarate_cmd(_adapter *padapter, u8 *rateset)
+{
+	struct cmd_obj*			ph2c;
+	struct setdatarate_parm*	pbsetdataratepara;
+	struct cmd_priv*		pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pbsetdataratepara = (struct setdatarate_parm*)rtw_zmalloc(sizeof(struct setdatarate_parm)); 
+	if (pbsetdataratepara == NULL) {
+		rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, GEN_CMD_CODE(_SetDataRate));
+#ifdef MP_FIRMWARE_OFFLOAD
+	pbsetdataratepara->curr_rateidx = *(u32*)rateset;
+//	_rtw_memcpy(pbsetdataratepara, rateset, sizeof(u32));
+#else
+	pbsetdataratepara->mac_id = 5;
+	_rtw_memcpy(pbsetdataratepara->datarates, rateset, NumRates);
+#endif
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+u8 rtw_setbasicrate_cmd(_adapter *padapter, u8 *rateset)
+{
+	struct cmd_obj*			ph2c;
+	struct setbasicrate_parm*	pssetbasicratepara;
+	struct cmd_priv*		pcmdpriv=&padapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+_func_enter_;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res= _FAIL;
+		goto exit;
+	}
+	pssetbasicratepara = (struct setbasicrate_parm*)rtw_zmalloc(sizeof(struct setbasicrate_parm)); 
+
+	if (pssetbasicratepara == NULL) {
+		rtw_mfree((u8*) ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, _SetBasicRate_CMD_);
+
+	_rtw_memcpy(pssetbasicratepara->basicrates, rateset, NumRates);	   
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:	
+
+_func_exit_;		
+
+	return res;
+}
+
+
+/*
+unsigned char rtw_setphy_cmd(unsigned char  *adapter) 
+
+1.  be called only after rtw_update_registrypriv_dev_network( ~) or mp testing program
+2.  for AdHoc/Ap mode or mp mode?
+
+*/
+u8 rtw_setphy_cmd(_adapter *padapter, u8 modem, u8 ch)
+{
+	struct cmd_obj*			ph2c;
+	struct setphy_parm*		psetphypara;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+//	struct mlme_priv			*pmlmepriv = &padapter->mlmepriv;
+//	struct registry_priv*		pregistry_priv = &padapter->registrypriv;
+	u8	res=_SUCCESS;
+
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+		}
+	psetphypara = (struct setphy_parm*)rtw_zmalloc(sizeof(struct setphy_parm)); 
+
+	if(psetphypara==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, psetphypara, _SetPhy_CMD_);
+
+	RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("CH=%d, modem=%d", ch, modem));
+
+	psetphypara->modem = modem;
+	psetphypara->rfchannel = ch;
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:	
+_func_exit_;		
+	return res;
+}
+
+u8 rtw_getmacreg_cmd(_adapter *padapter, u8 len, u32 addr)
+{
+	struct cmd_obj *ph2c;
+	struct readMAC_parm *preadmacparm;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+_func_enter_;
+	ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+	preadmacparm = (struct readMAC_parm *)rtw_zmalloc(sizeof(struct readMAC_parm));
+
+	if (preadmacparm == NULL) {
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, preadmacparm, GEN_CMD_CODE(_GetMACReg));
+
+	preadmacparm->len = len;
+	preadmacparm->addr = addr;
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+_func_exit_;
+	return res;
+}
+
+void rtw_usb_catc_trigger_cmd(_adapter *padapter, const char *caller)
+{
+	DBG_871X("%s caller:%s\n", __func__, caller);
+	rtw_getmacreg_cmd(padapter, 1, 0x1c4);
+}
+
+u8 rtw_setbbreg_cmd(_adapter*padapter, u8 offset, u8 val)
+{	
+	struct cmd_obj*			ph2c;
+	struct writeBB_parm*		pwritebbparm;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;	
+	u8	res=_SUCCESS;
+_func_enter_;
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+		}
+	pwritebbparm = (struct writeBB_parm*)rtw_zmalloc(sizeof(struct writeBB_parm)); 
+
+	if(pwritebbparm==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pwritebbparm, GEN_CMD_CODE(_SetBBReg));	
+
+	pwritebbparm->offset = offset;
+	pwritebbparm->value = val;
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:	
+_func_exit_;	
+	return res;
+}
+
+u8 rtw_getbbreg_cmd(_adapter  *padapter, u8 offset, u8 *pval)
+{	
+	struct cmd_obj*			ph2c;
+	struct readBB_parm*		prdbbparm;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+	u8	res=_SUCCESS;
+	
+_func_enter_;
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res=_FAIL;
+		goto exit;
+		}
+	prdbbparm = (struct readBB_parm*)rtw_zmalloc(sizeof(struct readBB_parm)); 
+
+	if(prdbbparm ==NULL){
+		rtw_mfree((unsigned char *) ph2c, sizeof(struct	cmd_obj));
+		return _FAIL;
+	}
+
+	_rtw_init_listhead(&ph2c->list);
+	ph2c->cmdcode =GEN_CMD_CODE(_GetBBReg);
+	ph2c->parmbuf = (unsigned char *)prdbbparm;
+	ph2c->cmdsz =  sizeof(struct readBB_parm);
+	ph2c->rsp = pval;
+	ph2c->rspsz = sizeof(struct readBB_rsp);
+	
+	prdbbparm ->offset = offset;
+	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:
+_func_exit_;	
+	return res;
+}
+
+u8 rtw_setrfreg_cmd(_adapter  *padapter, u8 offset, u32 val)
+{	
+	struct cmd_obj*			ph2c;
+	struct writeRF_parm*		pwriterfparm;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;	
+	u8	res=_SUCCESS;
+_func_enter_;
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;	
+		goto exit;
+	}
+	pwriterfparm = (struct writeRF_parm*)rtw_zmalloc(sizeof(struct writeRF_parm)); 
+
+	if(pwriterfparm==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));	
+
+	pwriterfparm->offset = offset;
+	pwriterfparm->value = val;
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:
+_func_exit_;	
+	return res;
+}
+
+u8 rtw_getrfreg_cmd(_adapter  *padapter, u8 offset, u8 *pval)
+{	
+	struct cmd_obj*			ph2c;
+	struct readRF_parm*		prdrfparm;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;	
+	u8	res=_SUCCESS;
+
+_func_enter_;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+
+	prdrfparm = (struct readRF_parm*)rtw_zmalloc(sizeof(struct readRF_parm)); 
+	if(prdrfparm ==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	_rtw_init_listhead(&ph2c->list);
+	ph2c->cmdcode =GEN_CMD_CODE(_GetRFReg);
+	ph2c->parmbuf = (unsigned char *)prdrfparm;
+	ph2c->cmdsz =  sizeof(struct readRF_parm);
+	ph2c->rsp = pval;
+	ph2c->rspsz = sizeof(struct readRF_rsp);
+	
+	prdrfparm ->offset = offset;
+	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+void rtw_getbbrfreg_cmdrsp_callback(_adapter*	padapter,  struct cmd_obj *pcmd)
+{       
+ _func_enter_;  
+		
+	//rtw_free_cmd_obj(pcmd);
+	rtw_mfree((unsigned char*) pcmd->parmbuf, pcmd->cmdsz);
+	rtw_mfree((unsigned char*) pcmd, sizeof(struct cmd_obj));
+	
+#ifdef CONFIG_MP_INCLUDED
+	if (padapter->registrypriv.mp_mode == 1)
+		padapter->mppriv.workparam.bcompleted= _TRUE;
+#endif	
+_func_exit_;		
+}
+
+void rtw_readtssi_cmdrsp_callback(_adapter*	padapter,  struct cmd_obj *pcmd)
+{
+ _func_enter_;  
+
+	rtw_mfree((unsigned char*) pcmd->parmbuf, pcmd->cmdsz);
+	rtw_mfree((unsigned char*) pcmd, sizeof(struct cmd_obj));
+	
+#ifdef CONFIG_MP_INCLUDED
+	if (padapter->registrypriv.mp_mode == 1)
+		padapter->mppriv.workparam.bcompleted= _TRUE;
+#endif
+
+_func_exit_;
+}
+
+static u8 rtw_createbss_cmd(_adapter  *adapter, int flags, bool adhoc
+	, s16 req_ch, u8 req_bw, u8 req_offset)
+{
+	struct cmd_obj *cmdobj;
+	struct createbss_parm *parm;
+	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct submit_ctx sctx;
+	u8 res = _SUCCESS;
+
+	/* prepare cmd parameter */
+	parm = (struct createbss_parm *)rtw_zmalloc(sizeof(*parm));
+	if (parm == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	if (adhoc) {
+		/* for now, adhoc doesn't support ch,bw,offset request */
+		parm->adhoc = 1;
+	} else {
+		parm->adhoc = 0;
+		parm->req_ch = req_ch;
+		parm->req_bw = req_bw;
+		parm->req_offset = req_offset;
+	}
+
+	if (flags & RTW_CMDF_DIRECTLY) {
+		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+		if (H2C_SUCCESS != createbss_hdl(adapter, (u8 *)parm))
+			res = _FAIL;
+		rtw_mfree((u8 *)parm, sizeof(*parm));
+	} else {
+		/* need enqueue, prepare cmd_obj and enqueue */
+		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
+		if (cmdobj == NULL) {
+			res = _FAIL;
+			rtw_mfree((u8 *)parm, sizeof(*parm));
+			goto exit;
+		}
+
+		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_CreateBss));
+
+		if (flags & RTW_CMDF_WAIT_ACK) {
+			cmdobj->sctx = &sctx;
+			rtw_sctx_init(&sctx, 2000);
+		}
+
+		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
+
+		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
+			rtw_sctx_wait(&sctx, __func__);
+			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
+			if (sctx.status == RTW_SCTX_SUBMITTED)
+				cmdobj->sctx = NULL;
+			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
+		}
+	}
+
+exit:
+	return res;
+}
+
+inline u8 rtw_create_ibss_cmd(_adapter *adapter, int flags)
+{
+	return rtw_createbss_cmd(adapter, flags
+		, 1
+		, -1, 0, 0 /* for now, adhoc doesn't support ch,bw,offset request */
+	);
+}
+
+inline u8 rtw_startbss_cmd(_adapter *adapter, int flags)
+{
+	return rtw_createbss_cmd(adapter, flags
+		, 0
+		, -1, 0, 0 /* doesn't request ch, bw, offset */
+	);
+}
+
+inline u8 rtw_change_bss_chbw_cmd(_adapter *adapter, int flags, u8 req_ch, u8 req_bw, u8 req_offset)
+{
+	return rtw_createbss_cmd(adapter, flags
+		, 0
+		, req_ch, req_bw, req_offset
+	);
+}
+
+u8 rtw_joinbss_cmd(_adapter  *padapter, struct wlan_network* pnetwork)
+{
+	u8	*auth, res = _SUCCESS;
+	uint	t_len = 0;
+	WLAN_BSSID_EX		*psecnetwork;
+	struct cmd_obj		*pcmd;
+	struct cmd_priv		*pcmdpriv=&padapter->cmdpriv;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct qos_priv		*pqospriv= &pmlmepriv->qospriv;
+	struct security_priv	*psecuritypriv=&padapter->securitypriv;
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+#ifdef CONFIG_80211N_HT
+	struct ht_priv			*phtpriv = &pmlmepriv->htpriv;
+#endif //CONFIG_80211N_HT
+#ifdef CONFIG_80211AC_VHT
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+#endif //CONFIG_80211AC_VHT
+	NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->network.InfrastructureMode;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u32 tmp_len;
+	u8 *ptmp=NULL;
+_func_enter_;
+
+	rtw_led_control(padapter, LED_CTL_START_TO_LINK);
+
+	if (pmlmepriv->assoc_ssid.SsidLength == 0){
+		RT_TRACE(_module_rtl871x_cmd_c_, _drv_info_, ("+Join cmd: Any SSid\n"));
+	} else {
+		RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+Join cmd: SSid=[%s]\n", pmlmepriv->assoc_ssid.Ssid));
+	}
+
+	pcmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(pcmd==NULL){
+		res=_FAIL;
+		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd: memory allocate for cmd_obj fail!!!\n"));
+		goto exit;
+	}
+	/* // for IEs is pointer 
+	t_len = sizeof (ULONG) + sizeof (NDIS_802_11_MAC_ADDRESS) + 2 + 
+			sizeof (NDIS_802_11_SSID) + sizeof (ULONG) + 
+			sizeof (NDIS_802_11_RSSI) + sizeof (NDIS_802_11_NETWORK_TYPE) + 
+			sizeof (NDIS_802_11_CONFIGURATION) +	
+			sizeof (NDIS_802_11_NETWORK_INFRASTRUCTURE) +   
+			sizeof (NDIS_802_11_RATES_EX)+ sizeof(WLAN_PHY_INFO)+ sizeof (ULONG) + MAX_IE_SZ;
+	*/
+	//for IEs is fix buf size
+	t_len = sizeof(WLAN_BSSID_EX);
+
+
+	//for hidden ap to set fw_state here
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != _TRUE)
+	{
+		switch(ndis_network_mode)
+		{
+			case Ndis802_11IBSS:
+				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+				break;
+
+			case Ndis802_11Infrastructure:
+				set_fwstate(pmlmepriv, WIFI_STATION_STATE);
+				break;
+
+			case Ndis802_11APMode:
+			case Ndis802_11AutoUnknown:
+			case Ndis802_11InfrastructureMax:
+			case Ndis802_11Monitor:
+				break;
+
+		}
+	}
+
+	pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->network.IEs, pnetwork->network.IELength);
+
+	/* 
+		Modified by Arvin 2015/05/13
+		Solution for allocating a new WLAN_BSSID_EX to avoid race condition issue between disconnect and joinbss 
+	*/
+	psecnetwork = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
+	if(psecnetwork==NULL)
+	{
+		if(pcmd !=NULL)
+			rtw_mfree((unsigned char *)pcmd, sizeof(struct	cmd_obj));
+		
+		res=_FAIL;
+		
+		RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("rtw_joinbss_cmd :psecnetwork==NULL!!!\n"));
+		
+		goto exit;
+	}
+
+	_rtw_memset(psecnetwork, 0, t_len);
+
+	_rtw_memcpy(psecnetwork, &pnetwork->network, get_WLAN_BSSID_EX_sz(&pnetwork->network));
+	
+	auth=&psecuritypriv->authenticator_ie[0];
+	psecuritypriv->authenticator_ie[0]=(unsigned char)psecnetwork->IELength;
+
+	if((psecnetwork->IELength-12) < (256-1)) {
+		_rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], psecnetwork->IELength-12);
+	} else {
+		_rtw_memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256-1));
+	}
+	  
+	psecnetwork->IELength = 0;
+	// Added by Albert 2009/02/18
+	// If the the driver wants to use the bssid to create the connection.
+	// If not,  we have to copy the connecting AP's MAC address to it so that
+	// the driver just has the bssid information for PMKIDList searching.
+        
+	if ( pmlmepriv->assoc_by_bssid == _FALSE )
+	{
+		_rtw_memcpy( &pmlmepriv->assoc_bssid[ 0 ], &pnetwork->network.MacAddress[ 0 ], ETH_ALEN );
+	}
+
+	psecnetwork->IELength = rtw_restruct_sec_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength);
+
+
+	pqospriv->qos_option = 0;
+	
+	if(pregistrypriv->wmm_enable)	
+	{
+		tmp_len = rtw_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], pnetwork->network.IELength, psecnetwork->IELength);	
+
+		if (psecnetwork->IELength != tmp_len)		
+		{
+			psecnetwork->IELength = tmp_len;
+			pqospriv->qos_option = 1; //There is WMM IE in this corresp. beacon
+		}
+		else 
+		{
+			pqospriv->qos_option = 0;//There is no WMM IE in this corresp. beacon
+		}		
+	}	
+
+#ifdef CONFIG_80211N_HT
+	phtpriv->ht_option = _FALSE;
+	ptmp = rtw_get_ie(&pnetwork->network.IEs[12], _HT_CAPABILITY_IE_, &tmp_len, pnetwork->network.IELength-12);
+	if(pregistrypriv->ht_enable && ptmp && tmp_len>0)
+	{
+		//	Added by Albert 2010/06/23
+		//	For the WEP mode, we will use the bg mode to do the connection to avoid some IOT issue.
+		//	Especially for Realtek 8192u SoftAP.
+		if (	( padapter->securitypriv.dot11PrivacyAlgrthm != _WEP40_ ) &&
+			( padapter->securitypriv.dot11PrivacyAlgrthm != _WEP104_ ) &&
+			( padapter->securitypriv.dot11PrivacyAlgrthm != _TKIP_ ))
+		{
+			rtw_ht_use_default_setting(padapter);
+
+			rtw_build_wmm_ie_ht(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
+
+			//rtw_restructure_ht_ie
+			rtw_restructure_ht_ie(padapter, &pnetwork->network.IEs[12], &psecnetwork->IEs[0], 
+									pnetwork->network.IELength-12, &psecnetwork->IELength,
+									pnetwork->network.Configuration.DSConfig);
+		}
+	}
+
+#ifdef CONFIG_80211AC_VHT
+	pvhtpriv->vht_option = _FALSE;
+	if (phtpriv->ht_option
+		&& REGSTY_IS_11AC_ENABLE(pregistrypriv)
+		&& hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
+		&& (!pmlmepriv->country_ent || COUNTRY_CHPLAN_EN_11AC(pmlmepriv->country_ent))
+	) {
+		rtw_restructure_vht_ie(padapter, &pnetwork->network.IEs[0], &psecnetwork->IEs[0], 
+								pnetwork->network.IELength, &psecnetwork->IELength);
+	}
+#endif
+
+	rtw_append_exented_cap(padapter, &psecnetwork->IEs[0], &psecnetwork->IELength);
+
+#endif //CONFIG_80211N_HT
+
+	#if 0
+	psecuritypriv->supplicant_ie[0]=(u8)psecnetwork->IELength;
+
+	if(psecnetwork->IELength < (256-1))
+	{
+		_rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], psecnetwork->IELength);
+	}
+	else
+	{
+		_rtw_memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], (256-1));
+	}
+	#endif
+	
+	pcmd->cmdsz = sizeof(WLAN_BSSID_EX);
+
+#ifdef CONFIG_RTL8712
+	//wlan_network endian conversion	
+	psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
+	psecnetwork->Ssid.SsidLength= cpu_to_le32(psecnetwork->Ssid.SsidLength);
+	psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
+	psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
+	psecnetwork->NetworkTypeInUse = cpu_to_le32(psecnetwork->NetworkTypeInUse);
+	psecnetwork->Configuration.ATIMWindow = cpu_to_le32(psecnetwork->Configuration.ATIMWindow);
+	psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(psecnetwork->Configuration.BeaconPeriod);
+	psecnetwork->Configuration.DSConfig = cpu_to_le32(psecnetwork->Configuration.DSConfig);
+	psecnetwork->Configuration.FHConfig.DwellTime=cpu_to_le32(psecnetwork->Configuration.FHConfig.DwellTime);
+	psecnetwork->Configuration.FHConfig.HopPattern=cpu_to_le32(psecnetwork->Configuration.FHConfig.HopPattern);
+	psecnetwork->Configuration.FHConfig.HopSet=cpu_to_le32(psecnetwork->Configuration.FHConfig.HopSet);
+	psecnetwork->Configuration.FHConfig.Length=cpu_to_le32(psecnetwork->Configuration.FHConfig.Length);	
+	psecnetwork->Configuration.Length = cpu_to_le32(psecnetwork->Configuration.Length);
+	psecnetwork->InfrastructureMode = cpu_to_le32(psecnetwork->InfrastructureMode);
+	psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);      
+#endif
+
+	_rtw_init_listhead(&pcmd->list);
+	pcmd->cmdcode = _JoinBss_CMD_;//GEN_CMD_CODE(_JoinBss)
+	pcmd->parmbuf = (unsigned char *)psecnetwork;
+	pcmd->rsp = NULL;
+	pcmd->rspsz = 0;
+
+	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+	
+_func_exit_;
+
+	return res;
+}
+
+u8 rtw_disassoc_cmd(_adapter*padapter, u32 deauth_timeout_ms, bool enqueue) /* for sta_mode */
+{
+	struct cmd_obj *cmdobj = NULL;
+	struct disconnect_parm *param = NULL;
+	struct cmd_priv *cmdpriv = &padapter->cmdpriv;
+	u8 res = _SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_disassoc_cmd\n"));
+
+	/* prepare cmd parameter */
+	param = (struct disconnect_parm *)rtw_zmalloc(sizeof(*param));
+	if (param == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+	param->deauth_timeout_ms = deauth_timeout_ms;
+
+	if (enqueue) {
+		/* need enqueue, prepare cmd_obj and enqueue */
+		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
+		if (cmdobj == NULL) {
+			res = _FAIL;
+			rtw_mfree((u8 *)param, sizeof(*param));
+			goto exit;
+		}
+		init_h2fwcmd_w_parm_no_rsp(cmdobj, param, _DisConnect_CMD_);
+		res = rtw_enqueue_cmd(cmdpriv, cmdobj);
+	} else {
+		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+		if (H2C_SUCCESS != disconnect_hdl(padapter, (u8 *)param))
+			res = _FAIL;
+		rtw_mfree((u8 *)param, sizeof(*param));
+	}
+
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_setopmode_cmd(_adapter  *padapter, NDIS_802_11_NETWORK_INFRASTRUCTURE networktype, bool enqueue)
+{
+	struct	cmd_obj*	ph2c;
+	struct	setopmode_parm* psetop;
+
+	struct	cmd_priv   *pcmdpriv= &padapter->cmdpriv;
+	u8	res=_SUCCESS;
+
+_func_enter_;
+	psetop = (struct setopmode_parm*)rtw_zmalloc(sizeof(struct setopmode_parm)); 
+
+	if(psetop==NULL){		
+		res=_FAIL;
+		goto exit;
+	}
+	psetop->mode = (u8)networktype;
+	
+	if(enqueue){
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));			
+		if(ph2c==NULL){		
+			rtw_mfree((u8 *)psetop, sizeof(*psetop));
+			res= _FAIL;
+			goto exit;
+		}	
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	}
+	else{
+		setopmode_hdl(padapter, (u8 *)psetop);
+		rtw_mfree((u8 *)psetop, sizeof(*psetop));
+	}
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_setstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 key_type, bool enqueue)
+{
+	struct cmd_obj*			ph2c;
+	struct set_stakey_parm	*psetstakey_para;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+	struct set_stakey_rsp		*psetstakey_rsp = NULL;
+	
+	struct mlme_priv			*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv 		*psecuritypriv = &padapter->securitypriv;
+	u8	res=_SUCCESS;
+
+_func_enter_;
+
+	psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
+	if(psetstakey_para==NULL){	
+		res=_FAIL;
+		goto exit;
+	}
+		
+	_rtw_memcpy(psetstakey_para->addr, sta->hwaddr,ETH_ALEN);
+		
+	if(check_fwstate(pmlmepriv, WIFI_STATION_STATE)){
+			psetstakey_para->algorithm =(unsigned char) psecuritypriv->dot11PrivacyAlgrthm;
+	}else{
+		GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, _FALSE);
+	}
+
+	if (key_type == GROUP_KEY) {
+		_rtw_memcpy(&psetstakey_para->key, &psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey, 16);
+	}
+	else if (key_type == UNICAST_KEY) {
+		_rtw_memcpy(&psetstakey_para->key, &sta->dot118021x_UncstKey, 16);
+	}
+#ifdef CONFIG_TDLS
+	else if(key_type == TDLS_KEY){
+			_rtw_memcpy(&psetstakey_para->key, sta->tpk.tk, 16);
+		psetstakey_para->algorithm=(u8)sta->dot118021XPrivacy;
+       }
+#endif /* CONFIG_TDLS */
+
+	//jeff: set this becasue at least sw key is ready
+	padapter->securitypriv.busetkipkey=_TRUE;
+
+	if(enqueue)
+	{
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+		if ( ph2c == NULL){
+			rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
+			res= _FAIL;
+			goto exit;
+		}	
+
+		psetstakey_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_stakey_rsp)); 
+		if(psetstakey_rsp == NULL){
+			rtw_mfree((u8 *) ph2c, sizeof(struct cmd_obj));
+			rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
+			res=_FAIL;
+			goto exit;
+		}
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+		ph2c->rsp = (u8 *) psetstakey_rsp;
+		ph2c->rspsz = sizeof(struct set_stakey_rsp);
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+	}
+	else{
+		set_stakey_hdl(padapter, (u8 *)psetstakey_para);
+		rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
+	}
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_clearstakey_cmd(_adapter *padapter, struct sta_info *sta, u8 enqueue)
+{
+	struct cmd_obj*			ph2c;
+	struct set_stakey_parm	*psetstakey_para;
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+	struct set_stakey_rsp		*psetstakey_rsp = NULL;	
+	struct mlme_priv			*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv 		*psecuritypriv = &padapter->securitypriv;
+	s16 cam_id = 0;
+	u8	res=_SUCCESS;
+
+_func_enter_;
+
+	if(!enqueue)
+	{
+		while ((cam_id = rtw_camid_search(padapter, sta->hwaddr, -1, -1)) >= 0) {
+			DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(sta->hwaddr), cam_id);
+			clear_cam_entry(padapter, cam_id);
+			rtw_camid_free(padapter, cam_id);
+		}
+	}
+	else
+	{
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+		if ( ph2c == NULL){
+			res= _FAIL;
+			goto exit;
+		}
+
+		psetstakey_para = (struct set_stakey_parm*)rtw_zmalloc(sizeof(struct set_stakey_parm));
+		if(psetstakey_para==NULL){
+			rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+			res=_FAIL;
+			goto exit;
+		}
+
+		psetstakey_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_stakey_rsp)); 
+		if(psetstakey_rsp == NULL){
+			rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+			rtw_mfree((u8 *) psetstakey_para, sizeof(struct set_stakey_parm));
+			res=_FAIL;
+			goto exit;
+		}
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
+		ph2c->rsp = (u8 *) psetstakey_rsp;
+		ph2c->rspsz = sizeof(struct set_stakey_rsp);
+
+		_rtw_memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
+
+		psetstakey_para->algorithm = _NO_PRIVACY_;
+	
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+		
+	}
+	
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_setrttbl_cmd(_adapter  *padapter, struct setratable_parm *prate_table)
+{
+	struct cmd_obj*			ph2c;
+	struct setratable_parm *	psetrttblparm;	
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+	u8	res=_SUCCESS;
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+		}
+	psetrttblparm = (struct setratable_parm*)rtw_zmalloc(sizeof(struct setratable_parm)); 
+
+	if(psetrttblparm==NULL){
+		rtw_mfree((unsigned char *) ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
+
+	_rtw_memcpy(psetrttblparm,prate_table,sizeof(struct setratable_parm));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:
+_func_exit_;	
+	return res;
+
+}
+
+u8 rtw_getrttbl_cmd(_adapter  *padapter, struct getratable_rsp *pval)
+{
+	struct cmd_obj*			ph2c;
+	struct getratable_parm *	pgetrttblparm;	
+	struct cmd_priv 			*pcmdpriv=&padapter->cmdpriv;
+	u8	res=_SUCCESS;
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	pgetrttblparm = (struct getratable_parm*)rtw_zmalloc(sizeof(struct getratable_parm)); 
+
+	if(pgetrttblparm==NULL){
+		rtw_mfree((unsigned char *) ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+//	init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, GEN_CMD_CODE(_SetRaTable));
+
+	_rtw_init_listhead(&ph2c->list);
+	ph2c->cmdcode =GEN_CMD_CODE(_GetRaTable);
+	ph2c->parmbuf = (unsigned char *)pgetrttblparm;
+	ph2c->cmdsz =  sizeof(struct getratable_parm);
+	ph2c->rsp = (u8*)pval;
+	ph2c->rspsz = sizeof(struct getratable_rsp);
+	
+	pgetrttblparm ->rsvd = 0x0;
+	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+exit:
+_func_exit_;	
+	return res;
+
+}
+
+u8 rtw_setassocsta_cmd(_adapter  *padapter, u8 *mac_addr)
+{
+	struct cmd_priv 		*pcmdpriv = &padapter->cmdpriv;
+	struct cmd_obj*			ph2c;
+	struct set_assocsta_parm	*psetassocsta_para;	
+	struct set_stakey_rsp		*psetassocsta_rsp = NULL;
+
+	u8	res=_SUCCESS;
+
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+
+	psetassocsta_para = (struct set_assocsta_parm*)rtw_zmalloc(sizeof(struct set_assocsta_parm));
+	if(psetassocsta_para==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		res=_FAIL;
+		goto exit;
+	}
+
+	psetassocsta_rsp = (struct set_stakey_rsp*)rtw_zmalloc(sizeof(struct set_assocsta_rsp)); 
+	if(psetassocsta_rsp==NULL){
+		rtw_mfree((u8 *) ph2c, sizeof(struct	cmd_obj));
+		rtw_mfree((u8 *) psetassocsta_para, sizeof(struct set_assocsta_parm));
+		return _FAIL;
+	}
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
+	ph2c->rsp = (u8 *) psetassocsta_rsp;
+	ph2c->rspsz = sizeof(struct set_assocsta_rsp);
+
+	_rtw_memcpy(psetassocsta_para->addr, mac_addr,ETH_ALEN);
+	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);	
+
+exit:
+
+_func_exit_;	
+
+	return res;
+ }
+
+u8 rtw_addbareq_cmd(_adapter*padapter, u8 tid, u8 *addr)
+{
+	struct cmd_priv		*pcmdpriv = &padapter->cmdpriv;
+	struct cmd_obj*		ph2c;
+	struct addBaReq_parm	*paddbareq_parm;
+
+	u8	res=_SUCCESS;
+	
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	
+	paddbareq_parm = (struct addBaReq_parm*)rtw_zmalloc(sizeof(struct addBaReq_parm)); 
+	if(paddbareq_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	paddbareq_parm->tid = tid;
+	_rtw_memcpy(paddbareq_parm->addr, addr, ETH_ALEN);
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
+
+	//DBG_871X("rtw_addbareq_cmd, tid=%d\n", tid);
+
+	//rtw_enqueue_cmd(pcmdpriv, ph2c);	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+}
+//add for CONFIG_IEEE80211W, none 11w can use it
+u8 rtw_reset_securitypriv_cmd(_adapter*padapter)
+{
+	struct cmd_obj*		ph2c;
+	struct drvextra_cmd_parm  *pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv=&padapter->cmdpriv;
+	u8	res=_SUCCESS;
+	
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = RESET_SECURITYPRIV;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	
+	//rtw_enqueue_cmd(pcmdpriv, ph2c);	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+
+u8 rtw_free_assoc_resources_cmd(_adapter*padapter)
+{
+	struct cmd_obj*		ph2c;
+	struct drvextra_cmd_parm  *pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv=&padapter->cmdpriv;
+	u8	res=_SUCCESS;
+	
+_func_enter_;	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = FREE_ASSOC_RESOURCES;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	
+	//rtw_enqueue_cmd(pcmdpriv, ph2c);	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+
+u8 rtw_dynamic_chk_wk_cmd(_adapter*padapter)
+{
+	struct cmd_obj*		ph2c;
+	struct drvextra_cmd_parm  *pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv=&padapter->cmdpriv;
+	u8	res=_SUCCESS;
+	
+_func_enter_;	
+
+	//only  primary padapter does this cmd
+/*
+#ifdef CONFIG_CONCURRENT_MODE
+	if (padapter->adapter_type != PRIMARY_ADAPTER && padapter->pbuddy_adapter)
+		pcmdpriv = &(padapter->pbuddy_adapter->cmdpriv);
+#endif
+*/
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = DYNAMIC_CHK_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	
+	//rtw_enqueue_cmd(pcmdpriv, ph2c);	
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+
+u8 rtw_set_ch_cmd(_adapter*padapter, u8 ch, u8 bw, u8 ch_offset, u8 enqueue)
+{
+	struct cmd_obj *pcmdobj;
+	struct set_ch_parm *set_ch_parm;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+	u8 res=_SUCCESS;
+
+_func_enter_;
+
+	DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
+		FUNC_NDEV_ARG(padapter->pnetdev), ch, bw, ch_offset);
+
+	/* check input parameter */
+
+	/* prepare cmd parameter */
+	set_ch_parm = (struct set_ch_parm *)rtw_zmalloc(sizeof(*set_ch_parm));
+	if (set_ch_parm == NULL) {
+		res= _FAIL;
+		goto exit;
+	}
+	set_ch_parm->ch = ch;
+	set_ch_parm->bw = bw;
+	set_ch_parm->ch_offset = ch_offset;
+
+	if (enqueue) {
+		/* need enqueue, prepare cmd_obj and enqueue */
+		pcmdobj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct	cmd_obj));
+		if(pcmdobj == NULL){
+			rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
+			res=_FAIL;
+			goto exit;
+		}
+
+		init_h2fwcmd_w_parm_no_rsp(pcmdobj, set_ch_parm, GEN_CMD_CODE(_SetChannel));
+		res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+	} else {
+		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+		if( H2C_SUCCESS !=set_ch_hdl(padapter, (u8 *)set_ch_parm) )
+			res = _FAIL;
+		
+		rtw_mfree((u8 *)set_ch_parm, sizeof(*set_ch_parm));
+	}
+
+	/* do something based on res... */
+
+exit:
+
+	DBG_871X(FUNC_NDEV_FMT" res:%u\n", FUNC_NDEV_ARG(padapter->pnetdev), res);
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_set_chplan_cmd(_adapter *adapter, int flags, u8 chplan, u8 swconfig)
+{
+	struct cmd_obj *cmdobj;
+	struct	SetChannelPlan_param *parm;
+	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct submit_ctx sctx;
+	u8 res = _SUCCESS;
+
+_func_enter_;
+
+	/* check if allow software config */
+	if (swconfig && rtw_hal_is_disable_sw_channel_plan(adapter) == _TRUE) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	/* check input parameter */
+	if (!rtw_is_channel_plan_valid(chplan)) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	if (rtw_chplan_is_empty(chplan) == _TRUE) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	/* prepare cmd parameter */
+	parm = (struct SetChannelPlan_param *)rtw_zmalloc(sizeof(*parm));
+	if (parm == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+	parm->channel_plan = chplan;
+
+	if (flags & RTW_CMDF_DIRECTLY) {
+		/* no need to enqueue, do the cmd hdl directly and free cmd parameter */
+		if (H2C_SUCCESS != set_chplan_hdl(adapter, (u8 *)parm))
+			res = _FAIL;
+		rtw_mfree((u8 *)parm, sizeof(*parm));
+	} else {
+		/* need enqueue, prepare cmd_obj and enqueue */
+		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(*cmdobj));
+		if (cmdobj == NULL) {
+			res = _FAIL;
+			rtw_mfree((u8 *)parm, sizeof(*parm));
+			goto exit;
+		}
+
+		init_h2fwcmd_w_parm_no_rsp(cmdobj, parm, GEN_CMD_CODE(_SetChannelPlan));
+
+		if (flags & RTW_CMDF_WAIT_ACK) {
+			cmdobj->sctx = &sctx;
+			rtw_sctx_init(&sctx, 2000);
+		}
+
+		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
+
+		if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
+			rtw_sctx_wait(&sctx, __func__);
+			_enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
+			if (sctx.status == RTW_SCTX_SUBMITTED)
+				cmdobj->sctx = NULL;
+			_exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
+		}
+	}
+	
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_led_blink_cmd(_adapter*padapter, PVOID pLed)
+{
+	struct	cmd_obj*	pcmdobj;
+	struct	LedBlink_param *ledBlink_param;
+	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
+
+	u8	res=_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_led_blink_cmd\n"));
+	
+	pcmdobj = (struct	cmd_obj*)rtw_zmalloc(sizeof(struct	cmd_obj));
+	if(pcmdobj == NULL){
+		res=_FAIL;
+		goto exit;
+	}
+
+	ledBlink_param = (struct	LedBlink_param *)rtw_zmalloc(sizeof(struct	LedBlink_param));
+	if(ledBlink_param == NULL) {
+		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	ledBlink_param->pLed=pLed;
+	
+	init_h2fwcmd_w_parm_no_rsp(pcmdobj, ledBlink_param, GEN_CMD_CODE(_LedBlink));
+	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+	
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_set_csa_cmd(_adapter*padapter, u8 new_ch_no)
+{
+	struct	cmd_obj*	pcmdobj;
+	struct	SetChannelSwitch_param*setChannelSwitch_param;
+	struct 	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
+
+	u8	res=_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_csa_cmd\n"));
+	
+	pcmdobj = (struct	cmd_obj*)rtw_zmalloc(sizeof(struct	cmd_obj));
+	if(pcmdobj == NULL){
+		res=_FAIL;
+		goto exit;
+	}
+
+	setChannelSwitch_param = (struct SetChannelSwitch_param *)rtw_zmalloc(sizeof(struct	SetChannelSwitch_param));
+	if(setChannelSwitch_param == NULL) {
+		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	setChannelSwitch_param->new_ch_no=new_ch_no;
+	
+	init_h2fwcmd_w_parm_no_rsp(pcmdobj, setChannelSwitch_param, GEN_CMD_CODE(_SetChannelSwitch));
+	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+	
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+u8 rtw_tdls_cmd(_adapter *padapter, u8 *addr, u8 option)
+{
+	struct	cmd_obj*	pcmdobj;
+	struct	TDLSoption_param	*TDLSoption;
+	struct 	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct	cmd_priv   *pcmdpriv = &padapter->cmdpriv;
+
+	u8	res=_SUCCESS;
+
+_func_enter_;
+
+#ifdef CONFIG_TDLS
+
+	RT_TRACE(_module_rtl871x_cmd_c_, _drv_notice_, ("+rtw_set_tdls_cmd\n"));
+
+	pcmdobj = (struct	cmd_obj*)rtw_zmalloc(sizeof(struct	cmd_obj));
+	if(pcmdobj == NULL){
+		res=_FAIL;
+		goto exit;
+	}
+
+	TDLSoption= (struct TDLSoption_param *)rtw_zmalloc(sizeof(struct TDLSoption_param));
+	if(TDLSoption == NULL) {
+		rtw_mfree((u8 *)pcmdobj, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	_rtw_spinlock(&(padapter->tdlsinfo.cmd_lock));
+	if (addr != NULL)
+		_rtw_memcpy(TDLSoption->addr, addr, 6);
+	TDLSoption->option = option;
+	_rtw_spinunlock(&(padapter->tdlsinfo.cmd_lock));
+	init_h2fwcmd_w_parm_no_rsp(pcmdobj, TDLSoption, GEN_CMD_CODE(_TDLS));
+	res = rtw_enqueue_cmd(pcmdpriv, pcmdobj);
+
+#endif	//CONFIG_TDLS
+	
+exit:
+
+
+_func_exit_;	
+
+	return res;
+}
+
+static void collect_traffic_statistics(_adapter *padapter)
+{
+	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (padapter->adapter_type != PRIMARY_ADAPTER)
+		return;
+#endif
+
+	// Tx
+	pdvobjpriv->traffic_stat.tx_bytes = padapter->xmitpriv.tx_bytes;
+	pdvobjpriv->traffic_stat.tx_pkts = padapter->xmitpriv.tx_pkts;
+	pdvobjpriv->traffic_stat.tx_drop = padapter->xmitpriv.tx_drop;
+
+	// Rx
+	pdvobjpriv->traffic_stat.rx_bytes = padapter->recvpriv.rx_bytes;
+	pdvobjpriv->traffic_stat.rx_pkts = padapter->recvpriv.rx_pkts;
+	pdvobjpriv->traffic_stat.rx_drop = padapter->recvpriv.rx_drop;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	// Add secondary adapter statistics
+	if(rtw_buddy_adapter_up(padapter))
+	{
+		// Tx
+		pdvobjpriv->traffic_stat.tx_bytes += padapter->pbuddy_adapter->xmitpriv.tx_bytes;
+		pdvobjpriv->traffic_stat.tx_pkts += padapter->pbuddy_adapter->xmitpriv.tx_pkts;
+		pdvobjpriv->traffic_stat.tx_drop += padapter->pbuddy_adapter->xmitpriv.tx_drop;
+
+		// Rx
+		pdvobjpriv->traffic_stat.rx_bytes += padapter->pbuddy_adapter->recvpriv.rx_bytes;
+		pdvobjpriv->traffic_stat.rx_pkts += padapter->pbuddy_adapter->recvpriv.rx_pkts;
+		pdvobjpriv->traffic_stat.rx_drop += padapter->pbuddy_adapter->recvpriv.rx_drop;
+	}
+#endif
+
+	// Calculate throughput in last interval
+	pdvobjpriv->traffic_stat.cur_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes - pdvobjpriv->traffic_stat.last_tx_bytes;
+	pdvobjpriv->traffic_stat.cur_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes - pdvobjpriv->traffic_stat.last_rx_bytes;
+	pdvobjpriv->traffic_stat.last_tx_bytes = pdvobjpriv->traffic_stat.tx_bytes;
+	pdvobjpriv->traffic_stat.last_rx_bytes = pdvobjpriv->traffic_stat.rx_bytes;
+
+	pdvobjpriv->traffic_stat.cur_tx_tp = (u32)(pdvobjpriv->traffic_stat.cur_tx_bytes *8/2/1024/1024);
+	pdvobjpriv->traffic_stat.cur_rx_tp = (u32)(pdvobjpriv->traffic_stat.cur_rx_bytes *8/2/1024/1024);
+}
+
+//from_timer == 1 means driver is in LPS
+u8 traffic_status_watchdog(_adapter *padapter, u8 from_timer)
+{
+	u8	bEnterPS = _FALSE;
+	u16 BusyThresholdHigh;
+	u16	BusyThresholdLow;
+	u16	BusyThreshold;
+	u8	bBusyTraffic = _FALSE, bTxBusyTraffic = _FALSE, bRxBusyTraffic = _FALSE;
+	u8	bHigherBusyTraffic = _FALSE, bHigherBusyRxTraffic = _FALSE, bHigherBusyTxTraffic = _FALSE;
+
+	struct mlme_priv		*pmlmepriv = &(padapter->mlmepriv);
+#ifdef CONFIG_TDLS
+	struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
+	struct tdls_txmgmt txmgmt;
+	u8 baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+#endif //CONFIG_TDLS
+
+	RT_LINK_DETECT_T * link_detect = &pmlmepriv->LinkDetectInfo;
+
+#ifdef CONFIG_BT_COEXIST
+	if (padapter->registrypriv.wifi_spec != 1) {
+		BusyThresholdHigh = 25;
+		BusyThresholdLow = 10;
+	} else
+#endif /* CONFIG_BT_COEXIST */
+	{
+		BusyThresholdHigh = 100;
+		BusyThresholdLow = 75;
+	}
+	BusyThreshold = BusyThresholdHigh;
+
+	collect_traffic_statistics(padapter);
+
+	//
+	// Determine if our traffic is busy now
+	//
+	if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) 
+		/*&& !MgntInitAdapterInProgress(pMgntInfo)*/)
+	{
+		// if we raise bBusyTraffic in last watchdog, using lower threshold.
+		if (pmlmepriv->LinkDetectInfo.bBusyTraffic)
+				BusyThreshold = BusyThresholdLow;
+
+		if( pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > BusyThreshold ||
+			pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > BusyThreshold )
+		{
+			bBusyTraffic = _TRUE;
+
+			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
+				bRxBusyTraffic = _TRUE;
+			else
+				bTxBusyTraffic = _TRUE;
+		}
+
+		// Higher Tx/Rx data.
+		if( pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > 4000 ||
+			pmlmepriv->LinkDetectInfo.NumTxOkInPeriod > 4000 )
+		{
+			bHigherBusyTraffic = _TRUE;
+
+			if (pmlmepriv->LinkDetectInfo.NumRxOkInPeriod > pmlmepriv->LinkDetectInfo.NumTxOkInPeriod)
+				bHigherBusyRxTraffic = _TRUE;
+			else
+				bHigherBusyTxTraffic = _TRUE;
+		}
+
+#ifdef CONFIG_TRAFFIC_PROTECT
+#define TX_ACTIVE_TH 10
+#define RX_ACTIVE_TH 20
+#define TRAFFIC_PROTECT_PERIOD_MS 4500
+
+	if (link_detect->NumTxOkInPeriod > TX_ACTIVE_TH
+		|| link_detect->NumRxUnicastOkInPeriod > RX_ACTIVE_TH) {
+		
+		DBG_871X_LEVEL(_drv_info_, FUNC_ADPT_FMT" acqiure wake_lock for %u ms(tx:%d,rx_unicast:%d)\n",
+			FUNC_ADPT_ARG(padapter),
+			TRAFFIC_PROTECT_PERIOD_MS,
+			link_detect->NumTxOkInPeriod,
+			link_detect->NumRxUnicastOkInPeriod);
+
+		rtw_lock_traffic_suspend_timeout(TRAFFIC_PROTECT_PERIOD_MS);
+	}
+#endif
+		
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_AUTOSETUP
+		/* TDLS_WATCHDOG_PERIOD * 2sec, periodically send */
+		if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _TRUE) {
+			if ((ptdlsinfo->watchdog_count % TDLS_WATCHDOG_PERIOD) == 0) {
+				_rtw_memcpy(txmgmt.peer, baddr, ETH_ALEN);
+				issue_tdls_dis_req(padapter, &txmgmt);
+			}
+			ptdlsinfo->watchdog_count++;
+		}
+#endif //CONFIG_TDLS_AUTOSETUP
+#endif //CONFIG_TDLS
+
+#ifdef CONFIG_LPS
+		// check traffic for  powersaving.
+		if( ((pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod + pmlmepriv->LinkDetectInfo.NumTxOkInPeriod) > 8 ) ||
+#ifdef CONFIG_LPS_SLOW_TRANSITION			
+			(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 2) 
+#else //CONFIG_LPS_SLOW_TRANSITION
+			(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4) 
+#endif //CONFIG_LPS_SLOW_TRANSITION
+			)
+		{
+#ifdef DBG_RX_COUNTER_DUMP
+			if( padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
+				DBG_871X("(-)Tx = %d, Rx = %d \n",pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
+#endif	
+			bEnterPS= _FALSE;
+#ifdef CONFIG_LPS_SLOW_TRANSITION
+			if(bBusyTraffic == _TRUE)
+			{
+				if(pmlmepriv->LinkDetectInfo.TrafficTransitionCount <= 4)
+					pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 4;
+
+				pmlmepriv->LinkDetectInfo.TrafficTransitionCount++;
+
+				//DBG_871X("Set TrafficTransitionCount to %d\n", pmlmepriv->LinkDetectInfo.TrafficTransitionCount);
+			
+				if(pmlmepriv->LinkDetectInfo.TrafficTransitionCount > 30/*TrafficTransitionLevel*/)
+				{
+					pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 30;
+				}	
+			}
+#endif //CONFIG_LPS_SLOW_TRANSITION
+	
+		}
+		else
+		{
+#ifdef DBG_RX_COUNTER_DUMP		
+			if( padapter->dump_rx_cnt_mode & DUMP_DRV_TRX_COUNTER_DATA)
+				DBG_871X("(+)Tx = %d, Rx = %d \n",pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);
+#endif			
+#ifdef CONFIG_LPS_SLOW_TRANSITION
+			if(pmlmepriv->LinkDetectInfo.TrafficTransitionCount>=2)
+				pmlmepriv->LinkDetectInfo.TrafficTransitionCount -=2;
+			else
+				pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
+
+			if(pmlmepriv->LinkDetectInfo.TrafficTransitionCount == 0)
+				bEnterPS= _TRUE;
+#else //CONFIG_LPS_SLOW_TRANSITION
+				bEnterPS= _TRUE;
+#endif //CONFIG_LPS_SLOW_TRANSITION
+		}
+
+#ifdef CONFIG_DYNAMIC_DTIM
+		if(pmlmepriv->LinkDetectInfo.LowPowerTransitionCount == 8)
+			bEnterPS= _FALSE;
+
+		DBG_871X("LowPowerTransitionCount=%d\n", pmlmepriv->LinkDetectInfo.LowPowerTransitionCount);
+#endif //CONFIG_DYNAMIC_DTIM
+
+		// LeisurePS only work in infra mode.
+		if(bEnterPS)
+		{
+			if(!from_timer)
+			{
+#ifdef CONFIG_DYNAMIC_DTIM
+				if(pmlmepriv->LinkDetectInfo.LowPowerTransitionCount < 8)
+				{					
+					adapter_to_pwrctl(padapter)->dtim = 1;
+				}	
+				else
+				{					
+					adapter_to_pwrctl(padapter)->dtim = 3;
+				}
+#endif //CONFIG_DYNAMIC_DTIM
+				LPS_Enter(padapter, "TRAFFIC_IDLE");
+			}	
+			else
+			{
+				//do this at caller
+				//rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 1);
+				//rtw_hal_dm_watchdog_in_lps(padapter);
+			}				
+#ifdef CONFIG_DYNAMIC_DTIM
+			if (adapter_to_pwrctl(padapter)->bFwCurrentInPSMode ==_TRUE )
+				pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
+#endif //CONFIG_DYNAMIC_DTIM
+		}
+		else
+		{
+#ifdef CONFIG_DYNAMIC_DTIM
+			if(pmlmepriv->LinkDetectInfo.LowPowerTransitionCount != 8)
+				pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
+			else
+				pmlmepriv->LinkDetectInfo.LowPowerTransitionCount++;
+#endif //CONFIG_DYNAMIC_DTIM			
+			if(!from_timer)
+			{
+				LPS_Leave(padapter, "TRAFFIC_BUSY");
+			}
+			else
+			{
+#ifdef CONFIG_CONCURRENT_MODE
+			 	if(padapter->iface_type == IFACE_PORT0) 
+#endif
+					rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_TRAFFIC_BUSY, 1);
+			}
+		}
+	
+#endif // CONFIG_LPS
+	}
+	else
+	{
+#ifdef CONFIG_LPS
+		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+		int n_assoc_iface = 0;
+		int i;
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
+				n_assoc_iface++;
+		}
+
+		if(!from_timer && n_assoc_iface == 0)
+			LPS_Leave(padapter, "NON_LINKED");
+#endif
+	}
+
+	session_tracker_chk_cmd(padapter, NULL);
+
+	pmlmepriv->LinkDetectInfo.NumRxOkInPeriod = 0;
+	pmlmepriv->LinkDetectInfo.NumTxOkInPeriod = 0;
+	pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod = 0;
+	pmlmepriv->LinkDetectInfo.bBusyTraffic = bBusyTraffic;
+	pmlmepriv->LinkDetectInfo.bTxBusyTraffic = bTxBusyTraffic;
+	pmlmepriv->LinkDetectInfo.bRxBusyTraffic = bRxBusyTraffic;
+	pmlmepriv->LinkDetectInfo.bHigherBusyTraffic = bHigherBusyTraffic;
+	pmlmepriv->LinkDetectInfo.bHigherBusyRxTraffic = bHigherBusyRxTraffic;
+	pmlmepriv->LinkDetectInfo.bHigherBusyTxTraffic = bHigherBusyTxTraffic;
+
+	return bEnterPS;
+	
+}
+
+void dynamic_chk_wk_hdl(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv;
+	pmlmepriv = &(padapter->mlmepriv);
+
+#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+#ifdef CONFIG_AP_MODE
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{			
+		expire_timeout_chk(padapter);
+	}
+#endif
+#endif //CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+
+#ifdef DBG_CONFIG_ERROR_DETECT	
+	rtw_hal_sreset_xmit_status_check(padapter);		
+	rtw_hal_sreset_linked_status_check(padapter);
+#endif	
+
+	//for debug purpose
+	_linked_info_dump(padapter);
+
+
+	//if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING|_FW_UNDER_SURVEY)==_FALSE)
+	{
+		linked_status_chk(padapter, 0);
+		traffic_status_watchdog(padapter, 0);
+		#ifdef DBG_RX_COUNTER_DUMP
+		rtw_dump_rx_counters(padapter);
+		#endif
+		dm_DynamicUsbTxAgg(padapter, 0);
+	}
+
+#ifdef CONFIG_BEAMFORMING
+#if (BEAMFORMING_SUPPORT == 0) /*for diver defined beamforming*/
+	beamforming_watchdog(padapter);
+#endif
+#endif
+
+	rtw_hal_dm_watchdog(padapter);
+
+	//check_hw_pbc(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->type);
+
+#ifdef CONFIG_BT_COEXIST
+	//
+	// BT-Coexist
+	//
+	rtw_btcoex_Handler(padapter);
+#endif
+
+	
+#ifdef CONFIG_IPS_CHECK_IN_WD
+	//always call rtw_ps_processor() at last one.
+	if (is_primary_adapter(padapter))
+		rtw_ps_processor(padapter);
+#endif
+}
+
+#ifdef CONFIG_LPS
+
+void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type);
+void lps_ctrl_wk_hdl(_adapter *padapter, u8 lps_ctrl_type)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	u8	mstatus;
+	
+_func_enter_;
+
+	if((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)
+		|| (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE))
+	{
+		return;
+	}
+
+	switch(lps_ctrl_type)
+	{
+		case LPS_CTRL_SCAN:
+			//DBG_871X("LPS_CTRL_SCAN \n");
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_ScanNotify(padapter, _TRUE);
+#endif // CONFIG_BT_COEXIST
+			if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+			{
+				// connect
+				LPS_Leave(padapter, "LPS_CTRL_SCAN");
+			}
+			break;
+		case LPS_CTRL_JOINBSS:
+			//DBG_871X("LPS_CTRL_JOINBSS \n");
+			LPS_Leave(padapter, "LPS_CTRL_JOINBSS");
+			break;
+		case LPS_CTRL_CONNECT:
+			//DBG_871X("LPS_CTRL_CONNECT \n");
+			mstatus = 1;//connect
+			// Reset LPS Setting
+			pwrpriv->LpsIdleCount = 0;
+			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_MediaStatusNotify(padapter, mstatus);
+#endif // CONFIG_BT_COEXIST
+			break;
+		case LPS_CTRL_DISCONNECT:
+			//DBG_871X("LPS_CTRL_DISCONNECT \n");
+			mstatus = 0;//disconnect
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_MediaStatusNotify(padapter, mstatus);
+#endif // CONFIG_BT_COEXIST
+			LPS_Leave(padapter, "LPS_CTRL_DISCONNECT");
+			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
+			break;
+		case LPS_CTRL_SPECIAL_PACKET:
+			//DBG_871X("LPS_CTRL_SPECIAL_PACKET \n");
+			pwrpriv->DelayLPSLastTimeStamp = rtw_get_current_time();
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_SpecialPacketNotify(padapter, PACKET_DHCP);
+#endif // CONFIG_BT_COEXIST
+			LPS_Leave(padapter, "LPS_CTRL_SPECIAL_PACKET");
+			break;
+		case LPS_CTRL_LEAVE:
+			LPS_Leave(padapter, "LPS_CTRL_LEAVE");
+			break;
+		case LPS_CTRL_LEAVE_CFG80211_PWRMGMT:
+			LPS_Leave(padapter, "CFG80211_PWRMGMT");
+			break;
+		case LPS_CTRL_TRAFFIC_BUSY:
+			LPS_Leave(padapter, "LPS_CTRL_TRAFFIC_BUSY");
+			break;
+		case LPS_CTRL_TX_TRAFFIC_LEAVE:
+			LPS_Leave(padapter, "LPS_CTRL_TX_TRAFFIC_LEAVE");
+			break;
+		case LPS_CTRL_RX_TRAFFIC_LEAVE:
+			LPS_Leave(padapter, "LPS_CTRL_RX_TRAFFIC_LEAVE");
+			break;
+		case LPS_CTRL_ENTER:
+			LPS_Enter(padapter, "TRAFFIC_IDLE_1");
+			break;
+		default:
+			break;
+	}
+
+_func_exit_;
+}
+
+u8 rtw_lps_ctrl_wk_cmd(_adapter*padapter, u8 lps_ctrl_type, u8 enqueue)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	//struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+	u8	res = _SUCCESS;
+	
+_func_enter_;
+
+	//if(!pwrctrlpriv->bLeisurePs)
+	//	return res;
+
+	if(enqueue)
+	{
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+		if(ph2c==NULL){
+			res= _FAIL;
+			goto exit;
+		}
+		
+		pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+		if(pdrvextra_cmd_parm==NULL){
+			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+			res= _FAIL;
+			goto exit;
+		}
+
+		pdrvextra_cmd_parm->ec_id = LPS_CTRL_WK_CID;
+		pdrvextra_cmd_parm->type = lps_ctrl_type;
+		pdrvextra_cmd_parm->size = 0;
+		pdrvextra_cmd_parm->pbuf = NULL;
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	}
+	else
+	{
+		lps_ctrl_wk_hdl(padapter, lps_ctrl_type);
+	}
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+
+void rtw_dm_in_lps_hdl(_adapter*padapter)
+{
+	rtw_hal_set_hwreg(padapter, HW_VAR_DM_IN_LPS, NULL);
+}
+
+u8 rtw_dm_in_lps_wk_cmd(_adapter*padapter)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+		
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = DM_IN_LPS_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+	return res;
+
+}
+
+void rtw_lps_change_dtim_hdl(_adapter *padapter, u8 dtim)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+
+	if(dtim <=0 || dtim > 16)
+		return;
+
+#ifdef CONFIG_BT_COEXIST
+	if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
+		return;
+#endif
+
+#ifdef CONFIG_LPS_LCLK
+	_enter_pwrlock(&pwrpriv->lock);
+#endif
+
+	if(pwrpriv->dtim!=dtim)
+	{
+		DBG_871X("change DTIM from %d to %d, bFwCurrentInPSMode=%d, ps_mode=%d\n", pwrpriv->dtim, dtim, 
+			pwrpriv->bFwCurrentInPSMode, pwrpriv->pwr_mode);
+		
+		pwrpriv->dtim = dtim;
+	}	
+
+	if((pwrpriv->bFwCurrentInPSMode ==_TRUE) && (pwrpriv->pwr_mode > PS_MODE_ACTIVE))		 
+	{
+		u8 ps_mode = pwrpriv->pwr_mode;
+
+		//DBG_871X("change DTIM from %d to %d, ps_mode=%d\n", pwrpriv->dtim, dtim, ps_mode);
+	
+		rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
+	}
+	
+#ifdef CONFIG_LPS_LCLK
+	_exit_pwrlock(&pwrpriv->lock);
+#endif
+
+}
+
+#endif
+
+u8 rtw_lps_change_dtim_cmd(_adapter*padapter, u8 dtim)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+/*
+#ifdef CONFIG_CONCURRENT_MODE
+	if (padapter->iface_type != IFACE_PORT0)
+		return res;
+#endif
+*/
+	{
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+		if(ph2c==NULL){
+			res= _FAIL;
+			goto exit;
+		}
+		
+		pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+		if(pdrvextra_cmd_parm==NULL){
+			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+			res= _FAIL;
+			goto exit;
+		}
+
+		pdrvextra_cmd_parm->ec_id = LPS_CHANGE_DTIM_CID;
+		pdrvextra_cmd_parm->type = dtim;
+		pdrvextra_cmd_parm->size = 0;
+		pdrvextra_cmd_parm->pbuf = NULL;
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	}
+	
+exit:
+	
+	return res;
+
+}
+
+#if (RATE_ADAPTIVE_SUPPORT==1)
+void rpt_timer_setting_wk_hdl(_adapter *padapter, u16 minRptTime)
+{
+	rtw_hal_set_hwreg(padapter, HW_VAR_RPT_TIMER_SETTING, (u8 *)(&minRptTime));
+}
+
+u8 rtw_rpt_timer_cfg_cmd(_adapter*padapter, u16 minRptTime)
+{
+	struct cmd_obj		*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+
+	u8	res = _SUCCESS;
+
+_func_enter_;
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = RTP_TIMER_CFG_WK_CID;
+	pdrvextra_cmd_parm->type = minRptTime;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+_func_exit_;
+
+	return res;
+
+}
+
+#endif
+
+#ifdef CONFIG_ANTENNA_DIVERSITY
+void antenna_select_wk_hdl(_adapter *padapter, u8 antenna)
+{
+	rtw_hal_set_hwreg(padapter, HW_VAR_ANTENNA_DIVERSITY_SELECT, (u8 *)(&antenna));
+}
+
+u8 rtw_antenna_select_cmd(_adapter*padapter, u8 antenna,u8 enqueue)
+{
+	struct cmd_obj		*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8 	bSupportAntDiv = _FALSE;
+	u8	res = _SUCCESS;
+
+_func_enter_;
+	rtw_hal_get_def_var(padapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));
+	if(_FALSE == bSupportAntDiv )	return res;
+
+	if(_TRUE == enqueue)
+	{
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+		if(ph2c==NULL){
+			res= _FAIL;
+			goto exit;
+		}
+
+		pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+		if(pdrvextra_cmd_parm==NULL){
+			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+			res= _FAIL;
+			goto exit;
+		}
+
+		pdrvextra_cmd_parm->ec_id = ANT_SELECT_WK_CID;
+		pdrvextra_cmd_parm->type = antenna;
+		pdrvextra_cmd_parm->size = 0;
+		pdrvextra_cmd_parm->pbuf = NULL;
+		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	}
+	else{
+		antenna_select_wk_hdl(padapter,antenna );
+	}
+exit:
+
+_func_exit_;
+
+	return res;
+
+}
+#endif
+
+void rtw_dm_ra_mask_hdl(_adapter *padapter, struct sta_info *psta)
+{
+	if (psta) {
+		set_sta_rate(padapter, psta);
+	}
+}
+
+u8 rtw_dm_ra_mask_wk_cmd(_adapter*padapter, u8 *psta)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+	
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+		
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = DM_RA_MSK_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = psta;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+	return res;
+
+}
+
+void power_saving_wk_hdl(_adapter *padapter)
+{
+	 rtw_ps_processor(padapter);
+}
+
+//add for CONFIG_IEEE80211W, none 11w can use it
+void reset_securitypriv_hdl(_adapter *padapter)
+{
+	 rtw_reset_securitypriv(padapter);
+}
+
+void free_assoc_resources_hdl(_adapter *padapter)
+{
+	 rtw_free_assoc_resources(padapter, 1);
+}
+
+#ifdef CONFIG_P2P
+u8 p2p_protocol_wk_cmd(_adapter*padapter, int intCmdType )
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+	
+_func_enter_;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+	{
+		return res;
+	}
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+			
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = P2P_PROTO_WK_CID;
+	pdrvextra_cmd_parm->type = intCmdType;	//	As the command tppe.
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;		//	Must be NULL here
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+#endif //CONFIG_P2P
+
+u8 rtw_ps_cmd(_adapter*padapter)
+{
+	struct cmd_obj		*ppscmd;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	
+	u8	res = _SUCCESS;
+_func_enter_;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (padapter->adapter_type != PRIMARY_ADAPTER)
+		goto exit;
+#endif
+	
+	ppscmd = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ppscmd==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+		
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ppscmd, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = POWER_SAVING_CTRL_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+	init_h2fwcmd_w_parm_no_rsp(ppscmd, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ppscmd);
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+
+#ifdef CONFIG_AP_MODE
+
+static void rtw_chk_hi_queue_hdl(_adapter *padapter)
+{
+	struct sta_info *psta_bmc;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u32 start = rtw_get_current_time();
+	u8 empty = _FALSE;
+
+	psta_bmc = rtw_get_bcmc_stainfo(padapter);
+	if(!psta_bmc)
+		return;
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
+
+	while(_FALSE == empty && rtw_get_passing_time_ms(start) < rtw_get_wait_hiq_empty_ms())
+	{
+		rtw_msleep_os(100);
+		rtw_hal_get_hwreg(padapter, HW_VAR_CHK_HI_QUEUE_EMPTY, &empty);
+	}
+
+	if(psta_bmc->sleepq_len==0)
+	{
+		if(empty == _SUCCESS)
+		{
+			bool update_tim = _FALSE;
+
+			if (pstapriv->tim_bitmap & BIT(0))
+				update_tim = _TRUE;
+
+			pstapriv->tim_bitmap &= ~BIT(0);
+			pstapriv->sta_dz_bitmap &= ~BIT(0);
+
+			if (update_tim == _TRUE)
+				_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "bmc sleepq and HIQ empty");
+		}
+		else //re check again
+		{
+			rtw_chk_hi_queue_cmd(padapter);
+		}
+		
+	}	
+	
+}
+
+u8 rtw_chk_hi_queue_cmd(_adapter*padapter)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;	
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+	
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+	if(ph2c==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+			
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+	if(pdrvextra_cmd_parm==NULL){
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = CHECK_HIQ_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = 0;
+	pdrvextra_cmd_parm->pbuf = NULL;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+	return res;
+
+}
+
+#ifdef CONFIG_DFS_MASTER
+u8 rtw_dfs_master_hdl(_adapter *adapter)
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+
+	if (!rfctl->dfs_master_enabled)
+		goto exit;
+
+	if (rtw_get_on_cur_ch_time(adapter) == 0
+		|| rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 300
+	) {
+		/* offchannel , by pass radar detect */
+		goto cac_status_chk;
+	}
+
+	if (rfctl->dbg_dfs_master_fake_radar_detect_cnt
+		|| rtw_odm_radar_detect(adapter) == _TRUE
+	) {
+		if (rfctl->dbg_dfs_master_fake_radar_detect_cnt != 0) {
+			DBG_871X(FUNC_ADPT_FMT" fake radar detect, cnt:%d\n", FUNC_ADPT_ARG(adapter)
+				, rfctl->dbg_dfs_master_fake_radar_detect_cnt);
+			rfctl->dbg_dfs_master_fake_radar_detect_cnt--;
+		}
+	
+		if (rfctl->dbg_dfs_master_radar_detect_trigger_non) {
+			/* radar detect debug mode, trigger no mlme flow */
+			DBG_871X(FUNC_ADPT_FMT" radar detected, trigger no mlme flow for debug\n", FUNC_ADPT_ARG(adapter));
+		} else {
+			/* TODO: move timer to rfctl */
+			struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+			int i;
+
+			for (i = 0; i < dvobj->iface_nums; i++) {
+				if (!dvobj->padapters[i])
+					continue;
+				if (check_fwstate(&dvobj->padapters[i]->mlmepriv, WIFI_AP_STATE)
+					&& check_fwstate(&dvobj->padapters[i]->mlmepriv, WIFI_AP_STATE))
+					break;
+			}
+
+			if (i >= dvobj->iface_nums) {
+				/* what? */
+				rtw_warn_on(1);
+			} else {
+				rtw_chset_update_non_ocp(dvobj->padapters[i]->mlmeextpriv.channel_set
+					, rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset);
+
+				/* change op ch, inform ch switch */
+				rtw_change_bss_chbw_cmd(dvobj->padapters[i], RTW_CMDF_DIRECTLY, 0, 0, 0);
+			}
+
+			if (rfctl->dfs_master_enabled)
+				goto set_timer;
+			goto exit;
+		}
+	}
+
+cac_status_chk:
+
+	if (!IS_UNDER_CAC(rfctl) && !IS_CAC_STOPPED(rfctl)) {
+		u8 pause = 0x00;
+
+		rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
+		rfctl->cac_end_time = RTW_CAC_STOPPED;
+	}
+
+set_timer:
+	_set_timer(&mlme->dfs_master_timer, DFS_MASTER_TIMER_MS);
+
+exit:
+	return H2C_SUCCESS;
+}
+
+u8 rtw_dfs_master_cmd(_adapter *adapter, bool enqueue)
+{
+	struct cmd_obj *cmdobj;
+	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+	u8 res = _FAIL;
+
+	if (enqueue) {
+		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));	
+		if (cmdobj == NULL)
+			goto exit;
+
+		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+		if (pdrvextra_cmd_parm == NULL) {
+			rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
+			goto exit;
+		}
+
+		pdrvextra_cmd_parm->ec_id = DFS_MASTER_WK_CID;
+		pdrvextra_cmd_parm->type = 0;
+		pdrvextra_cmd_parm->size = 0;
+		pdrvextra_cmd_parm->pbuf = NULL;
+
+		init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
+	} else {
+		rtw_dfs_master_hdl(adapter);
+		res = _SUCCESS;
+	}
+
+exit:
+	return res;
+}
+
+void rtw_dfs_master_timer_hdl(struct timer_list *t)
+{
+	_adapter *adapter =
+		from_timer(adapter, t, pmlmepriv->dfs_master_timer);
+
+	rtw_dfs_master_cmd(adapter, _TRUE);
+}
+
+void rtw_dfs_master_enable(_adapter *adapter, u8 ch, u8 bw, u8 offset)
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+
+	/* TODO: move timer to rfctl */
+	adapter = GET_PRIMARY_ADAPTER(adapter);
+
+	DBG_871X(FUNC_ADPT_FMT" on %u,%u,%u\n", FUNC_ADPT_ARG(adapter), ch, bw, offset);
+
+	rfctl->pre_radar_detect_by_sta_link = rfctl->radar_detect_by_sta_link;
+	rfctl->radar_detect_by_sta_link = _FALSE;
+
+	rfctl->pre_radar_detect_ch = rfctl->radar_detect_ch;
+	rfctl->pre_radar_detect_bw = rfctl->radar_detect_bw;
+	rfctl->pre_radar_detect_offset = rfctl->radar_detect_offset;
+	rfctl->radar_detect_ch = ch;
+	rfctl->radar_detect_bw = bw;
+	rfctl->radar_detect_offset = offset;
+
+	if (rtw_is_cac_reset_needed(adapter) == _TRUE)
+		rtw_rfctl_reset_cac(adapter_to_rfctl(adapter));
+
+	if (!rfctl->dfs_master_enabled) {
+		DBG_871X(FUNC_ADPT_FMT" set dfs_master_enabled\n", FUNC_ADPT_ARG(adapter));
+		rfctl->dfs_master_enabled = 1;
+		_set_timer(&adapter->mlmepriv.dfs_master_timer, DFS_MASTER_TIMER_MS);
+
+		if (rtw_rfctl_overlap_radar_detect_ch(rfctl)) {
+			if (IS_UNDER_CAC(rfctl)) {
+				u8 pause = 0xFF;
+
+				rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
+			}
+			rtw_odm_radar_detect_enable(adapter);
+		}
+	}
+}
+
+void rtw_dfs_master_disable(_adapter *adapter, bool ld_sta_in_dfs)
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+	
+	/* TODO: move timer to rfctl */
+	adapter = GET_PRIMARY_ADAPTER(adapter);
+
+	rfctl->pre_radar_detect_by_sta_link = rfctl->radar_detect_by_sta_link;
+	rfctl->radar_detect_by_sta_link = ld_sta_in_dfs;
+
+	if (rfctl->dfs_master_enabled) {
+		bool overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
+
+		DBG_871X(FUNC_ADPT_FMT" clear dfs_master_enabled\n", FUNC_ADPT_ARG(adapter));
+
+		rfctl->dfs_master_enabled = 0;
+		rfctl->radar_detect_ch = rfctl->pre_radar_detect_ch = 0;
+		rfctl->radar_detect_bw = rfctl->pre_radar_detect_bw = 0;
+		rfctl->radar_detect_offset = rfctl->pre_radar_detect_offset = 0;
+		rfctl->cac_end_time = RTW_CAC_STOPPED;
+		_cancel_timer_ex(&adapter->mlmepriv.dfs_master_timer);
+
+		if (overlap_radar_detect_ch) {
+			u8 pause = 0x00;
+
+			rtw_hal_set_hwreg(adapter, HW_VAR_TXPAUSE, &pause);
+			rtw_odm_radar_detect_disable(adapter);
+		}
+	}
+}
+
+void rtw_dfs_master_status_apply(_adapter *adapter, u8 self_action)
+{
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	u8 ld_sta_num, lg_sta_num, ap_num;
+	u8 u_ch, u_bw, u_offset;
+	bool ld_sta_in_dfs = _FALSE;
+	bool sync_ch = _FALSE; /* _FALSE: asign channel directly */
+	bool needed = _FALSE;
+
+	rtw_dev_iface_status_no_self(adapter, NULL, &ld_sta_num, &lg_sta_num, &ap_num, NULL);
+	rtw_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset);
+	if (u_ch != 0)
+		sync_ch = _TRUE;
+
+	switch (self_action) {
+	case MLME_STA_CONNECTING:
+		lg_sta_num++;
+		break;
+	case MLME_STA_CONNECTED:
+		ld_sta_num++;
+		break;
+	case MLME_AP_STARTED:
+		ap_num++;
+		break;
+	case MLME_AP_STOPPED:
+	case MLME_STA_DISCONNECTED:
+	default:
+		break;
+	}
+
+	if (sync_ch == _TRUE) {
+		if (!rtw_is_chbw_grouped(mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset)) {
+			DBG_871X(FUNC_ADPT_FMT" can't sync %u,%u,%u with %u,%u,%u\n", FUNC_ADPT_ARG(adapter)
+				, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset, u_ch, u_bw, u_offset);
+			goto apply;
+		}
+
+		rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
+			, &u_ch, &u_bw, &u_offset);
+	} else {
+		u_ch = mlmeext->cur_channel;
+		u_bw = mlmeext->cur_bwmode;
+		u_offset = mlmeext->cur_ch_offset;
+	}
+
+	if (ld_sta_num > 0) {
+		/* rely on AP on which STA mode connects */
+		if (rtw_is_dfs_ch(u_ch, u_bw, u_offset))
+			ld_sta_in_dfs = _TRUE;
+		goto apply;
+	}
+
+	if (lg_sta_num > 0) {
+		/* STA mode is linking */
+		goto apply;
+	}
+
+	if (ap_num == 0) {
+		/* No working AP mode */
+		goto apply;
+	}
+
+	if (rtw_is_dfs_ch(u_ch, u_bw, u_offset))
+		needed = _TRUE;
+
+apply:
+
+	DBG_871X(FUNC_ADPT_FMT" needed:%d, self_action:%u\n"
+		, FUNC_ADPT_ARG(adapter), needed, self_action);
+	DBG_871X(FUNC_ADPT_FMT" ld_sta_num:%u, lg_sta_num:%u, ap_num:%u, %u,%u,%u\n"
+		, FUNC_ADPT_ARG(adapter), ld_sta_num, lg_sta_num, ap_num, u_ch, u_bw, u_offset);
+
+	if (needed == _TRUE)
+		rtw_dfs_master_enable(adapter, u_ch, u_bw, u_offset);
+	else
+		rtw_dfs_master_disable(adapter, ld_sta_in_dfs);
+}
+#endif /* CONFIG_DFS_MASTER */
+
+#endif /* CONFIG_AP_MODE */
+
+#ifdef CONFIG_BT_COEXIST
+struct btinfo {
+	u8 cid;
+	u8 len;
+
+	u8 bConnection:1;
+	u8 bSCOeSCO:1;
+	u8 bInQPage:1;
+	u8 bACLBusy:1;
+	u8 bSCOBusy:1;
+	u8 bHID:1;
+	u8 bA2DP:1;
+	u8 bFTP:1;
+
+	u8 retry_cnt:4;
+	u8 rsvd_34:1;
+	u8 rsvd_35:1;
+	u8 rsvd_36:1;
+	u8 rsvd_37:1;
+
+	u8 rssi;
+
+	u8 rsvd_50:1;
+	u8 rsvd_51:1;
+	u8 rsvd_52:1;
+	u8 rsvd_53:1;
+	u8 rsvd_54:1;
+	u8 rsvd_55:1;
+	u8 eSCO_SCO:1;
+	u8 Master_Slave:1;
+
+	u8 rsvd_6;
+	u8 rsvd_7;
+};
+
+void btinfo_evt_dump(void *sel, void *buf)
+{
+	struct btinfo *info = (struct btinfo *)buf;
+	
+	DBG_871X_SEL_NL(sel, "cid:0x%02x, len:%u\n", info->cid, info->len);
+
+	if (info->len > 2)
+		DBG_871X_SEL_NL(sel, "byte2:%s%s%s%s%s%s%s%s\n"
+			, info->bConnection?"bConnection ":""
+			, info->bSCOeSCO?"bSCOeSCO ":""
+			, info->bInQPage?"bInQPage ":""
+			, info->bACLBusy?"bACLBusy ":""
+			, info->bSCOBusy?"bSCOBusy ":""
+			, info->bHID?"bHID ":""
+			, info->bA2DP?"bA2DP ":""
+			, info->bFTP?"bFTP":""
+		);
+
+	if (info->len > 3)
+		DBG_871X_SEL_NL(sel, "retry_cnt:%u\n", info->retry_cnt);
+
+	if (info->len > 4)
+		DBG_871X_SEL_NL(sel, "rssi:%u\n", info->rssi);
+
+	if (info->len > 5)
+		DBG_871X_SEL_NL(sel, "byte5:%s%s\n"
+			, info->eSCO_SCO?"eSCO_SCO ":""
+			, info->Master_Slave?"Master_Slave ":""
+		);
+}
+
+static void rtw_btinfo_hdl(_adapter *adapter, u8 *buf, u16 buf_len)
+{
+	#define BTINFO_WIFI_FETCH 0x23
+	#define BTINFO_BT_AUTO_RPT 0x27
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	struct btinfo_8761ATV *info = (struct btinfo_8761ATV *)buf;
+#else //!CONFIG_BT_COEXIST_SOCKET_TRX
+	struct btinfo *info = (struct btinfo *)buf;
+#endif //CONFIG_BT_COEXIST_SOCKET_TRX
+	u8 cmd_idx;
+	u8 len;
+
+	cmd_idx = info->cid;
+
+	if (info->len > buf_len-2) {
+		rtw_warn_on(1);
+		len = buf_len-2;
+	} else {
+		len = info->len;
+	}
+
+//#define DBG_PROC_SET_BTINFO_EVT
+#ifdef DBG_PROC_SET_BTINFO_EVT
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	DBG_871X("%s: btinfo[0]=%x,btinfo[1]=%x,btinfo[2]=%x,btinfo[3]=%x btinfo[4]=%x,btinfo[5]=%x,btinfo[6]=%x,btinfo[7]=%x\n"
+				, __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+#else//!CONFIG_BT_COEXIST_SOCKET_TRX
+	btinfo_evt_dump(RTW_DBGDUMP, info);
+#endif //CONFIG_BT_COEXIST_SOCKET_TRX
+#endif // DBG_PROC_SET_BTINFO_EVT
+
+	/* transform BT-FW btinfo to WiFI-FW C2H format and notify */
+	if (cmd_idx == BTINFO_WIFI_FETCH)
+		buf[1] = 0;
+	else if (cmd_idx == BTINFO_BT_AUTO_RPT)
+		buf[1] = 2;
+#ifdef CONFIG_BT_COEXIST_SOCKET_TRX
+	else if(0x01 == cmd_idx || 0x02 == cmd_idx)
+		buf[1] = buf[0];
+#endif //CONFIG_BT_COEXIST_SOCKET_TRX
+	rtw_btcoex_BtInfoNotify(adapter ,len+1, &buf[1]);
+}
+
+u8 rtw_btinfo_cmd(_adapter *adapter, u8 *buf, u16 len)
+{
+	struct cmd_obj *ph2c;
+	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+	u8 *btinfo;
+	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if (pdrvextra_cmd_parm == NULL) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	btinfo = rtw_zmalloc(len);
+	if (btinfo == NULL) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		rtw_mfree((u8*)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = BTINFO_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = len;
+	pdrvextra_cmd_parm->pbuf = btinfo;
+
+	_rtw_memcpy(btinfo, buf, len);
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+	return res;
+}
+#endif //CONFIG_BT_COEXIST
+
+//#ifdef CONFIG_C2H_PACKET_EN
+u8 rtw_c2h_packet_wk_cmd(PADAPTER padapter, u8 *pbuf, u16 length)
+{
+	struct cmd_obj *ph2c;
+	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if (pdrvextra_cmd_parm == NULL) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size = length;
+	pdrvextra_cmd_parm->pbuf = pbuf;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+	return res;
+}
+
+//#else //CONFIG_C2H_PACKET_EN
+/* dont call R/W in this function, beucase SDIO interrupt have claim host */
+/* or deadlock will happen and cause special-systemserver-died in android */
+
+u8 rtw_c2h_wk_cmd(PADAPTER padapter, u8 *c2h_evt)
+{
+	struct cmd_obj *ph2c;
+	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (ph2c == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if (pdrvextra_cmd_parm == NULL) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	pdrvextra_cmd_parm->ec_id = C2H_WK_CID;
+	pdrvextra_cmd_parm->type = 0;
+	pdrvextra_cmd_parm->size =  c2h_evt?16:0;
+	pdrvextra_cmd_parm->pbuf = c2h_evt;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	
+exit:
+	
+	return res;
+}
+//#endif //CONFIG_C2H_PACKET_EN
+
+u8 rtw_run_in_thread_cmd(PADAPTER padapter, void (*func)(void*), void* context)
+{
+	struct cmd_priv *pcmdpriv;
+	struct cmd_obj *ph2c;
+	struct RunInThread_param *parm;
+	s32 res = _SUCCESS;
+
+_func_enter_;
+
+	pcmdpriv = &padapter->cmdpriv;
+
+	ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (NULL == ph2c) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	parm = (struct RunInThread_param*)rtw_zmalloc(sizeof(struct RunInThread_param));
+	if (NULL == parm) {
+		rtw_mfree((u8*)ph2c, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	parm->func = func;
+	parm->context = context;
+	init_h2fwcmd_w_parm_no_rsp(ph2c, parm, GEN_CMD_CODE(_RunInThreadCMD));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter)
+{
+	s32 ret = _FAIL;
+	u8 buf[16];
+
+	if (!c2h_evt) {
+		/* No c2h event in cmd_obj, read c2h event before handling*/
+		if (rtw_hal_c2h_evt_read(adapter, buf) == _SUCCESS) {
+			c2h_evt = buf;
+			
+			if (filter && filter(c2h_evt) == _FALSE)
+				goto exit;
+
+			ret = rtw_hal_c2h_handler(adapter, c2h_evt);
+		}
+	} else {
+
+		if (filter && filter(c2h_evt) == _FALSE)
+			goto exit;
+
+		ret = rtw_hal_c2h_handler(adapter, c2h_evt);
+	}
+exit:
+	return ret;
+}
+
+#ifdef CONFIG_C2H_WK
+static void c2h_wk_callback(_workitem *work)
+{
+	struct evt_priv *evtpriv = container_of(work, struct evt_priv, c2h_wk);
+	_adapter *adapter = container_of(evtpriv, _adapter, evtpriv);
+	u8 *c2h_evt;
+	c2h_id_filter ccx_id_filter = rtw_hal_c2h_id_filter_ccx(adapter);
+
+	evtpriv->c2h_wk_alive = _TRUE;
+
+	while (!rtw_cbuf_empty(evtpriv->c2h_queue)) {
+		if ((c2h_evt = (u8 *)rtw_cbuf_pop(evtpriv->c2h_queue)) != NULL) {
+			/* This C2H event is read, clear it */
+			c2h_evt_clear(adapter);
+		} else if ((c2h_evt = (u8 *)rtw_malloc(16)) != NULL) {
+			/* This C2H event is not read, read & clear now */
+			if (rtw_hal_c2h_evt_read(adapter, c2h_evt) != _SUCCESS) {
+				rtw_mfree(c2h_evt, 16);
+				continue;
+			}
+		} else {
+			rtw_warn_on(1);
+			continue;
+		}
+
+		/* Special pointer to trigger c2h_evt_clear only */
+		if ((void *)c2h_evt == (void *)evtpriv)
+			continue;
+
+		if (!rtw_hal_c2h_valid(adapter, c2h_evt)) {
+			rtw_mfree(c2h_evt, 16);
+			continue;
+		}
+		
+		if (ccx_id_filter(c2h_evt) == _TRUE) {
+			/* Handle CCX report here */
+			rtw_hal_c2h_handler(adapter, c2h_evt);
+			rtw_mfree(c2h_evt, 16);
+		} else {
+			/* Enqueue into cmd_thread for others */
+			rtw_c2h_wk_cmd(adapter, c2h_evt);
+		}
+	}
+
+	evtpriv->c2h_wk_alive = _FALSE;
+}
+#endif
+
+u8 session_tracker_cmd(_adapter *adapter, u8 cmd, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
+{
+	struct cmd_priv	*cmdpriv = &adapter->cmdpriv;
+	struct cmd_obj *cmdobj;
+	struct drvextra_cmd_parm *cmd_parm;
+	struct st_cmd_parm *st_parm;
+	u8	res = _SUCCESS;
+
+	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (cmdobj == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if (cmd_parm == NULL) {
+		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	st_parm = (struct st_cmd_parm *)rtw_zmalloc(sizeof(struct st_cmd_parm));
+	if (st_parm == NULL) {
+		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
+		rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
+		res = _FAIL;
+		goto exit;
+	}
+
+	st_parm->cmd = cmd;
+	st_parm->sta = sta;
+	if (cmd != ST_CMD_CHK) {
+		_rtw_memcpy(&st_parm->local_naddr, local_naddr, 4);
+		_rtw_memcpy(&st_parm->local_port, local_port, 2);
+		_rtw_memcpy(&st_parm->remote_naddr, remote_naddr, 4);
+		_rtw_memcpy(&st_parm->remote_port, remote_port, 2);
+	}
+
+	cmd_parm->ec_id = SESSION_TRACKER_WK_CID;
+	cmd_parm->type = 0;
+	cmd_parm->size = sizeof(struct st_cmd_parm);
+	cmd_parm->pbuf = (u8 *)st_parm;
+	init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+	cmdobj->no_io = 1;
+
+	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
+
+exit:
+	return res;
+}
+
+inline u8 session_tracker_chk_cmd(_adapter *adapter, struct sta_info *sta)
+{
+	return session_tracker_cmd(adapter, ST_CMD_CHK, sta, NULL, NULL, NULL, NULL);
+}
+
+inline u8 session_tracker_add_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
+{
+	return session_tracker_cmd(adapter, ST_CMD_ADD, sta, local_naddr, local_port, remote_naddr, remote_port);
+}
+
+inline u8 session_tracker_del_cmd(_adapter *adapter, struct sta_info *sta, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
+{
+	return session_tracker_cmd(adapter, ST_CMD_DEL, sta, local_naddr, local_port, remote_naddr, remote_port);
+}
+
+void session_tracker_chk_for_sta(_adapter *adapter, struct sta_info *sta)
+{
+	struct st_ctl_t *st_ctl = &sta->st_ctl;
+	int i;
+	_irqL irqL;
+	_list *plist, *phead, *pnext;
+	_list dlist;
+	struct session_tracker *st = NULL;
+	u8 op_wfd_mode = MIRACAST_DISABLED;
+
+	if (DBG_SESSION_TRACKER)
+		DBG_871X(FUNC_ADPT_FMT" sta:%p\n", FUNC_ADPT_ARG(adapter), sta);
+
+	if (!(sta->state & _FW_LINKED))
+		goto exit;
+
+	for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
+		if (st_ctl->reg[i].s_proto != 0)
+			break;
+	}
+	if (i >= SESSION_TRACKER_REG_ID_NUM)
+		goto chk_sta;
+
+	_rtw_init_listhead(&dlist);
+
+	_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+
+	phead = &st_ctl->tracker_q.queue;
+	plist = get_next(phead);
+	pnext = get_next(plist);
+	while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+		st = LIST_CONTAINOR(plist, struct session_tracker, list);
+		plist = pnext;
+		pnext = get_next(pnext);
+
+		if (st->status != ST_STATUS_ESTABLISH
+			&& rtw_get_passing_time_ms(st->set_time) > ST_EXPIRE_MS
+		) {
+			rtw_list_delete(&st->list);
+			rtw_list_insert_tail(&st->list, &dlist);
+		}
+
+		/* TODO: check OS for status update */
+		if (st->status == ST_STATUS_CHECK)
+			st->status = ST_STATUS_ESTABLISH;
+
+		if (st->status != ST_STATUS_ESTABLISH)
+			continue;
+
+		#ifdef CONFIG_WFD
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" local:%u, remote:%u, rtsp:%u, %u, %u\n", FUNC_ADPT_ARG(adapter)
+				, ntohs(st->local_port), ntohs(st->remote_port), adapter->wfd_info.rtsp_ctrlport, adapter->wfd_info.tdls_rtsp_ctrlport
+				, adapter->wfd_info.peer_rtsp_ctrlport);
+		if (ntohs(st->local_port) == adapter->wfd_info.rtsp_ctrlport)
+			op_wfd_mode |= MIRACAST_SINK;
+		if (ntohs(st->local_port) == adapter->wfd_info.tdls_rtsp_ctrlport)
+			op_wfd_mode |= MIRACAST_SINK;
+		if (ntohs(st->remote_port) == adapter->wfd_info.peer_rtsp_ctrlport)
+			op_wfd_mode |= MIRACAST_SOURCE;
+		#endif
+	}
+
+	_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+
+	plist = get_next(&dlist);
+	while (rtw_end_of_queue_search(&dlist, plist) == _FALSE) {
+		st = LIST_CONTAINOR(plist, struct session_tracker, list);
+		plist = get_next(plist);
+		rtw_mfree((u8 *)st, sizeof(struct session_tracker));
+	}
+
+chk_sta:
+	if (STA_OP_WFD_MODE(sta) != op_wfd_mode) {
+		STA_SET_OP_WFD_MODE(sta, op_wfd_mode);
+		rtw_sta_media_status_rpt_cmd(adapter, sta, 1);
+	}
+
+exit:
+	return;
+}
+
+void session_tracker_chk_for_adapter(_adapter *adapter)
+{
+	struct sta_priv *stapriv = &adapter->stapriv;
+	struct sta_info *sta;
+	int i;
+	_irqL irqL;
+	_list *plist, *phead;
+	u8 op_wfd_mode = MIRACAST_DISABLED;
+
+	_enter_critical_bh(&stapriv->sta_hash_lock, &irqL);
+
+	for (i = 0; i < NUM_STA; i++) {
+		phead = &(stapriv->sta_hash[i]);
+		plist = get_next(phead);
+
+		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+			sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+			plist = get_next(plist);
+
+			session_tracker_chk_for_sta(adapter, sta);
+
+			op_wfd_mode |= STA_OP_WFD_MODE(sta);
+		}
+	}
+
+	_exit_critical_bh(&stapriv->sta_hash_lock, &irqL);
+
+#ifdef CONFIG_WFD
+	adapter->wfd_info.op_wfd_mode = MIRACAST_MODE_REVERSE(op_wfd_mode);
+#endif
+}
+
+void session_tracker_cmd_hdl(_adapter *adapter, struct st_cmd_parm *parm)
+{
+	u8 cmd = parm->cmd;
+	struct sta_info *sta = parm->sta;
+
+	if (cmd == ST_CMD_CHK) {
+		if (sta)
+			session_tracker_chk_for_sta(adapter, sta);
+		else
+			session_tracker_chk_for_adapter(adapter);
+
+		goto exit;
+
+	} else if (cmd == ST_CMD_ADD || cmd == ST_CMD_DEL) {
+		struct st_ctl_t *st_ctl;
+		u32 local_naddr = parm->local_naddr;
+		u16 local_port = parm->local_port;
+		u32 remote_naddr = parm->remote_naddr;
+		u16 remote_port = parm->remote_port;
+		struct session_tracker *st = NULL;
+		_irqL irqL;
+		_list *plist, *phead;
+		u8 free_st = 0;
+		u8 alloc_st = 0;
+
+		if (DBG_SESSION_TRACKER)
+			DBG_871X(FUNC_ADPT_FMT" cmd:%u, sta:%p, local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT"\n"
+				, FUNC_ADPT_ARG(adapter), cmd, sta
+				, IP_ARG(&local_naddr), PORT_ARG(&local_port)
+				, IP_ARG(&remote_naddr), PORT_ARG(&remote_port)
+			);
+
+		if (!(sta->state & _FW_LINKED))
+			goto exit;
+
+		st_ctl = &sta->st_ctl;
+
+		_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+
+		phead = &st_ctl->tracker_q.queue;
+		plist = get_next(phead);
+		while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+			st = LIST_CONTAINOR(plist, struct session_tracker, list);
+
+			if (st->local_naddr == local_naddr
+				&& st->local_port == local_port
+				&& st->remote_naddr == remote_naddr
+				&& st->remote_port == remote_port)
+				break;
+
+			plist = get_next(plist);
+		}
+
+		if (rtw_end_of_queue_search(phead, plist) == _TRUE)
+			st = NULL;
+
+		switch (cmd) {
+		case ST_CMD_DEL:
+			if (st) {
+				rtw_list_delete(plist);
+				free_st = 1;
+			}
+			goto unlock;
+		case ST_CMD_ADD:
+			if (!st)
+				alloc_st = 1;
+		}
+
+unlock:
+		_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+
+		if (free_st) {
+			rtw_mfree((u8 *)st, sizeof(struct session_tracker));
+			goto exit;
+		}
+
+		if (alloc_st) {
+			st = (struct session_tracker *)rtw_zmalloc(sizeof(struct session_tracker));
+			if (!st)
+				goto exit;
+
+			st->local_naddr = local_naddr;
+			st->local_port = local_port;
+			st->remote_naddr = remote_naddr;
+			st->remote_port = remote_port;
+			st->set_time = rtw_get_current_time();
+			st->status = ST_STATUS_CHECK;
+
+			_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+			rtw_list_insert_tail(&st->list, phead);
+			_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+		}
+	}
+
+exit:
+	return;
+}
+
+u8 rtw_drvextra_cmd_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	struct drvextra_cmd_parm *pdrvextra_cmd;
+
+	if(!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	pdrvextra_cmd = (struct drvextra_cmd_parm*)pbuf;
+	
+	switch (pdrvextra_cmd->ec_id) {
+	case STA_MSTATUS_RPT_WK_CID:
+		rtw_sta_media_status_rpt_cmd_hdl(padapter, (struct sta_media_status_rpt_cmd_parm *)pdrvextra_cmd->pbuf);
+		break;
+
+	case DYNAMIC_CHK_WK_CID:/*only  primary padapter go to this cmd, but execute dynamic_chk_wk_hdl() for two interfaces */
+#ifdef CONFIG_CONCURRENT_MODE
+		if (padapter->pbuddy_adapter)
+			dynamic_chk_wk_hdl(padapter->pbuddy_adapter);
+#endif
+		dynamic_chk_wk_hdl(padapter);
+		break;
+	case POWER_SAVING_CTRL_WK_CID:
+		power_saving_wk_hdl(padapter);
+		break;
+#ifdef CONFIG_LPS
+	case LPS_CTRL_WK_CID:
+		lps_ctrl_wk_hdl(padapter, (u8)pdrvextra_cmd->type);
+		break;
+	case DM_IN_LPS_WK_CID:
+		rtw_dm_in_lps_hdl(padapter);
+		break;
+	case LPS_CHANGE_DTIM_CID:
+		rtw_lps_change_dtim_hdl(padapter, (u8)pdrvextra_cmd->type);
+		break;
+#endif
+#if (RATE_ADAPTIVE_SUPPORT==1)
+	case RTP_TIMER_CFG_WK_CID:
+		rpt_timer_setting_wk_hdl(padapter, pdrvextra_cmd->type);
+		break;
+#endif
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	case ANT_SELECT_WK_CID:
+		antenna_select_wk_hdl(padapter, pdrvextra_cmd->type);
+		break;
+#endif
+#ifdef CONFIG_P2P_PS
+	case P2P_PS_WK_CID:
+		p2p_ps_wk_hdl(padapter, pdrvextra_cmd->type);
+		break;
+#endif
+#ifdef CONFIG_P2P
+	case P2P_PROTO_WK_CID:
+		/*
+		* Commented by Albert 2011/07/01
+		* I used the type_size as the type command
+		*/
+		p2p_protocol_wk_hdl(padapter, pdrvextra_cmd->type);
+		break;
+#endif
+#ifdef CONFIG_AP_MODE
+	case CHECK_HIQ_WK_CID:
+		rtw_chk_hi_queue_hdl(padapter);
+		break;
+#endif
+#ifdef CONFIG_INTEL_WIDI
+	case INTEl_WIDI_WK_CID:
+		intel_widi_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
+		break;
+#endif
+	/* add for CONFIG_IEEE80211W, none 11w can use it */
+	case RESET_SECURITYPRIV:
+		reset_securitypriv_hdl(padapter);
+		break;
+	case FREE_ASSOC_RESOURCES:
+		free_assoc_resources_hdl(padapter);
+		break;
+	case C2H_WK_CID:
+#ifdef CONFIG_C2H_PACKET_EN
+		rtw_hal_set_hwreg_with_buf(padapter, HW_VAR_C2H_HANDLE, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
+#else		
+		c2h_evt_hdl(padapter, pdrvextra_cmd->pbuf, NULL);
+#endif
+		break;
+#ifdef CONFIG_BEAMFORMING
+	case BEAMFORMING_WK_CID:
+		beamforming_wk_hdl(padapter, pdrvextra_cmd->type, pdrvextra_cmd->pbuf);
+		break;
+#endif
+	case DM_RA_MSK_WK_CID:
+		rtw_dm_ra_mask_hdl(padapter, (struct sta_info *)pdrvextra_cmd->pbuf);
+		break;
+#ifdef CONFIG_BT_COEXIST
+	case BTINFO_WK_CID:
+		rtw_btinfo_hdl(padapter, pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
+		break;
+#endif
+#ifdef CONFIG_DFS_MASTER
+	case DFS_MASTER_WK_CID:
+		rtw_dfs_master_hdl(padapter);
+		break;
+#endif
+	case SESSION_TRACKER_WK_CID:
+		session_tracker_cmd_hdl(padapter, (struct st_cmd_parm *)pdrvextra_cmd->pbuf);
+		break;
+	default:
+		break;
+	}
+
+	if (pdrvextra_cmd->pbuf && pdrvextra_cmd->size>0)
+	{
+		rtw_mfree(pdrvextra_cmd->pbuf, pdrvextra_cmd->size);
+	}
+
+	return H2C_SUCCESS;
+}
+
+void rtw_survey_cmd_callback(_adapter*	padapter ,  struct cmd_obj *pcmd)
+{
+	struct 	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+_func_enter_;
+
+	if(pcmd->res == H2C_DROPPED)
+	{
+		//TODO: cancel timer and do timeout handler directly...
+		//need to make timeout handlerOS independent
+		mlme_set_scan_to_timer(pmlmepriv, 1);
+	}
+	else if (pcmd->res != H2C_SUCCESS) {
+		mlme_set_scan_to_timer(pmlmepriv, 1);
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\n ********Error: MgntActrtw_set_802_11_bssid_LIST_SCAN Fail ************\n\n."));
+	} 
+
+	// free cmd
+	rtw_free_cmd_obj(pcmd);
+
+_func_exit_;	
+}
+void rtw_disassoc_cmd_callback(_adapter*	padapter,  struct cmd_obj *pcmd)
+{
+	_irqL	irqL;
+	struct 	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	
+_func_enter_;	
+
+	if (pcmd->res != H2C_SUCCESS)
+	{
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);
+		set_fwstate(pmlmepriv, _FW_LINKED);
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+				
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\n ***Error: disconnect_cmd_callback Fail ***\n."));
+
+		goto exit;
+	}
+#ifdef CONFIG_BR_EXT
+	else //clear bridge database
+		nat25_db_cleanup(padapter);
+#endif //CONFIG_BR_EXT
+
+	// free cmd
+	rtw_free_cmd_obj(pcmd);
+	
+exit:
+	
+_func_exit_;	
+}
+
+
+void rtw_getmacreg_cmdrsp_callback(_adapter *padapter,  struct cmd_obj *pcmd)
+{
+
+_func_enter_;
+
+	rtw_free_cmd_obj(pcmd);
+
+_func_exit_;
+}
+
+void rtw_joinbss_cmd_callback(_adapter*	padapter,  struct cmd_obj *pcmd)
+{
+	struct 	mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+_func_enter_;	
+
+	if(pcmd->res == H2C_DROPPED)
+	{
+		//TODO: cancel timer and do timeout handler directly...
+		//need to make timeout handlerOS independent
+		_set_timer(&pmlmepriv->assoc_timer, 1);
+	}
+	else if(pcmd->res != H2C_SUCCESS)
+	{
+		_set_timer(&pmlmepriv->assoc_timer, 1);
+	}
+
+	rtw_free_cmd_obj(pcmd);
+	
+_func_exit_;	
+}
+
+void rtw_create_ibss_post_hdl(_adapter *padapter, int status)
+{	
+	_irqL irqL;
+	u8 timer_cancelled;
+	struct sta_info *psta = NULL;
+	struct wlan_network *pwlan = NULL;		
+	struct 	mlme_priv *pmlmepriv = &padapter->mlmepriv;	
+	WLAN_BSSID_EX *pdev_network = &padapter->registrypriv.dev_network;
+	struct wlan_network *mlme_cur_network = &(pmlmepriv->cur_network);
+
+	if (status != H2C_SUCCESS)
+		_set_timer(&pmlmepriv->assoc_timer, 1);
+
+	_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	{	
+		_irqL irqL;
+
+		pwlan = _rtw_alloc_network(pmlmepriv);
+		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		if (pwlan == NULL) {
+			pwlan = rtw_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
+			if (pwlan == NULL) {
+				RT_TRACE(_module_rtl871x_cmd_c_, _drv_err_, ("Error:  can't get pwlan in rtw_joinbss_event_callback\n"));
+				_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+				goto createbss_cmd_fail;
+			}
+			pwlan->last_scanned = rtw_get_current_time();
+		} else {
+			rtw_list_insert_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
+		}
+
+		pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
+		_rtw_memcpy(&(pwlan->network), pdev_network, pdev_network->Length);
+		//pwlan->fixed = _TRUE;
+
+		/* copy pdev_network information to pmlmepriv->cur_network */
+		_rtw_memcpy(&mlme_cur_network->network, pdev_network, (get_WLAN_BSSID_EX_sz(pdev_network)));
+
+		#if 0
+		/* reset DSConfig */
+		mlme_cur_network->network.Configuration.DSConfig = (u32)rtw_ch2freq(pdev_network->Configuration.DSConfig);
+		#endif
+
+		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		/* we will set _FW_LINKED when there is one more sat to join us (rtw_stassoc_event_callback) */
+	}
+
+createbss_cmd_fail:
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+exit:
+	return;
+}
+
+
+
+void rtw_setstaKey_cmdrsp_callback(_adapter*	padapter ,  struct cmd_obj *pcmd)
+{
+	
+	struct sta_priv * pstapriv = &padapter->stapriv;
+	struct set_stakey_rsp* psetstakey_rsp = (struct set_stakey_rsp*) (pcmd->rsp);
+	struct sta_info*	psta = rtw_get_stainfo(pstapriv, psetstakey_rsp->addr);
+
+_func_enter_;	
+
+	if(psta==NULL)
+	{
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nERROR: rtw_setstaKey_cmdrsp_callback => can't get sta_info \n\n"));
+		goto exit;
+	}
+	
+	//psta->aid = psta->mac_id = psetstakey_rsp->keyid; //CAM_ID(CAM_ENTRY)
+	
+exit:	
+
+	rtw_free_cmd_obj(pcmd);
+	
+_func_exit_;	
+
+}
+void rtw_setassocsta_cmdrsp_callback(_adapter*	padapter,  struct cmd_obj *pcmd)
+{
+	_irqL	irqL;
+	struct sta_priv * pstapriv = &padapter->stapriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;	
+	struct set_assocsta_parm* passocsta_parm = (struct set_assocsta_parm*)(pcmd->parmbuf);
+	struct set_assocsta_rsp* passocsta_rsp = (struct set_assocsta_rsp*) (pcmd->rsp);		
+	struct sta_info*	psta = rtw_get_stainfo(pstapriv, passocsta_parm->addr);
+
+_func_enter_;	
+	
+	if(psta==NULL)
+	{
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nERROR: setassocsta_cmdrsp_callbac => can't get sta_info \n\n"));
+		goto exit;
+	}
+	
+	psta->aid = psta->mac_id = passocsta_rsp->cam_id;
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE))           	
+		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+	set_fwstate(pmlmepriv, _FW_LINKED);
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+exit:
+	rtw_free_cmd_obj(pcmd);
+
+_func_exit_;
+}
+
+void rtw_getrttbl_cmd_cmdrsp_callback(_adapter*	padapter,  struct cmd_obj *pcmd);
+void rtw_getrttbl_cmd_cmdrsp_callback(_adapter*	padapter,  struct cmd_obj *pcmd)
+{
+_func_enter_;
+
+	rtw_free_cmd_obj(pcmd);
+#ifdef CONFIG_MP_INCLUDED
+	if (padapter->registrypriv.mp_mode == 1)
+		padapter->mppriv.workparam.bcompleted=_TRUE;
+#endif
+
+_func_exit_;
+
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_debug.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_debug.c
new file mode 100644
index 000000000..3f32a8595
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_debug.c
@@ -0,0 +1,3864 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_DEBUG_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+u32 GlobalDebugLevel = _drv_err_;
+
+#ifdef CONFIG_DEBUG_RTL871X
+
+	u64 GlobalDebugComponents = \
+			_module_rtl871x_xmit_c_ |
+			_module_xmit_osdep_c_ |
+			_module_rtl871x_recv_c_ |
+			_module_recv_osdep_c_ |
+			_module_rtl871x_mlme_c_ |
+			_module_mlme_osdep_c_ |
+			_module_rtl871x_sta_mgt_c_ |
+			_module_rtl871x_cmd_c_ |
+			_module_cmd_osdep_c_ |
+			_module_rtl871x_io_c_ |
+			_module_io_osdep_c_ |
+			_module_os_intfs_c_|
+			_module_rtl871x_security_c_|
+			_module_rtl871x_eeprom_c_|
+			_module_hal_init_c_|
+			_module_hci_hal_init_c_|
+			_module_rtl871x_ioctl_c_|
+			_module_rtl871x_ioctl_set_c_|
+			_module_rtl871x_ioctl_query_c_|
+			_module_rtl871x_pwrctrl_c_|
+			_module_hci_intfs_c_|
+			_module_hci_ops_c_|
+			_module_hci_ops_os_c_|
+			_module_rtl871x_ioctl_os_c|
+			_module_rtl8712_cmd_c_|
+			_module_hal_xmit_c_|
+			_module_rtl8712_recv_c_ |
+			_module_mp_ |
+			_module_efuse_;
+
+#endif /* CONFIG_DEBUG_RTL871X */
+
+#include <rtw_version.h>
+
+#ifdef CONFIG_TDLS
+#define TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE	41
+#endif
+
+void dump_drv_version(void *sel)
+{
+	DBG_871X_SEL_NL(sel, "%s %s\n", DRV_NAME, DRIVERVERSION);
+	DBG_871X_SEL_NL(sel, "build time: %s %s\n", __DATE__, __TIME__);
+}
+
+void dump_drv_cfg(void *sel)
+{
+	char *kernel_version = utsname()->release;
+	
+	DBG_871X_SEL_NL(sel, "\nKernel Version: %s\n", kernel_version);
+	DBG_871X_SEL_NL(sel, "Driver Version: %s\n", DRIVERVERSION);
+	DBG_871X_SEL_NL(sel, "------------------------------------------------\n");
+#ifdef CONFIG_IOCTL_CFG80211
+	DBG_871X_SEL_NL(sel, "CFG80211\n");
+	#ifdef RTW_USE_CFG80211_STA_EVENT
+	DBG_871X_SEL_NL(sel, "RTW_USE_CFG80211_STA_EVENT\n");
+	#endif
+#else
+	DBG_871X_SEL_NL(sel, "WEXT\n");
+#endif
+
+	DBG_871X_SEL_NL(sel, "DBG:%d\n", DBG);
+#ifdef CONFIG_DEBUG
+	DBG_871X_SEL_NL(sel, "CONFIG_DEBUG\n");
+#endif
+
+#ifdef CONFIG_CONCURRENT_MODE
+	DBG_871X_SEL_NL(sel, "CONFIG_CONCURRENT_MODE\n");
+#endif
+
+#ifdef CONFIG_POWER_SAVING
+	DBG_871X_SEL_NL(sel, "CONFIG_POWER_SAVING\n");
+#endif
+
+#ifdef CONFIG_LOAD_PHY_PARA_FROM_FILE
+	DBG_871X_SEL_NL(sel, "LOAD_PHY_PARA_FROM_FILE - REALTEK_CONFIG_PATH=%s\n", REALTEK_CONFIG_PATH);
+	#ifdef CONFIG_CALIBRATE_TX_POWER_BY_REGULATORY
+	DBG_871X_SEL_NL(sel, "CONFIG_CALIBRATE_TX_POWER_BY_REGULATORY\n");
+	#endif
+	#ifdef CONFIG_CALIBRATE_TX_POWER_TO_MAX
+	DBG_871X_SEL_NL(sel, "CONFIG_CALIBRATE_TX_POWER_TO_MAX\n");
+	#endif
+#endif
+
+#ifdef CONFIG_DISABLE_ODM
+	DBG_871X_SEL_NL(sel, "CONFIG_DISABLE_ODM\n");
+#endif
+
+#ifdef CONFIG_MINIMAL_MEMORY_USAGE
+	DBG_871X_SEL_NL(sel, "CONFIG_MINIMAL_MEMORY_USAGE\n");
+#endif
+
+	DBG_871X_SEL_NL(sel, "CONFIG_RTW_ADAPTIVITY_EN = %d\n", CONFIG_RTW_ADAPTIVITY_EN);
+#if (CONFIG_RTW_ADAPTIVITY_EN)
+	DBG_871X_SEL_NL(sel, "ADAPTIVITY_MODE = %s\n", (CONFIG_RTW_ADAPTIVITY_MODE) ? "carrier_sense" : "normal");
+#endif
+
+#ifdef CONFIG_WOWLAN
+	DBG_871X_SEL_NL(sel, "CONFIG_WOWLAN - ");
+
+	#ifdef CONFIG_GPIO_WAKEUP
+	DBG_871X_SEL_NL(sel, "CONFIG_GPIO_WAKEUP - WAKEUP_GPIO_IDX:%d\n", WAKEUP_GPIO_IDX);
+	#endif
+#endif
+
+#ifdef CONFIG_TDLS
+	DBG_871X_SEL_NL(sel, "CONFIG_TDLS\n");
+#endif
+
+#ifdef CONFIG_USB_HCI
+	#ifdef CONFIG_SUPPORT_USB_INT	
+	DBG_871X_SEL_NL(sel, "CONFIG_SUPPORT_USB_INT\n");
+	#endif
+	#ifdef CONFIG_USB_INTERRUPT_IN_PIPE		
+	DBG_871X_SEL_NL(sel, "CONFIG_USB_INTERRUPT_IN_PIPE\n");
+	#endif
+	#ifdef CONFIG_USB_TX_AGGREGATION
+	DBG_871X_SEL_NL(sel, "CONFIG_USB_TX_AGGREGATION\n");
+	#endif
+	#ifdef CONFIG_USB_RX_AGGREGATION
+	DBG_871X_SEL_NL(sel, "CONFIG_USB_RX_AGGREGATION\n");
+	#endif
+	#ifdef CONFIG_USE_USB_BUFFER_ALLOC_TX
+	DBG_871X_SEL_NL(sel, "CONFIG_USE_USB_BUFFER_ALLOC_TX\n");
+	#endif
+	#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+	DBG_871X_SEL_NL(sel, "CONFIG_USE_USB_BUFFER_ALLOC_RX\n");
+	#endif	
+	#ifdef CONFIG_PREALLOC_RECV_SKB
+	DBG_871X_SEL_NL(sel, "CONFIG_PREALLOC_RECV_SKB\n");
+	#endif
+	#ifdef CONFIG_FIX_NR_BULKIN_BUFFER
+	DBG_871X_SEL_NL(sel, "CONFIG_FIX_NR_BULKIN_BUFFER\n");
+	#endif
+#endif /*CONFIG_USB_HCI*/
+	
+#ifdef CONFIG_SDIO_HCI
+	#ifdef CONFIG_TX_AGGREGATION
+	DBG_871X_SEL_NL(sel, "CONFIG_TX_AGGREGATION\n");
+	#endif
+	#ifdef CONFIG_RX_AGGREGATION
+	DBG_871X_SEL_NL(sel, "CONFIG_RX_AGGREGATION\n");
+	#endif
+#endif /*CONFIG_SDIO_HCI*/
+
+#ifdef CONFIG_PCI_HCI
+#endif
+	
+	DBG_871X_SEL_NL(sel, "MAX_XMITBUF_SZ = %d\n", MAX_XMITBUF_SZ);
+	DBG_871X_SEL_NL(sel, "MAX_RECVBUF_SZ = %d\n", MAX_RECVBUF_SZ);
+	
+}
+
+void dump_log_level(void *sel)
+{
+	DBG_871X_SEL_NL(sel, "log_level:%d\n", GlobalDebugLevel);
+}
+
+#ifdef CONFIG_SDIO_HCI
+void sd_f0_reg_dump(void *sel, _adapter *adapter)
+{
+	int i;
+
+	for(i=0x0;i<=0xff;i++)
+	{	
+		if(i%16==0)
+			DBG_871X_SEL_NL(sel, "0x%02x ",i);
+
+		DBG_871X_SEL(sel, "%02x ", rtw_sd_f0_read8(adapter, i));
+
+		if(i%16==15)
+			DBG_871X_SEL(sel, "\n");
+		else if(i%8==7)
+			DBG_871X_SEL(sel, "\t");
+	}
+}
+
+void sdio_local_reg_dump(void *sel, _adapter *adapter)
+{
+	int i, j = 1;
+
+	for (i = 0x0; i < 0x100; i += 4) {
+		if (j % 4 == 1)
+			DBG_871X_SEL_NL(sel, "0x%02x", i);
+		DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter, (0x1025 << 16) | i));
+		if ((j++) % 4 == 0)
+			DBG_871X_SEL(sel, "\n");
+	}
+}
+#endif /* CONFIG_SDIO_HCI */
+
+void mac_reg_dump(void *sel, _adapter *adapter)
+{
+	int i, j = 1;
+
+	DBG_871X_SEL_NL(sel, "======= MAC REG =======\n");
+
+	for(i=0x0;i<0x800;i+=4)
+	{
+		if(j%4==1)
+			DBG_871X_SEL_NL(sel, "0x%03x",i);
+		DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter,i));
+		if((j++)%4 == 0)
+			DBG_871X_SEL(sel, "\n");
+	}
+	
+#ifdef CONFIG_RTL8814A
+	{
+		for(i=0x1000;i<0x1650;i+=4)
+		{
+			if(j%4==1)
+				DBG_871X_SEL_NL(sel, "0x%03x",i);
+			DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter,i));
+			if((j++)%4 == 0)
+				DBG_871X_SEL(sel, "\n");
+		}
+	}
+#endif /* CONFIG_RTL8814A */
+}
+
+void bb_reg_dump(void *sel, _adapter *adapter)
+{
+	int i, j = 1;
+
+	DBG_871X_SEL_NL(sel, "======= BB REG =======\n");
+	for(i=0x800;i<0x1000;i+=4)
+	{
+		if(j%4==1)
+			DBG_871X_SEL_NL(sel, "0x%03x",i);
+		DBG_871X_SEL(sel, " 0x%08x ", rtw_read32(adapter,i));
+		if((j++)%4 == 0)
+			DBG_871X_SEL(sel, "\n");
+	}
+}
+
+void rf_reg_dump(void *sel, _adapter *adapter)
+{
+	int i, j = 1, path;
+	u32 value;
+	u8 rf_type = 0;
+	u8 path_nums = 0;
+
+	rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	if((RF_1T2R == rf_type) ||(RF_1T1R ==rf_type ))
+		path_nums = 1;
+	else
+		path_nums = 2;
+
+	DBG_871X_SEL_NL(sel, "======= RF REG =======\n");
+
+	for (path=0;path<path_nums;path++) {
+		DBG_871X_SEL_NL(sel, "RF_Path(%x)\n",path);
+		for (i=0;i<0x100;i++) {
+			value = rtw_hal_read_rfreg(adapter, path, i, 0xffffffff);
+			if(j%4==1)
+				DBG_871X_SEL_NL(sel, "0x%02x ",i);
+			DBG_871X_SEL(sel, " 0x%08x ",value);
+			if((j++)%4==0)
+				DBG_871X_SEL(sel, "\n");
+		}
+	}
+}
+
+static u8 fwdl_test_chksum_fail = 0;
+static u8 fwdl_test_wintint_rdy_fail = 0;
+
+bool rtw_fwdl_test_trigger_chksum_fail(void)
+{
+	if (fwdl_test_chksum_fail) {
+		DBG_871X_LEVEL(_drv_always_, "fwdl test case: trigger chksum_fail\n");
+		fwdl_test_chksum_fail--;
+		return _TRUE;
+	}
+	return _FALSE;
+}
+
+bool rtw_fwdl_test_trigger_wintint_rdy_fail(void)
+{
+	if (fwdl_test_wintint_rdy_fail) {
+		DBG_871X_LEVEL(_drv_always_, "fwdl test case: trigger wintint_rdy_fail\n");
+		fwdl_test_wintint_rdy_fail--;
+		return _TRUE;
+	}
+	return _FALSE;
+}
+
+static u32 g_wait_hiq_empty_ms = 0;
+
+u32 rtw_get_wait_hiq_empty_ms(void)
+{
+	return g_wait_hiq_empty_ms;
+}
+
+static u8 del_rx_ampdu_test_no_tx_fail = 0;
+
+bool rtw_del_rx_ampdu_test_trigger_no_tx_fail(void)
+{
+	if (del_rx_ampdu_test_no_tx_fail) {
+		DBG_871X_LEVEL(_drv_always_, "del_rx_ampdu test case: trigger no_tx_fail\n");
+		del_rx_ampdu_test_no_tx_fail--;
+		return _TRUE;
+	}
+	return _FALSE;
+}
+
+void rtw_sink_rtp_seq_dbg( _adapter *adapter,_pkt *pkt)
+{
+	struct recv_priv *precvpriv = &(adapter->recvpriv);
+	if( precvpriv->sink_udpport > 0)
+	{
+		if(*((u16*)((pkt->data)+0x24)) == cpu_to_be16(precvpriv->sink_udpport))
+		{
+			precvpriv->pre_rtp_rxseq= precvpriv->cur_rtp_rxseq;
+			precvpriv->cur_rtp_rxseq = be16_to_cpu(*((u16*)((pkt->data)+0x2C)));
+			if( precvpriv->pre_rtp_rxseq+1 != precvpriv->cur_rtp_rxseq)
+				DBG_871X("%s : RTP Seq num from %d to %d\n",__FUNCTION__,precvpriv->pre_rtp_rxseq,precvpriv->cur_rtp_rxseq);
+		}
+	}
+}
+
+void sta_rx_reorder_ctl_dump(void *sel, struct sta_info *sta)
+{
+	struct recv_reorder_ctrl *reorder_ctl;
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		reorder_ctl = &sta->recvreorder_ctrl[i];
+		if (reorder_ctl->ampdu_size != RX_AMPDU_SIZE_INVALID || reorder_ctl->indicate_seq != 0xFFFF) {
+			DBG_871X_SEL_NL(sel, "tid=%d, enable=%d, ampdu_size=%u, indicate_seq=%u\n"
+				, i, reorder_ctl->enable, reorder_ctl->ampdu_size, reorder_ctl->indicate_seq
+			);
+		}
+	}
+}
+
+void dump_adapters_status(void *sel, struct dvobj_priv *dvobj)
+{
+	struct rf_ctl_t *rfctl = dvobj_to_rfctl(dvobj);
+	int i;
+	_adapter *iface;
+	u8 u_ch, u_bw, u_offset;
+
+	DBG_871X_SEL_NL(sel, "%-2s %-8s %-17s %-4s %-7s %s\n"
+		, "id", "ifname", "macaddr", "port", "ch", "status");
+
+	DBG_871X_SEL_NL(sel, "------------------------------------------\n");
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		if (iface) {
+			DBG_871X_SEL_NL(sel, "%2d %-8s "MAC_FMT" %4hhu %3u,%u,%u "MLME_STATE_FMT" %s%s\n"
+				, i, ADPT_ARG(iface)
+				, MAC_ARG(adapter_mac_addr(iface))
+				, get_iface_type(iface)
+				, iface->mlmeextpriv.cur_channel
+				, iface->mlmeextpriv.cur_bwmode
+				, iface->mlmeextpriv.cur_ch_offset
+				, MLME_STATE_ARG(iface)
+				, rtw_is_surprise_removed(iface)?" SR":""
+				, rtw_is_drv_stopped(iface)?" DS":""
+			);
+		}
+	}
+
+	DBG_871X_SEL_NL(sel, "------------------------------------------\n");
+
+	rtw_get_ch_setting_union(dvobj->padapters[IFACE_ID0], &u_ch, &u_bw, &u_offset);
+	DBG_871X_SEL_NL(sel, "%34s %3u,%u,%u\n"
+		, "union:"
+		, u_ch, u_bw, u_offset
+	);
+
+	DBG_871X_SEL_NL(sel, "%34s %3u,%u,%u\n"
+		, "oper:"
+		, dvobj->oper_channel
+		, dvobj->oper_bwmode
+		, dvobj->oper_ch_offset
+	);
+
+	#ifdef CONFIG_DFS_MASTER
+	if (rfctl->radar_detect_ch != 0) {
+		DBG_871X_SEL_NL(sel, "%34s %3u,%u,%u"
+			, "radar_detect:"
+			, rfctl->radar_detect_ch
+			, rfctl->radar_detect_bw
+			, rfctl->radar_detect_offset
+		);
+
+		if (IS_UNDER_CAC(rfctl))
+			DBG_871X_SEL(sel, ", cac:%d\n", rtw_systime_to_ms(rfctl->cac_end_time - rtw_get_current_time()));
+		else
+			DBG_871X_SEL(sel, "\n");
+	}
+	#endif
+}
+
+#define SEC_CAM_ENT_ID_TITLE_FMT "%-2s"
+#define SEC_CAM_ENT_ID_TITLE_ARG "id"
+#define SEC_CAM_ENT_ID_VALUE_FMT "%2u"
+#define SEC_CAM_ENT_ID_VALUE_ARG(id) (id)
+
+#define SEC_CAM_ENT_TITLE_FMT "%-6s %-17s %-32s %-3s %-7s %-2s %-2s %-5s"
+#define SEC_CAM_ENT_TITLE_ARG "ctrl", "addr", "key", "kid", "type", "MK", "GK", "valid"
+#define SEC_CAM_ENT_VALUE_FMT "0x%04x "MAC_FMT" "KEY_FMT" %3u %-7s %2u %2u %5u"
+#define SEC_CAM_ENT_VALUE_ARG(ent) \
+	(ent)->ctrl \
+	, MAC_ARG((ent)->mac) \
+	, KEY_ARG((ent)->key) \
+	, ((ent)->ctrl) & 0x03 \
+	, security_type_str((((ent)->ctrl) >> 2) & 0x07) \
+	, (((ent)->ctrl) >> 5) & 0x01 \
+	, (((ent)->ctrl) >> 6) & 0x01 \
+	, (((ent)->ctrl) >> 15) & 0x01
+
+void dump_sec_cam_ent(void *sel, struct sec_cam_ent *ent, int id)
+{
+	if (id >= 0) {
+		DBG_871X_SEL_NL(sel, SEC_CAM_ENT_ID_VALUE_FMT " " SEC_CAM_ENT_VALUE_FMT"\n"
+			, SEC_CAM_ENT_ID_VALUE_ARG(id), SEC_CAM_ENT_VALUE_ARG(ent));
+	} else {
+		DBG_871X_SEL_NL(sel, SEC_CAM_ENT_VALUE_FMT"\n", SEC_CAM_ENT_VALUE_ARG(ent));
+	}
+}
+
+void dump_sec_cam_ent_title(void *sel, u8 has_id)
+{
+	if (has_id) {
+		DBG_871X_SEL_NL(sel, SEC_CAM_ENT_ID_TITLE_FMT " " SEC_CAM_ENT_TITLE_FMT"\n"
+			, SEC_CAM_ENT_ID_TITLE_ARG, SEC_CAM_ENT_TITLE_ARG);
+	} else {
+		DBG_871X_SEL_NL(sel, SEC_CAM_ENT_TITLE_FMT"\n", SEC_CAM_ENT_TITLE_ARG);
+	}
+}
+
+void dump_sec_cam(void *sel, _adapter *adapter)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	struct sec_cam_ent ent;
+	int i;
+
+	DBG_871X_SEL_NL(sel, "HW sec cam:\n");
+	dump_sec_cam_ent_title(sel, 1);
+	for (i = 0; i < cam_ctl->num; i++) {
+		rtw_sec_read_cam_ent(adapter, i, (u8 *)(&ent.ctrl), ent.mac, ent.key);
+		dump_sec_cam_ent(sel , &ent, i);
+	}
+}
+
+#ifdef CONFIG_PROC_DEBUG
+ssize_t proc_set_write_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u32 addr, val, len;
+
+	if (count < 3)
+	{
+		DBG_871X("argument size is less than 3\n");
+		return -EFAULT;
+	}	
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%x %x %x", &addr, &val, &len);
+
+		if (num !=  3) {
+			DBG_871X("invalid write_reg parameter!\n");
+			return count;
+		}
+
+		switch(len)
+		{
+			case 1:
+				rtw_write8(padapter, addr, (u8)val);				
+				break;
+			case 2:
+				rtw_write16(padapter, addr, (u16)val);				
+				break;
+			case 4:
+				rtw_write32(padapter, addr, val);				
+				break;
+			default:
+				DBG_871X("error write length=%d", len);
+				break;
+		}			
+		
+	}
+	
+	return count;
+	
+}
+
+static u32 proc_get_read_addr=0xeeeeeeee;
+static u32 proc_get_read_len=0x4;
+
+int proc_get_read_reg(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	if (proc_get_read_addr==0xeeeeeeee) {
+		DBG_871X_SEL_NL(m, "address not initialized\n");
+		return 0;
+	}	
+
+	switch(proc_get_read_len)
+	{
+		case 1:			
+			DBG_871X_SEL_NL(m, "rtw_read8(0x%x)=0x%x\n", proc_get_read_addr, rtw_read8(padapter, proc_get_read_addr));
+			break;
+		case 2:
+			DBG_871X_SEL_NL(m, "rtw_read16(0x%x)=0x%x\n", proc_get_read_addr, rtw_read16(padapter, proc_get_read_addr));
+			break;
+		case 4:
+			DBG_871X_SEL_NL(m, "rtw_read32(0x%x)=0x%x\n", proc_get_read_addr, rtw_read32(padapter, proc_get_read_addr));
+			break;
+		default:
+			DBG_871X_SEL_NL(m, "error read length=%d\n", proc_get_read_len);
+			break;
+	}
+
+	return 0;
+}
+
+ssize_t proc_set_read_reg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	char tmp[16];
+	u32 addr, len;
+
+	if (count < 2)
+	{
+		DBG_871X("argument size is less than 2\n");
+		return -EFAULT;
+	}	
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%x %x", &addr, &len);
+
+		if (num !=  2) {
+			DBG_871X("invalid read_reg parameter!\n");
+			return count;
+		}
+
+		proc_get_read_addr = addr;
+		
+		proc_get_read_len = len;
+	}
+	
+	return count;
+
+}
+
+int proc_get_fwstate(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	DBG_871X_SEL_NL(m, "fwstate=0x%x\n", get_fwstate(pmlmepriv));
+
+	return 0;
+}
+
+int proc_get_sec_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);	
+	struct security_priv *sec = &padapter->securitypriv;
+
+	DBG_871X_SEL_NL(m, "auth_alg=0x%x, enc_alg=0x%x, auth_type=0x%x, enc_type=0x%x\n", 
+						sec->dot11AuthAlgrthm, sec->dot11PrivacyAlgrthm,
+						sec->ndisauthtype, sec->ndisencryptstatus);
+
+	DBG_871X_SEL_NL(m, "hw_decrypted=%d\n", sec->hw_decrypted);
+
+#ifdef DBG_SW_SEC_CNT
+	DBG_871X_SEL_NL(m, "wep_sw_enc_cnt=%llu, %llu, %llu\n"
+		, sec->wep_sw_enc_cnt_bc , sec->wep_sw_enc_cnt_mc, sec->wep_sw_enc_cnt_uc);
+	DBG_871X_SEL_NL(m, "wep_sw_dec_cnt=%llu, %llu, %llu\n"
+		, sec->wep_sw_dec_cnt_bc , sec->wep_sw_dec_cnt_mc, sec->wep_sw_dec_cnt_uc);
+
+	DBG_871X_SEL_NL(m, "tkip_sw_enc_cnt=%llu, %llu, %llu\n"
+		, sec->tkip_sw_enc_cnt_bc , sec->tkip_sw_enc_cnt_mc, sec->tkip_sw_enc_cnt_uc);	
+	DBG_871X_SEL_NL(m, "tkip_sw_dec_cnt=%llu, %llu, %llu\n"
+		, sec->tkip_sw_dec_cnt_bc , sec->tkip_sw_dec_cnt_mc, sec->tkip_sw_dec_cnt_uc);
+
+	DBG_871X_SEL_NL(m, "aes_sw_enc_cnt=%llu, %llu, %llu\n"
+		, sec->aes_sw_enc_cnt_bc , sec->aes_sw_enc_cnt_mc, sec->aes_sw_enc_cnt_uc);
+	DBG_871X_SEL_NL(m, "aes_sw_dec_cnt=%llu, %llu, %llu\n"
+		, sec->aes_sw_dec_cnt_bc , sec->aes_sw_dec_cnt_mc, sec->aes_sw_dec_cnt_uc);
+#endif /* DBG_SW_SEC_CNT */
+
+	return 0;
+}
+
+int proc_get_mlmext_state(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);	
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	DBG_871X_SEL_NL(m, "pmlmeinfo->state=0x%x\n", pmlmeinfo->state);
+
+	return 0;
+}
+
+#ifdef CONFIG_LAYER2_ROAMING
+int proc_get_roam_flags(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	DBG_871X_SEL_NL(m, "0x%02x\n", rtw_roam_flags(adapter));
+
+	return 0;
+}
+
+ssize_t proc_set_roam_flags(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	char tmp[32];
+	u8 flags;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx", &flags);
+
+		if (num == 1)
+			rtw_assign_roam_flags(adapter, flags);
+	}
+	
+	return count;
+	
+}
+
+int proc_get_roam_param(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+
+	DBG_871X_SEL_NL(m, "%12s %12s %11s\n", "rssi_diff_th", "scanr_exp_ms", "scan_int_ms");
+	DBG_871X_SEL_NL(m, "%-12u %-12u %-11u\n"
+		, mlme->roam_rssi_diff_th
+		, mlme->roam_scanr_exp_ms
+		, mlme->roam_scan_int_ms
+	);
+
+	return 0;
+}
+
+ssize_t proc_set_roam_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+
+	char tmp[32];
+	u8 rssi_diff_th;
+	u32 scanr_exp_ms;
+	u32 scan_int_ms;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhu %u %u", &rssi_diff_th, &scanr_exp_ms, &scan_int_ms);
+
+		if (num >= 1)
+			mlme->roam_rssi_diff_th = rssi_diff_th;
+		if (num >= 2)
+			mlme->roam_scanr_exp_ms = scanr_exp_ms;
+		if (num >= 3)
+			mlme->roam_scan_int_ms = scan_int_ms;
+	}
+	
+	return count;
+	
+}
+
+ssize_t proc_set_roam_tgt_addr(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	char tmp[32];
+	u8 addr[ETH_ALEN];
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", addr, addr+1, addr+2, addr+3, addr+4, addr+5);
+		if (num == 6)
+			_rtw_memcpy(adapter->mlmepriv.roam_tgt_addr, addr, ETH_ALEN);
+
+		DBG_871X("set roam_tgt_addr to "MAC_FMT"\n", MAC_ARG(adapter->mlmepriv.roam_tgt_addr));
+	}
+
+	return count;
+}
+#endif /* CONFIG_LAYER2_ROAMING */
+
+int proc_get_qos_option(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	DBG_871X_SEL_NL(m, "qos_option=%d\n", pmlmepriv->qospriv.qos_option);
+
+	return 0;
+}
+
+int proc_get_ht_option(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	
+#ifdef CONFIG_80211N_HT
+	DBG_871X_SEL_NL(m, "ht_option=%d\n", pmlmepriv->htpriv.ht_option);
+#endif //CONFIG_80211N_HT
+
+	return 0;
+}
+
+int proc_get_rf_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);	
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;	
+
+	DBG_871X_SEL_NL(m, "cur_ch=%d, cur_bw=%d, cur_ch_offet=%d\n", 
+					pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
+	
+	DBG_871X_SEL_NL(m, "oper_ch=%d, oper_bw=%d, oper_ch_offet=%d\n", 
+					rtw_get_oper_ch(padapter), rtw_get_oper_bw(padapter),  rtw_get_oper_choffset(padapter));
+
+	return 0;
+}
+
+int proc_get_scan_param(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	struct ss_res *ss = &mlmeext->sitesurvey_res;
+
+#define SCAN_PARAM_TITLE_FMT "%10s"
+#define SCAN_PARAM_VALUE_FMT "%-10u"
+#define SCAN_PARAM_TITLE_ARG , "scan_ch_ms"
+#define SCAN_PARAM_VALUE_ARG , ss->scan_ch_ms
+#ifdef CONFIG_80211N_HT
+	#define SCAN_PARAM_TITLE_FMT_HT " %15s %13s"
+	#define SCAN_PARAM_VALUE_FMT_HT " %-15u %-13u"
+	#define SCAN_PARAM_TITLE_ARG_HT , "rx_ampdu_accept", "rx_ampdu_size"
+	#define SCAN_PARAM_VALUE_ARG_HT , ss->rx_ampdu_accept, ss->rx_ampdu_size
+#else
+	#define SCAN_PARAM_TITLE_FMT_HT ""
+	#define SCAN_PARAM_VALUE_FMT_HT ""
+	#define SCAN_PARAM_TITLE_ARG_HT
+	#define SCAN_PARAM_VALUE_ARG_HT
+#endif
+#ifdef CONFIG_SCAN_BACKOP
+	#define SCAN_PARAM_TITLE_FMT_BACKOP " %9s %12s"
+	#define SCAN_PARAM_VALUE_FMT_BACKOP " %-9u %-12u"
+	#define SCAN_PARAM_TITLE_ARG_BACKOP , "backop_ms", "scan_cnt_max"
+	#define SCAN_PARAM_VALUE_ARG_BACKOP , ss->backop_ms, ss->scan_cnt_max
+#else
+	#define SCAN_PARAM_TITLE_FMT_BACKOP ""
+	#define SCAN_PARAM_VALUE_FMT_BACKOP ""
+	#define SCAN_PARAM_TITLE_ARG_BACKOP
+	#define SCAN_PARAM_VALUE_ARG_BACKOP
+#endif
+
+	DBG_871X_SEL_NL(m,
+		SCAN_PARAM_TITLE_FMT
+		SCAN_PARAM_TITLE_FMT_HT
+		SCAN_PARAM_TITLE_FMT_BACKOP
+		"\n"
+		SCAN_PARAM_TITLE_ARG
+		SCAN_PARAM_TITLE_ARG_HT
+		SCAN_PARAM_TITLE_ARG_BACKOP
+	);
+
+	DBG_871X_SEL_NL(m,
+		SCAN_PARAM_VALUE_FMT
+		SCAN_PARAM_VALUE_FMT_HT
+		SCAN_PARAM_VALUE_FMT_BACKOP
+		"\n"
+		SCAN_PARAM_VALUE_ARG
+		SCAN_PARAM_VALUE_ARG_HT
+		SCAN_PARAM_VALUE_ARG_BACKOP
+	);
+
+	return 0;
+}
+
+ssize_t proc_set_scan_param(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	struct ss_res *ss = &mlmeext->sitesurvey_res;
+
+	char tmp[32] = {0};
+
+u16 scan_ch_ms;
+#define SCAN_PARAM_INPUT_FMT "%hu"
+#define SCAN_PARAM_INPUT_ARG , &scan_ch_ms
+#ifdef CONFIG_80211N_HT
+	u8 rx_ampdu_accept;
+	u8 rx_ampdu_size;
+	#define SCAN_PARAM_INPUT_FMT_HT " %hhu %hhu"
+	#define SCAN_PARAM_INPUT_ARG_HT , &rx_ampdu_accept, &rx_ampdu_size
+#else
+	#define SCAN_PARAM_INPUT_FMT_HT ""
+	#define SCAN_PARAM_INPUT_ARG_HT
+#endif
+#ifdef CONFIG_SCAN_BACKOP
+	u16 backop_ms;
+	u8 scan_cnt_max;
+	#define SCAN_PARAM_INPUT_FMT_BACKOP " %hu %hhu"
+	#define SCAN_PARAM_INPUT_ARG_BACKOP , &backop_ms, &scan_cnt_max
+#else
+	#define SCAN_PARAM_INPUT_FMT_BACKOP ""
+	#define SCAN_PARAM_INPUT_ARG_BACKOP
+#endif
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp,
+			SCAN_PARAM_INPUT_FMT
+			SCAN_PARAM_INPUT_FMT_HT
+			SCAN_PARAM_INPUT_FMT_BACKOP
+			SCAN_PARAM_INPUT_ARG
+			SCAN_PARAM_INPUT_ARG_HT
+			SCAN_PARAM_INPUT_ARG_BACKOP
+		);
+
+		if (num-- > 0)
+			ss->scan_ch_ms = scan_ch_ms;
+		#ifdef CONFIG_80211N_HT
+		if (num-- > 0)
+			ss->rx_ampdu_accept = rx_ampdu_accept;
+		if (num-- > 0)
+			ss->rx_ampdu_size = rx_ampdu_size;
+		#endif
+		#ifdef CONFIG_SCAN_BACKOP
+		if (num-- > 0)
+			ss->backop_ms = backop_ms;
+		if (num-- > 0)
+			ss->scan_cnt_max = scan_cnt_max;
+		#endif
+	}
+	
+	return count;	
+}
+
+int proc_get_scan_abort(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u32 pass_ms;
+
+	pass_ms = rtw_scan_abort_timeout(adapter, 10000);
+
+	DBG_871X_SEL_NL(m, "%u\n", pass_ms);
+
+	return 0;
+}
+
+#ifdef CONFIG_SCAN_BACKOP
+int proc_get_backop_flags_sta(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+
+	DBG_871X_SEL_NL(m, "0x%02x\n", mlmeext_scan_backop_flags_sta(mlmeext));
+
+	return 0;
+}
+
+ssize_t proc_set_backop_flags_sta(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+
+	char tmp[32];
+	u8 flags;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx", &flags);
+
+		if (num == 1)
+			mlmeext_assign_scan_backop_flags_sta(mlmeext, flags);
+	}
+	
+	return count;
+}
+
+int proc_get_backop_flags_ap(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+
+	DBG_871X_SEL_NL(m, "0x%02x\n", mlmeext_scan_backop_flags_ap(mlmeext));
+
+	return 0;
+}
+
+ssize_t proc_set_backop_flags_ap(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+
+	char tmp[32];
+	u8 flags;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx", &flags);
+
+		if (num == 1)
+			mlmeext_assign_scan_backop_flags_ap(mlmeext, flags);
+	}
+	
+	return count;
+}
+
+#endif /* CONFIG_SCAN_BACKOP */
+
+int proc_get_survey_info(struct seq_file *m, void *v)
+{
+	_irqL irqL;
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	_queue	*queue	= &(pmlmepriv->scanned_queue);
+	struct wlan_network	*pnetwork = NULL;
+	_list	*plist, *phead;
+	s32 notify_signal;
+	s16 notify_noise = 0;
+	u16  index = 0, ie_cap = 0;
+	unsigned char *ie_wpa = NULL, *ie_wpa2 = NULL, *ie_wps = NULL;
+	unsigned char *ie_p2p = NULL, *ssid = NULL;
+	char flag_str[64];
+	int ielen = 0;
+	u32 wpsielen = 0;
+
+	_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);	
+	phead = get_list_head(queue);
+	if(!phead)
+		return 0;
+	plist = get_next(phead);
+	if (!plist)
+		return 0;
+
+	DBG_871X_SEL_NL(m, "%5s  %-17s  %3s  %-3s  %-4s  %-4s  %5s  %32s  %32s\n", "index", "bssid", "ch", "RSSI", "SdBm", "Noise", "age", "flag", "ssid");
+	while(1)
+	{
+		if (rtw_end_of_queue_search(phead,plist)== _TRUE)
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+                if (!pnetwork)
+			break;
+	
+		if ( check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE &&
+			is_same_network(&pmlmepriv->cur_network.network, &pnetwork->network, 0)) {
+			notify_signal = translate_percentage_to_dbm(padapter->recvpriv.signal_strength);//dbm
+		} else {
+			notify_signal = translate_percentage_to_dbm(pnetwork->network.PhyInfo.SignalStrength);//dbm
+		}
+
+		#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
+		rtw_hal_get_odm_var(padapter, HAL_ODM_NOISE_MONITOR,&(pnetwork->network.Configuration.DSConfig), &(notify_noise));
+		#endif
+	
+		ie_wpa = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &ielen, pnetwork->network.IELength-12);	
+		ie_wpa2 = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &ielen, pnetwork->network.IELength-12);
+		ie_cap = rtw_get_capability(&pnetwork->network);
+		ie_wps = rtw_get_wps_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength-12, NULL, &wpsielen);
+		ie_p2p = rtw_get_p2p_ie(&pnetwork->network.IEs[12], pnetwork->network.IELength-12, NULL, &ielen);
+		ssid = pnetwork->network.Ssid.Ssid;
+		sprintf(flag_str, "%s%s%s%s%s%s%s",
+					(ie_wpa) ? "[WPA]":"",
+					(ie_wpa2) ? "[WPA2]":"",
+					(!ie_wpa && !ie_wpa && ie_cap & BIT(4)) ? "[WEP]":"",
+					(ie_wps) ? "[WPS]":"",
+					(pnetwork->network.InfrastructureMode == Ndis802_11IBSS) ? "[IBSS]":"",
+					(ie_cap & BIT(0)) ? "[ESS]":"",
+					(ie_p2p) ? "[P2P]":"");
+		DBG_871X_SEL_NL(m, "%5d  "MAC_FMT"  %3d  %3d  %4d  %4d    %5d  %32s  %32s\n", 
+			++index,
+			MAC_ARG(pnetwork->network.MacAddress), 
+			pnetwork->network.Configuration.DSConfig,
+			(int)pnetwork->network.Rssi,
+			notify_signal,
+			notify_noise,
+			rtw_get_passing_time_ms((u32)pnetwork->last_scanned),
+			flag_str,
+			pnetwork->network.Ssid.Ssid);
+		plist = get_next(plist);
+	}
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	return 0;
+}
+
+ssize_t proc_set_survey_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	_irqL irqL;
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	bool need_indicate_scan_done = _FALSE;
+	u8 _status = _FALSE;
+	NDIS_802_11_SSID ssid[RTW_SSID_SCAN_AMOUNT];
+
+	if (count < 1)
+		return -EFAULT;
+
+#ifdef CONFIG_MP_INCLUDED
+		if ((padapter->registrypriv.mp_mode == 1)
+#ifdef CONFIG_CONCURRENT_MODE
+		|| ((padapter->pbuddy_adapter) && (padapter->pbuddy_adapter->registrypriv.mp_mode == 1))
+#endif			
+		){
+			DBG_871X(FUNC_ADPT_FMT ": MP mode block Scan request\n", FUNC_ADPT_ARG(padapter));	
+			goto exit;
+		}
+#endif
+	rtw_ps_deny(padapter, PS_DENY_SCAN);
+	if (_FAIL == rtw_pwr_wakeup(padapter))
+		goto exit;
+
+	if (rtw_is_drv_stopped(padapter)) {
+		DBG_871X("scan abort!! bDriverStopped=_TRUE\n");
+		goto exit;
+	}
+	
+	if (!padapter->bup) {
+		DBG_871X("scan abort!! bup=%d\n", padapter->bup);
+		goto exit;
+	}
+	
+	if (!rtw_is_hw_init_completed(padapter)) {
+		DBG_871X("scan abort!! hw_init_completed=FALSE\n");
+		goto exit;
+	}
+	
+	if (rtw_is_scan_deny(padapter)) {
+		DBG_871X(FUNC_ADPT_FMT  ": scan deny\n", FUNC_ADPT_ARG(padapter));
+		goto exit;
+	}
+	
+	if ((pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE)
+#ifdef CONFIG_CONCURRENT_MODE
+	|| (rtw_get_buddy_bBusyTraffic(padapter) == _TRUE)
+#endif
+	) {
+		DBG_871X("scan abort!! BusyTraffic == _TRUE\n");
+		goto exit;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE) {
+		DBG_8192C("scan abort!! fwstate=0x%x\n", pmlmepriv->fw_state);
+		goto exit;
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (check_buddy_fwstate(padapter,
+		_FW_UNDER_SURVEY|_FW_UNDER_LINKING|WIFI_UNDER_WPS) == _TRUE) {
+		DBG_871X("scan abort!! buddy_fwstate=0x%x\n",
+				get_fwstate(&(padapter->pbuddy_adapter->mlmepriv)));
+		goto exit;
+	}
+#endif
+	_status = rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
+
+exit:
+	rtw_ps_deny_cancel(padapter, PS_DENY_SCAN);
+	return count;
+}
+
+int proc_get_ap_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	struct sta_info *psta;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+	if(psta)
+	{
+		int i;
+		struct recv_reorder_ctrl *preorder_ctrl;
+					
+		DBG_871X_SEL_NL(m, "SSID=%s\n", cur_network->network.Ssid.Ssid);		
+		DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
+		DBG_871X_SEL_NL(m, "cur_channel=%d, cur_bwmode=%d, cur_ch_offset=%d\n", pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);		
+		DBG_871X_SEL_NL(m, "wireless_mode=0x%x, rtsen=%d, cts2slef=%d\n", psta->wireless_mode, psta->rtsen, psta->cts2self);
+		DBG_871X_SEL_NL(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+#ifdef CONFIG_80211N_HT
+		DBG_871X_SEL_NL(m, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);		
+		DBG_871X_SEL_NL(m, "bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
+		DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);	
+		DBG_871X_SEL_NL(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+		DBG_871X_SEL_NL(m, "ldpc_cap=0x%x, stbc_cap=0x%x, beamform_cap=0x%x\n", psta->htpriv.ldpc_cap, psta->htpriv.stbc_cap, psta->htpriv.beamform_cap);
+#endif //CONFIG_80211N_HT
+#ifdef CONFIG_80211AC_VHT
+		DBG_871X_SEL_NL(m, "vht_en=%d, vht_sgi_80m=%d\n", psta->vhtpriv.vht_option, psta->vhtpriv.sgi_80m);
+		DBG_871X_SEL_NL(m, "vht_ldpc_cap=0x%x, vht_stbc_cap=0x%x, vht_beamform_cap=0x%x\n", psta->vhtpriv.ldpc_cap, psta->vhtpriv.stbc_cap, psta->vhtpriv.beamform_cap);
+		DBG_871X_SEL_NL(m, "vht_mcs_map=0x%x, vht_highest_rate=0x%x, vht_ampdu_len=%d\n", *(u16*)psta->vhtpriv.vht_mcs_map, psta->vhtpriv.vht_highest_rate, psta->vhtpriv.ampdu_len);
+#endif
+
+		sta_rx_reorder_ctl_dump(m, psta);
+	}
+	else
+	{							
+		DBG_871X_SEL_NL(m, "can't get sta's macaddr, cur_network's macaddr:" MAC_FMT "\n", MAC_ARG(cur_network->network.MacAddress));
+	}
+
+	return 0;
+}
+
+ssize_t proc_reset_trx_info(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	char cmd[32] = {0};
+	u8 cnt = 0;
+
+	if (count > sizeof(cmd)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(cmd, buffer, count)) {
+		int num = sscanf(cmd, "%hhx", &cnt);
+
+		if (0 == cnt) {
+			pdbgpriv->dbg_rx_ampdu_drop_count = 0;
+			pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0;
+			pdbgpriv->dbg_rx_ampdu_loss_count = 0;
+			pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0;
+			pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0;
+			pdbgpriv->dbg_rx_conflic_mac_addr_cnt = 0;
+		}
+	}
+
+	return count;
+}
+	
+int proc_get_trx_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	int i;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct recv_priv  *precvpriv = &padapter->recvpriv;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	struct hw_xmit *phwxmit;
+
+	dump_os_queue(m, padapter);
+
+	DBG_871X_SEL_NL(m, "free_xmitbuf_cnt=%d, free_xmitframe_cnt=%d\n"
+		, pxmitpriv->free_xmitbuf_cnt, pxmitpriv->free_xmitframe_cnt);
+	DBG_871X_SEL_NL(m, "free_ext_xmitbuf_cnt=%d, free_xframe_ext_cnt=%d\n"
+		, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xframe_ext_cnt);
+	DBG_871X_SEL_NL(m, "free_recvframe_cnt=%d\n"
+		, precvpriv->free_recvframe_cnt);
+
+	for(i = 0; i < 4; i++) 
+	{
+		phwxmit = pxmitpriv->hwxmits + i;
+		DBG_871X_SEL_NL(m, "%d, hwq.accnt=%d\n", i, phwxmit->accnt);
+	}
+
+#ifdef CONFIG_USB_HCI
+	DBG_871X_SEL_NL(m, "rx_urb_pending_cn=%d\n", ATOMIC_READ(&(precvpriv->rx_pending_cnt)));
+#endif
+
+	//Folowing are RX info
+	//Counts of packets whose seq_num is less than preorder_ctrl->indicate_seq, Ex delay, retransmission, redundant packets and so on
+	DBG_871X_SEL_NL(m,"Rx: Counts of Packets Whose Seq_Num Less Than Reorder Control Seq_Num: %llu\n",(unsigned long long)pdbgpriv->dbg_rx_ampdu_drop_count);
+	//How many times the Rx Reorder Timer is triggered.
+	DBG_871X_SEL_NL(m,"Rx: Reorder Time-out Trigger Counts: %llu\n",(unsigned long long)pdbgpriv->dbg_rx_ampdu_forced_indicate_count);
+	//Total counts of packets loss
+	DBG_871X_SEL_NL(m,"Rx: Packet Loss Counts: %llu\n",(unsigned long long)pdbgpriv->dbg_rx_ampdu_loss_count);
+	DBG_871X_SEL_NL(m,"Rx: Duplicate Management Frame Drop Count: %llu\n",(unsigned long long)pdbgpriv->dbg_rx_dup_mgt_frame_drop_count);
+	DBG_871X_SEL_NL(m,"Rx: AMPDU BA window shift Count: %llu\n",(unsigned long long)pdbgpriv->dbg_rx_ampdu_window_shift_cnt);
+	/*The same mac addr counts*/
+	DBG_871X_SEL_NL(m, "Rx: Conflict MAC Address Frames Count: %llu\n", (unsigned long long)pdbgpriv->dbg_rx_conflic_mac_addr_cnt);
+	return 0;
+}
+
+int proc_get_dis_pwt(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 dis_pwt = 0;
+	rtw_hal_get_def_var(padapter, HAL_DEF_DBG_DIS_PWT, &(dis_pwt));
+	DBG_871X_SEL_NL(m, " Tx Power training mode:%s \n",(dis_pwt==_TRUE)?"Disable":"Enable");
+	return 0;
+}
+ssize_t proc_set_dis_pwt(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[4]={0};
+	u8 dis_pwt = 0;
+	
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx", &dis_pwt);
+		DBG_871X("Set Tx Power training mode:%s\n", (dis_pwt == _TRUE)?"Disable":"Enable");
+		
+		if (num >= 1)
+			rtw_hal_set_def_var(padapter, HAL_DEF_DBG_DIS_PWT, &(dis_pwt));
+	}
+
+	return count;
+	
+}
+
+int proc_get_rate_ctl(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	int i;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 data_rate = 0, sgi=0, data_fb = 0;
+		
+	if (adapter->fix_rate != 0xff) {
+		data_rate = adapter->fix_rate & 0x7F;
+		sgi = adapter->fix_rate >>7;
+		data_fb = adapter->data_fb?1:0;
+		DBG_871X_SEL_NL(m, "FIXED %s%s%s\n"
+			, HDATA_RATE(data_rate)
+			, data_rate>DESC_RATE54M?(sgi?" SGI":" LGI"):""
+			, data_fb?" FB":""
+		);
+		DBG_871X_SEL_NL(m, "0x%02x %u\n", adapter->fix_rate, adapter->data_fb);
+	} else {
+		DBG_871X_SEL_NL(m, "RA\n");
+	}
+
+	return 0;
+}
+
+ssize_t proc_set_rate_ctl(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u8 fix_rate;
+	u8 data_fb;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx %hhu", &fix_rate, &data_fb);
+
+		if (num >= 1)
+			adapter->fix_rate = fix_rate;
+		if (num >= 2)
+			adapter->data_fb = data_fb?1:0;
+	}
+
+	return count;
+}
+#ifdef DBG_RX_COUNTER_DUMP
+int proc_get_rx_cnt_dump(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	int i;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+
+	DBG_871X_SEL_NL(m, "BIT0- Dump RX counters of DRV \n");
+	DBG_871X_SEL_NL(m, "BIT1- Dump RX counters of MAC \n");
+	DBG_871X_SEL_NL(m, "BIT2- Dump RX counters of PHY \n");
+	DBG_871X_SEL_NL(m, "BIT3- Dump TRX data frame of DRV \n");
+	DBG_871X_SEL_NL(m, "dump_rx_cnt_mode = 0x%02x \n", adapter->dump_rx_cnt_mode);
+
+	return 0;
+}
+ssize_t proc_set_rx_cnt_dump(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u8 dump_rx_cnt_mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhx", &dump_rx_cnt_mode);
+
+		rtw_dump_phy_rxcnts_preprocess(adapter,dump_rx_cnt_mode);
+		adapter->dump_rx_cnt_mode = dump_rx_cnt_mode;
+		
+	}
+
+	return count;
+}
+#endif
+ssize_t proc_set_fwdl_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	int num;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count))
+		num = sscanf(tmp, "%hhu %hhu", &fwdl_test_chksum_fail, &fwdl_test_wintint_rdy_fail);
+
+	return count;
+}
+
+ssize_t proc_set_del_rx_ampdu_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	int num;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count))
+		num = sscanf(tmp, "%hhu", &del_rx_ampdu_test_no_tx_fail);
+
+	return count;
+}
+
+#ifdef CONFIG_DFS_MASTER
+int proc_get_dfs_master_test_case(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+
+	DBG_871X_SEL_NL(m, "%-24s %-19s\n", "radar_detect_trigger_non", "choose_dfs_ch_first");
+	DBG_871X_SEL_NL(m, "%24hhu %19hhu\n"
+		, rfctl->dbg_dfs_master_radar_detect_trigger_non
+		, rfctl->dbg_dfs_master_choose_dfs_ch_first
+	);
+
+	return 0;
+}
+
+ssize_t proc_set_dfs_master_test_case(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *adapter = (_adapter *)rtw_netdev_priv(dev);
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+	char tmp[32];
+	u8 radar_detect_trigger_non;
+	u8 choose_dfs_ch_first;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		int num = sscanf(tmp, "%hhu %hhu", &radar_detect_trigger_non, &choose_dfs_ch_first);
+
+		if (num >= 1)
+			rfctl->dbg_dfs_master_radar_detect_trigger_non = radar_detect_trigger_non;
+		if (num >= 2)
+			rfctl->dbg_dfs_master_choose_dfs_ch_first = choose_dfs_ch_first;
+	}
+
+	return count;
+}
+#endif /* CONFIG_DFS_MASTER */
+
+ssize_t proc_set_wait_hiq_empty(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	int num;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count))
+		num = sscanf(tmp, "%u", &g_wait_hiq_empty_ms);
+
+	return count;
+}
+
+int proc_get_suspend_resume_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
+
+	DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_cnt=%d\n", pdbgpriv->dbg_sdio_alloc_irq_cnt);
+	DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_cnt=%d\n", pdbgpriv->dbg_sdio_free_irq_cnt);
+	DBG_871X_SEL_NL(m, "dbg_sdio_alloc_irq_error_cnt=%d\n",pdbgpriv->dbg_sdio_alloc_irq_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_sdio_free_irq_error_cnt=%d\n", pdbgpriv->dbg_sdio_free_irq_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_sdio_init_error_cnt=%d\n",pdbgpriv->dbg_sdio_init_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_sdio_deinit_error_cnt=%d\n", pdbgpriv->dbg_sdio_deinit_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_suspend_error_cnt=%d\n", pdbgpriv->dbg_suspend_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_suspend_cnt=%d\n",pdbgpriv->dbg_suspend_cnt);
+	DBG_871X_SEL_NL(m, "dbg_resume_cnt=%d\n", pdbgpriv->dbg_resume_cnt);
+	DBG_871X_SEL_NL(m, "dbg_resume_error_cnt=%d\n", pdbgpriv->dbg_resume_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_deinit_fail_cnt=%d\n",pdbgpriv->dbg_deinit_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_carddisable_cnt=%d\n", pdbgpriv->dbg_carddisable_cnt);
+	DBG_871X_SEL_NL(m, "dbg_ps_insuspend_cnt=%d\n",pdbgpriv->dbg_ps_insuspend_cnt);
+	DBG_871X_SEL_NL(m, "dbg_dev_unload_inIPS_cnt=%d\n", pdbgpriv->dbg_dev_unload_inIPS_cnt);
+	DBG_871X_SEL_NL(m, "dbg_scan_pwr_state_cnt=%d\n", pdbgpriv->dbg_scan_pwr_state_cnt);
+	DBG_871X_SEL_NL(m, "dbg_downloadfw_pwr_state_cnt=%d\n", pdbgpriv->dbg_downloadfw_pwr_state_cnt);
+	DBG_871X_SEL_NL(m, "dbg_carddisable_error_cnt=%d\n", pdbgpriv->dbg_carddisable_error_cnt);
+	DBG_871X_SEL_NL(m, "dbg_fw_read_ps_state_fail_cnt=%d\n", pdbgpriv->dbg_fw_read_ps_state_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_leave_ips_fail_cnt=%d\n", pdbgpriv->dbg_leave_ips_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_leave_lps_fail_cnt=%d\n", pdbgpriv->dbg_leave_lps_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_h2c_leave32k_fail_cnt=%d\n", pdbgpriv->dbg_h2c_leave32k_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_diswow_dload_fw_fail_cnt=%d\n", pdbgpriv->dbg_diswow_dload_fw_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_enwow_dload_fw_fail_cnt=%d\n", pdbgpriv->dbg_enwow_dload_fw_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_ips_drvopen_fail_cnt=%d\n", pdbgpriv->dbg_ips_drvopen_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_poll_fail_cnt=%d\n", pdbgpriv->dbg_poll_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_rpwm_toogle_cnt=%d\n", pdbgpriv->dbg_rpwm_toogle_cnt);
+	DBG_871X_SEL_NL(m, "dbg_rpwm_timeout_fail_cnt=%d\n", pdbgpriv->dbg_rpwm_timeout_fail_cnt);
+	DBG_871X_SEL_NL(m, "dbg_sreset_cnt=%d\n", pdbgpriv->dbg_sreset_cnt);
+
+	return 0;
+}
+
+#ifdef CONFIG_DBG_COUNTER
+
+int proc_get_rx_logs(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct rx_logs *rx_logs = &padapter->rx_logs;
+
+	DBG_871X_SEL_NL(m, 
+		"intf_rx=%d\n"
+		"intf_rx_err_recvframe=%d\n"
+		"intf_rx_err_skb=%d\n"
+		"intf_rx_report=%d\n"
+		"core_rx=%d\n"
+		"core_rx_pre=%d\n"
+		"core_rx_pre_ver_err=%d\n"
+		"core_rx_pre_mgmt=%d\n"
+		"core_rx_pre_mgmt_err_80211w=%d\n"
+		"core_rx_pre_mgmt_err=%d\n"
+		"core_rx_pre_ctrl=%d\n"
+		"core_rx_pre_ctrl_err=%d\n"
+		"core_rx_pre_data=%d\n"
+		"core_rx_pre_data_wapi_seq_err=%d\n"
+		"core_rx_pre_data_wapi_key_err=%d\n"
+		"core_rx_pre_data_handled=%d\n"
+		"core_rx_pre_data_err=%d\n"
+		"core_rx_pre_data_unknown=%d\n"
+		"core_rx_pre_unknown=%d\n"
+		"core_rx_enqueue=%d\n"
+		"core_rx_dequeue=%d\n"
+		"core_rx_post=%d\n"
+		"core_rx_post_decrypt=%d\n"
+		"core_rx_post_decrypt_wep=%d\n"
+		"core_rx_post_decrypt_tkip=%d\n"
+		"core_rx_post_decrypt_aes=%d\n"
+		"core_rx_post_decrypt_wapi=%d\n"
+		"core_rx_post_decrypt_hw=%d\n"
+		"core_rx_post_decrypt_unknown=%d\n"
+		"core_rx_post_decrypt_err=%d\n"
+		"core_rx_post_defrag_err=%d\n"
+		"core_rx_post_portctrl_err=%d\n"
+		"core_rx_post_indicate=%d\n"
+		"core_rx_post_indicate_in_oder=%d\n"
+		"core_rx_post_indicate_reoder=%d\n"
+		"core_rx_post_indicate_err=%d\n"
+		"os_indicate=%d\n"
+		"os_indicate_ap_mcast=%d\n"
+		"os_indicate_ap_forward=%d\n"
+		"os_indicate_ap_self=%d\n"
+		"os_indicate_err=%d\n"
+		"os_netif_ok=%d\n"
+		"os_netif_err=%d\n",
+		rx_logs->intf_rx,
+		rx_logs->intf_rx_err_recvframe,
+		rx_logs->intf_rx_err_skb,
+		rx_logs->intf_rx_report,
+		rx_logs->core_rx,
+		rx_logs->core_rx_pre,
+		rx_logs->core_rx_pre_ver_err,
+		rx_logs->core_rx_pre_mgmt,
+		rx_logs->core_rx_pre_mgmt_err_80211w,
+		rx_logs->core_rx_pre_mgmt_err,
+		rx_logs->core_rx_pre_ctrl,
+		rx_logs->core_rx_pre_ctrl_err,
+		rx_logs->core_rx_pre_data,
+		rx_logs->core_rx_pre_data_wapi_seq_err,
+		rx_logs->core_rx_pre_data_wapi_key_err,
+		rx_logs->core_rx_pre_data_handled,
+		rx_logs->core_rx_pre_data_err,
+		rx_logs->core_rx_pre_data_unknown,
+		rx_logs->core_rx_pre_unknown,
+		rx_logs->core_rx_enqueue,
+		rx_logs->core_rx_dequeue,
+		rx_logs->core_rx_post,
+		rx_logs->core_rx_post_decrypt,
+		rx_logs->core_rx_post_decrypt_wep,
+		rx_logs->core_rx_post_decrypt_tkip,
+		rx_logs->core_rx_post_decrypt_aes,
+		rx_logs->core_rx_post_decrypt_wapi,
+		rx_logs->core_rx_post_decrypt_hw,
+		rx_logs->core_rx_post_decrypt_unknown,
+		rx_logs->core_rx_post_decrypt_err,
+		rx_logs->core_rx_post_defrag_err,
+		rx_logs->core_rx_post_portctrl_err,
+		rx_logs->core_rx_post_indicate,
+		rx_logs->core_rx_post_indicate_in_oder,
+		rx_logs->core_rx_post_indicate_reoder,
+		rx_logs->core_rx_post_indicate_err,
+		rx_logs->os_indicate,
+		rx_logs->os_indicate_ap_mcast,
+		rx_logs->os_indicate_ap_forward,
+		rx_logs->os_indicate_ap_self,
+		rx_logs->os_indicate_err,
+		rx_logs->os_netif_ok,
+		rx_logs->os_netif_err
+	);
+
+	return 0;
+}
+
+int proc_get_tx_logs(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tx_logs *tx_logs = &padapter->tx_logs;
+	
+	DBG_871X_SEL_NL(m,
+		"os_tx=%d\n"
+		"os_tx_err_up=%d\n"
+		"os_tx_err_xmit=%d\n"
+		"os_tx_m2u=%d\n"
+		"os_tx_m2u_ignore_fw_linked=%d\n"
+		"os_tx_m2u_ignore_self=%d\n"
+		"os_tx_m2u_entry=%d\n"
+		"os_tx_m2u_entry_err_xmit=%d\n"
+		"os_tx_m2u_entry_err_skb=%d\n"
+		"os_tx_m2u_stop=%d\n"
+		"core_tx=%d\n"
+		"core_tx_err_pxmitframe=%d\n"
+		"core_tx_err_brtx=%d\n"
+		"core_tx_upd_attrib=%d\n"
+		"core_tx_upd_attrib_adhoc=%d\n"
+		"core_tx_upd_attrib_sta=%d\n"
+		"core_tx_upd_attrib_ap=%d\n"
+		"core_tx_upd_attrib_unknown=%d\n"
+		"core_tx_upd_attrib_dhcp=%d\n"
+		"core_tx_upd_attrib_icmp=%d\n"
+		"core_tx_upd_attrib_active=%d\n"
+		"core_tx_upd_attrib_err_ucast_sta=%d\n"
+		"core_tx_upd_attrib_err_ucast_ap_link=%d\n"
+		"core_tx_upd_attrib_err_sta=%d\n"
+		"core_tx_upd_attrib_err_link=%d\n"
+		"core_tx_upd_attrib_err_sec=%d\n"
+		"core_tx_ap_enqueue_warn_fwstate=%d\n"
+		"core_tx_ap_enqueue_warn_sta=%d\n"
+		"core_tx_ap_enqueue_warn_nosta=%d\n"
+		"core_tx_ap_enqueue_warn_link=%d\n"
+		"core_tx_ap_enqueue_warn_trigger=%d\n"
+		"core_tx_ap_enqueue_mcast=%d\n"
+		"core_tx_ap_enqueue_ucast=%d\n"
+		"core_tx_ap_enqueue=%d\n"
+		"intf_tx=%d\n"
+		"intf_tx_pending_ac=%d\n"
+		"intf_tx_pending_fw_under_survey=%d\n"
+		"intf_tx_pending_fw_under_linking=%d\n"
+		"intf_tx_pending_xmitbuf=%d\n"
+		"intf_tx_enqueue=%d\n"
+		"core_tx_enqueue=%d\n"
+		"core_tx_enqueue_class=%d\n"
+		"core_tx_enqueue_class_err_sta=%d\n"
+		"core_tx_enqueue_class_err_nosta=%d\n"
+		"core_tx_enqueue_class_err_fwlink=%d\n"
+		"intf_tx_direct=%d\n"
+		"intf_tx_direct_err_coalesce=%d\n"
+		"intf_tx_dequeue=%d\n"
+		"intf_tx_dequeue_err_coalesce=%d\n"
+		"intf_tx_dump_xframe=%d\n"
+		"intf_tx_dump_xframe_err_txdesc=%d\n"
+		"intf_tx_dump_xframe_err_port=%d\n",
+		tx_logs->os_tx,
+		tx_logs->os_tx_err_up,
+		tx_logs->os_tx_err_xmit,
+		tx_logs->os_tx_m2u,
+		tx_logs->os_tx_m2u_ignore_fw_linked,
+		tx_logs->os_tx_m2u_ignore_self,
+		tx_logs->os_tx_m2u_entry,
+		tx_logs->os_tx_m2u_entry_err_xmit,
+		tx_logs->os_tx_m2u_entry_err_skb,
+		tx_logs->os_tx_m2u_stop,
+		tx_logs->core_tx,
+		tx_logs->core_tx_err_pxmitframe,
+		tx_logs->core_tx_err_brtx,
+		tx_logs->core_tx_upd_attrib,
+		tx_logs->core_tx_upd_attrib_adhoc,
+		tx_logs->core_tx_upd_attrib_sta,
+		tx_logs->core_tx_upd_attrib_ap,
+		tx_logs->core_tx_upd_attrib_unknown,
+		tx_logs->core_tx_upd_attrib_dhcp,
+		tx_logs->core_tx_upd_attrib_icmp,
+		tx_logs->core_tx_upd_attrib_active,
+		tx_logs->core_tx_upd_attrib_err_ucast_sta,
+		tx_logs->core_tx_upd_attrib_err_ucast_ap_link,
+		tx_logs->core_tx_upd_attrib_err_sta,
+		tx_logs->core_tx_upd_attrib_err_link,
+		tx_logs->core_tx_upd_attrib_err_sec,
+		tx_logs->core_tx_ap_enqueue_warn_fwstate,
+		tx_logs->core_tx_ap_enqueue_warn_sta,
+		tx_logs->core_tx_ap_enqueue_warn_nosta,
+		tx_logs->core_tx_ap_enqueue_warn_link,
+		tx_logs->core_tx_ap_enqueue_warn_trigger,
+		tx_logs->core_tx_ap_enqueue_mcast,
+		tx_logs->core_tx_ap_enqueue_ucast,
+		tx_logs->core_tx_ap_enqueue,
+		tx_logs->intf_tx,
+		tx_logs->intf_tx_pending_ac,
+		tx_logs->intf_tx_pending_fw_under_survey,
+		tx_logs->intf_tx_pending_fw_under_linking,
+		tx_logs->intf_tx_pending_xmitbuf,
+		tx_logs->intf_tx_enqueue,
+		tx_logs->core_tx_enqueue,
+		tx_logs->core_tx_enqueue_class,
+		tx_logs->core_tx_enqueue_class_err_sta,
+		tx_logs->core_tx_enqueue_class_err_nosta,
+		tx_logs->core_tx_enqueue_class_err_fwlink,
+		tx_logs->intf_tx_direct,
+		tx_logs->intf_tx_direct_err_coalesce,
+		tx_logs->intf_tx_dequeue,
+		tx_logs->intf_tx_dequeue_err_coalesce,
+		tx_logs->intf_tx_dump_xframe,
+		tx_logs->intf_tx_dump_xframe_err_txdesc,
+		tx_logs->intf_tx_dump_xframe_err_port
+	);
+
+	return 0;
+}
+
+int proc_get_int_logs(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	DBG_871X_SEL_NL(m,
+		"all=%d\n"
+		"err=%d\n"
+		"tbdok=%d\n"
+		"tbder=%d\n"
+		"bcnderr=%d\n"
+		"bcndma=%d\n"
+		"bcndma_e=%d\n"
+		"rx=%d\n"
+		"rx_rdu=%d\n"
+		"rx_fovw=%d\n"
+		"txfovw=%d\n"
+		"mgntok=%d\n"
+		"highdok=%d\n"
+		"bkdok=%d\n"
+		"bedok=%d\n"
+		"vidok=%d\n"
+		"vodok=%d\n",
+		padapter->int_logs.all,
+		padapter->int_logs.err,
+		padapter->int_logs.tbdok,
+		padapter->int_logs.tbder,
+		padapter->int_logs.bcnderr,
+		padapter->int_logs.bcndma,
+		padapter->int_logs.bcndma_e,
+		padapter->int_logs.rx,
+		padapter->int_logs.rx_rdu,
+		padapter->int_logs.rx_fovw,
+		padapter->int_logs.txfovw,
+		padapter->int_logs.mgntok,
+		padapter->int_logs.highdok,
+		padapter->int_logs.bkdok,
+		padapter->int_logs.bedok,
+		padapter->int_logs.vidok,
+		padapter->int_logs.vodok
+	);
+
+	return 0;
+}
+
+#endif // CONFIG_DBG_COUNTER
+
+int proc_get_hw_status(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct dvobj_priv *dvobj = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
+
+	if (pdbgpriv->dbg_rx_fifo_last_overflow == 1
+		&& pdbgpriv->dbg_rx_fifo_curr_overflow == 1
+		&& pdbgpriv->dbg_rx_fifo_diff_overflow == 1
+	) {
+		DBG_871X_SEL_NL(m, "RX FIFO full count: no implementation\n");
+	} else {
+		DBG_871X_SEL_NL(m, "RX FIFO full count: last_time=%llu, current_time=%llu, differential=%llu\n"
+			, pdbgpriv->dbg_rx_fifo_last_overflow, pdbgpriv->dbg_rx_fifo_curr_overflow, pdbgpriv->dbg_rx_fifo_diff_overflow);
+	}
+
+	return 0;
+}
+
+int proc_get_rx_signal(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	DBG_871X_SEL_NL(m, "rssi:%d\n", padapter->recvpriv.rssi);
+	//DBG_871X_SEL_NL(m, "rxpwdb:%d\n", padapter->recvpriv.rxpwdb);
+	DBG_871X_SEL_NL(m, "signal_strength:%u\n", padapter->recvpriv.signal_strength);
+	DBG_871X_SEL_NL(m, "signal_qual:%u\n", padapter->recvpriv.signal_qual);
+
+	rtw_get_noise(padapter);
+	DBG_871X_SEL_NL(m, "noise:%d\n", padapter->recvpriv.noise);
+	#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
+	rtw_odm_get_perpkt_rssi(m,padapter);
+	rtw_get_raw_rssi_info(m,padapter);
+	#endif
+	return 0;
+}
+
+ssize_t proc_set_rx_signal(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u32 is_signal_dbg, signal_strength;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%u %u", &is_signal_dbg, &signal_strength);
+
+		is_signal_dbg = is_signal_dbg==0?0:1;
+		
+		if(is_signal_dbg && num!=2)
+			return count;
+			
+		signal_strength = signal_strength>100?100:signal_strength;
+
+		padapter->recvpriv.is_signal_dbg = is_signal_dbg;
+		padapter->recvpriv.signal_strength_dbg=signal_strength;
+
+		if(is_signal_dbg)
+			DBG_871X("set %s %u\n", "DBG_SIGNAL_STRENGTH", signal_strength);
+		else
+			DBG_871X("set %s\n", "HW_SIGNAL_STRENGTH");
+		
+	}
+	
+	return count;
+	
+}
+#ifdef CONFIG_80211N_HT
+
+int proc_get_ht_enable(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+
+	if(pregpriv)
+		DBG_871X_SEL_NL(m, "%d\n", pregpriv->ht_enable);
+
+	return 0;
+}
+
+ssize_t proc_set_ht_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	char tmp[32];
+	u32 mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &mode);
+
+		if( pregpriv && mode < 2 )
+		{
+			pregpriv->ht_enable= mode;
+			DBG_871X("ht_enable=%d\n", pregpriv->ht_enable);
+		}
+	}
+	
+	return count;
+	
+}
+
+int proc_get_bw_mode(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+
+	if(pregpriv)
+		DBG_871X_SEL_NL(m, "0x%02x\n", pregpriv->bw_mode);
+
+	return 0;
+}
+
+ssize_t proc_set_bw_mode(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	char tmp[32];
+	u32 mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &mode);
+
+		if( pregpriv &&  mode < 2 )
+		{
+
+			pregpriv->bw_mode = mode;
+			printk("bw_mode=%d\n", mode);
+
+		}
+	}
+	
+	return count;
+	
+}
+
+int proc_get_ampdu_enable(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+
+	if(pregpriv)
+		DBG_871X_SEL_NL(m, "%d\n", pregpriv->ampdu_enable);
+
+	return 0;
+}
+
+ssize_t proc_set_ampdu_enable(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	char tmp[32];
+	u32 mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &mode);
+
+		if( pregpriv && mode < 3 )
+		{
+			pregpriv->ampdu_enable= mode;
+			printk("ampdu_enable=%d\n", mode);
+		}
+
+	}
+	
+	return count;
+	
+}
+
+int proc_get_mac_rptbuf(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u16 i;
+	u16 mac_id;
+	u32 shcut_addr = 0;
+	u32 read_addr = 0;
+#ifdef CONFIG_RTL8814A
+	DBG_871X_SEL_NL(m, "TX ShortCut:\n");
+	for (mac_id = 0; mac_id < 64; mac_id++) {
+		rtw_write16(padapter, 0x140, 0x662 | ((mac_id & BIT5)>>5));
+		shcut_addr = 0x8000;
+		shcut_addr = shcut_addr | ((mac_id&0x1f) << 7);
+		DBG_871X_SEL_NL(m, "mac_id=%d, 0x140=%x =>\n", mac_id, 0x662 | ((mac_id & BIT5)>>5));
+		for (i = 0; i < 30; i++) {
+			read_addr = 0;
+			read_addr = shcut_addr | (i<<2);
+			DBG_871X_SEL_NL(m, "i=%02d: MAC_%04x= %08x ", i, read_addr, rtw_read32(padapter, read_addr));
+			if (!((i+1) % 4))
+				DBG_871X_SEL_NL(m, "\n");
+			if (i == 29)
+				DBG_871X_SEL_NL(m, "\n");
+		}
+	}
+#endif /* CONFIG_RTL8814A */
+	return 0;
+}
+
+
+int proc_get_rx_ampdu(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	DBG_871X_SEL(m, "accept: ");
+	if (padapter->fix_rx_ampdu_accept == RX_AMPDU_ACCEPT_INVALID)
+		DBG_871X_SEL_NL(m, "%u%s\n", rtw_rx_ampdu_is_accept(padapter), "(auto)");
+	else
+		DBG_871X_SEL_NL(m, "%u%s\n", padapter->fix_rx_ampdu_accept, "(fixed)");
+
+	DBG_871X_SEL(m, "size: ");
+	if (padapter->fix_rx_ampdu_size == RX_AMPDU_SIZE_INVALID)
+		DBG_871X_SEL_NL(m, "%u%s\n", rtw_rx_ampdu_size(padapter), "(auto)");
+	else
+		DBG_871X_SEL_NL(m, "%u%s\n", padapter->fix_rx_ampdu_size, "(fixed)");
+
+	DBG_871X_SEL_NL(m, "%19s %17s\n", "fix_rx_ampdu_accept", "fix_rx_ampdu_size");
+
+	DBG_871X_SEL(m, "%-19d %-17u\n"
+		, padapter->fix_rx_ampdu_accept
+		, padapter->fix_rx_ampdu_size);
+
+	return 0;
+}
+
+ssize_t proc_set_rx_ampdu(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	char tmp[32];
+	u8 accept;
+	u8 size;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%hhu %hhu", &accept, &size);
+
+		if (num >= 1)
+			rtw_rx_ampdu_set_accept(padapter, accept, RX_AMPDU_DRV_FIXED);
+		if (num >= 2)
+			rtw_rx_ampdu_set_size(padapter, size, RX_AMPDU_DRV_FIXED);
+
+		rtw_rx_ampdu_apply(padapter);
+	}
+
+exit:
+	return count;
+}
+int proc_get_rx_ampdu_factor(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	if(padapter)
+	{
+		DBG_871X_SEL_NL(m,"rx ampdu factor = %x\n",padapter->driver_rx_ampdu_factor);
+	}
+	
+	return 0;
+}
+
+ssize_t proc_set_rx_ampdu_factor(struct file *file, const char __user *buffer
+                                 , size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u32 factor;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &factor);
+
+		if( padapter && (num == 1) )
+		{
+			DBG_871X("padapter->driver_rx_ampdu_factor = %x\n", factor);
+
+			if(factor  > 0x03)
+				padapter->driver_rx_ampdu_factor = 0xFF;
+			else
+				padapter->driver_rx_ampdu_factor = factor;			
+		}
+	}
+
+	return count;
+}
+
+int proc_get_rx_ampdu_density(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	if(padapter)
+	{
+		DBG_871X_SEL_NL(m,"rx ampdu densityg = %x\n",padapter->driver_rx_ampdu_spacing);
+	}
+
+	return 0;
+}
+
+ssize_t proc_set_rx_ampdu_density(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u32 density;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &density);
+
+		if( padapter && (num == 1) )
+		{
+			DBG_871X("padapter->driver_rx_ampdu_spacing = %x\n", density);
+
+			if(density > 0x07)
+				padapter->driver_rx_ampdu_spacing = 0xFF;
+			else
+				padapter->driver_rx_ampdu_spacing = density;
+		}
+	}
+
+	return count;
+}
+
+int proc_get_tx_ampdu_density(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+
+	if(padapter)
+	{
+		DBG_871X_SEL_NL(m,"tx ampdu density = %x\n",padapter->driver_ampdu_spacing);
+	}
+
+	return 0;
+}
+
+ssize_t proc_set_tx_ampdu_density(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u32 density;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &density);
+
+		if( padapter && (num == 1) )
+		{
+			DBG_871X("padapter->driver_ampdu_spacing = %x\n", density);
+
+			if(density > 0x07)
+				padapter->driver_ampdu_spacing = 0xFF;
+			else
+				padapter->driver_ampdu_spacing = density;
+		}
+	}
+
+	return count;
+}
+#endif //CONFIG_80211N_HT
+
+int proc_get_en_fwps(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if(pregpriv)
+		DBG_871X_SEL_NL(m, "check_fw_ps = %d , 1:enable get FW PS state , 0: disable get FW PS state\n"
+			, pregpriv->check_fw_ps);
+
+	return 0;
+}
+
+ssize_t proc_set_en_fwps(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	char tmp[32];
+	u32 mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &mode);
+
+		if( pregpriv &&  mode < 2 )
+		{
+			pregpriv->check_fw_ps = mode;
+			DBG_871X("pregpriv->check_fw_ps=%d \n",pregpriv->check_fw_ps);
+		}
+
+	}
+
+	return count;
+}
+
+/*
+int proc_get_two_path_rssi(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+
+	if(padapter)
+		DBG_871X_SEL_NL(m, "%d %d\n",
+			padapter->recvpriv.RxRssi[0], padapter->recvpriv.RxRssi[1]);
+
+	return 0;
+}
+*/
+#ifdef CONFIG_80211N_HT
+int proc_get_rx_stbc(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+
+	if(pregpriv)
+		DBG_871X_SEL_NL(m, "%d\n", pregpriv->rx_stbc);
+
+	return 0;
+}
+
+ssize_t proc_set_rx_stbc(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	char tmp[32];
+	u32 mode;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d ", &mode);
+
+		if( pregpriv && (mode == 0 || mode == 1|| mode == 2|| mode == 3))
+		{
+			pregpriv->rx_stbc= mode;
+			printk("rx_stbc=%d\n", mode);
+		}
+	}
+	
+	return count;
+	
+}
+#endif //CONFIG_80211N_HT
+
+/*int proc_get_rssi_disp(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	return 0;
+}
+*/
+
+/*ssize_t proc_set_rssi_disp(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	u32 enable=0;
+
+	if (count < 1)
+	{
+		DBG_8192C("argument size is less than 1\n");
+		return -EFAULT;
+	}	
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%x", &enable);
+
+		if (num !=  1) {
+			DBG_8192C("invalid set_rssi_disp parameter!\n");
+			return count;
+		}
+		
+		if(enable)
+		{			
+			DBG_8192C("Linked info Function Enable\n");
+			padapter->bLinkInfoDump = enable ;			
+		}
+		else
+		{
+			DBG_8192C("Linked info Function Disable\n");
+			padapter->bLinkInfoDump = 0 ;
+		}
+	
+	}
+	
+	return count;
+	
+}	
+
+*/		
+#ifdef CONFIG_AP_MODE
+
+int proc_get_all_sta_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_irqL irqL;
+	struct sta_info *psta;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	int i;
+	_list	*plist, *phead;
+
+	DBG_871X_SEL_NL(m, "sta_dz_bitmap=0x%x, tim_bitmap=0x%x\n", pstapriv->sta_dz_bitmap, pstapriv->tim_bitmap);
+
+	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+	for(i=0; i< NUM_STA; i++)
+	{
+		phead = &(pstapriv->sta_hash[i]);
+		plist = get_next(phead);
+		
+		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+		{
+			psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+
+			plist = get_next(plist);
+
+			//if(extra_arg == psta->aid)
+			{
+				DBG_871X_SEL_NL(m, "==============================\n");
+				DBG_871X_SEL_NL(m, "sta's macaddr:" MAC_FMT "\n", MAC_ARG(psta->hwaddr));
+				DBG_871X_SEL_NL(m, "rtsen=%d, cts2slef=%d\n", psta->rtsen, psta->cts2self);
+				DBG_871X_SEL_NL(m, "state=0x%x, aid=%d, macid=%d, raid=%d\n", psta->state, psta->aid, psta->mac_id, psta->raid);
+#ifdef CONFIG_80211N_HT
+				DBG_871X_SEL_NL(m, "qos_en=%d, ht_en=%d, init_rate=%d\n", psta->qos_option, psta->htpriv.ht_option, psta->init_rate);	
+				DBG_871X_SEL_NL(m, "bwmode=%d, ch_offset=%d, sgi_20m=%d,sgi_40m=%d\n", psta->bw_mode, psta->htpriv.ch_offset, psta->htpriv.sgi_20m, psta->htpriv.sgi_40m);
+				DBG_871X_SEL_NL(m, "ampdu_enable = %d\n", psta->htpriv.ampdu_enable);									
+				DBG_871X_SEL_NL(m, "agg_enable_bitmap=%x, candidate_tid_bitmap=%x\n", psta->htpriv.agg_enable_bitmap, psta->htpriv.candidate_tid_bitmap);
+#endif //CONFIG_80211N_HT
+				DBG_871X_SEL_NL(m, "sleepq_len=%d\n", psta->sleepq_len);
+				DBG_871X_SEL_NL(m, "sta_xmitpriv.vo_q_qcnt=%d\n", psta->sta_xmitpriv.vo_q.qcnt);
+				DBG_871X_SEL_NL(m, "sta_xmitpriv.vi_q_qcnt=%d\n", psta->sta_xmitpriv.vi_q.qcnt);
+				DBG_871X_SEL_NL(m, "sta_xmitpriv.be_q_qcnt=%d\n", psta->sta_xmitpriv.be_q.qcnt);
+				DBG_871X_SEL_NL(m, "sta_xmitpriv.bk_q_qcnt=%d\n", psta->sta_xmitpriv.bk_q.qcnt);
+
+				DBG_871X_SEL_NL(m, "capability=0x%x\n", psta->capability);
+				DBG_871X_SEL_NL(m, "flags=0x%x\n", psta->flags);
+				DBG_871X_SEL_NL(m, "wpa_psk=0x%x\n", psta->wpa_psk);
+				DBG_871X_SEL_NL(m, "wpa2_group_cipher=0x%x\n", psta->wpa2_group_cipher);
+				DBG_871X_SEL_NL(m, "wpa2_pairwise_cipher=0x%x\n", psta->wpa2_pairwise_cipher);
+				DBG_871X_SEL_NL(m, "qos_info=0x%x\n", psta->qos_info);
+				DBG_871X_SEL_NL(m, "dot118021XPrivacy=0x%x\n", psta->dot118021XPrivacy);
+
+				sta_rx_reorder_ctl_dump(m, psta);
+
+#ifdef CONFIG_TDLS
+				DBG_871X_SEL_NL(m, "tdls_sta_state=0x%08x\n", psta->tdls_sta_state);
+				DBG_871X_SEL_NL(m, "PeerKey_Lifetime=%d\n", psta->TDLS_PeerKey_Lifetime);
+				DBG_871X_SEL_NL(m, "rx_data_pkts=%llu\n", psta->sta_stats.rx_data_pkts);
+				DBG_871X_SEL_NL(m, "rx_bytes=%llu\n", psta->sta_stats.rx_bytes);
+				DBG_871X_SEL_NL(m, "tx_data_pkts=%llu\n", psta->sta_stats.tx_pkts);
+				DBG_871X_SEL_NL(m, "tx_bytes=%llu\n", psta->sta_stats.tx_bytes);
+#endif //CONFIG_TDLS
+
+				dump_st_ctl(m, &psta->st_ctl);
+
+				if (STA_OP_WFD_MODE(psta))
+					DBG_871X_SEL_NL(m, "op_wfd_mode:0x%02x\n", STA_OP_WFD_MODE(psta));
+
+				DBG_871X_SEL_NL(m, "==============================\n");
+			}
+
+		}
+
+	}
+
+	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+	return 0;
+}
+
+#endif		
+
+#ifdef CONFIG_PREALLOC_RX_SKB_BUFFER
+int proc_get_rtkm_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct recv_priv	*precvpriv = &padapter->recvpriv;
+	struct recv_buf *precvbuf;
+	
+	precvbuf = (struct recv_buf *)precvpriv->precv_buf;
+
+	DBG_871X_SEL_NL(m, "============[RTKM Info]============\n");
+	DBG_871X_SEL_NL(m, "MAX_RTKM_NR_PREALLOC_RECV_SKB: %d\n", rtw_rtkm_get_nr_recv_skb());
+	DBG_871X_SEL_NL(m, "MAX_RTKM_RECVBUF_SZ: %d\n", rtw_rtkm_get_buff_size());
+
+	DBG_871X_SEL_NL(m, "============[Driver Info]============\n");
+	DBG_871X_SEL_NL(m, "NR_PREALLOC_RECV_SKB: %d\n", NR_PREALLOC_RECV_SKB);
+	DBG_871X_SEL_NL(m, "MAX_RECVBUF_SZ: %d\n", precvbuf->alloc_sz);
+
+	return 0;
+}
+#endif /* CONFIG_PREALLOC_RX_SKB_BUFFER */
+
+#ifdef DBG_MEMORY_LEAK
+#include <asm/atomic.h>
+extern atomic_t _malloc_cnt;;
+extern atomic_t _malloc_size;;
+
+int proc_get_malloc_cnt(struct seq_file *m, void *v)
+{
+	DBG_871X_SEL_NL(m, "_malloc_cnt=%d\n", atomic_read(&_malloc_cnt));
+	DBG_871X_SEL_NL(m, "_malloc_size=%d\n", atomic_read(&_malloc_size));
+
+	return 0;
+}
+#endif /* DBG_MEMORY_LEAK */
+
+#ifdef CONFIG_FIND_BEST_CHANNEL
+int proc_get_best_channel(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	u32 i, best_channel_24G = 1, best_channel_5G = 36, index_24G = 0, index_5G = 0;
+
+	for (i=0; pmlmeext->channel_set[i].ChannelNum !=0; i++) {
+		if ( pmlmeext->channel_set[i].ChannelNum == 1)
+			index_24G = i;
+		if ( pmlmeext->channel_set[i].ChannelNum == 36)
+			index_5G = i;
+	}	
+	
+	for (i=0; (i < MAX_CHANNEL_NUM) && (pmlmeext->channel_set[i].ChannelNum !=0) ; i++) {
+		// 2.4G
+		if ( pmlmeext->channel_set[i].ChannelNum == 6 ) {
+			if ( pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_24G].rx_count ) {
+				index_24G = i;
+				best_channel_24G = pmlmeext->channel_set[i].ChannelNum;
+			}
+		}
+
+		// 5G
+		if ( pmlmeext->channel_set[i].ChannelNum >= 36
+			&& pmlmeext->channel_set[i].ChannelNum < 140 ) {
+			 // Find primary channel
+			if ( (( pmlmeext->channel_set[i].ChannelNum - 36) % 8 == 0)
+				&& (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count) ) {
+				index_5G = i;
+				best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
+			}
+		}
+
+		if ( pmlmeext->channel_set[i].ChannelNum >= 149
+			&& pmlmeext->channel_set[i].ChannelNum < 165) {
+			 // find primary channel
+			if ( (( pmlmeext->channel_set[i].ChannelNum - 149) % 8 == 0)
+				&& (pmlmeext->channel_set[i].rx_count < pmlmeext->channel_set[index_5G].rx_count) ) {
+				index_5G = i;
+				best_channel_5G = pmlmeext->channel_set[i].ChannelNum;
+			}
+		}
+#if 1 // debug
+		DBG_871X_SEL_NL(m, "The rx cnt of channel %3d = %d\n", 
+					pmlmeext->channel_set[i].ChannelNum, pmlmeext->channel_set[i].rx_count);
+#endif
+	}
+	
+	DBG_871X_SEL_NL(m, "best_channel_5G = %d\n", best_channel_5G);
+	DBG_871X_SEL_NL(m, "best_channel_24G = %d\n", best_channel_24G);
+
+	return 0;
+}
+
+ssize_t proc_set_best_channel(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	char tmp[32];
+
+	if(count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		int i;
+		for(i = 0; pmlmeext->channel_set[i].ChannelNum != 0; i++)
+		{
+			pmlmeext->channel_set[i].rx_count = 0;
+		}
+
+		DBG_871X("set %s\n", "Clean Best Channel Count");
+	}
+
+	return count;
+}
+#endif /* CONFIG_FIND_BEST_CHANNEL */
+
+#ifdef CONFIG_BT_COEXIST
+int proc_get_btcoex_dbg(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	PADAPTER padapter;
+	char buf[512] = {0};
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	rtw_btcoex_GetDBG(padapter, buf, 512);
+
+	DBG_871X_SEL(m, "%s", buf);
+
+	return 0;
+}
+
+ssize_t proc_set_btcoex_dbg(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	PADAPTER padapter;
+	u8 tmp[80] = {0};
+	u32 module[2] = {0};
+	u32 num;
+
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+//	DBG_871X("+" FUNC_ADPT_FMT "\n", FUNC_ADPT_ARG(padapter));
+
+	if (NULL == buffer)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": input buffer is NULL!\n",
+			FUNC_ADPT_ARG(padapter));
+		
+		return -EFAULT;
+	}
+
+	if (count < 1)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": input length is 0!\n",
+			FUNC_ADPT_ARG(padapter));
+
+		return -EFAULT;
+	}
+
+	num = count;
+	if (num > (sizeof(tmp) - 1))
+		num = (sizeof(tmp) - 1);
+
+	if (copy_from_user(tmp, buffer, num))
+	{
+		DBG_871X(FUNC_ADPT_FMT ": copy buffer from user space FAIL!\n",
+			FUNC_ADPT_ARG(padapter));
+
+		return -EFAULT;
+	}
+
+	num = sscanf(tmp, "%x %x", module, module+1);
+	if (1 == num)
+	{
+		if (0 == module[0])
+			_rtw_memset(module, 0, sizeof(module));
+		else
+			_rtw_memset(module, 0xFF, sizeof(module));
+	}
+	else if (2 != num)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": input(\"%s\") format incorrect!\n",
+			FUNC_ADPT_ARG(padapter), tmp);
+
+		if (0 == num)
+			return -EFAULT;
+	}
+
+	DBG_871X(FUNC_ADPT_FMT ": input 0x%08X 0x%08X\n",
+		FUNC_ADPT_ARG(padapter), module[0], module[1]);
+	rtw_btcoex_SetDBG(padapter, module);
+
+	return count;
+}
+
+int proc_get_btcoex_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	PADAPTER padapter;
+	const u32 bufsize = 30*100;
+	u8 *pbuf = NULL;
+
+	padapter = (PADAPTER)rtw_netdev_priv(dev);
+
+	pbuf = rtw_zmalloc(bufsize);
+	if (NULL == pbuf) {
+		return -ENOMEM;
+	}
+
+	rtw_btcoex_DisplayBtCoexInfo(padapter, pbuf, bufsize);
+
+	DBG_871X_SEL(m, "%s\n", pbuf);
+	
+	rtw_mfree(pbuf, bufsize);
+
+	return 0;
+}
+#endif /* CONFIG_BT_COEXIST */
+
+#if defined(DBG_CONFIG_ERROR_DETECT)
+int proc_get_sreset(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+	return 0;
+}
+
+ssize_t proc_set_sreset(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	char tmp[32];
+	s32 trigger_point;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%d", &trigger_point);
+
+		if (trigger_point == SRESET_TGP_NULL)
+			rtw_hal_sreset_reset(padapter);
+		else
+			sreset_set_trigger_point(padapter, trigger_point);
+	}
+	
+	return count;
+	
+}
+#endif /* DBG_CONFIG_ERROR_DETECT */
+
+#ifdef CONFIG_PCI_HCI
+
+int proc_get_rx_ring(struct seq_file *m, void *v)
+{
+	_irqL irqL;
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	struct rtw_rx_ring *rx_ring = &precvpriv->rx_ring[RX_MPDU_QUEUE];
+	int i, j;
+
+	DBG_871X_SEL_NL(m, "rx ring (%p)\n", rx_ring);
+	DBG_871X_SEL_NL(m, "  dma: 0x%08x\n", (int) rx_ring->dma);
+	DBG_871X_SEL_NL(m, "  idx: %d\n", rx_ring->idx);
+
+	_enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
+	for (i=0; i<precvpriv->rxringcount; i++)
+	{
+		struct recv_stat *entry = &rx_ring->desc[i];
+		struct sk_buff *skb = rx_ring->rx_buf[i];
+
+		DBG_871X_SEL_NL(m, "  desc[%03d]: %p, rx_buf[%03d]: 0x%08x\n",
+			i, entry, i, cpu_to_le32(*((dma_addr_t *)skb->cb)));
+
+		for (j=0; j<sizeof(*entry)/4; j++)
+		{
+			if ((j % 4) == 0)
+				DBG_871X_SEL_NL(m, "  0x%03x", j);
+
+			DBG_871X_SEL_NL(m, " 0x%08x ", ((int *) entry)[j]);
+
+			if ((j % 4) == 3)
+				DBG_871X_SEL_NL(m, "\n");
+		}
+	}
+	_exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
+
+	return 0;
+}
+
+int proc_get_tx_ring(struct seq_file *m, void *v)
+{
+	_irqL irqL;
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *) rtw_netdev_priv(dev);
+	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	int i, j, k;
+
+	_enter_critical(&pdvobjpriv->irq_th_lock, &irqL);
+	for (i = 0; i < PCI_MAX_TX_QUEUE_COUNT; i++)
+	{
+		struct rtw_tx_ring *tx_ring = &pxmitpriv->tx_ring[i];
+
+		DBG_871X_SEL_NL(m, "tx ring[%d] (%p)\n", i, tx_ring);
+		DBG_871X_SEL_NL(m, "  dma: 0x%08x\n", (int) tx_ring->dma);
+		DBG_871X_SEL_NL(m, "  idx: %d\n", tx_ring->idx);
+		DBG_871X_SEL_NL(m, "  entries: %d\n", tx_ring->entries);
+//		DBG_871X_SEL_NL(m, "  queue: %d\n", tx_ring->queue);
+		DBG_871X_SEL_NL(m, "  qlen: %d\n", tx_ring->qlen);
+
+		for (j=0; j < pxmitpriv->txringcount[i]; j++)
+		{
+			struct tx_desc *entry = &tx_ring->desc[j];
+
+			DBG_871X_SEL_NL(m, "  desc[%03d]: %p\n", j, entry);
+			for (k=0; k < sizeof(*entry)/4; k++)
+			{
+				if ((k % 4) == 0)
+					DBG_871X_SEL_NL(m, "  0x%03x", k);
+
+				DBG_871X_SEL_NL(m, " 0x%08x ", ((int *) entry)[k]);
+
+				if ((k % 4) == 3)
+					DBG_871X_SEL_NL(m, "\n");
+			}
+		}
+	}
+	_exit_critical(&pdvobjpriv->irq_th_lock, &irqL);
+
+	return 0;
+}
+#endif
+
+#ifdef CONFIG_GPIO_WAKEUP
+int proc_get_wowlan_gpio_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	u8 val = pwrpriv->is_high_active;
+
+	DBG_871X_SEL_NL(m, "wakeup_gpio_idx: %d\n", WAKEUP_GPIO_IDX);
+	DBG_871X_SEL_NL(m, "high_active: %d\n", val);
+
+	return 0;
+}
+
+ssize_t proc_set_wowlan_gpio_info(struct file *file, const char __user *buffer,
+		size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	char tmp[32] = {0};
+	int num = 0;
+	u32 is_high_active = 0;
+	u8 val8 = 0;
+
+	if (count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		num = sscanf(tmp, "%u", &is_high_active);
+
+		is_high_active = is_high_active == 0 ? 0 : 1;
+
+		pwrpriv->is_high_active = is_high_active;
+
+		rtw_ps_deny(padapter, PS_DENY_IOCTL);
+		LeaveAllPowerSaveModeDirect(padapter);
+		val8 = (pwrpriv->is_high_active == 0) ? 1 : 0;
+		rtw_hal_set_output_gpio(padapter, WAKEUP_GPIO_IDX, val8);
+		rtw_ps_deny_cancel(padapter, PS_DENY_IOCTL);
+
+		DBG_871X("set %s %d\n", "gpio_high_active",
+				pwrpriv->is_high_active);
+		DBG_871X("%s: set GPIO_%d %d as default.\n",
+			 __func__, WAKEUP_GPIO_IDX, val8);
+	}
+	
+	return count;
+}
+#endif /* CONFIG_GPIO_WAKEUP */
+
+#ifdef CONFIG_P2P_WOWLAN
+int proc_get_p2p_wowlan_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+	struct p2p_wowlan_info	 peerinfo = pwdinfo->p2p_wow_info;
+	if(_TRUE == peerinfo.is_trigger)
+	{
+		DBG_871X_SEL_NL(m,"is_trigger: TRUE\n");
+		switch(peerinfo.wowlan_recv_frame_type)
+		{
+			case P2P_WOWLAN_RECV_NEGO_REQ:
+				DBG_871X_SEL_NL(m,"Frame Type: Nego Request\n");
+				break;
+			case P2P_WOWLAN_RECV_INVITE_REQ:
+				DBG_871X_SEL_NL(m,"Frame Type: Invitation Request\n");
+				break;
+			case P2P_WOWLAN_RECV_PROVISION_REQ:
+				DBG_871X_SEL_NL(m,"Frame Type: Provision Request\n");
+				break;
+			default:
+				break;
+		}
+		DBG_871X_SEL_NL(m,"Peer Addr: "MAC_FMT"\n", MAC_ARG(peerinfo.wowlan_peer_addr));
+		DBG_871X_SEL_NL(m,"Peer WPS Config: %x\n", peerinfo.wowlan_peer_wpsconfig);
+		DBG_871X_SEL_NL(m,"Persistent Group: %d\n", peerinfo.wowlan_peer_is_persistent);
+		DBG_871X_SEL_NL(m,"Intivation Type: %d\n", peerinfo.wowlan_peer_invitation_type);
+	}
+	else
+	{
+		DBG_871X_SEL_NL(m,"is_trigger: False\n");
+	}
+	return 0;
+}
+#endif /* CONFIG_P2P_WOWLAN */
+
+int proc_get_new_bcn_max(struct seq_file *m, void *v)
+{
+	extern int new_bcn_max;
+
+	DBG_871X_SEL_NL(m, "%d", new_bcn_max);
+	return 0;
+}
+
+ssize_t proc_set_new_bcn_max(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	char tmp[32];
+	extern int new_bcn_max;
+
+	if(count < 1)
+		return -EFAULT;
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count))
+		sscanf(tmp, "%d ", &new_bcn_max);
+
+	return count;
+}
+
+#ifdef CONFIG_POWER_SAVING
+int proc_get_ps_info(struct seq_file *m, void *v)
+{	
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	u8 ips_mode = pwrpriv->ips_mode;
+	u8 lps_mode = pwrpriv->power_mgnt;
+	char *str = "";
+
+	DBG_871X_SEL_NL(m, "======Power Saving Info:======\n");
+	DBG_871X_SEL_NL(m, "*IPS:\n");
+
+	if (ips_mode == IPS_NORMAL) {
+#ifdef CONFIG_FWLPS_IN_IPS
+		str = "FW_LPS_IN_IPS";
+#else
+		str = "Card Disable";
+#endif
+	} else if (ips_mode == IPS_NONE) {
+		str = "NO IPS";
+	} else if (ips_mode == IPS_LEVEL_2) {
+		str = "IPS_LEVEL_2";
+	} else {
+		str = "invalid ips_mode";
+	}
+
+	DBG_871X_SEL_NL(m, " IPS mode: %s\n", str);
+	DBG_871X_SEL_NL(m, " IPS enter count:%d, IPS leave count:%d\n",
+			pwrpriv->ips_enter_cnts, pwrpriv->ips_leave_cnts);
+	DBG_871X_SEL_NL(m, "------------------------------\n");
+	DBG_871X_SEL_NL(m, "*LPS:\n");
+
+	if (lps_mode == PS_MODE_ACTIVE) {
+		str = "NO LPS";
+	} else if (lps_mode == PS_MODE_MIN) {
+		str = "MIN";
+	} else if (lps_mode == PS_MODE_MAX) {
+		str = "MAX";
+	} else if (lps_mode == PS_MODE_DTIM) {
+		str = "DTIM";
+	} else {
+		sprintf(str, "%d", lps_mode);
+	}
+
+	DBG_871X_SEL_NL(m, " LPS mode: %s\n", str);
+
+	if (pwrpriv->dtim != 0)
+		DBG_871X_SEL_NL(m, " DTIM: %d\n", pwrpriv->dtim);
+	DBG_871X_SEL_NL(m, " LPS enter count:%d, LPS leave count:%d\n",
+			pwrpriv->lps_enter_cnts, pwrpriv->lps_leave_cnts);
+	DBG_871X_SEL_NL(m, "=============================\n");
+	return 0;
+}
+#endif //CONFIG_POWER_SAVING
+
+#ifdef CONFIG_TDLS
+static int proc_tdls_display_tdls_function_info(struct seq_file *m)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	u8 SpaceBtwnItemAndValue = TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE;
+	u8 SpaceBtwnItemAndValueTmp = 0;
+	BOOLEAN FirstMatchFound = _FALSE;
+	int j= 0;
+	
+	DBG_871X_SEL_NL(m, "============[TDLS Function Info]============\n");
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Prohibited", (ptdlsinfo->ap_prohibited == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Channel Switch Prohibited", (ptdlsinfo->ch_switch_prohibited == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Link Established", (ptdlsinfo->link_established == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %d/%d\n", SpaceBtwnItemAndValue, "TDLS STA Num (Linked/Allowed)", ptdlsinfo->sta_cnt, MAX_ALLOWED_TDLS_STA_NUM);
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Allowed STA Num Reached", (ptdlsinfo->sta_maximum == _TRUE) ? "_TRUE" : "_FALSE");
+
+#ifdef CONFIG_TDLS_CH_SW
+	DBG_871X_SEL_NL(m, "%-*s =", SpaceBtwnItemAndValue, "TDLS CH SW State");
+	if (ptdlsinfo->chsw_info.ch_sw_state == TDLS_STATE_NONE)
+	{
+		DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_STATE_NONE");
+	}
+	else
+	{
+		for (j = 0; j < 32; j++)
+		{
+			if (ptdlsinfo->chsw_info.ch_sw_state & BIT(j))
+			{
+				if (FirstMatchFound ==  _FALSE)
+				{
+					SpaceBtwnItemAndValueTmp = 1;
+					FirstMatchFound = _TRUE;
+				}
+				else
+				{
+					SpaceBtwnItemAndValueTmp = SpaceBtwnItemAndValue + 3;
+				}
+				switch (BIT(j))
+				{
+					case TDLS_INITIATOR_STATE:
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_INITIATOR_STATE");
+						break;
+					case TDLS_RESPONDER_STATE:
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_RESPONDER_STATE");
+						break;
+					case TDLS_LINKED_STATE:
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_LINKED_STATE");
+						break;
+					case TDLS_WAIT_PTR_STATE:		
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_WAIT_PTR_STATE");
+						break;
+					case TDLS_ALIVE_STATE:		
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_ALIVE_STATE");
+						break;
+					case TDLS_CH_SWITCH_ON_STATE:	
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SWITCH_ON_STATE");
+						break;
+					case TDLS_PEER_AT_OFF_STATE:		
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_PEER_AT_OFF_STATE");
+						break;
+					case TDLS_CH_SW_INITIATOR_STATE:		
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SW_INITIATOR_STATE");
+						break;
+					case TDLS_WAIT_CH_RSP_STATE:		
+						DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValue, " ", "TDLS_WAIT_CH_RSP_STATE");
+						break;
+					default:
+						DBG_871X_SEL_NL(m, "%-*sBIT(%d)\n", SpaceBtwnItemAndValueTmp, " ", j);
+						break;
+				}
+			}
+		}
+	}
+
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS CH SW On", (ATOMIC_READ(&ptdlsinfo->chsw_info.chsw_on) == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Off-Channel Num", ptdlsinfo->chsw_info.off_ch_num);
+	DBG_871X_SEL_NL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Channel Offset", ptdlsinfo->chsw_info.ch_offset);
+	DBG_871X_SEL_NL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Current Time", ptdlsinfo->chsw_info.cur_time);
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS CH SW Delay Switch Back", (ptdlsinfo->chsw_info.delay_switch_back == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "TDLS CH SW Dump Back", ptdlsinfo->chsw_info.dump_stack);
+#endif
+
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Device Discovered", (ptdlsinfo->dev_discovered == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Enable", (ptdlsinfo->tdls_enable == _TRUE) ? "_TRUE" : "_FALSE");
+	DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "TDLS Driver Setup", (ptdlsinfo->driver_setup == _TRUE) ? "_TRUE" : "_FALSE");
+	
+	return 0;
+}
+
+static int proc_tdls_display_network_info(struct seq_file *m)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+	int i = 0;
+	u8 SpaceBtwnItemAndValue = TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE;
+
+	/* Display the linked AP/GO info */
+	DBG_871X_SEL_NL(m, "============[Associated AP/GO Info]============\n");
+	
+	if ((pmlmepriv->fw_state & WIFI_STATION_STATE) && (pmlmepriv->fw_state & _FW_LINKED))
+	{
+		DBG_871X_SEL_NL(m, "%-*s = %s\n", SpaceBtwnItemAndValue, "BSSID", cur_network->network.Ssid.Ssid);
+		DBG_871X_SEL_NL(m, "%-*s = "MAC_FMT"\n", SpaceBtwnItemAndValue, "Mac Address", MAC_ARG(cur_network->network.MacAddress));
+		
+		DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Wireless Mode");
+		for (i = 0; i < 8; i++)
+		{
+			if (pmlmeext->cur_wireless_mode & BIT(i))
+			{
+				switch (BIT(i))
+				{
+					case WIRELESS_11B: 
+						DBG_871X_SEL_NL(m, "%4s", "11B ");
+						break;
+					case WIRELESS_11G:
+						DBG_871X_SEL_NL(m, "%4s", "11G ");
+						break;
+					case WIRELESS_11A:
+						DBG_871X_SEL_NL(m, "%4s", "11A ");
+						break;
+					case WIRELESS_11_24N:
+						DBG_871X_SEL_NL(m, "%7s", "11_24N ");
+						break;
+					case WIRELESS_11_5N:
+						DBG_871X_SEL_NL(m, "%6s", "11_5N ");
+						break;
+					case WIRELESS_AUTO:
+						DBG_871X_SEL_NL(m, "%5s", "AUTO ");
+						break;
+					case WIRELESS_11AC:
+						DBG_871X_SEL_NL(m, "%5s", "11AC ");
+						break;
+				}
+			}
+		}
+		DBG_871X_SEL_NL(m, "\n");
+
+		DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Privacy");
+		switch (padapter->securitypriv.dot11PrivacyAlgrthm)
+		{
+			case _NO_PRIVACY_:
+				DBG_871X_SEL_NL(m, "%s\n", "NO PRIVACY");
+				break;
+			case _WEP40_:	
+				DBG_871X_SEL_NL(m, "%s\n", "WEP 40");
+				break;
+			case _TKIP_:
+				DBG_871X_SEL_NL(m, "%s\n", "TKIP");
+				break;
+			case _TKIP_WTMIC_:
+				DBG_871X_SEL_NL(m, "%s\n", "TKIP WTMIC");
+				break;
+			case _AES_:				
+				DBG_871X_SEL_NL(m, "%s\n", "AES");
+				break;
+			case _WEP104_:
+				DBG_871X_SEL_NL(m, "%s\n", "WEP 104");
+				break;
+			case _WEP_WPA_MIXED_:
+				DBG_871X_SEL_NL(m, "%s\n", "WEP/WPA Mixed");
+				break;
+			case _SMS4_:
+				DBG_871X_SEL_NL(m, "%s\n", "SMS4");
+				break;
+#ifdef CONFIG_IEEE80211W
+			case _BIP_:
+				DBG_871X_SEL_NL(m, "%s\n", "BIP");
+				break;	
+#endif //CONFIG_IEEE80211W
+		}
+		
+		DBG_871X_SEL_NL(m, "%-*s = %d\n", SpaceBtwnItemAndValue, "Channel", pmlmeext->cur_channel);
+		DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Channel Offset");
+		switch (pmlmeext->cur_ch_offset)
+		{
+			case HAL_PRIME_CHNL_OFFSET_DONT_CARE:
+				DBG_871X_SEL_NL(m, "%s\n", "N/A");
+				break;
+			case HAL_PRIME_CHNL_OFFSET_LOWER:
+				DBG_871X_SEL_NL(m, "%s\n", "Lower");
+				break;
+			case HAL_PRIME_CHNL_OFFSET_UPPER:
+				DBG_871X_SEL_NL(m, "%s\n", "Upper");
+				break;
+		}
+		
+		DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Bandwidth Mode");
+		switch (pmlmeext->cur_bwmode)
+		{
+			case CHANNEL_WIDTH_20:
+				DBG_871X_SEL_NL(m, "%s\n", "20MHz");
+				break;
+			case CHANNEL_WIDTH_40:
+				DBG_871X_SEL_NL(m, "%s\n", "40MHz");
+				break;
+			case CHANNEL_WIDTH_80:
+				DBG_871X_SEL_NL(m, "%s\n", "80MHz");
+				break;
+			case CHANNEL_WIDTH_160:
+				DBG_871X_SEL_NL(m, "%s\n", "160MHz");
+				break;
+			case CHANNEL_WIDTH_80_80:
+				DBG_871X_SEL_NL(m, "%s\n", "80MHz + 80MHz");
+				break;
+		}
+	}
+	else
+	{
+		DBG_871X_SEL_NL(m, "No association with AP/GO exists!\n");
+	}
+
+	return 0;
+}
+
+static int proc_tdls_display_tdls_sta_info(struct seq_file *m)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct sta_info *psta;
+	int i = 0, j = 0;
+	_irqL irqL;
+	_list	*plist, *phead;
+	u8 SpaceBtwnItemAndValue = TDLS_DBG_INFO_SPACE_BTWN_ITEM_AND_VALUE;
+	u8 SpaceBtwnItemAndValueTmp = 0;
+	u8 NumOfTdlsStaToShow = 0;
+	BOOLEAN FirstMatchFound = _FALSE;
+	
+	/* Search for TDLS sta info to display */
+	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+	for (i=0; i< NUM_STA; i++)
+	{
+		phead = &(pstapriv->sta_hash[i]);
+		plist = get_next(phead);	
+		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+		{
+				psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+				plist = get_next(plist);
+				if (psta->tdls_sta_state != TDLS_STATE_NONE)
+				{
+					/* We got one TDLS sta info to show */
+					DBG_871X_SEL_NL(m, "============[TDLS Peer STA Info: STA %d]============\n", ++NumOfTdlsStaToShow);
+					DBG_871X_SEL_NL(m, "%-*s = "MAC_FMT"\n", SpaceBtwnItemAndValue, "Mac Address", MAC_ARG(psta->hwaddr));
+					DBG_871X_SEL_NL(m, "%-*s =", SpaceBtwnItemAndValue, "TDLS STA State");
+					SpaceBtwnItemAndValueTmp = 0;
+					FirstMatchFound = _FALSE;
+					for (j = 0; j < 32; j++)
+					{
+						if (psta->tdls_sta_state & BIT(j))
+						{
+							if (FirstMatchFound ==  _FALSE)
+							{
+								SpaceBtwnItemAndValueTmp = 1;
+								FirstMatchFound = _TRUE;
+							}
+							else
+							{
+								SpaceBtwnItemAndValueTmp = SpaceBtwnItemAndValue + 3;
+							}
+							switch (BIT(j))
+							{
+								case TDLS_INITIATOR_STATE:
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_INITIATOR_STATE");
+									break;
+								case TDLS_RESPONDER_STATE:
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_RESPONDER_STATE");
+									break;
+								case TDLS_LINKED_STATE:
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_LINKED_STATE");
+									break;
+								case TDLS_WAIT_PTR_STATE:		
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_WAIT_PTR_STATE");
+									break;
+								case TDLS_ALIVE_STATE:		
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_ALIVE_STATE");
+									break;
+								case TDLS_CH_SWITCH_ON_STATE:	
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SWITCH_ON_STATE");
+									break;
+								case TDLS_PEER_AT_OFF_STATE:		
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_PEER_AT_OFF_STATE");
+									break;
+								case TDLS_CH_SW_INITIATOR_STATE:		
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValueTmp, " ", "TDLS_CH_SW_INITIATOR_STATE");
+									break;
+								case TDLS_WAIT_CH_RSP_STATE:		
+									DBG_871X_SEL_NL(m, "%-*s%s\n", SpaceBtwnItemAndValue, " ", "TDLS_WAIT_CH_RSP_STATE");
+									break;
+								default:
+									DBG_871X_SEL_NL(m, "%-*sBIT(%d)\n", SpaceBtwnItemAndValueTmp, " ", j);
+									break;
+							}
+						}
+					}
+
+					DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Wireless Mode");
+					for (j = 0; j < 8; j++)
+					{
+						if (psta->wireless_mode & BIT(j))
+						{
+							switch (BIT(j))
+							{
+								case WIRELESS_11B: 
+									DBG_871X_SEL_NL(m, "%4s", "11B ");
+									break;
+								case WIRELESS_11G:
+									DBG_871X_SEL_NL(m, "%4s", "11G ");
+									break;
+								case WIRELESS_11A:
+									DBG_871X_SEL_NL(m, "%4s", "11A ");
+									break;
+								case WIRELESS_11_24N:
+									DBG_871X_SEL_NL(m, "%7s", "11_24N ");
+									break;
+								case WIRELESS_11_5N:
+									DBG_871X_SEL_NL(m, "%6s", "11_5N ");
+									break;
+								case WIRELESS_AUTO:
+									DBG_871X_SEL_NL(m, "%5s", "AUTO ");
+									break;
+								case WIRELESS_11AC:
+									DBG_871X_SEL_NL(m, "%5s", "11AC ");
+									break;
+							}
+						}
+					}
+					DBG_871X_SEL_NL(m, "\n");
+
+					DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Bandwidth Mode");
+					switch (psta->bw_mode)
+					{
+						case CHANNEL_WIDTH_20:
+							DBG_871X_SEL_NL(m, "%s\n", "20MHz");
+							break;
+						case CHANNEL_WIDTH_40:
+							DBG_871X_SEL_NL(m, "%s\n", "40MHz");
+							break;
+						case CHANNEL_WIDTH_80:
+							DBG_871X_SEL_NL(m, "%s\n", "80MHz");
+							break;
+						case CHANNEL_WIDTH_160:
+							DBG_871X_SEL_NL(m, "%s\n", "160MHz");
+							break;
+						case CHANNEL_WIDTH_80_80:
+							DBG_871X_SEL_NL(m, "%s\n", "80MHz + 80MHz");
+							break;
+					}
+
+					DBG_871X_SEL_NL(m, "%-*s = ", SpaceBtwnItemAndValue, "Privacy");
+					switch (psta->dot118021XPrivacy)
+					{
+						case _NO_PRIVACY_:
+							DBG_871X_SEL_NL(m, "%s\n", "NO PRIVACY");
+							break;
+						case _WEP40_:	
+							DBG_871X_SEL_NL(m, "%s\n", "WEP 40");
+							break;
+						case _TKIP_:
+							DBG_871X_SEL_NL(m, "%s\n", "TKIP");
+							break;
+						case _TKIP_WTMIC_:
+							DBG_871X_SEL_NL(m, "%s\n", "TKIP WTMIC");
+							break;
+						case _AES_:				
+							DBG_871X_SEL_NL(m, "%s\n", "AES");
+							break;
+						case _WEP104_:
+							DBG_871X_SEL_NL(m, "%s\n", "WEP 104");
+							break;
+						case _WEP_WPA_MIXED_:
+							DBG_871X_SEL_NL(m, "%s\n", "WEP/WPA Mixed");
+							break;
+						case _SMS4_:
+							DBG_871X_SEL_NL(m, "%s\n", "SMS4");
+							break;
+#ifdef CONFIG_IEEE80211W
+						case _BIP_:
+							DBG_871X_SEL_NL(m, "%s\n", "BIP");
+							break;
+#endif //CONFIG_IEEE80211W
+					}
+
+					DBG_871X_SEL_NL(m, "%-*s = %d sec/%d sec\n", SpaceBtwnItemAndValue, "TPK Lifetime (Current/Expire)", psta->TPK_count, psta->TDLS_PeerKey_Lifetime);
+					DBG_871X_SEL_NL(m, "%-*s = %llu\n", SpaceBtwnItemAndValue, "Tx Packets Over Direct Link", psta->sta_stats.tx_pkts);
+					DBG_871X_SEL_NL(m, "%-*s = %llu\n", SpaceBtwnItemAndValue, "Rx Packets Over Direct Link", psta->sta_stats.rx_data_pkts);
+				}
+		}
+	}
+	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+	if (NumOfTdlsStaToShow == 0)
+	{
+		DBG_871X_SEL_NL(m, "============[TDLS Peer STA Info]============\n");
+		DBG_871X_SEL_NL(m, "No TDLS direct link exists!\n");
+	}
+
+	return 0;
+}
+
+int proc_get_tdls_info(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct sta_info *psta;
+	int i = 0, j = 0;
+	_irqL irqL;
+	_list	*plist, *phead;
+	u8 SpaceBtwnItemAndValue = 41;
+	u8 SpaceBtwnItemAndValueTmp = 0;
+	u8 NumOfTdlsStaToShow = 0;
+	BOOLEAN FirstMatchFound = _FALSE;
+
+	if (hal_chk_wl_func(padapter, WL_FUNC_TDLS) == _FALSE) {
+		DBG_871X_SEL_NL(m, "No tdls info can be shown since hal doesn't support tdls\n");
+		return 0;
+	}
+
+	proc_tdls_display_tdls_function_info(m);
+	proc_tdls_display_network_info(m);
+	proc_tdls_display_tdls_sta_info(m);	
+
+	return 0;
+}
+#endif
+
+int proc_get_monitor(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	if (WIFI_MONITOR_STATE == get_fwstate(pmlmepriv)) {
+		DBG_871X_SEL_NL(m, "Monitor mode : Enable\n");
+
+		DBG_871X_SEL_NL(m, "ch=%d, ch_offset=%d, bw=%d\n",
+						rtw_get_oper_ch(padapter), rtw_get_oper_choffset(padapter), rtw_get_oper_bw(padapter));
+	} else {
+		DBG_871X_SEL_NL(m, "Monitor mode : Disable\n");
+	}
+
+	return 0;
+}
+
+ssize_t proc_set_monitor(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	char tmp[32];
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	u8 target_chan, target_offset, target_bw;
+
+	if (count < 3) {
+		DBG_871X("argument size is less than 3\n");
+		return -EFAULT;
+	}
+
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+		int num = sscanf(tmp, "%hhu %hhu %hhu", &target_chan, &target_offset, &target_bw);
+
+		if (num != 3) {
+			DBG_871X("invalid write_reg parameter!\n");
+			return count;
+		}
+
+		padapter->mlmeextpriv.cur_channel  = target_chan;
+		set_channel_bwmode(padapter, target_chan, target_offset, target_bw);
+	}
+
+	return count;
+}
+
+#include <hal_data.h>
+int proc_get_efuse_map(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	PHAL_DATA_TYPE pHalData = GET_HAL_DATA(padapter);
+	struct pwrctrl_priv *pwrctrlpriv  = adapter_to_pwrctl(padapter);
+	PEFUSE_HAL pEfuseHal = &pHalData->EfuseHal;
+	int i, j;
+	u8 ips_mode = IPS_NUM; 
+	int mapLen = EFUSE_MAP_SIZE;
+
+	ips_mode = pwrctrlpriv->ips_mode;
+	rtw_pm_set_ips(padapter, IPS_NONE);
+	if (rtw_efuse_map_read(padapter, EFUSE_WIFI, mapLen, pEfuseHal->fakeEfuseInitMap) == _FAIL)
+		DBG_871X_SEL_NL(m, "WARN - Read Realmap Failed\n");	
+	
+	DBG_871X_SEL_NL(m, "\n");
+	for (i = 0; i < EFUSE_MAP_SIZE; i += 16) {
+		DBG_871X_SEL_NL(m, "0x%02x\t", i);
+		for (j = 0; j < 8; j++) 
+			DBG_871X_SEL_NL(m, "%02X ", pEfuseHal->fakeEfuseInitMap[i+j]);
+		
+		DBG_871X_SEL_NL(m, "\t");
+				
+		for (; j < 16; j++)
+			DBG_871X_SEL_NL(m, "%02X ", pEfuseHal->fakeEfuseInitMap[i+j]);
+		
+		DBG_871X_SEL_NL(m, "\n");
+				
+	}
+	rtw_pm_set_ips(padapter, ips_mode);
+	return 0;
+}
+
+ssize_t proc_set_efuse_map(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+#if 0
+	char tmp[256] = {0};
+	u32 addr, cnts;
+	u8 efuse_data;
+	
+	int jj, kk;
+
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct pwrctrl_priv *pwrctrlpriv  = adapter_to_pwrctl(padapter);
+	u8 ips_mode = IPS_NUM;
+	
+	if (count < 3) {
+		DBG_871X("argument size is less than 3\n");
+		return -EFAULT;
+	}
+	
+	if (count > sizeof(tmp)) {
+		rtw_warn_on(1);
+		return -EFAULT;
+	}
+	
+	if (buffer && !copy_from_user(tmp, buffer, count)) {
+
+		int num = sscanf(tmp, "%x %d %x", &addr, &cnts, &efuse_data);
+	
+		if (num != 3) {
+			DBG_871X("invalid write_reg parameter!\n");
+			return count;
+		}
+	}
+	ips_mode = pwrctrlpriv->ips_mode;
+	rtw_pm_set_ips(padapter, IPS_NONE);
+	if (rtw_efuse_map_write(padapter, addr, cnts, &efuse_data) == _FAIL) 
+		DBG_871X("WARN - rtw_efuse_map_write error!!\n");		
+	rtw_pm_set_ips(padapter, ips_mode);
+#endif	
+	return count;
+}
+
+#ifdef CONFIG_IEEE80211W
+ssize_t proc_set_tx_sa_query(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	struct sta_info *psta;
+	_list	*plist, *phead;
+	_irqL	 irqL;
+	char tmp[16];
+	u8	mac_addr[NUM_STA][ETH_ALEN];
+	u32 key_type;
+	u8 index;
+
+	if (count > 2) {
+		DBG_871X("argument size is more than 2\n");
+		return -EFAULT;
+	}	
+
+	if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {		
+
+		int num = sscanf(tmp, "%x", &key_type);
+
+		if (num !=  1) {
+			DBG_871X("invalid read_reg parameter!\n");
+			return count;
+		}
+		DBG_871X("0: set sa query request , key_type=%d\n", key_type);
+	}
+	
+	if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+		&& (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) && padapter->securitypriv.binstallBIPkey == _TRUE) {
+		DBG_871X("STA:"MAC_FMT"\n", MAC_ARG(get_my_bssid(&(pmlmeinfo->network))));
+		/* TX unicast sa_query to AP */
+		issue_action_SA_Query(padapter, get_my_bssid(&(pmlmeinfo->network)), 0, 0, (u8)key_type);
+	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE && padapter->securitypriv.binstallBIPkey == _TRUE) {
+		/* TX unicast sa_query to every client STA */
+		_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		for (index = 0; index < NUM_STA; index++) {
+			psta = NULL;
+			
+			phead = &(pstapriv->sta_hash[index]);
+			plist = get_next(phead);
+			
+			while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+				psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+				plist = get_next(plist);
+				_rtw_memcpy(&mac_addr[psta->mac_id][0], psta->hwaddr, ETH_ALEN);
+			}
+		}
+		_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		
+		for (index = 0; index < macid_ctl->num && index < NUM_STA; index++) {
+			if (rtw_macid_is_used(macid_ctl, index) && !rtw_macid_is_bmc(macid_ctl, index)) {
+				if (!_rtw_memcmp(get_my_bssid(&(pmlmeinfo->network)), &mac_addr[index][0], ETH_ALEN) 
+					&& !IS_MCAST(&mac_addr[index][0])) {
+					issue_action_SA_Query(padapter, &mac_addr[index][0], 0, 0, (u8)key_type);
+					DBG_871X("STA[%u]:"MAC_FMT"\n", index , MAC_ARG(&mac_addr[index][0]));
+				}
+			}
+		}
+	}
+	
+	return count;
+}
+
+int proc_get_tx_sa_query(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	
+	DBG_871X_SEL_NL(m, "%s\n", __func__);
+	return 0;
+}
+
+ssize_t proc_set_tx_deauth(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	struct sta_info *psta;
+	_list	*plist, *phead;
+	_irqL	 irqL;
+	char tmp[16];
+	u8	mac_addr[NUM_STA][ETH_ALEN];
+	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u32 key_type;
+	u8 index;
+	
+
+	if (count > 2) {
+		DBG_871X("argument size is more than 2\n");
+		return -EFAULT;
+	}	
+
+	if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {		
+
+		int num = sscanf(tmp, "%x", &key_type);
+
+		if (num !=  1) {
+			DBG_871X("invalid read_reg parameter!\n");
+			return count;
+		}
+		DBG_871X("key_type=%d\n", key_type);
+	}
+	if (key_type < 0 || key_type > 4)
+		return count;
+	
+	if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+		&& (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)) {
+		if (key_type == 3) /* key_type 3 only for AP mode */
+			return count;
+		/* TX unicast deauth to AP */
+		issue_deauth_11w(padapter, get_my_bssid(&(pmlmeinfo->network)), 0, (u8)key_type);
+	} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE) {
+		
+		if (key_type == 3)
+			issue_deauth_11w(padapter, bc_addr, 0, IEEE80211W_RIGHT_KEY);
+		
+		/* TX unicast deauth to every client STA */
+		_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		for (index = 0; index < NUM_STA; index++) {
+			psta = NULL;
+			
+			phead = &(pstapriv->sta_hash[index]);
+			plist = get_next(phead);
+			
+			while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+				psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+				plist = get_next(plist);
+				_rtw_memcpy(&mac_addr[psta->mac_id][0], psta->hwaddr, ETH_ALEN);
+			}
+		}
+		_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		
+		for (index = 0; index < macid_ctl->num && index < NUM_STA; index++) {
+			if (rtw_macid_is_used(macid_ctl, index) && !rtw_macid_is_bmc(macid_ctl, index)) {
+				if (!_rtw_memcmp(get_my_bssid(&(pmlmeinfo->network)), &mac_addr[index][0], ETH_ALEN)) {
+					if (key_type != 3)
+						issue_deauth_11w(padapter, &mac_addr[index][0], 0, (u8)key_type);
+					
+					psta = rtw_get_stainfo(pstapriv, &mac_addr[index][0]);	
+					if (psta && key_type != IEEE80211W_WRONG_KEY && key_type != IEEE80211W_NO_KEY) {
+						u8 updated = _FALSE;
+					
+						_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+						if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {			
+							rtw_list_delete(&psta->asoc_list);
+							pstapriv->asoc_list_cnt--;
+							updated = ap_free_sta(padapter, psta, _FALSE, WLAN_REASON_PREV_AUTH_NOT_VALID, _TRUE);
+			
+						}
+						_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+			
+						associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
+					}
+					
+					DBG_871X("STA[%u]:"MAC_FMT"\n", index , MAC_ARG(&mac_addr[index][0]));
+				}
+			}
+		}
+	}
+	
+	return count;
+}
+
+int proc_get_tx_deauth(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	
+	DBG_871X_SEL_NL(m, "%s\n", __func__);
+	return 0;
+}
+
+ssize_t proc_set_tx_auth(struct file *file, const char __user *buffer, size_t count, loff_t *pos, void *data)
+{
+	struct net_device *dev = data;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	struct sta_info *psta;
+	_list	*plist, *phead;
+	_irqL	 irqL;
+	char tmp[16];
+	u8	mac_addr[NUM_STA][ETH_ALEN];
+	u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u32 tx_auth;
+	u8 index;
+	
+
+	if (count > 2) {
+		DBG_871X("argument size is more than 2\n");
+		return -EFAULT;
+	}	
+
+	if (buffer && !copy_from_user(tmp, buffer, sizeof(tmp))) {		
+
+		int num = sscanf(tmp, "%x", &tx_auth);
+
+		if (num !=  1) {
+			DBG_871X("invalid read_reg parameter!\n");
+			return count;
+		}
+		DBG_871X("1: setnd auth, 2: send assoc request. tx_auth=%d\n", tx_auth);
+	}
+	
+	if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+		&& (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)) {
+		if (tx_auth == 1) {
+			/* TX unicast auth to AP */
+			issue_auth(padapter, NULL, 0);
+		} else if (tx_auth == 2) {
+			/* TX unicast auth to AP */
+			issue_assocreq(padapter);
+		}
+	} 
+	
+	return count;
+}
+
+int proc_get_tx_auth(struct seq_file *m, void *v)
+{
+	struct net_device *dev = m->private;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(dev);
+	
+	DBG_871X_SEL_NL(m, "%s\n", __func__);
+	return 0;
+}
+#endif /* CONFIG_IEEE80211W */
+
+#endif /* CONFIG_PROC_DEBUG */
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_eeprom.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_eeprom.c
new file mode 100644
index 000000000..e83c090ac
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_eeprom.c
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_EEPROM_C_
+
+#include <drv_conf.h>
+#include <osdep_service.h>
+#include <drv_types.h>
+
+void up_clk(_adapter*	padapter,	 u16 *x)
+{
+_func_enter_;
+	*x = *x | _EESK;
+	rtw_write8(padapter, EE_9346CR, (u8)*x);
+	rtw_udelay_os(CLOCK_RATE);
+
+_func_exit_;
+	
+}
+
+void down_clk(_adapter *	padapter, u16 *x	)
+{
+_func_enter_;
+	*x = *x & ~_EESK;
+	rtw_write8(padapter, EE_9346CR, (u8)*x);
+	rtw_udelay_os(CLOCK_RATE);
+_func_exit_;	
+}
+
+void shift_out_bits(_adapter * padapter, u16 data, u16 count)
+{
+	u16 x,mask;
+_func_enter_;
+
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	mask = 0x01 << (count - 1);
+	x = rtw_read8(padapter, EE_9346CR);
+
+	x &= ~(_EEDO | _EEDI);
+
+	do
+	{
+		x &= ~_EEDI;
+		if(data & mask)
+			x |= _EEDI;
+		if (rtw_is_surprise_removed(padapter)) {
+			RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+			goto out;
+		}
+		rtw_write8(padapter, EE_9346CR, (u8)x);
+		rtw_udelay_os(CLOCK_RATE);
+		up_clk(padapter, &x);
+		down_clk(padapter, &x);
+		mask = mask >> 1;
+	} while(mask);
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	x &= ~_EEDI;
+	rtw_write8(padapter, EE_9346CR, (u8)x);
+out:	
+_func_exit_;		
+}
+
+u16 shift_in_bits (_adapter * padapter)
+{
+	u16 x,d=0,i;
+_func_enter_;	
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	x = rtw_read8(padapter, EE_9346CR);
+
+	x &= ~( _EEDO | _EEDI);
+	d = 0;
+
+	for(i=0; i<16; i++)
+	{
+		d = d << 1;
+		up_clk(padapter, &x);
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+		x = rtw_read8(padapter, EE_9346CR);
+
+		x &= ~(_EEDI);
+		if(x & _EEDO)
+		d |= 1;
+
+		down_clk(padapter, &x);
+	}
+out:	
+_func_exit_;		
+
+	return d;
+}
+
+void standby(_adapter *	padapter	)
+{
+	u8   x;
+_func_enter_;	
+	x = rtw_read8(padapter, EE_9346CR);
+
+	x &= ~(_EECS | _EESK);
+	rtw_write8(padapter, EE_9346CR,x);
+
+	rtw_udelay_os(CLOCK_RATE);
+	x |= _EECS;
+	rtw_write8(padapter, EE_9346CR, x);
+	rtw_udelay_os(CLOCK_RATE);
+_func_exit_;		
+}
+
+u16 wait_eeprom_cmd_done(_adapter* padapter)
+{
+	u8 	x;
+	u16	i,res=_FALSE;
+_func_enter_;	
+	standby(padapter );
+	for (i=0; i<200; i++) 
+	{
+		x = rtw_read8(padapter, EE_9346CR);
+		if (x & _EEDO){
+			res=_TRUE;
+			goto exit;
+			}
+		rtw_udelay_os(CLOCK_RATE);
+	}
+exit:	
+_func_exit_;			
+	return res;
+}
+
+void eeprom_clean(_adapter * padapter)
+{
+	u16 x;
+_func_enter_;		
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	x = rtw_read8(padapter, EE_9346CR);
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	x &= ~(_EECS | _EEDI);
+	rtw_write8(padapter, EE_9346CR, (u8)x);
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	up_clk(padapter, &x);
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	down_clk(padapter, &x);
+out:	
+_func_exit_;			
+}
+
+void eeprom_write16(_adapter * padapter, u16 reg, u16 data)
+{
+	u8 x;
+#ifdef CONFIG_RTL8712
+	u8	tmp8_ori,tmp8_new,tmp8_clk_ori,tmp8_clk_new;
+	tmp8_ori=rtw_read8(padapter, 0x102502f1);
+	tmp8_new=tmp8_ori & 0xf7;
+	if(tmp8_ori != tmp8_new){	
+		rtw_write8(padapter, 0x102502f1, tmp8_new);
+		RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x102502f1=====\n"));
+	}
+	tmp8_clk_ori=rtw_read8(padapter,0x10250003);
+	tmp8_clk_new=tmp8_clk_ori|0x20;
+	if(tmp8_clk_new!=tmp8_clk_ori){
+		RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x10250003=====\n"));
+		rtw_write8(padapter, 0x10250003, tmp8_clk_new);
+	}	
+#endif
+_func_enter_;		
+	
+	x = rtw_read8(padapter, EE_9346CR);
+
+	x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
+	x |= _EEM1 | _EECS;
+	rtw_write8(padapter, EE_9346CR, x);
+
+	shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
+	
+	if(padapter->EepromAddressSize==8)	//CF+ and SDIO
+		shift_out_bits(padapter, 0, 6);
+	else									//USB
+		shift_out_bits(padapter, 0, 4);
+	
+	standby( padapter);
+
+// Commented out by rcnjko, 2004.0
+//	// Erase this particular word.  Write the erase opcode and register
+//	// number in that order. The opcode is 3bits in length; reg is 6 bits long.
+//	shift_out_bits(Adapter, EEPROM_ERASE_OPCODE, 3);
+//	shift_out_bits(Adapter, reg, Adapter->EepromAddressSize);
+//
+//	if (wait_eeprom_cmd_done(Adapter ) == FALSE) 
+//	{
+//		return;
+//	}
+
+
+	standby(padapter );
+
+	// write the new word to the EEPROM
+
+	// send the write opcode the EEPORM
+	shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
+
+	// select which word in the EEPROM that we are writing to.
+	shift_out_bits(padapter, reg, padapter->EepromAddressSize);
+
+	// write the data to the selected EEPROM word.
+	shift_out_bits(padapter, data, 16);
+
+	if (wait_eeprom_cmd_done(padapter ) == _FALSE) 
+	{
+
+		goto exit;
+	}
+
+	standby(padapter );
+
+	shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
+	shift_out_bits(padapter, reg, 4);
+
+	eeprom_clean(padapter );
+exit:	
+#ifdef CONFIG_RTL8712
+	if(tmp8_clk_new!=tmp8_clk_ori)
+		rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
+	if(tmp8_new!=tmp8_ori)
+		rtw_write8(padapter, 0x102502f1, tmp8_ori);
+
+#endif
+_func_exit_;	
+	return;
+}
+
+u16 eeprom_read16(_adapter * padapter, u16 reg) //ReadEEprom
+{
+
+	u16 x;
+	u16 data=0;
+#ifdef CONFIG_RTL8712
+	u8	tmp8_ori,tmp8_new,tmp8_clk_ori,tmp8_clk_new;
+	tmp8_ori= rtw_read8(padapter, 0x102502f1);
+	tmp8_new = tmp8_ori & 0xf7;
+	if(tmp8_ori != tmp8_new){	
+		rtw_write8(padapter, 0x102502f1, tmp8_new);
+		RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x102502f1=====\n"));
+	}
+	tmp8_clk_ori=rtw_read8(padapter,0x10250003);
+	tmp8_clk_new=tmp8_clk_ori|0x20;
+	if(tmp8_clk_new!=tmp8_clk_ori){
+		RT_TRACE(_module_rtl871x_mp_ioctl_c_,_drv_err_,("====write 0x10250003=====\n"));
+		rtw_write8(padapter, 0x10250003, tmp8_clk_new);
+	}	
+#endif
+_func_enter_;		
+
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	// select EEPROM, reset bits, set _EECS
+	x = rtw_read8(padapter, EE_9346CR);
+
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+
+	x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
+	x |= _EEM1 | _EECS;
+	rtw_write8(padapter, EE_9346CR, (unsigned char)x);
+
+	// write the read opcode and register number in that order
+	// The opcode is 3bits in length, reg is 6 bits long
+	shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
+	shift_out_bits(padapter, reg, padapter->EepromAddressSize);
+
+	// Now read the data (16 bits) in from the selected EEPROM word
+	data = shift_in_bits(padapter);
+
+	eeprom_clean(padapter);
+out:	
+#ifdef CONFIG_RTL8712
+	if(tmp8_clk_new!=tmp8_clk_ori)
+		rtw_write8(padapter, 0x10250003, tmp8_clk_ori);
+	if(tmp8_new!=tmp8_ori)
+		rtw_write8(padapter, 0x102502f1, tmp8_ori);
+
+#endif
+_func_exit_;		
+	return data;
+
+
+}
+
+
+
+
+//From even offset
+void eeprom_read_sz(_adapter * padapter, u16 reg, u8* data, u32 sz) 
+{
+
+	u16 x, data16;
+	u32 i;
+_func_enter_;		
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+	// select EEPROM, reset bits, set _EECS
+	x = rtw_read8(padapter, EE_9346CR);
+
+	if (rtw_is_surprise_removed(padapter)) {
+		RT_TRACE(_module_rtl871x_eeprom_c_, _drv_err_, ("padapter->bSurpriseRemoved==_TRUE"));
+		goto out;
+	}
+
+	x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
+	x |= _EEM1 | _EECS;
+	rtw_write8(padapter, EE_9346CR, (unsigned char)x);
+
+	// write the read opcode and register number in that order
+	// The opcode is 3bits in length, reg is 6 bits long
+	shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
+	shift_out_bits(padapter, reg, padapter->EepromAddressSize);
+
+
+	for(i=0; i<sz; i+=2)
+	{
+		data16 = shift_in_bits(padapter);
+		data[i] = data16 & 0xff;
+		data[i+1] = data16 >>8;		
+	}
+
+	eeprom_clean(padapter);
+out:	
+_func_exit_;		
+
+
+
+}
+
+
+//addr_off : address offset of the entry in eeprom (not the tuple number of eeprom (reg); that is addr_off !=reg)
+u8 eeprom_read(_adapter * padapter, u32 addr_off, u8 sz, u8* rbuf)
+{
+	u8 quotient, remainder, addr_2align_odd;
+	u16 reg, stmp , i=0, idx = 0;
+_func_enter_;		
+	reg = (u16)(addr_off >> 1);
+	addr_2align_odd = (u8)(addr_off & 0x1);
+
+	if(addr_2align_odd) //read that start at high part: e.g  1,3,5,7,9,...
+	{
+		stmp = eeprom_read16(padapter, reg);
+		rbuf[idx++] = (u8) ((stmp>>8)&0xff); //return hogh-part of the short
+		reg++; sz--;
+	}
+	
+	quotient = sz >> 1;
+	remainder = sz & 0x1;
+
+	for( i=0 ; i < quotient; i++)
+	{
+		stmp = eeprom_read16(padapter, reg+i);
+		rbuf[idx++] = (u8) (stmp&0xff);
+		rbuf[idx++] = (u8) ((stmp>>8)&0xff);
+	}
+	
+	reg = reg+i;
+	if(remainder){ //end of read at lower part of short : 0,2,4,6,...
+		stmp = eeprom_read16(padapter, reg);
+		rbuf[idx] = (u8)(stmp & 0xff); 
+	}
+_func_exit_;		
+	return _TRUE;
+}
+
+
+
+VOID read_eeprom_content(_adapter *	padapter)
+{
+
+_func_enter_;		
+
+
+_func_exit_;		
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ieee80211.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ieee80211.c
new file mode 100644
index 000000000..b0a3a86a6
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ieee80211.c
@@ -0,0 +1,2847 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _IEEE80211_C
+
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+#include <linux/fs.h>
+#endif 
+#include <drv_types.h>
+#include <linux/of.h>
+
+
+u8 RTW_WPA_OUI_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
+u16 RTW_WPA_VERSION = 1;
+u8 WPA_AUTH_KEY_MGMT_NONE[] = { 0x00, 0x50, 0xf2, 0 };
+u8 WPA_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x50, 0xf2, 2 };
+u8 WPA_CIPHER_SUITE_NONE[] = { 0x00, 0x50, 0xf2, 0 };
+u8 WPA_CIPHER_SUITE_WEP40[] = { 0x00, 0x50, 0xf2, 1 };
+u8 WPA_CIPHER_SUITE_TKIP[] = { 0x00, 0x50, 0xf2, 2 };
+u8 WPA_CIPHER_SUITE_WRAP[] = { 0x00, 0x50, 0xf2, 3 };
+u8 WPA_CIPHER_SUITE_CCMP[] = { 0x00, 0x50, 0xf2, 4 };
+u8 WPA_CIPHER_SUITE_WEP104[] = { 0x00, 0x50, 0xf2, 5 };
+
+u16 RSN_VERSION_BSD = 1;
+u8 RSN_AUTH_KEY_MGMT_UNSPEC_802_1X[] = { 0x00, 0x0f, 0xac, 1 };
+u8 RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X[] = { 0x00, 0x0f, 0xac, 2 };
+u8 RSN_CIPHER_SUITE_NONE[] = { 0x00, 0x0f, 0xac, 0 };
+u8 RSN_CIPHER_SUITE_WEP40[] = { 0x00, 0x0f, 0xac, 1 };
+u8 RSN_CIPHER_SUITE_TKIP[] = { 0x00, 0x0f, 0xac, 2 };
+u8 RSN_CIPHER_SUITE_WRAP[] = { 0x00, 0x0f, 0xac, 3 };
+u8 RSN_CIPHER_SUITE_CCMP[] = { 0x00, 0x0f, 0xac, 4 };
+u8 RSN_CIPHER_SUITE_WEP104[] = { 0x00, 0x0f, 0xac, 5 };
+//-----------------------------------------------------------
+// for adhoc-master to generate ie and provide supported-rate to fw 
+//-----------------------------------------------------------
+
+static u8 	WIFI_CCKRATES[] = 
+{(IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
+ (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
+ (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
+ (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)};
+
+static u8 	WIFI_OFDMRATES[] = 
+{(IEEE80211_OFDM_RATE_6MB),
+ (IEEE80211_OFDM_RATE_9MB),
+ (IEEE80211_OFDM_RATE_12MB),
+ (IEEE80211_OFDM_RATE_18MB),
+ (IEEE80211_OFDM_RATE_24MB),
+ IEEE80211_OFDM_RATE_36MB,
+ IEEE80211_OFDM_RATE_48MB,
+ IEEE80211_OFDM_RATE_54MB};
+
+u8 mgn_rates_cck[4] = {MGN_1M, MGN_2M, MGN_5_5M, MGN_11M};
+u8 mgn_rates_ofdm[8] = {MGN_6M, MGN_9M, MGN_12M, MGN_18M, MGN_24M, MGN_36M, MGN_48M, MGN_54M};
+u8 mgn_rates_mcs0_7[8] = {MGN_MCS0, MGN_MCS1, MGN_MCS2, MGN_MCS3, MGN_MCS4, MGN_MCS5, MGN_MCS6, MGN_MCS7};
+u8 mgn_rates_mcs8_15[8] = {MGN_MCS8, MGN_MCS9, MGN_MCS10, MGN_MCS11, MGN_MCS12, MGN_MCS13, MGN_MCS14, MGN_MCS15};
+u8 mgn_rates_mcs16_23[8] = {MGN_MCS16, MGN_MCS17, MGN_MCS18, MGN_MCS19, MGN_MCS20, MGN_MCS21, MGN_MCS22, MGN_MCS23};
+u8 mgn_rates_mcs24_31[8] = {MGN_MCS24, MGN_MCS25, MGN_MCS26, MGN_MCS27, MGN_MCS28, MGN_MCS29, MGN_MCS30, MGN_MCS31};
+u8 mgn_rates_vht1ss[10] = {MGN_VHT1SS_MCS0, MGN_VHT1SS_MCS1, MGN_VHT1SS_MCS2, MGN_VHT1SS_MCS3, MGN_VHT1SS_MCS4
+	, MGN_VHT1SS_MCS5, MGN_VHT1SS_MCS6, MGN_VHT1SS_MCS7, MGN_VHT1SS_MCS8, MGN_VHT1SS_MCS9};
+u8 mgn_rates_vht2ss[10] = {MGN_VHT2SS_MCS0, MGN_VHT2SS_MCS1, MGN_VHT2SS_MCS2, MGN_VHT2SS_MCS3, MGN_VHT2SS_MCS4
+	, MGN_VHT2SS_MCS5, MGN_VHT2SS_MCS6, MGN_VHT2SS_MCS7, MGN_VHT2SS_MCS8, MGN_VHT2SS_MCS9};
+u8 mgn_rates_vht3ss[10] = {MGN_VHT3SS_MCS0, MGN_VHT3SS_MCS1, MGN_VHT3SS_MCS2, MGN_VHT3SS_MCS3, MGN_VHT3SS_MCS4
+	, MGN_VHT3SS_MCS5, MGN_VHT3SS_MCS6, MGN_VHT3SS_MCS7, MGN_VHT3SS_MCS8, MGN_VHT3SS_MCS9};
+u8 mgn_rates_vht4ss[10] = {MGN_VHT4SS_MCS0, MGN_VHT4SS_MCS1, MGN_VHT4SS_MCS2, MGN_VHT4SS_MCS3, MGN_VHT4SS_MCS4
+	, MGN_VHT4SS_MCS5, MGN_VHT4SS_MCS6, MGN_VHT4SS_MCS7, MGN_VHT4SS_MCS8, MGN_VHT4SS_MCS9};
+
+static const char * const _rate_section_str[] = {
+	"CCK",
+	"OFDM",
+	"HT_1SS",
+	"HT_2SS",
+	"HT_3SS",
+	"HT_4SS",
+	"VHT_1SS",
+	"VHT_2SS",
+	"VHT_3SS",
+	"VHT_4SS",
+	"RATE_SECTION_UNKNOWN",
+};
+
+const char *rate_section_str(u8 section)
+{
+	section = (section >= RATE_SECTION_NUM) ? RATE_SECTION_NUM : section;
+	return _rate_section_str[section];
+}
+
+struct rate_section_ent rates_by_sections[RATE_SECTION_NUM] = {
+	{RF_1TX, 4, mgn_rates_cck},
+	{RF_1TX, 8, mgn_rates_ofdm},
+	{RF_1TX, 8, mgn_rates_mcs0_7},
+	{RF_2TX, 8, mgn_rates_mcs8_15},
+	{RF_3TX, 8, mgn_rates_mcs16_23},
+	{RF_4TX, 8, mgn_rates_mcs24_31},
+	{RF_1TX, 10, mgn_rates_vht1ss},
+	{RF_2TX, 10, mgn_rates_vht2ss},
+	{RF_3TX, 10, mgn_rates_vht3ss},
+	{RF_4TX, 10, mgn_rates_vht4ss},
+};
+
+int rtw_get_bit_value_from_ieee_value(u8 val)
+{
+	unsigned char dot11_rate_table[]={2,4,11,22,12,18,24,36,48,72,96,108,0}; // last element must be zero!!
+
+	int i=0;
+	while(dot11_rate_table[i] != 0) {
+		if (dot11_rate_table[i] == val)
+			return BIT(i);
+		i++;
+	}
+	return 0;
+}
+
+uint	rtw_is_cckrates_included(u8 *rate)
+{	
+		u32	i = 0;			
+
+		while(rate[i]!=0)
+		{		
+			if  (  (((rate[i]) & 0x7f) == 2)	|| (((rate[i]) & 0x7f) == 4) ||		
+			(((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22) )		
+				return _TRUE;
+			i++;
+		}
+		
+		return _FALSE;
+}
+
+uint	rtw_is_cckratesonly_included(u8 *rate)
+{
+	u32 i = 0;
+
+
+	while(rate[i]!=0)
+	{
+			if  (  (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
+				(((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22) )
+				return _FALSE;
+
+			i++;
+	}
+	
+	return _TRUE;
+
+}
+
+int rtw_check_network_type(unsigned char *rate, int ratelen, int channel)
+{
+	if (channel > 14)
+	{
+		if ((rtw_is_cckrates_included(rate)) == _TRUE)
+			return WIRELESS_INVALID;
+		else
+			return WIRELESS_11A;
+	}	
+	else  // could be pure B, pure G, or B/G
+	{
+		if ((rtw_is_cckratesonly_included(rate)) == _TRUE)	
+			return WIRELESS_11B;
+		else if((rtw_is_cckrates_included(rate)) == _TRUE)
+			return 	WIRELESS_11BG;
+		else
+			return WIRELESS_11G;
+	}
+	
+}
+
+u8 *rtw_set_fixed_ie(unsigned char *pbuf, unsigned int len, unsigned char *source,
+				unsigned int *frlen)
+{
+	_rtw_memcpy((void *)pbuf, (void *)source, len);
+	*frlen = *frlen + len;
+	return (pbuf + len);
+}
+
+// rtw_set_ie will update frame length
+u8 *rtw_set_ie
+(
+	u8 *pbuf, 
+	sint index, 
+	uint len,
+	u8 *source, 
+	uint *frlen //frame length
+)
+{
+	*pbuf = (u8)index;
+
+	*(pbuf + 1) = (u8)len;
+
+	if (len > 0)
+		_rtw_memcpy((void *)(pbuf + 2), (void *)source, len);
+	
+	*frlen = *frlen + (len + 2);
+	
+	return (pbuf + len + 2);
+}
+
+inline u8 *rtw_set_ie_ch_switch(u8 *buf, u32 *buf_len, u8 ch_switch_mode,
+	u8 new_ch, u8 ch_switch_cnt)
+{
+	u8 ie_data[3];
+
+	ie_data[0] = ch_switch_mode;
+	ie_data[1] = new_ch;
+	ie_data[2] = ch_switch_cnt;
+	return rtw_set_ie(buf, WLAN_EID_CHANNEL_SWITCH,  3, ie_data, buf_len);
+}
+
+inline u8 secondary_ch_offset_to_hal_ch_offset(u8 ch_offset)
+{
+	if (ch_offset == SCN)
+		return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	else if(ch_offset == SCA)
+		return HAL_PRIME_CHNL_OFFSET_UPPER;
+	else if(ch_offset == SCB)
+		return HAL_PRIME_CHNL_OFFSET_LOWER;
+
+	return HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+}
+
+inline u8 hal_ch_offset_to_secondary_ch_offset(u8 ch_offset)
+{
+	if (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
+		return SCN;
+	else if(ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
+		return SCB;
+	else if(ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
+		return SCA;
+
+	return SCN;
+}
+
+inline u8 *rtw_set_ie_secondary_ch_offset(u8 *buf, u32 *buf_len, u8 secondary_ch_offset)
+{
+	return rtw_set_ie(buf, WLAN_EID_SECONDARY_CHANNEL_OFFSET,  1, &secondary_ch_offset, buf_len);
+}
+
+inline u8 *rtw_set_ie_mesh_ch_switch_parm(u8 *buf, u32 *buf_len, u8 ttl,
+	u8 flags, u16 reason, u16 precedence)
+{
+	u8 ie_data[6];
+
+	ie_data[0] = ttl;
+	ie_data[1] = flags;
+	RTW_PUT_LE16((u8*)&ie_data[2], reason);
+	RTW_PUT_LE16((u8*)&ie_data[4], precedence);
+
+	return rtw_set_ie(buf, 0x118,  6, ie_data, buf_len);
+}
+
+/*----------------------------------------------------------------------------
+index: the information element id index, limit is the limit for search
+-----------------------------------------------------------------------------*/
+u8 *rtw_get_ie(u8 *pbuf, sint index, sint *len, sint limit)
+{
+	sint tmp,i;
+	u8 *p;
+_func_enter_;
+	if (limit < 1){
+		_func_exit_;	
+		return NULL;
+	}
+
+	p = pbuf;
+	i = 0;
+	*len = 0;
+	while(1)
+	{
+		if (*p == index)
+		{
+			*len = *(p + 1);
+			return (p);
+		}
+		else
+		{
+			tmp = *(p + 1);
+			p += (tmp + 2);
+			i += (tmp + 2);
+		}
+		if (i >= limit)
+			break;
+	}
+_func_exit_;		
+	return NULL;
+}
+
+/**
+ * rtw_get_ie_ex - Search specific IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @eid: Element ID to match
+ * @oui: OUI to match
+ * @oui_len: OUI length
+ * @ie: If not NULL and the specific IE is found, the IE will be copied to the buf starting from the specific IE
+ * @ielen: If not NULL and the specific IE is found, will set to the length of the entire IE
+ *
+ * Returns: The address of the specific IE found, or NULL
+ */
+u8 *rtw_get_ie_ex(u8 *in_ie, uint in_len, u8 eid, u8 *oui, u8 oui_len, u8 *ie, uint *ielen)
+{
+	uint cnt;
+	u8 *target_ie = NULL;
+
+
+	if(ielen)
+		*ielen = 0;
+
+	if(!in_ie || in_len<=0)
+		return target_ie;
+
+	cnt = 0;
+
+	while(cnt<in_len)
+	{
+		if(eid == in_ie[cnt]
+			&& ( !oui || _rtw_memcmp(&in_ie[cnt+2], oui, oui_len) == _TRUE))
+		{
+			target_ie = &in_ie[cnt];
+
+			if(ie)
+				_rtw_memcpy(ie, &in_ie[cnt], in_ie[cnt+1]+2);
+			
+			if(ielen)
+				*ielen = in_ie[cnt+1]+2;
+
+			break;
+		}
+		else
+		{
+			cnt+=in_ie[cnt+1]+2; //goto next	
+		}		
+
+	}	
+
+	return target_ie;
+}
+
+/**
+ * rtw_ies_remove_ie - Find matching IEs and remove
+ * @ies: Address of IEs to search
+ * @ies_len: Pointer of length of ies, will update to new length
+ * @offset: The offset to start scarch
+ * @eid: Element ID to match
+ * @oui: OUI to match
+ * @oui_len: OUI length
+ *
+ * Returns: _SUCCESS: ies is updated, _FAIL: not updated
+ */
+int rtw_ies_remove_ie(u8 *ies, uint *ies_len, uint offset, u8 eid, u8 *oui, u8 oui_len)
+{
+	int ret = _FAIL;
+	u8 *target_ie;
+	u32 target_ielen;
+	u8 *start;
+	uint search_len;
+	
+	if(!ies || !ies_len || *ies_len <= offset)
+		goto exit;
+
+	start = ies + offset;
+	search_len = *ies_len - offset;
+
+	while (1) {
+		target_ie = rtw_get_ie_ex(start, search_len, eid, oui, oui_len, NULL, &target_ielen);
+		if (target_ie && target_ielen) {
+			u8 *remain_ies = target_ie + target_ielen;
+			uint remain_len = search_len - (remain_ies - start);
+
+			_rtw_memmove(target_ie, remain_ies, remain_len);
+			*ies_len = *ies_len - target_ielen;
+			ret = _SUCCESS;
+
+			start = target_ie;
+			search_len = remain_len;
+		} else {
+			break;
+		}
+	}
+exit:
+	return ret;
+}
+
+void rtw_set_supported_rate(u8* SupportedRates, uint mode) 
+{
+_func_enter_;
+
+	_rtw_memset(SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+	
+	switch (mode)
+	{
+		case WIRELESS_11B:
+			_rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+			break;
+		
+		case WIRELESS_11G:
+		case WIRELESS_11A:
+		case WIRELESS_11_5N:
+		case WIRELESS_11A_5N://Todo: no basic rate for ofdm ?
+		case WIRELESS_11_5AC:
+			_rtw_memcpy(SupportedRates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+			break;
+		
+		case WIRELESS_11BG:
+		case WIRELESS_11G_24N:
+		case WIRELESS_11_24N:
+		case WIRELESS_11BG_24N:
+			_rtw_memcpy(SupportedRates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
+			_rtw_memcpy(SupportedRates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
+			break;
+	
+	}
+_func_exit_;	
+}
+
+uint	rtw_get_rateset_len(u8	*rateset)
+{
+	uint i = 0;
+_func_enter_;	
+	while(1)
+	{
+		if ((rateset[i]) == 0)
+			break;
+			
+		if (i > 12)
+			break;
+			
+		i++;			
+	}
+_func_exit_;		
+	return i;
+}
+
+int rtw_generate_ie(struct registry_priv *pregistrypriv)
+{
+	u8	wireless_mode;
+	int 	sz = 0, rateLen;
+	WLAN_BSSID_EX*	pdev_network = &pregistrypriv->dev_network;
+	u8*	ie = pdev_network->IEs;
+	
+_func_enter_;		
+
+	//timestamp will be inserted by hardware
+	sz += 8;	
+	ie += sz;
+	
+	//beacon interval : 2bytes
+	*(u16*)ie = cpu_to_le16((u16)pdev_network->Configuration.BeaconPeriod);//BCN_INTERVAL;
+	sz += 2; 
+	ie += 2;
+	
+	//capability info
+	*(u16*)ie = 0;
+	
+	*(u16*)ie |= cpu_to_le16(cap_IBSS);
+
+	if(pregistrypriv->preamble == PREAMBLE_SHORT)
+		*(u16*)ie |= cpu_to_le16(cap_ShortPremble);
+	
+	if (pdev_network->Privacy)
+		*(u16*)ie |= cpu_to_le16(cap_Privacy);
+	
+	sz += 2;
+	ie += 2;
+	
+	//SSID
+	ie = rtw_set_ie(ie, _SSID_IE_, pdev_network->Ssid.SsidLength, pdev_network->Ssid.Ssid, &sz);
+	
+	//supported rates
+	if(pregistrypriv->wireless_mode == WIRELESS_11ABGN)
+	{
+		if(pdev_network->Configuration.DSConfig > 14)
+			wireless_mode = WIRELESS_11A_5N;
+		else
+			wireless_mode = WIRELESS_11BG_24N;
+	}
+	else
+	{
+		wireless_mode = pregistrypriv->wireless_mode;
+	}
+	
+	rtw_set_supported_rate(pdev_network->SupportedRates, wireless_mode) ;
+	
+	rateLen = rtw_get_rateset_len(pdev_network->SupportedRates);
+
+	if (rateLen > 8)
+	{
+		ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, pdev_network->SupportedRates, &sz);
+		//ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
+	}
+	else
+	{
+		ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, pdev_network->SupportedRates, &sz);
+	}
+
+	//DS parameter set
+	ie = rtw_set_ie(ie, _DSSET_IE_, 1, (u8 *)&(pdev_network->Configuration.DSConfig), &sz);
+
+
+	//IBSS Parameter Set
+	
+	ie = rtw_set_ie(ie, _IBSS_PARA_IE_, 2, (u8 *)&(pdev_network->Configuration.ATIMWindow), &sz);
+
+	if (rateLen > 8)
+	{		
+		ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (pdev_network->SupportedRates + 8), &sz);
+	}
+	
+#ifdef CONFIG_80211N_HT
+	//HT Cap.
+	if(((pregistrypriv->wireless_mode&WIRELESS_11_5N)||(pregistrypriv->wireless_mode&WIRELESS_11_24N)) 
+		&& (pregistrypriv->ht_enable==_TRUE))
+	{
+		//todo:
+	}
+#endif //CONFIG_80211N_HT
+
+	//pdev_network->IELength =  sz; //update IELength
+
+_func_exit_;
+
+	//return _SUCCESS;
+
+	return sz;
+
+}
+
+unsigned char *rtw_get_wpa_ie(unsigned char *pie, int *wpa_ie_len, int limit)
+{
+	int len;
+	u16 val16;
+	unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
+	u8 *pbuf = pie;
+	int limit_new = limit;
+
+	while(1) 
+	{
+		pbuf = rtw_get_ie(pbuf, _WPA_IE_ID_, &len, limit_new);
+
+		if (pbuf) {
+
+			//check if oui matches...
+			if (_rtw_memcmp((pbuf + 2), wpa_oui_type, sizeof (wpa_oui_type)) == _FALSE) {
+
+				goto check_next_ie;
+			}
+
+			//check version...
+			_rtw_memcpy((u8 *)&val16, (pbuf + 6), sizeof(val16));
+
+			val16 = le16_to_cpu(val16);
+			if (val16 != 0x0001)
+				goto check_next_ie;
+
+			*wpa_ie_len = *(pbuf + 1);
+
+			return pbuf;
+
+		}
+		else {
+
+			*wpa_ie_len = 0;
+			return NULL;
+		}
+
+check_next_ie:
+
+		limit_new = limit - (pbuf - pie) - 2 - len;
+
+		if (limit_new <= 0)
+			break;
+
+		pbuf += (2 + len);
+
+	}
+
+	*wpa_ie_len = 0;
+
+	return NULL;
+
+}
+
+unsigned char *rtw_get_wpa2_ie(unsigned char *pie, int *rsn_ie_len, int limit)
+{	
+
+	return rtw_get_ie(pie, _WPA2_IE_ID_,rsn_ie_len, limit);
+
+}
+
+int rtw_get_wpa_cipher_suite(u8 *s)
+{
+	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_NONE;
+	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_WEP40;
+	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_TKIP;
+	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_CCMP;
+	if (_rtw_memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_WEP104;
+
+	return 0;
+}
+
+int rtw_get_wpa2_cipher_suite(u8 *s)
+{
+	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_NONE;
+	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_WEP40;
+	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_TKIP;
+	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_CCMP;
+	if (_rtw_memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == _TRUE)
+		return WPA_CIPHER_WEP104;
+
+	return 0;
+}
+
+
+int rtw_parse_wpa_ie(u8* wpa_ie, int wpa_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+{
+	int i, ret=_SUCCESS;
+	int left, count;
+	u8 *pos;
+	u8 SUITE_1X[4] = {0x00, 0x50, 0xf2, 1};
+
+	if (wpa_ie_len <= 0) {
+		/* No WPA IE - fail silently */
+		return _FAIL;
+	}
+
+	
+	if ((*wpa_ie != _WPA_IE_ID_) || (*(wpa_ie+1) != (u8)(wpa_ie_len - 2)) ||
+	   (_rtw_memcmp(wpa_ie+2, RTW_WPA_OUI_TYPE, WPA_SELECTOR_LEN) != _TRUE) )
+	{		
+		return _FAIL;
+	}
+
+	pos = wpa_ie;
+
+	pos += 8;
+	left = wpa_ie_len - 8;	
+
+
+	//group_cipher
+	if (left >= WPA_SELECTOR_LEN) {
+
+		*group_cipher = rtw_get_wpa_cipher_suite(pos);
+		
+		pos += WPA_SELECTOR_LEN;
+		left -= WPA_SELECTOR_LEN;
+		
+	} 
+	else if (left > 0)
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie length mismatch, %u too much", __FUNCTION__, left));
+		
+		return _FAIL;
+	}
+
+
+	//pairwise_cipher
+	if (left >= 2)
+	{		
+                //count = le16_to_cpu(*(u16*)pos);	
+		count = RTW_GET_LE16(pos);
+		pos += 2;
+		left -= 2;
+		
+		if (count == 0 || left < count * WPA_SELECTOR_LEN) {
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie count botch (pairwise), "
+				   		"count %u left %u", __FUNCTION__, count, left));
+			return _FAIL;
+		}
+		
+		for (i = 0; i < count; i++)
+		{
+			*pairwise_cipher |= rtw_get_wpa_cipher_suite(pos);
+			
+			pos += WPA_SELECTOR_LEN;
+			left -= WPA_SELECTOR_LEN;
+		}
+		
+	} 
+	else if (left == 1)
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie too short (for key mgmt)",   __FUNCTION__));
+		return _FAIL;
+	}
+
+	if (is_8021x) {
+		if (left >= 6) {
+			pos += 2;
+			if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s : there has 802.1x auth\n", __FUNCTION__));
+				*is_8021x = 1;
+			}
+		}
+	}
+	
+	return ret;
+	
+}
+
+int rtw_parse_wpa2_ie(u8* rsn_ie, int rsn_ie_len, int *group_cipher, int *pairwise_cipher, int *is_8021x)
+{
+	int i, ret=_SUCCESS;
+	int left, count;
+	u8 *pos;
+	u8 SUITE_1X[4] = {0x00,0x0f, 0xac, 0x01};
+
+	if (rsn_ie_len <= 0) {
+		/* No RSN IE - fail silently */
+		return _FAIL;
+	}
+
+
+	if ((*rsn_ie!= _WPA2_IE_ID_) || (*(rsn_ie+1) != (u8)(rsn_ie_len - 2)))
+	{		
+		return _FAIL;
+	}
+	
+	pos = rsn_ie;
+	pos += 4;
+	left = rsn_ie_len - 4;	
+
+	//group_cipher
+	if (left >= RSN_SELECTOR_LEN) {
+
+		*group_cipher = rtw_get_wpa2_cipher_suite(pos);
+		
+		pos += RSN_SELECTOR_LEN;
+		left -= RSN_SELECTOR_LEN;
+		
+	} else if (left > 0) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie length mismatch, %u too much", __FUNCTION__, left));
+		return _FAIL;
+	}
+
+	//pairwise_cipher
+	if (left >= 2)
+	{		
+	        //count = le16_to_cpu(*(u16*)pos);
+		count = RTW_GET_LE16(pos);
+		pos += 2;
+		left -= 2;
+
+		if (count == 0 || left < count * RSN_SELECTOR_LEN) {
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie count botch (pairwise), "
+				  		 "count %u left %u", __FUNCTION__, count, left));
+			return _FAIL;
+		}
+		
+		for (i = 0; i < count; i++)
+		{			
+			*pairwise_cipher |= rtw_get_wpa2_cipher_suite(pos);
+			
+			pos += RSN_SELECTOR_LEN;
+			left -= RSN_SELECTOR_LEN;
+		}
+
+	} 
+	else if (left == 1)
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s: ie too short (for key mgmt)",  __FUNCTION__));
+		
+		return _FAIL;
+	}
+
+	if (is_8021x) {
+		if (left >= 6) {
+			pos += 2;
+			if (_rtw_memcmp(pos, SUITE_1X, 4) == 1) {
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s (): there has 802.1x auth\n", __FUNCTION__));
+				*is_8021x = 1;
+			}
+		}
+	}
+
+	return ret;
+	
+}
+
+//#ifdef CONFIG_WAPI_SUPPORT
+int rtw_get_wapi_ie(u8 *in_ie,uint in_len,u8 *wapi_ie,u16 *wapi_len)
+{
+	int len = 0;
+	u8 authmode, i;
+	uint 	cnt;
+	u8 wapi_oui1[4]={0x0,0x14,0x72,0x01};
+	u8 wapi_oui2[4]={0x0,0x14,0x72,0x02};
+
+_func_enter_;
+
+	if(wapi_len)
+		*wapi_len = 0;
+
+	if(!in_ie || in_len<=0)
+		return len;
+
+	cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
+	
+	while(cnt<in_len)
+	{
+		authmode=in_ie[cnt];
+
+		//if(authmode==_WAPI_IE_)
+		if(authmode==_WAPI_IE_ && (_rtw_memcmp(&in_ie[cnt+6], wapi_oui1,4)==_TRUE ||
+				       	_rtw_memcmp(&in_ie[cnt+6], wapi_oui2,4)==_TRUE))
+		{
+			if (wapi_ie) {
+				_rtw_memcpy(wapi_ie, &in_ie[cnt],in_ie[cnt+1]+2);
+
+				for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
+					RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
+								wapi_ie[i],wapi_ie[i+1],wapi_ie[i+2],wapi_ie[i+3],wapi_ie[i+4],
+								wapi_ie[i+5],wapi_ie[i+6],wapi_ie[i+7]));
+				}
+			}
+
+			if(wapi_len)
+				*wapi_len=in_ie[cnt+1]+2;
+			
+			cnt+=in_ie[cnt+1]+2;  //get next
+		}
+		else
+		{
+			cnt+=in_ie[cnt+1]+2;   //get next
+		}
+	}
+
+	if(wapi_len)
+		len = *wapi_len;
+
+_func_exit_;
+
+	return len;
+
+}
+//#endif
+
+int rtw_get_sec_ie(u8 *in_ie,uint in_len,u8 *rsn_ie,u16 *rsn_len,u8 *wpa_ie,u16 *wpa_len)
+{
+	u8 authmode, sec_idx, i;
+	u8 wpa_oui[4]={0x0,0x50,0xf2,0x01};
+	uint 	cnt;
+	
+_func_enter_;
+
+	//Search required WPA or WPA2 IE and copy to sec_ie[ ]
+	
+	cnt = (_TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_);
+	
+	sec_idx=0;
+		
+	while(cnt<in_len)
+	{
+		authmode=in_ie[cnt];
+		
+		if((authmode==_WPA_IE_ID_)&&(_rtw_memcmp(&in_ie[cnt+2], &wpa_oui[0],4)==_TRUE))
+		{	
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw_get_wpa_ie: sec_idx=%d in_ie[cnt+1]+2=%d\n",sec_idx,in_ie[cnt+1]+2));		
+
+				if (wpa_ie) {
+				_rtw_memcpy(wpa_ie, &in_ie[cnt],in_ie[cnt+1]+2);
+
+				for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
+						RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
+									wpa_ie[i],wpa_ie[i+1],wpa_ie[i+2],wpa_ie[i+3],wpa_ie[i+4],
+									wpa_ie[i+5],wpa_ie[i+6],wpa_ie[i+7]));
+					}
+				}
+
+				*wpa_len=in_ie[cnt+1]+2;
+				cnt+=in_ie[cnt+1]+2;  //get next
+		}
+		else
+		{
+			if(authmode==_WPA2_IE_ID_)
+			{
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n get_rsn_ie: sec_idx=%d in_ie[cnt+1]+2=%d\n",sec_idx,in_ie[cnt+1]+2));		
+
+				if (rsn_ie) {
+				_rtw_memcpy(rsn_ie, &in_ie[cnt],in_ie[cnt+1]+2);
+
+				for(i=0;i<(in_ie[cnt+1]+2);i=i+8){
+						RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n %2x,%2x,%2x,%2x,%2x,%2x,%2x,%2x\n",
+									rsn_ie[i],rsn_ie[i+1],rsn_ie[i+2],rsn_ie[i+3],rsn_ie[i+4],
+									rsn_ie[i+5],rsn_ie[i+6],rsn_ie[i+7]));
+					}
+				}
+
+				*rsn_len=in_ie[cnt+1]+2;
+				cnt+=in_ie[cnt+1]+2;  //get next
+			}
+			else
+			{
+				cnt+=in_ie[cnt+1]+2;   //get next
+			}	
+		}
+		
+	}
+	
+_func_exit_;
+
+	return (*rsn_len+*wpa_len);
+	
+}
+
+u8 rtw_is_wps_ie(u8 *ie_ptr, uint *wps_ielen)
+{	
+	u8 match = _FALSE;
+	u8 eid, wps_oui[4]={0x0,0x50,0xf2,0x04};
+	
+	if(ie_ptr == NULL) return match;
+	
+	eid = ie_ptr[0];
+	
+	if((eid==_WPA_IE_ID_)&&(_rtw_memcmp(&ie_ptr[2], wps_oui, 4)==_TRUE))
+	{			
+		//DBG_8192C("==> found WPS_IE.....\n");
+		*wps_ielen = ie_ptr[1]+2;			
+		match=_TRUE;
+	}	
+	return match;
+}
+
+u8 *rtw_get_wps_ie_from_scan_queue(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen, u8 frame_type)
+{
+	u8*	wps = NULL;
+
+	DBG_871X( "[%s] frame_type = %d\n", __FUNCTION__, frame_type );
+	switch( frame_type )
+	{
+		case 1:
+		case 3:
+		{	//	Beacon or Probe Response
+			wps = rtw_get_wps_ie(in_ie + _PROBERSP_IE_OFFSET_, in_len - _PROBERSP_IE_OFFSET_, wps_ie, wps_ielen);
+			break;
+		}
+		case 2:
+		{	//	Probe Request
+			wps = rtw_get_wps_ie(in_ie + _PROBEREQ_IE_OFFSET_ , in_len - _PROBEREQ_IE_OFFSET_ , wps_ie, wps_ielen);
+			break;
+		}
+	}
+	return wps;
+}
+
+/**
+ * rtw_get_wps_ie - Search WPS IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @wps_ie: If not NULL and WPS IE is found, WPS IE will be copied to the buf starting from wps_ie
+ * @wps_ielen: If not NULL and WPS IE is found, will set to the length of the entire WPS IE
+ *
+ * Returns: The address of the WPS IE found, or NULL
+ */
+u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
+{
+	uint cnt;
+	u8 *wpsie_ptr = NULL;
+	u8 eid, wps_oui[4] = {0x00, 0x50, 0xf2, 0x04};
+
+	if (wps_ielen)
+		*wps_ielen = 0;
+
+	if (!in_ie) {
+		rtw_warn_on(1);
+		return wpsie_ptr;
+	}
+
+	if (in_len <= 0)
+		return wpsie_ptr;
+
+	cnt = 0;
+
+	while (cnt + 1 + 4 < in_len) {
+		eid = in_ie[cnt];
+
+		if (cnt + 1 + 4 >= MAX_IE_SZ) {
+			rtw_warn_on(1);
+			return NULL;
+		}
+
+		if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], wps_oui, 4) == _TRUE) {
+			wpsie_ptr = in_ie + cnt;
+
+			if (wps_ie)
+				_rtw_memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+			if (wps_ielen)
+				*wps_ielen = in_ie[cnt + 1] + 2;
+
+			break;
+		} else {
+			cnt += in_ie[cnt + 1] + 2;
+		}
+
+	}
+
+	return wpsie_ptr;
+}
+
+/**
+ * rtw_get_wps_attr - Search a specific WPS attribute from a given WPS IE
+ * @wps_ie: Address of WPS IE to search
+ * @wps_ielen: Length limit from wps_ie
+ * @target_attr_id: The attribute ID of WPS attribute to search
+ * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute will be copied to the buf starting from buf_attr
+ * @len_attr: If not NULL and the WPS attribute is found, will set to the length of the entire WPS attribute
+ *
+ * Returns: the address of the specific WPS attribute found, or NULL
+ */
+u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_attr, u32 *len_attr)
+{
+	u8 *attr_ptr = NULL;
+	u8 * target_attr_ptr = NULL;
+	u8 wps_oui[4]={0x00,0x50,0xF2,0x04};
+
+	if(len_attr)
+		*len_attr = 0;
+
+	if ( ( wps_ie[0] != _VENDOR_SPECIFIC_IE_ ) ||
+		( _rtw_memcmp( wps_ie + 2, wps_oui , 4 ) != _TRUE ) )
+	{
+		return attr_ptr;
+	}
+
+	// 6 = 1(Element ID) + 1(Length) + 4(WPS OUI)
+	attr_ptr = wps_ie + 6; //goto first attr
+	
+	while(attr_ptr - wps_ie < wps_ielen)
+	{
+		// 4 = 2(Attribute ID) + 2(Length)
+		u16 attr_id = RTW_GET_BE16(attr_ptr);
+		u16 attr_data_len = RTW_GET_BE16(attr_ptr + 2);
+		u16 attr_len = attr_data_len + 4;
+		
+		//DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __FUNCTION__, attr_ptr, attr_id, attr_data_len);
+		if( attr_id == target_attr_id )
+		{
+			target_attr_ptr = attr_ptr;
+		
+			if(buf_attr)
+				_rtw_memcpy(buf_attr, attr_ptr, attr_len);
+			
+			if(len_attr)
+				*len_attr = attr_len;
+			
+			break;
+		}
+		else
+		{
+			attr_ptr += attr_len; //goto next
+		}		
+		
+	}	
+
+	return target_attr_ptr;
+}
+
+/**
+ * rtw_get_wps_attr_content - Search a specific WPS attribute content from a given WPS IE
+ * @wps_ie: Address of WPS IE to search
+ * @wps_ielen: Length limit from wps_ie
+ * @target_attr_id: The attribute ID of WPS attribute to search
+ * @buf_content: If not NULL and the WPS attribute is found, WPS attribute content will be copied to the buf starting from buf_content
+ * @len_content: If not NULL and the WPS attribute is found, will set to the length of the WPS attribute content
+ *
+ * Returns: the address of the specific WPS attribute content found, or NULL
+ */
+u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_id ,u8 *buf_content, uint *len_content)
+{
+	u8 *attr_ptr;
+	u32 attr_len;
+
+	if(len_content)
+		*len_content = 0;
+	
+	attr_ptr = rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &attr_len);
+
+	if(attr_ptr && attr_len)
+	{
+		if(buf_content)
+			_rtw_memcpy(buf_content, attr_ptr+4, attr_len-4);
+
+		if(len_content)
+			*len_content = attr_len-4;
+
+		return attr_ptr+4;
+	}
+
+	return NULL;
+}
+
+static int rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
+					    struct rtw_ieee802_11_elems *elems,
+					    int show_errors)
+{
+	unsigned int oui;
+
+	/* first 3 bytes in vendor specific information element are the IEEE
+	 * OUI of the vendor. The following byte is used a vendor specific
+	 * sub-type. */
+	if (elen < 4) {
+		if (show_errors) {
+			DBG_871X("short vendor specific "
+				   "information element ignored (len=%lu)\n",
+				   (unsigned long) elen);
+		}
+		return -1;
+	}
+
+	oui = RTW_GET_BE24(pos);
+	switch (oui) {
+	case OUI_MICROSOFT:
+		/* Microsoft/Wi-Fi information elements are further typed and
+		 * subtyped */
+		switch (pos[3]) {
+		case 1:
+			/* Microsoft OUI (00:50:F2) with OUI Type 1:
+			 * real WPA information element */
+			elems->wpa_ie = pos;
+			elems->wpa_ie_len = elen;
+			break;
+		case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
+			if (elen < 5) {
+				DBG_871X("short WME "
+					   "information element ignored "
+					   "(len=%lu)\n",
+					   (unsigned long) elen);
+				return -1;
+			}
+			switch (pos[4]) {
+			case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
+			case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
+				elems->wme = pos;
+				elems->wme_len = elen;
+				break;
+			case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
+				elems->wme_tspec = pos;
+				elems->wme_tspec_len = elen;
+				break;
+			default:
+				DBG_871X_LEVEL(_drv_warning_, "unknown WME "
+					   "information element ignored "
+					   "(subtype=%d len=%lu)\n",
+					   pos[4], (unsigned long) elen);
+				return -1;
+			}
+			break;
+		case 4:
+			/* Wi-Fi Protected Setup (WPS) IE */
+			elems->wps_ie = pos;
+			elems->wps_ie_len = elen;
+			break;
+		default:
+			DBG_871X_LEVEL(_drv_warning_, "Unknown Microsoft "
+				   "information element ignored "
+				   "(type=%d len=%lu)\n",
+				   pos[3], (unsigned long) elen);
+			return -1;
+		}
+		break;
+
+	case OUI_BROADCOM:
+		switch (pos[3]) {
+		case VENDOR_HT_CAPAB_OUI_TYPE:
+			elems->vendor_ht_cap = pos;
+			elems->vendor_ht_cap_len = elen;
+			break;
+		default:
+			DBG_871X_LEVEL(_drv_warning_, "Unknown Broadcom "
+				   "information element ignored "
+				   "(type=%d len=%lu)\n",
+				   pos[3], (unsigned long) elen);
+			return -1;
+		}
+		break;
+
+	default:
+		DBG_871X_LEVEL(_drv_warning_, "unknown vendor specific information "
+			   "element ignored (vendor OUI %02x:%02x:%02x "
+			   "len=%lu)\n",
+			   pos[0], pos[1], pos[2], (unsigned long) elen);
+		return -1;
+	}
+
+	return 0;
+	
+}
+
+/**
+ * ieee802_11_parse_elems - Parse information elements in management frames
+ * @start: Pointer to the start of IEs
+ * @len: Length of IE buffer in octets
+ * @elems: Data structure for parsed elements
+ * @show_errors: Whether to show parsing errors in debug log
+ * Returns: Parsing result
+ */
+ParseRes rtw_ieee802_11_parse_elems(u8 *start, uint len,
+				struct rtw_ieee802_11_elems *elems,
+				int show_errors)
+{
+	uint left = len;
+	u8 *pos = start;
+	int unknown = 0;
+
+	_rtw_memset(elems, 0, sizeof(*elems));
+
+	while (left >= 2) {
+		u8 id, elen;
+
+		id = *pos++;
+		elen = *pos++;
+		left -= 2;
+
+		if (elen > left) {
+			if (show_errors) {
+				DBG_871X("IEEE 802.11 element "
+					   "parse failed (id=%d elen=%d "
+					   "left=%lu)\n",
+					   id, elen, (unsigned long) left);				
+			}
+			return ParseFailed;
+		}
+
+		switch (id) {
+		case WLAN_EID_SSID:
+			elems->ssid = pos;
+			elems->ssid_len = elen;
+			break;
+		case WLAN_EID_SUPP_RATES:
+			elems->supp_rates = pos;
+			elems->supp_rates_len = elen;
+			break;
+		case WLAN_EID_FH_PARAMS:
+			elems->fh_params = pos;
+			elems->fh_params_len = elen;
+			break;
+		case WLAN_EID_DS_PARAMS:
+			elems->ds_params = pos;
+			elems->ds_params_len = elen;
+			break;
+		case WLAN_EID_CF_PARAMS:
+			elems->cf_params = pos;
+			elems->cf_params_len = elen;
+			break;
+		case WLAN_EID_TIM:
+			elems->tim = pos;
+			elems->tim_len = elen;
+			break;
+		case WLAN_EID_IBSS_PARAMS:
+			elems->ibss_params = pos;
+			elems->ibss_params_len = elen;
+			break;
+		case WLAN_EID_CHALLENGE:
+			elems->challenge = pos;
+			elems->challenge_len = elen;
+			break;
+		case WLAN_EID_ERP_INFO:
+			elems->erp_info = pos;
+			elems->erp_info_len = elen;
+			break;
+		case WLAN_EID_EXT_SUPP_RATES:
+			elems->ext_supp_rates = pos;
+			elems->ext_supp_rates_len = elen;
+			break;
+		case WLAN_EID_VENDOR_SPECIFIC:
+			if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
+							     elems,
+							     show_errors))
+				unknown++;
+			break;
+		case WLAN_EID_RSN:
+			elems->rsn_ie = pos;
+			elems->rsn_ie_len = elen;
+			break;
+		case WLAN_EID_PWR_CAPABILITY:
+			elems->power_cap = pos;
+			elems->power_cap_len = elen;
+			break;
+		case WLAN_EID_SUPPORTED_CHANNELS:
+			elems->supp_channels = pos;
+			elems->supp_channels_len = elen;
+			break;
+		case WLAN_EID_MOBILITY_DOMAIN:
+			elems->mdie = pos;
+			elems->mdie_len = elen;
+			break;
+		case WLAN_EID_FAST_BSS_TRANSITION:
+			elems->ftie = pos;
+			elems->ftie_len = elen;
+			break;
+		case WLAN_EID_TIMEOUT_INTERVAL:
+			elems->timeout_int = pos;
+			elems->timeout_int_len = elen;
+			break;
+		case WLAN_EID_HT_CAP:
+			elems->ht_capabilities = pos;
+			elems->ht_capabilities_len = elen;
+			break;
+		case WLAN_EID_HT_OPERATION:
+			elems->ht_operation = pos;
+			elems->ht_operation_len = elen;
+			break;
+		case WLAN_EID_VHT_CAPABILITY:
+			elems->vht_capabilities = pos;
+			elems->vht_capabilities_len = elen;
+			break;
+		case WLAN_EID_VHT_OPERATION:
+			elems->vht_operation = pos;
+			elems->vht_operation_len = elen;
+			break;
+		case WLAN_EID_VHT_OP_MODE_NOTIFY:
+			elems->vht_op_mode_notify = pos;
+			elems->vht_op_mode_notify_len = elen;
+			break;
+		default:
+			unknown++;
+			if (!show_errors)
+				break;
+			DBG_871X_LEVEL(_drv_warning_,
+				"IEEE 802.11 element parse "
+				"ignored unknown element (id=%d elen=%d)\n",
+				id, elen);
+			break;
+		}
+
+		left -= elen;
+		pos += elen;
+	}
+
+	if (left)
+		return ParseFailed;
+
+	return unknown ? ParseUnknown : ParseOK;
+	
+}
+
+static u8 key_char2num(u8 ch);
+static u8 key_char2num(u8 ch)
+{
+    if((ch>='0')&&(ch<='9'))
+        return ch - '0';
+    else if ((ch>='a')&&(ch<='f'))
+        return ch - 'a' + 10;
+    else if ((ch>='A')&&(ch<='F'))
+        return ch - 'A' + 10;
+    else
+	 return 0xff;
+}
+
+u8 str_2char2num(u8 hch, u8 lch);
+u8 str_2char2num(u8 hch, u8 lch)
+{
+    return ((key_char2num(hch) * 10 ) + key_char2num(lch));
+}
+
+u8 key_2char2num(u8 hch, u8 lch);
+u8 key_2char2num(u8 hch, u8 lch)
+{
+    return ((key_char2num(hch) << 4) | key_char2num(lch));
+}
+
+void macstr2num(u8 *dst, u8 *src);
+void macstr2num(u8 *dst, u8 *src)
+{
+	int	jj, kk;
+	for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+	{
+		dst[jj] = key_2char2num(src[kk], src[kk + 1]);
+	}
+}
+
+u8 convert_ip_addr(u8 hch, u8 mch, u8 lch)
+{
+    return ((key_char2num(hch) * 100) + (key_char2num(mch) * 10 ) + key_char2num(lch));
+}
+
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+#define MAC_ADDRESS_LEN 12
+
+int rtw_get_mac_addr_intel(unsigned char *buf)
+{
+	int ret = 0;
+	int i;
+	struct file *fp = NULL;
+	mm_segment_t oldfs;
+	unsigned char c_mac[MAC_ADDRESS_LEN];
+	char fname[]="/config/wifi/mac.txt";
+	int jj,kk;
+
+	DBG_871X("%s Enter\n", __FUNCTION__);
+
+	ret = rtw_retrieve_from_file(fname, c_mac, MAC_ADDRESS_LEN);
+	if(ret < MAC_ADDRESS_LEN)
+	{
+		return -1;
+	}
+
+	for( jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 2 )
+	{
+		buf[jj] = key_2char2num(c_mac[kk], c_mac[kk+ 1]);
+	}
+
+	DBG_871X("%s: read from file mac address: "MAC_FMT"\n",
+		 __FUNCTION__, MAC_ARG(buf));
+
+	return 0;
+}
+#endif //CONFIG_PLATFORM_INTEL_BYT
+
+/*
+ * Description:
+ * rtw_check_invalid_mac_address: 
+ * This is only used for checking mac address valid or not.
+ *
+ * Input:
+ * adapter: mac_address pointer.
+ * check_local_bit: check locally bit or not.
+ *
+ * Output:
+ * _TRUE: The mac address is invalid.
+ * _FALSE: The mac address is valid.
+ *
+ * Auther: Isaac.Li
+ */
+u8 rtw_check_invalid_mac_address(u8 *mac_addr, u8 check_local_bit)
+{
+	u8 null_mac_addr[ETH_ALEN] = {0, 0, 0, 0, 0, 0};
+	u8 multi_mac_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	u8 res = _FALSE;
+
+	if (_rtw_memcmp(mac_addr, null_mac_addr, ETH_ALEN)) {
+		res = _TRUE;
+		goto func_exit;
+	}
+
+	if (_rtw_memcmp(mac_addr, multi_mac_addr, ETH_ALEN)) {
+		res = _TRUE;
+		goto func_exit;
+	}
+
+	if (mac_addr[0] & BIT0) {
+		res = _TRUE;
+		goto func_exit;
+	}
+
+	if (check_local_bit == _TRUE) {
+		if (mac_addr[0] & BIT1) {
+			res = _TRUE;
+			goto func_exit;
+		}
+	}
+
+func_exit:
+	return res;
+}
+
+extern char* rtw_initmac;
+/**
+ * rtw_macaddr_cfg - Decide the mac address used
+ * @out: buf to store mac address decided
+ * @hw_mac_addr: mac address from efuse/epprom
+ */
+void rtw_macaddr_cfg(struct device *dev, u8 *out, const u8 *hw_mac_addr)
+{
+#define DEFAULT_RANDOM_MACADDR 1
+	u8 mac[ETH_ALEN];
+	struct device_node *np = dev->of_node;
+	const unsigned char *addr;
+	int len;
+
+	if (out == NULL) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	/* Users specify the mac address */
+	if (rtw_initmac) {
+		int jj,kk;
+
+		for (jj = 0, kk = 0; jj < ETH_ALEN; jj++, kk += 3)
+			mac[jj] = key_2char2num(rtw_initmac[kk], rtw_initmac[kk + 1]);
+
+		goto err_chk;
+	}
+
+	/* platform specified */
+#ifdef CONFIG_PLATFORM_INTEL_BYT
+	if (rtw_get_mac_addr_intel(mac) == 0)
+		goto err_chk;
+#endif
+
+	/* Use the mac address stored in the Efuse */
+	if (hw_mac_addr) {
+		_rtw_memcpy(mac, hw_mac_addr, ETH_ALEN);
+		goto err_chk;
+	}
+
+err_chk:
+	if (rtw_check_invalid_mac_address(mac, _TRUE) == _TRUE) {
+		if (np &&
+		    (addr = of_get_property(np, "local-mac-address", &len)) &&
+		    len == ETH_ALEN) {
+			memcpy(mac, addr, ETH_ALEN);
+		} else {
+			#if DEFAULT_RANDOM_MACADDR
+			DBG_871X_LEVEL(_drv_err_, "invalid mac addr:"MAC_FMT", assign random MAC\n", MAC_ARG(mac));
+			*((u32 *)(&mac[2])) = rtw_random32();
+			mac[0] = 0x00;
+			mac[1] = 0xe0;
+			mac[2] = 0x4c;
+			#else
+			DBG_871X_LEVEL(_drv_err_, "invalid mac addr:"MAC_FMT", assign default one\n", MAC_ARG(mac));
+			mac[0] = 0x00;
+			mac[1] = 0xe0;
+			mac[2] = 0x4c;
+			mac[3] = 0x87;
+			mac[4] = 0x00;
+			mac[5] = 0x00;
+			#endif
+		}
+	}
+
+	_rtw_memcpy(out, mac, ETH_ALEN);
+	DBG_871X("%s mac addr:"MAC_FMT"\n", __func__, MAC_ARG(out));
+}
+
+#ifdef CONFIG_80211N_HT
+void dump_ht_cap_ie_content(void *sel, u8 *buf, u32 buf_len)
+{
+	if (buf_len != 26) {
+		DBG_871X_SEL_NL(sel, "Invalid HT capability IE len:%d != %d\n", buf_len, 26);
+		return;
+	}
+
+	DBG_871X_SEL_NL(sel, "HT Capabilities Info:%02x%02x\n", *(buf), *(buf+1));
+	DBG_871X_SEL_NL(sel, "A-MPDU Parameters:"HT_AMPDU_PARA_FMT"\n"
+		, HT_AMPDU_PARA_ARG(HT_CAP_ELE_AMPDU_PARA(buf)));
+	DBG_871X_SEL_NL(sel, "Supported MCS Set:"HT_SUP_MCS_SET_FMT"\n"
+		, HT_SUP_MCS_SET_ARG(HT_CAP_ELE_SUP_MCS_SET(buf)));
+}
+
+void dump_ht_cap_ie(void *sel, u8 *ie, u32 ie_len)
+{
+	u8* pos = (u8*)ie;
+	u16 id;
+	u16 len;
+
+	u8 *ht_cap_ie;
+	sint ht_cap_ielen;
+
+	ht_cap_ie = rtw_get_ie(ie, _HT_CAPABILITY_IE_, &ht_cap_ielen, ie_len);
+	if(!ie || ht_cap_ie != ie)
+		return;
+
+	dump_ht_cap_ie_content(sel, ht_cap_ie+2, ht_cap_ielen);
+}
+#endif /* CONFIG_80211N_HT */
+
+void dump_ies(void *sel, u8 *buf, u32 buf_len)
+{
+	u8* pos = (u8*)buf;
+	u8 id, len;
+
+	while(pos-buf+1<buf_len){
+		id = *pos;
+		len = *(pos+1);
+
+		DBG_871X_SEL_NL(sel, "%s ID:%u, LEN:%u\n", __FUNCTION__, id, len);
+		#ifdef CONFIG_80211N_HT
+		dump_ht_cap_ie(sel, pos, len + 2);
+		#endif
+		dump_wps_ie(sel, pos, len + 2);
+		#ifdef CONFIG_P2P
+		dump_p2p_ie(sel, pos, len + 2);
+		#ifdef CONFIG_WFD
+		dump_wfd_ie(sel, pos, len + 2);
+		#endif
+		#endif
+
+		pos+=(2+len);
+	}
+}
+
+void dump_wps_ie(void *sel, u8 *ie, u32 ie_len)
+{
+	u8* pos = (u8*)ie;
+	u16 id;
+	u16 len;
+
+	u8 *wps_ie;
+	uint wps_ielen;
+
+	wps_ie = rtw_get_wps_ie(ie, ie_len, NULL, &wps_ielen);
+	if (wps_ie != ie || wps_ielen == 0)
+		return;
+
+	pos += 6;
+	while (pos - ie + 4 <= ie_len) {
+		id = RTW_GET_BE16(pos);
+		len = RTW_GET_BE16(pos + 2);
+
+		DBG_871X_SEL_NL(sel, "%s ID:0x%04x, LEN:%u%s\n", __func__, id, len
+			, ((pos - ie + 4 + len) <= ie_len) ? "" : "(exceed ie_len)");
+
+		pos += (4 + len);
+	}
+}
+
+/**
+ * rtw_ies_get_chbw - get operation ch, bw, offset from IEs of BSS.
+ * @ies: pointer of the first tlv IE
+ * @ies_len: length of @ies
+ * @ch: pointer of ch, used as output
+ * @bw: pointer of bw, used as output
+ * @offset: pointer of offset, used as output
+ */
+void rtw_ies_get_chbw(u8 *ies, int ies_len, u8 *ch, u8 *bw, u8 *offset)
+{
+	u8 *p;
+	int	ie_len;
+
+	*ch = 0;
+	*bw = CHANNEL_WIDTH_20;
+	*offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+	p = rtw_get_ie(ies, _DSSET_IE_, &ie_len, ies_len);
+	if (p && ie_len > 0)
+		*ch = *(p + 2);
+
+#ifdef CONFIG_80211N_HT
+{
+	u8 *ht_cap_ie, *ht_op_ie;
+	int ht_cap_ielen, ht_op_ielen;
+
+	ht_cap_ie = rtw_get_ie(ies, EID_HTCapability, &ht_cap_ielen, ies_len);
+	if (ht_cap_ie && ht_cap_ielen) {
+		if (GET_HT_CAP_ELE_CHL_WIDTH(ht_cap_ie + 2))
+			*bw = CHANNEL_WIDTH_40;
+	}
+
+	ht_op_ie = rtw_get_ie(ies, EID_HTInfo, &ht_op_ielen, ies_len);
+	if (ht_op_ie && ht_op_ielen) {
+		if (*ch == 0) {
+			*ch = GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2);
+		} else if (*ch != 0 && *ch != GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2)) {
+			DBG_871X("%s ch inconsistent, DSSS:%u, HT primary:%u\n"
+				, __func__, *ch, GET_HT_OP_ELE_PRI_CHL(ht_op_ie + 2));
+		}
+
+		if (!GET_HT_OP_ELE_STA_CHL_WIDTH(ht_op_ie + 2))
+			*bw = CHANNEL_WIDTH_20;
+
+		if (*bw == CHANNEL_WIDTH_40) {
+			switch (GET_HT_OP_ELE_2ND_CHL_OFFSET(ht_op_ie + 2)) {
+			case SCA:
+				*offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+				break;
+			case SCB:
+				*offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+				break;
+			}
+		}
+	}
+}
+#endif /* CONFIG_80211N_HT */
+#ifdef CONFIG_80211AC_VHT
+{
+	u8 *vht_op_ie;
+	int vht_op_ielen;
+
+	vht_op_ie = rtw_get_ie(ies, EID_VHTOperation, &vht_op_ielen, ies_len);
+	if (vht_op_ie && vht_op_ielen) {
+		if (GET_VHT_OPERATION_ELE_CHL_WIDTH(vht_op_ie + 2) >= 1)
+			*bw = CHANNEL_WIDTH_80;
+	}
+}
+#endif
+}
+
+void rtw_bss_get_chbw(WLAN_BSSID_EX *bss, u8 *ch, u8 *bw, u8 *offset)
+{
+	rtw_ies_get_chbw(bss->IEs + sizeof(NDIS_802_11_FIXED_IEs)
+		, bss->IELength - sizeof(NDIS_802_11_FIXED_IEs)
+		, ch, bw, offset);
+
+	if (*ch == 0) {
+		*ch = bss->Configuration.DSConfig;
+	} else if (*ch != bss->Configuration.DSConfig) {
+		DBG_871X("inconsistent ch - ies:%u bss->Configuration.DSConfig:%u\n"
+			, *ch, bss->Configuration.DSConfig);
+		*ch = bss->Configuration.DSConfig;
+		rtw_warn_on(1);
+	}
+}
+
+/**
+ * rtw_is_chbw_grouped - test if the two ch settings can be grouped together
+ * @ch_a: ch of set a
+ * @bw_a: bw of set a
+ * @offset_a: offset of set a
+ * @ch_b: ch of set b
+ * @bw_b: bw of set b
+ * @offset_b: offset of set b
+ */
+bool rtw_is_chbw_grouped(u8 ch_a, u8 bw_a, u8 offset_a
+	, u8 ch_b, u8 bw_b, u8 offset_b)
+{
+	bool is_grouped = _FALSE;
+
+	if (ch_a != ch_b) {
+		/* ch is different */
+		goto exit;
+	} else if ((bw_a == CHANNEL_WIDTH_40 || bw_a == CHANNEL_WIDTH_80)
+			&& (bw_b == CHANNEL_WIDTH_40 || bw_b == CHANNEL_WIDTH_80)
+	) {
+		if (offset_a != offset_b)
+			goto exit;
+	}
+
+	is_grouped = _TRUE;
+
+exit:
+	return is_grouped;
+}
+
+/**
+ * rtw_sync_chbw - obey g_ch, adjust g_bw, g_offset, bw, offset
+ * @req_ch: pointer of the request ch, may be modified further
+ * @req_bw: pointer of the request bw, may be modified further
+ * @req_offset: pointer of the request offset, may be modified further
+ * @g_ch: pointer of the ongoing group ch
+ * @g_bw: pointer of the ongoing group bw, may be modified further
+ * @g_offset: pointer of the ongoing group offset, may be modified further
+ */
+void rtw_sync_chbw(u8 *req_ch, u8 *req_bw, u8 *req_offset
+	, u8 *g_ch, u8 *g_bw, u8 *g_offset)
+{
+
+	*req_ch = *g_ch;
+
+	if (*req_bw == CHANNEL_WIDTH_80 && *g_ch <= 14) {
+		/*2.4G ch, downgrade to 40Mhz */
+		*req_bw = CHANNEL_WIDTH_40;
+	}
+
+	switch (*req_bw) {
+	case CHANNEL_WIDTH_80:
+		if (*g_bw == CHANNEL_WIDTH_40 || *g_bw == CHANNEL_WIDTH_80)
+			*req_offset = *g_offset;
+		else if (*g_bw == CHANNEL_WIDTH_20)
+			*req_offset = rtw_get_offset_by_ch(*req_ch);
+
+		if (*req_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
+			DBG_871X_LEVEL(_drv_err_, "%s req 80MHz BW without offset, down to 20MHz\n", __func__);
+			rtw_warn_on(1);
+			*req_bw = CHANNEL_WIDTH_20;
+		}
+		break;
+	case CHANNEL_WIDTH_40:
+		if (*g_bw == CHANNEL_WIDTH_40 || *g_bw == CHANNEL_WIDTH_80)
+			*req_offset = *g_offset;
+		else if (*g_bw == CHANNEL_WIDTH_20)
+			*req_offset = rtw_get_offset_by_ch(*req_ch);
+
+		if (*req_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) {
+			DBG_871X_LEVEL(_drv_err_, "%s req 40MHz BW without offset, down to 20MHz\n", __func__);
+			rtw_warn_on(1);
+			*req_bw = CHANNEL_WIDTH_20;
+		}
+		break;
+	case CHANNEL_WIDTH_20:
+		*req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		break;
+	default:
+		DBG_871X_LEVEL(_drv_err_, "%s req unsupported BW:%u\n", __func__, *req_bw);
+		rtw_warn_on(1);
+	}
+
+	if (*req_bw > *g_bw) {
+		*g_bw = *req_bw;
+		*g_offset = *req_offset;
+	}
+}
+
+#ifdef CONFIG_P2P
+/**
+ * rtw_get_p2p_merged_len - Get merged ie length from muitiple p2p ies.
+ * @in_ie: Pointer of the first p2p ie
+ * @in_len: Total len of muiltiple p2p ies
+ * Returns: Length of merged p2p ie length
+ */
+u32 rtw_get_p2p_merged_ies_len(u8 *in_ie, u32 in_len)
+{
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 OUI[4] = { 0x50, 0x6f, 0x9a, 0x09 };
+	int i=0;
+	int j=0, len=0;
+
+	while( i < in_len)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(in_ie+ i);
+
+		if( pIE->ElementID == _VENDOR_SPECIFIC_IE_ && _rtw_memcmp(pIE->data, OUI, 4) )
+		{
+			len += pIE->Length-4; // 4 is P2P OUI length, don't count it in this loop
+		}
+
+		i += (pIE->Length + 2);
+	}
+
+	return len + 4;	// Append P2P OUI length at last.
+}
+
+/**
+ * rtw_p2p_merge_ies - Merge muitiple p2p ies into one
+ * @in_ie: Pointer of the first p2p ie
+ * @in_len: Total len of muiltiple p2p ies
+ * @merge_ie: Pointer of merged ie
+ * Returns: Length of merged p2p ie
+ */
+int rtw_p2p_merge_ies(u8 *in_ie, u32 in_len, u8 *merge_ie)
+{
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 len = 0;
+	u8 OUI[4] = { 0x50, 0x6f, 0x9a, 0x09 };
+	u8 ELOUI[6] = { 0xDD, 0x00, 0x50, 0x6f, 0x9a, 0x09 };	//EID;Len;OUI, Len would copy at the end of function
+	int i=0;
+
+	if( merge_ie != NULL)
+	{
+		//Set first P2P OUI
+		_rtw_memcpy(merge_ie, ELOUI, 6);
+		merge_ie += 6;
+
+		while( i < in_len)
+		{
+			pIE = (PNDIS_802_11_VARIABLE_IEs)(in_ie+ i);
+
+			// Take out the rest of P2P OUIs
+			if( pIE->ElementID == _VENDOR_SPECIFIC_IE_ && _rtw_memcmp(pIE->data, OUI, 4) )
+			{
+				_rtw_memcpy( merge_ie, pIE->data +4, pIE->Length -4);
+				len += pIE->Length-4;
+				merge_ie += pIE->Length-4;
+			}
+
+			i += (pIE->Length + 2);
+		}
+
+		return len + 4;	// 4 is for P2P OUI
+
+	}
+
+	return 0;
+}
+
+void dump_p2p_ie(void *sel, u8 *ie, u32 ie_len)
+{
+	u8* pos = (u8*)ie;
+	u8 id;
+	u16 len;
+
+	u8 *p2p_ie;
+	uint p2p_ielen;
+
+	p2p_ie = rtw_get_p2p_ie(ie, ie_len, NULL, &p2p_ielen);
+	if (p2p_ie != ie || p2p_ielen == 0)
+		return;
+
+	pos += 6;
+	while (pos - ie + 3 <= ie_len) {
+		id = *pos;
+		len = RTW_GET_LE16(pos + 1);
+
+		DBG_871X_SEL_NL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len
+			, ((pos - ie + 3 + len) <= ie_len) ? "" : "(exceed ie_len)");
+
+		pos += (3 + len);
+	}
+}
+
+/**
+ * rtw_get_p2p_ie - Search P2P IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @p2p_ie: If not NULL and P2P IE is found, P2P IE will be copied to the buf starting from p2p_ie
+ * @p2p_ielen: If not NULL and P2P IE is found, will set to the length of the entire P2P IE
+ *
+ * Returns: The address of the P2P IE found, or NULL
+ */
+u8 *rtw_get_p2p_ie(u8 *in_ie, int in_len, u8 *p2p_ie, uint *p2p_ielen)
+{
+	uint cnt;
+	u8 *p2p_ie_ptr = NULL;
+	u8 eid, p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
+
+	if (p2p_ielen)
+		*p2p_ielen = 0;
+
+	if (!in_ie || in_len < 0) {
+		rtw_warn_on(1);
+		return p2p_ie_ptr;
+	}
+
+	if (in_len <= 0)
+		return p2p_ie_ptr;
+
+	cnt = 0;
+
+	while (cnt + 1 + 4 < in_len) {
+		eid = in_ie[cnt];
+
+		if (cnt + 1 + 4 >= MAX_IE_SZ) {
+			rtw_warn_on(1);
+			return NULL;
+		}
+
+		if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], p2p_oui, 4) == _TRUE) {
+			p2p_ie_ptr = in_ie + cnt;
+
+			if (p2p_ie)
+				_rtw_memcpy(p2p_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+			if (p2p_ielen)
+				*p2p_ielen = in_ie[cnt + 1] + 2;
+
+			break;
+		} else {
+			cnt += in_ie[cnt + 1] + 2;
+		}
+
+	}
+
+	return p2p_ie_ptr;
+}
+
+/**
+ * rtw_get_p2p_attr - Search a specific P2P attribute from a given P2P IE
+ * @p2p_ie: Address of P2P IE to search
+ * @p2p_ielen: Length limit from p2p_ie
+ * @target_attr_id: The attribute ID of P2P attribute to search
+ * @buf_attr: If not NULL and the P2P attribute is found, P2P attribute will be copied to the buf starting from buf_attr
+ * @len_attr: If not NULL and the P2P attribute is found, will set to the length of the entire P2P attribute
+ *
+ * Returns: the address of the specific WPS attribute found, or NULL
+ */
+u8 *rtw_get_p2p_attr(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_attr, u32 *len_attr)
+{
+	u8 *attr_ptr = NULL;
+	u8 *target_attr_ptr = NULL;
+	u8 p2p_oui[4] = {0x50, 0x6F, 0x9A, 0x09};
+
+	if (len_attr)
+		*len_attr = 0;
+
+	if (!p2p_ie
+		|| p2p_ielen <= 6
+		|| (p2p_ie[0] != WLAN_EID_VENDOR_SPECIFIC)
+		|| (_rtw_memcmp(p2p_ie + 2, p2p_oui, 4) != _TRUE))
+		return attr_ptr;
+
+	/* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
+	attr_ptr = p2p_ie + 6; /* goto first attr */
+
+	while ((attr_ptr - p2p_ie + 3) <= p2p_ielen) {
+		/* 3 = 1(Attribute ID) + 2(Length) */
+		u8 attr_id = *attr_ptr;
+		u16 attr_data_len = RTW_GET_LE16(attr_ptr + 1);
+		u16 attr_len = attr_data_len + 3;
+
+		if (0)
+			DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len);
+
+		if ((attr_ptr - p2p_ie + attr_len) > p2p_ielen)
+			break;
+
+		if (attr_id == target_attr_id) {
+			target_attr_ptr = attr_ptr;
+
+			if (buf_attr)
+				_rtw_memcpy(buf_attr, attr_ptr, attr_len);
+
+			if (len_attr)
+				*len_attr = attr_len;
+
+			break;
+		} else {
+			attr_ptr += attr_len;
+		}
+	}	
+
+	return target_attr_ptr;
+}
+
+/**
+ * rtw_get_p2p_attr_content - Search a specific P2P attribute content from a given P2P IE
+ * @p2p_ie: Address of P2P IE to search
+ * @p2p_ielen: Length limit from p2p_ie
+ * @target_attr_id: The attribute ID of P2P attribute to search
+ * @buf_content: If not NULL and the P2P attribute is found, P2P attribute content will be copied to the buf starting from buf_content
+ * @len_content: If not NULL and the P2P attribute is found, will set to the length of the P2P attribute content
+ *
+ * Returns: the address of the specific P2P attribute content found, or NULL
+ */
+u8 *rtw_get_p2p_attr_content(u8 *p2p_ie, uint p2p_ielen, u8 target_attr_id ,u8 *buf_content, uint *len_content)
+{
+	u8 *attr_ptr;
+	u32 attr_len;
+
+	if (len_content)
+		*len_content = 0;
+
+	attr_ptr = rtw_get_p2p_attr(p2p_ie, p2p_ielen, target_attr_id, NULL, &attr_len);
+
+	if (attr_ptr && attr_len) {
+		if (buf_content)
+			_rtw_memcpy(buf_content, attr_ptr + 3, attr_len - 3);
+
+		if (len_content)
+			*len_content = attr_len - 3;
+
+		return attr_ptr + 3;
+	}
+
+	return NULL;
+}
+
+u32 rtw_set_p2p_attr_content(u8 *pbuf, u8 attr_id, u16 attr_len, u8 *pdata_attr)
+{	
+	u32 a_len;
+
+	*pbuf = attr_id;
+		
+	//*(u16*)(pbuf + 1) = cpu_to_le16(attr_len);
+	RTW_PUT_LE16(pbuf + 1, attr_len);
+
+	if(pdata_attr)
+		_rtw_memcpy(pbuf + 3, pdata_attr, attr_len);		
+		
+	a_len = attr_len + 3;
+		
+	return a_len;
+}
+
+uint rtw_del_p2p_ie(u8 *ies, uint ies_len_ori, const char *msg)
+{
+#define DBG_DEL_P2P_IE 0
+
+	u8 *target_ie;
+	u32 target_ie_len;
+	uint ies_len = ies_len_ori;
+	int index = 0;
+
+	while (1) {
+		target_ie = rtw_get_p2p_ie(ies, ies_len, NULL, &target_ie_len);
+		if (target_ie && target_ie_len) {
+			u8 *next_ie = target_ie + target_ie_len;
+			uint remain_len = ies_len - (next_ie - ies);
+
+			if (DBG_DEL_P2P_IE && msg) {
+				DBG_871X("%s %d before\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ies, ies_len);
+
+				DBG_871X("ies:%p, ies_len:%u\n", ies, ies_len);
+				DBG_871X("target_ie:%p, target_ie_len:%u\n", target_ie, target_ie_len);
+				DBG_871X("next_ie:%p, remain_len:%u\n", next_ie, remain_len);
+			}
+
+			_rtw_memmove(target_ie, next_ie, remain_len);
+			_rtw_memset(target_ie + remain_len, 0, target_ie_len);
+			ies_len -= target_ie_len;
+
+			if (DBG_DEL_P2P_IE && msg) {
+				DBG_871X("%s %d after\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ies, ies_len);
+			}
+
+			index++;
+		} else {
+			break;
+		}
+	}
+
+	return ies_len;
+}
+
+uint rtw_del_p2p_attr(u8 *ie, uint ielen_ori, u8 attr_id)
+{
+#define DBG_DEL_P2P_ATTR 0
+
+	u8 *target_attr;
+	u32 target_attr_len;
+	uint ielen = ielen_ori;
+	int index = 0;
+
+	while(1) {
+		target_attr = rtw_get_p2p_attr(ie, ielen, attr_id, NULL, &target_attr_len);
+		if (target_attr && target_attr_len) {
+			u8 *next_attr = target_attr + target_attr_len;
+			uint remain_len = ielen - (next_attr - ie);
+
+			if (DBG_DEL_P2P_ATTR) {
+				DBG_871X("%s %d before\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ie, ielen);
+
+				DBG_871X("ie:%p, ielen:%u\n", ie, ielen);
+				DBG_871X("target_attr:%p, target_attr_len:%u\n", target_attr, target_attr_len);
+				DBG_871X("next_attr:%p, remain_len:%u\n", next_attr, remain_len);
+			}
+
+			_rtw_memmove(target_attr, next_attr, remain_len);
+			_rtw_memset(target_attr + remain_len, 0, target_attr_len);
+			*(ie + 1) -= target_attr_len;
+			ielen -= target_attr_len;
+
+			if (DBG_DEL_P2P_ATTR) {
+				DBG_871X("%s %d after\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ie, ielen);
+			}
+
+			index++;
+		} else {
+			break;
+		}
+	}
+
+	return ielen;
+}
+
+inline u8 *rtw_bss_ex_get_p2p_ie(WLAN_BSSID_EX *bss_ex, u8 *p2p_ie, uint *p2p_ielen)
+{
+	return rtw_get_p2p_ie(BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex), p2p_ie, p2p_ielen);
+}
+
+void rtw_bss_ex_del_p2p_ie(WLAN_BSSID_EX *bss_ex)
+{
+#define DBG_BSS_EX_DEL_P2P_IE 0
+
+	u8 *ies = BSS_EX_TLV_IES(bss_ex);
+	uint ies_len_ori = BSS_EX_TLV_IES_LEN(bss_ex);
+	uint ies_len;
+
+	ies_len = rtw_del_p2p_ie(ies, ies_len_ori, DBG_BSS_EX_DEL_P2P_IE ? __func__ : NULL);
+	bss_ex->IELength -= ies_len_ori - ies_len;
+}
+
+void rtw_bss_ex_del_p2p_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
+{
+#define DBG_BSS_EX_DEL_P2P_ATTR 0
+
+	u8 *ies = BSS_EX_TLV_IES(bss_ex);
+	uint ies_len = BSS_EX_TLV_IES_LEN(bss_ex);
+
+	u8 *ie;
+	uint ie_len, ie_len_ori;
+
+	int index = 0;
+
+	while (1) {
+		ie = rtw_get_p2p_ie(ies, ies_len, NULL, &ie_len_ori);
+		if (ie) {
+			u8 *next_ie_ori = ie + ie_len_ori;
+			uint remain_len = bss_ex->IELength - (next_ie_ori - bss_ex->IEs);
+			u8 has_target_attr = 0;
+
+			if (DBG_BSS_EX_DEL_P2P_ATTR) {
+				if (rtw_get_p2p_attr(ie, ie_len_ori, attr_id, NULL, NULL)) {
+					DBG_871X("%s %d before\n", __func__, index);
+					dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex));
+
+					DBG_871X("ies:%p, ies_len:%u\n", ies, ies_len);
+					DBG_871X("ie:%p, ie_len_ori:%u\n", ie, ie_len_ori);
+					DBG_871X("next_ie_ori:%p, remain_len:%u\n", next_ie_ori, remain_len);
+					has_target_attr = 1;
+				}
+			}
+
+			ie_len = rtw_del_p2p_attr(ie, ie_len_ori, attr_id);
+			if (ie_len != ie_len_ori) {
+				u8 *next_ie = ie + ie_len;
+
+				_rtw_memmove(next_ie, next_ie_ori, remain_len);
+				_rtw_memset(next_ie + remain_len, 0, ie_len_ori - ie_len);
+				bss_ex->IELength -= ie_len_ori - ie_len;
+
+				ies = next_ie;
+			} else {
+				ies = next_ie_ori;
+			}
+
+			if (DBG_BSS_EX_DEL_P2P_ATTR) {
+				if (has_target_attr) {
+					DBG_871X("%s %d after\n", __func__, index);
+					dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex));
+				}
+			}
+
+			ies_len = remain_len;
+
+			index++;
+		} else {
+			break;
+		}
+	}
+}
+#endif /* CONFIG_P2P */
+
+#ifdef CONFIG_WFD
+void dump_wfd_ie(void *sel, u8 *ie, u32 ie_len)
+{
+	u8* pos = (u8*)ie;
+	u8 id;
+	u16 len;
+
+	u8 *wfd_ie;
+	uint wfd_ielen;
+
+	wfd_ie = rtw_get_wfd_ie(ie, ie_len, NULL, &wfd_ielen);
+	if (wfd_ie != ie || wfd_ielen == 0)
+		return;
+
+	pos += 6;
+	while (pos - ie + 3 <= ie_len) {
+		id = *pos;
+		len = RTW_GET_BE16(pos + 1);
+
+		DBG_871X_SEL_NL(sel, "%s ID:%u, LEN:%u%s\n", __func__, id, len
+			, ((pos - ie + 3 + len) <= ie_len) ? "" : "(exceed ie_len)");
+
+		pos += (3 + len);
+	}
+}
+
+/**
+ * rtw_get_wfd_ie - Search WFD IE from a series of IEs
+ * @in_ie: Address of IEs to search
+ * @in_len: Length limit from in_ie
+ * @wfd_ie: If not NULL and WFD IE is found, WFD IE will be copied to the buf starting from wfd_ie
+ * @wfd_ielen: If not NULL and WFD IE is found, will set to the length of the entire WFD IE
+ *
+ * Returns: The address of the P2P IE found, or NULL
+ */
+u8 *rtw_get_wfd_ie(u8 *in_ie, int in_len, u8 *wfd_ie, uint *wfd_ielen)
+{
+	uint cnt;
+	u8 *wfd_ie_ptr = NULL;
+	u8 eid, wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
+
+	if (wfd_ielen)
+		*wfd_ielen = 0;
+
+	if (!in_ie || in_len < 0) {
+		rtw_warn_on(1);
+		return wfd_ie_ptr;
+	}
+
+	if (in_len <= 0)
+		return wfd_ie_ptr;
+
+	cnt = 0;
+
+	while (cnt + 1 + 4 < in_len) {
+		eid = in_ie[cnt];
+
+		if (cnt + 1 + 4 >= MAX_IE_SZ) {
+			rtw_warn_on(1);
+			return NULL;
+		}
+
+		if (eid == WLAN_EID_VENDOR_SPECIFIC && _rtw_memcmp(&in_ie[cnt + 2], wfd_oui, 4) == _TRUE) {
+			wfd_ie_ptr = in_ie + cnt;
+
+			if (wfd_ie)
+				_rtw_memcpy(wfd_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
+
+			if (wfd_ielen)
+				*wfd_ielen = in_ie[cnt + 1] + 2;
+
+			break;
+		} else {
+			cnt += in_ie[cnt + 1] + 2;
+		}
+
+	}
+
+	return wfd_ie_ptr;
+}
+
+/**
+ * rtw_get_wfd_attr - Search a specific WFD attribute from a given WFD IE
+ * @wfd_ie: Address of WFD IE to search
+ * @wfd_ielen: Length limit from wfd_ie
+ * @target_attr_id: The attribute ID of WFD attribute to search
+ * @buf_attr: If not NULL and the WFD attribute is found, WFD attribute will be copied to the buf starting from buf_attr
+ * @len_attr: If not NULL and the WFD attribute is found, will set to the length of the entire WFD attribute
+ *
+ * Returns: the address of the specific WPS attribute found, or NULL
+ */
+u8 *rtw_get_wfd_attr(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id, u8 *buf_attr, u32 *len_attr)
+{
+	u8 *attr_ptr = NULL;
+	u8 *target_attr_ptr = NULL;
+	u8 wfd_oui[4] = {0x50, 0x6F, 0x9A, 0x0A};
+
+	if (len_attr)
+		*len_attr = 0;
+
+	if (!wfd_ie
+		|| wfd_ielen <= 6
+		|| (wfd_ie[0] != WLAN_EID_VENDOR_SPECIFIC)
+		|| (_rtw_memcmp(wfd_ie + 2, wfd_oui, 4) != _TRUE))
+		return attr_ptr;
+
+	/* 6 = 1(Element ID) + 1(Length) + 3 (OUI) + 1(OUI Type) */
+	attr_ptr = wfd_ie + 6; /* goto first attr */
+
+	while ((attr_ptr - wfd_ie + 3) <= wfd_ielen) {
+		/* 3 = 1(Attribute ID) + 2(Length) */
+		u8 attr_id = *attr_ptr;
+		u16 attr_data_len = RTW_GET_BE16(attr_ptr + 1);
+		u16 attr_len = attr_data_len + 3;
+
+		if (0)
+			DBG_871X("%s attr_ptr:%p, id:%u, length:%u\n", __func__, attr_ptr, attr_id, attr_data_len);
+
+		if ((attr_ptr - wfd_ie + attr_len) > wfd_ielen)
+			break;
+
+		if (attr_id == target_attr_id) {
+			target_attr_ptr = attr_ptr;
+
+			if (buf_attr)
+				_rtw_memcpy(buf_attr, attr_ptr, attr_len);
+
+			if (len_attr)
+				*len_attr = attr_len;
+
+			break;
+		} else {
+			attr_ptr += attr_len;
+		}
+	}
+
+	return target_attr_ptr;
+}
+
+/**
+ * rtw_get_wfd_attr_content - Search a specific WFD attribute content from a given WFD IE
+ * @wfd_ie: Address of WFD IE to search
+ * @wfd_ielen: Length limit from wfd_ie
+ * @target_attr_id: The attribute ID of WFD attribute to search
+ * @buf_content: If not NULL and the WFD attribute is found, WFD attribute content will be copied to the buf starting from buf_content
+ * @len_content: If not NULL and the WFD attribute is found, will set to the length of the WFD attribute content
+ *
+ * Returns: the address of the specific WFD attribute content found, or NULL
+ */
+u8 *rtw_get_wfd_attr_content(u8 *wfd_ie, uint wfd_ielen, u8 target_attr_id, u8 *buf_content, uint *len_content)
+{
+	u8 *attr_ptr;
+	u32 attr_len;
+
+	if (len_content)
+		*len_content = 0;
+
+	attr_ptr = rtw_get_wfd_attr(wfd_ie, wfd_ielen, target_attr_id, NULL, &attr_len);
+
+	if (attr_ptr && attr_len) {
+		if (buf_content)
+			_rtw_memcpy(buf_content, attr_ptr + 3, attr_len - 3);
+
+		if (len_content)
+			*len_content = attr_len - 3;
+
+		return attr_ptr + 3;
+	}
+
+	return NULL;
+}
+
+uint rtw_del_wfd_ie(u8 *ies, uint ies_len_ori, const char *msg)
+{
+#define DBG_DEL_WFD_IE 0
+
+	u8 *target_ie;
+	u32 target_ie_len;
+	uint ies_len = ies_len_ori;
+	int index = 0;
+
+	while (1) {
+		target_ie = rtw_get_wfd_ie(ies, ies_len, NULL, &target_ie_len);
+		if (target_ie && target_ie_len) {
+			u8 *next_ie = target_ie + target_ie_len;
+			uint remain_len = ies_len - (next_ie - ies);
+
+			if (DBG_DEL_WFD_IE && msg) {
+				DBG_871X("%s %d before\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ies, ies_len);
+
+				DBG_871X("ies:%p, ies_len:%u\n", ies, ies_len);
+				DBG_871X("target_ie:%p, target_ie_len:%u\n", target_ie, target_ie_len);
+				DBG_871X("next_ie:%p, remain_len:%u\n", next_ie, remain_len);
+			}
+
+			_rtw_memmove(target_ie, next_ie, remain_len);
+			_rtw_memset(target_ie + remain_len, 0, target_ie_len);
+			ies_len -= target_ie_len;
+
+			if (DBG_DEL_WFD_IE && msg) {
+				DBG_871X("%s %d after\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ies, ies_len);
+			}
+
+			index++;
+		} else {
+			break;
+		}
+	}
+
+	return ies_len;
+}
+
+uint rtw_del_wfd_attr(u8 *ie, uint ielen_ori, u8 attr_id)
+{
+#define DBG_DEL_WFD_ATTR 0
+
+	u8 *target_attr;
+	u32 target_attr_len;
+	uint ielen = ielen_ori;
+	int index = 0;
+
+	while (1) {
+		target_attr = rtw_get_wfd_attr(ie, ielen, attr_id, NULL, &target_attr_len);
+		if (target_attr && target_attr_len) {
+			u8 *next_attr = target_attr + target_attr_len;
+			uint remain_len = ielen - (next_attr - ie);
+
+			if (DBG_DEL_WFD_ATTR) {
+				DBG_871X("%s %d before\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ie, ielen);
+
+				DBG_871X("ie:%p, ielen:%u\n", ie, ielen);
+				DBG_871X("target_attr:%p, target_attr_len:%u\n", target_attr, target_attr_len);
+				DBG_871X("next_attr:%p, remain_len:%u\n", next_attr, remain_len);
+			}
+
+			_rtw_memmove(target_attr, next_attr, remain_len);
+			_rtw_memset(target_attr + remain_len, 0, target_attr_len);
+			*(ie + 1) -= target_attr_len;
+			ielen -= target_attr_len;
+
+			if (DBG_DEL_WFD_ATTR) {
+				DBG_871X("%s %d after\n", __func__, index);
+				dump_ies(RTW_DBGDUMP, ie, ielen);
+			}
+
+			index++;
+		} else {
+			break;
+		}
+	}
+
+	return ielen;
+}
+
+inline u8 *rtw_bss_ex_get_wfd_ie(WLAN_BSSID_EX *bss_ex, u8 *wfd_ie, uint *wfd_ielen)
+{
+	return rtw_get_wfd_ie(BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex), wfd_ie, wfd_ielen);
+}
+
+void rtw_bss_ex_del_wfd_ie(WLAN_BSSID_EX *bss_ex)
+{
+#define DBG_BSS_EX_DEL_WFD_IE 0
+	u8 *ies = BSS_EX_TLV_IES(bss_ex);
+	uint ies_len_ori = BSS_EX_TLV_IES_LEN(bss_ex);
+	uint ies_len;
+
+	ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_BSS_EX_DEL_WFD_IE ? __func__ : NULL);
+	bss_ex->IELength -= ies_len_ori - ies_len;
+}
+
+void rtw_bss_ex_del_wfd_attr(WLAN_BSSID_EX *bss_ex, u8 attr_id)
+{
+#define DBG_BSS_EX_DEL_WFD_ATTR 0
+
+	u8 *ies = BSS_EX_TLV_IES(bss_ex);
+	uint ies_len = BSS_EX_TLV_IES_LEN(bss_ex);
+
+	u8 *ie;
+	uint ie_len, ie_len_ori;
+
+	int index = 0;
+
+	while (1) {
+		ie = rtw_get_wfd_ie(ies, ies_len, NULL, &ie_len_ori);
+		if (ie) {
+			u8 *next_ie_ori = ie + ie_len_ori;
+			uint remain_len = bss_ex->IELength - (next_ie_ori - bss_ex->IEs);
+			u8 has_target_attr = 0;
+
+			if (DBG_BSS_EX_DEL_WFD_ATTR) {
+				if (rtw_get_wfd_attr(ie, ie_len_ori, attr_id, NULL, NULL)) {
+					DBG_871X("%s %d before\n", __func__, index);
+					dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex));
+
+					DBG_871X("ies:%p, ies_len:%u\n", ies, ies_len);
+					DBG_871X("ie:%p, ie_len_ori:%u\n", ie, ie_len_ori);
+					DBG_871X("next_ie_ori:%p, remain_len:%u\n", next_ie_ori, remain_len);
+					has_target_attr = 1;
+				}
+			}
+
+			ie_len = rtw_del_wfd_attr(ie, ie_len_ori, attr_id);
+			if (ie_len != ie_len_ori) {
+				u8 *next_ie = ie + ie_len;
+
+				_rtw_memmove(next_ie, next_ie_ori, remain_len);
+				_rtw_memset(next_ie + remain_len, 0, ie_len_ori - ie_len);
+				bss_ex->IELength -= ie_len_ori - ie_len;
+
+				ies = next_ie;
+			} else {
+				ies = next_ie_ori;
+			}
+
+			if (DBG_BSS_EX_DEL_WFD_ATTR) {
+				if (has_target_attr) {
+					DBG_871X("%s %d after\n", __func__, index);
+					dump_ies(RTW_DBGDUMP, BSS_EX_TLV_IES(bss_ex), BSS_EX_TLV_IES_LEN(bss_ex));
+				}
+			}
+
+			ies_len = remain_len;
+
+			index++;
+		} else {
+			break;
+		}
+	}
+}
+#endif /* CONFIG_WFD */
+
+//Baron adds to avoid FreeBSD warning
+int ieee80211_is_empty_essid(const char *essid, int essid_len)
+{
+	/* Single white space is for Linksys APs */
+	if (essid_len == 1 && essid[0] == ' ')
+		return 1;
+
+	/* Otherwise, if the entire essid is 0, we assume it is hidden */
+	while (essid_len) {
+		essid_len--;
+		if (essid[essid_len] != '\0')
+			return 0;
+	}
+
+	return 1;
+}
+
+int ieee80211_get_hdrlen(u16 fc)
+{
+	int hdrlen = 24;
+
+	switch (WLAN_FC_GET_TYPE(fc)) {
+	case RTW_IEEE80211_FTYPE_DATA:
+		if (fc & RTW_IEEE80211_STYPE_QOS_DATA)
+			hdrlen += 2;
+		if ((fc & RTW_IEEE80211_FCTL_FROMDS) && (fc & RTW_IEEE80211_FCTL_TODS))
+			hdrlen += 6; /* Addr4 */
+		break;
+	case RTW_IEEE80211_FTYPE_CTL:
+		switch (WLAN_FC_GET_STYPE(fc)) {
+		case RTW_IEEE80211_STYPE_CTS:
+		case RTW_IEEE80211_STYPE_ACK:
+			hdrlen = 10;
+			break;
+		default:
+			hdrlen = 16;
+			break;
+		}
+		break;
+	}
+
+	return hdrlen;
+}
+
+int rtw_get_cipher_info(struct wlan_network *pnetwork)
+{
+	u32 wpa_ielen;
+	unsigned char *pbuf;
+	int group_cipher = 0, pairwise_cipher = 0, is8021x = 0;
+	int ret = _FAIL;
+	pbuf = rtw_get_wpa_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
+
+	if(pbuf && (wpa_ielen>0)) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_cipher_info: wpa_ielen: %d", wpa_ielen));
+		if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
+
+			pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
+			pnetwork->BcnInfo.group_cipher = group_cipher;
+			pnetwork->BcnInfo.is_8021x = is8021x;
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s: pnetwork->pairwise_cipher: %d, is_8021x is %d",
+						__func__, pnetwork->BcnInfo.pairwise_cipher, pnetwork->BcnInfo.is_8021x));
+			ret = _SUCCESS;
+		}
+	} else {
+
+		pbuf = rtw_get_wpa2_ie(&pnetwork->network.IEs[12], &wpa_ielen, pnetwork->network.IELength-12);
+
+		if(pbuf && (wpa_ielen>0)) {
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("get RSN IE\n"));
+			if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is8021x)) {
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("get RSN IE  OK!!!\n"));
+				pnetwork->BcnInfo.pairwise_cipher = pairwise_cipher;
+				pnetwork->BcnInfo.group_cipher = group_cipher;
+				pnetwork->BcnInfo.is_8021x = is8021x;
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s: pnetwork->pairwise_cipher: %d,"
+							"pnetwork->group_cipher is %d, is_8021x is %d",	__func__, pnetwork->BcnInfo.pairwise_cipher,
+							pnetwork->BcnInfo.group_cipher,pnetwork->BcnInfo.is_8021x));
+				ret = _SUCCESS;
+			}
+		}
+	}
+
+	return ret;
+}
+
+void rtw_get_bcn_info(struct wlan_network *pnetwork)
+{
+	unsigned short cap = 0;
+	u8 bencrypt = 0;
+	//u8 wpa_ie[255],rsn_ie[255];
+	u16 wpa_len=0,rsn_len=0;
+	struct HT_info_element *pht_info = NULL;
+	struct rtw_ieee80211_ht_cap *pht_cap = NULL;
+	unsigned int		len;
+	unsigned char		*p;
+
+	_rtw_memcpy((u8 *)&cap, rtw_get_capability_from_ie(pnetwork->network.IEs), 2);
+	cap = le16_to_cpu(cap);
+	if (cap & WLAN_CAPABILITY_PRIVACY) {
+		bencrypt = 1;
+		pnetwork->network.Privacy = 1;
+	} else {
+		pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_OPENSYS;
+	}
+	rtw_get_sec_ie(pnetwork->network.IEs ,pnetwork->network.IELength,NULL,&rsn_len,NULL,&wpa_len);
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: ssid=%s\n",pnetwork->network.Ssid.Ssid));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: ssid=%s\n",pnetwork->network.Ssid.Ssid));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: wpa_len=%d rsn_len=%d\n",wpa_len,rsn_len));
+
+	if (rsn_len > 0) {
+		pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+	} else if (wpa_len > 0) {
+		pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WPA;
+	} else {
+		if (bencrypt)
+			pnetwork->BcnInfo.encryp_protocol = ENCRYP_PROTOCOL_WEP;
+	}
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
+				pnetwork->BcnInfo.encryp_protocol));
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_get_bcn_info: pnetwork->encryp_protocol is %x\n",
+				pnetwork->BcnInfo.encryp_protocol));
+	rtw_get_cipher_info(pnetwork);
+
+	/* get bwmode and ch_offset */
+	/* parsing HT_CAP_IE */
+	p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+	if(p && len>0) {
+			pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
+			pnetwork->BcnInfo.ht_cap_info = pht_cap->cap_info;
+	} else {
+			pnetwork->BcnInfo.ht_cap_info = 0;
+	}
+	/* parsing HT_INFO_IE */
+	p = rtw_get_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, pnetwork->network.IELength - _FIXED_IE_LENGTH_);
+	if(p && len>0) {
+			pht_info = (struct HT_info_element *)(p + 2);
+			pnetwork->BcnInfo.ht_info_infos_0 = pht_info->infos[0];
+	} else {
+			pnetwork->BcnInfo.ht_info_infos_0 = 0;
+	}
+}
+
+u8	rtw_ht_mcsset_to_nss(u8 *supp_mcs_set)
+{
+	u8 nss = 1;
+	
+	if (supp_mcs_set[3])
+		nss = 4;
+	else if (supp_mcs_set[2])
+		nss = 3;
+	else if (supp_mcs_set[1])
+		nss = 2;
+	else if (supp_mcs_set[0])
+		nss = 1;
+	else
+		DBG_871X("%s,%d, warning! supp_mcs_set is zero\n", __func__, __LINE__);
+	/* DBG_871X("%s HT: %dSS\n", __FUNCTION__, nss); */
+	return nss;
+}
+
+//show MCS rate, unit: 100Kbps
+u16 rtw_mcs_rate(u8 rf_type, u8 bw_40MHz, u8 short_GI, unsigned char * MCS_rate)
+{
+	u16 max_rate = 0;
+
+	/*MCS_rate[2] = 3T3R , MCS_rate[1] = 2T2R , MCS_rate[0] = 1T1R*/
+	if (MCS_rate[2]) {
+		if (MCS_rate[2] & BIT(7))
+			max_rate = (bw_40MHz) ? ((short_GI)?4500:4050):((short_GI)?2167:1950);
+		else if (MCS_rate[2] & BIT(6))
+			max_rate = (bw_40MHz) ? ((short_GI)?4050:3645):((short_GI)?1950:1750);
+		else if (MCS_rate[2] & BIT(5))
+			max_rate = (bw_40MHz) ? ((short_GI)?3600:3240):((short_GI)?1733:1560);
+		else if (MCS_rate[2] & BIT(4))
+			max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170);
+		else if (MCS_rate[2] & BIT(3))
+			max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780);
+		else if (MCS_rate[2] & BIT(2))
+			max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
+		else if (MCS_rate[2] & BIT(1))
+			max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
+		else if (MCS_rate[2] & BIT(0))
+			max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
+	} else if (MCS_rate[1]) {
+			if(MCS_rate[1] & BIT(7))
+				max_rate = (bw_40MHz) ? ((short_GI)?3000:2700):((short_GI)?1444:1300);
+			else if(MCS_rate[1] & BIT(6))
+				max_rate = (bw_40MHz) ? ((short_GI)?2700:2430):((short_GI)?1300:1170);
+			else if(MCS_rate[1] & BIT(5))
+				max_rate = (bw_40MHz) ? ((short_GI)?2400:2160):((short_GI)?1156:1040);
+			else if(MCS_rate[1] & BIT(4))
+				max_rate = (bw_40MHz) ? ((short_GI)?1800:1620):((short_GI)?867:780);
+			else if(MCS_rate[1] & BIT(3))
+				max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
+			else if(MCS_rate[1] & BIT(2))
+				max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
+			else if(MCS_rate[1] & BIT(1))
+				max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
+			else if(MCS_rate[1] & BIT(0))
+				max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
+	} else {
+			if(MCS_rate[0] & BIT(7))
+				max_rate = (bw_40MHz) ? ((short_GI)?1500:1350):((short_GI)?722:650);
+			else if(MCS_rate[0] & BIT(6))
+				max_rate = (bw_40MHz) ? ((short_GI)?1350:1215):((short_GI)?650:585);
+			else if(MCS_rate[0] & BIT(5))
+				max_rate = (bw_40MHz) ? ((short_GI)?1200:1080):((short_GI)?578:520);
+			else if(MCS_rate[0] & BIT(4))
+				max_rate = (bw_40MHz) ? ((short_GI)?900:810):((short_GI)?433:390);
+			else if(MCS_rate[0] & BIT(3))
+				max_rate = (bw_40MHz) ? ((short_GI)?600:540):((short_GI)?289:260);
+			else if(MCS_rate[0] & BIT(2))
+				max_rate = (bw_40MHz) ? ((short_GI)?450:405):((short_GI)?217:195);
+			else if(MCS_rate[0] & BIT(1))
+				max_rate = (bw_40MHz) ? ((short_GI)?300:270):((short_GI)?144:130);
+			else if(MCS_rate[0] & BIT(0))
+				max_rate = (bw_40MHz) ? ((short_GI)?150:135):((short_GI)?72:65);
+		}
+
+	return max_rate;
+}
+
+int rtw_action_frame_parse(const u8 *frame, u32 frame_len, u8* category, u8 *action)
+{
+	const u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u16 fc;
+	u8 c;
+	u8 a = ACT_PUBLIC_MAX;
+
+	fc = le16_to_cpu(((struct rtw_ieee80211_hdr_3addr *)frame)->frame_ctl);
+
+	if ((fc & (RTW_IEEE80211_FCTL_FTYPE|RTW_IEEE80211_FCTL_STYPE))
+		!= (RTW_IEEE80211_FTYPE_MGMT|RTW_IEEE80211_STYPE_ACTION)
+	)
+	{
+		return _FALSE;
+	}
+
+	c = frame_body[0];
+
+	switch(c) {
+	case RTW_WLAN_CATEGORY_P2P: /* vendor-specific */
+		break;
+	default:
+		a = frame_body[1];
+	}
+
+	if (category)
+		*category = c;
+	if (action)
+		*action = a;
+
+	return _TRUE;
+}
+
+static const char *_action_public_str[] = {
+	"ACT_PUB_BSSCOEXIST",
+	"ACT_PUB_DSE_ENABLE",
+	"ACT_PUB_DSE_DEENABLE",
+	"ACT_PUB_DSE_REG_LOCATION",
+	"ACT_PUB_EXT_CHL_SWITCH",
+	"ACT_PUB_DSE_MSR_REQ",
+	"ACT_PUB_DSE_MSR_RPRT",
+	"ACT_PUB_MP",
+	"ACT_PUB_DSE_PWR_CONSTRAINT",
+	"ACT_PUB_VENDOR",
+	"ACT_PUB_GAS_INITIAL_REQ",
+	"ACT_PUB_GAS_INITIAL_RSP",
+	"ACT_PUB_GAS_COMEBACK_REQ",
+	"ACT_PUB_GAS_COMEBACK_RSP",
+	"ACT_PUB_TDLS_DISCOVERY_RSP",
+	"ACT_PUB_LOCATION_TRACK",
+	"ACT_PUB_RSVD",
+};
+
+const char *action_public_str(u8 action)
+{
+	action = (action >= ACT_PUBLIC_MAX) ? ACT_PUBLIC_MAX : action;
+	return _action_public_str[action];
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_io.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_io.c
new file mode 100644
index 000000000..d08c16dac
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_io.c
@@ -0,0 +1,737 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+/*
+
+The purpose of rtw_io.c
+
+a. provides the API
+
+b. provides the protocol engine
+
+c. provides the software interface between caller and the hardware interface
+
+
+Compiler Flag Option:
+
+1. CONFIG_SDIO_HCI:
+    a. USE_SYNC_IRP:  Only sync operations are provided.
+    b. USE_ASYNC_IRP:Both sync/async operations are provided.
+
+2. CONFIG_USB_HCI:
+   a. USE_ASYNC_IRP: Both sync/async operations are provided.
+
+3. CONFIG_CFIO_HCI:
+   b. USE_SYNC_IRP: Only sync operations are provided.
+
+
+Only sync read/rtw_write_mem operations are provided.
+
+jackson@realtek.com.tw
+
+*/
+
+#define _RTW_IO_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+#error "Shall be Linux or Windows, but not both!\n"
+#endif
+
+#ifdef CONFIG_SDIO_HCI
+#define rtw_le16_to_cpu(val) 		val
+#define rtw_le32_to_cpu(val)		val
+#define rtw_cpu_to_le16(val)		val
+#define rtw_cpu_to_le32(val)		val
+#else
+#define rtw_le16_to_cpu(val) 		le16_to_cpu(val)
+#define rtw_le32_to_cpu(val)		le32_to_cpu(val)
+#define rtw_cpu_to_le16(val)		cpu_to_le16(val)
+#define rtw_cpu_to_le32(val)		cpu_to_le32(val)
+#endif
+
+
+u8 _rtw_read8(_adapter *adapter, u32 addr)
+{
+	u8 r_val;
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
+	_func_enter_;
+	_read8 = pintfhdl->io_ops._read8;
+
+	r_val = _read8(pintfhdl, addr);
+	_func_exit_;
+	return r_val;
+}
+
+u16 _rtw_read16(_adapter *adapter, u32 addr)
+{
+	u16 r_val;
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	u16 	(*_read16)(struct intf_hdl *pintfhdl, u32 addr);
+	_func_enter_;
+	_read16 = pintfhdl->io_ops._read16;
+
+	r_val = _read16(pintfhdl, addr);
+	_func_exit_;
+	return rtw_le16_to_cpu(r_val);
+}
+
+u32 _rtw_read32(_adapter *adapter, u32 addr)
+{
+	u32 r_val;
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	u32 	(*_read32)(struct intf_hdl *pintfhdl, u32 addr);
+	_func_enter_;
+	_read32 = pintfhdl->io_ops._read32;
+
+	r_val = _read32(pintfhdl, addr);
+	_func_exit_;
+	return rtw_le32_to_cpu(r_val);
+
+}
+
+int _rtw_write8(_adapter *adapter, u32 addr, u8 val)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	int (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+	int ret;
+	_func_enter_;
+	_write8 = pintfhdl->io_ops._write8;
+
+	ret = _write8(pintfhdl, addr, val);
+	_func_exit_;
+	
+	return RTW_STATUS_CODE(ret);
+}
+int _rtw_write16(_adapter *adapter, u32 addr, u16 val)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	int (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+	int ret;
+	_func_enter_;
+	_write16 = pintfhdl->io_ops._write16;
+
+	val = rtw_cpu_to_le16(val);
+	ret = _write16(pintfhdl, addr, val);
+	_func_exit_;
+
+	return RTW_STATUS_CODE(ret);
+}
+int _rtw_write32(_adapter *adapter, u32 addr, u32 val)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	int (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+	int ret;
+	_func_enter_;
+	_write32 = pintfhdl->io_ops._write32;
+	
+	val = rtw_cpu_to_le32(val);
+	ret = _write32(pintfhdl, addr, val);
+	_func_exit_;
+
+	return RTW_STATUS_CODE(ret);
+}
+
+int _rtw_writeN(_adapter *adapter, u32 addr ,u32 length , u8 *pdata)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+        struct	intf_hdl	*pintfhdl = (struct intf_hdl*)(&(pio_priv->intf));
+	int (*_writeN)(struct intf_hdl *pintfhdl, u32 addr,u32 length, u8 *pdata);
+	int ret;
+	_func_enter_;
+	_writeN = pintfhdl->io_ops._writeN;
+
+	ret = _writeN(pintfhdl, addr,length,pdata);
+	_func_exit_;
+
+	return RTW_STATUS_CODE(ret);
+}
+
+#ifdef CONFIG_SDIO_HCI
+u8 _rtw_sd_f0_read8(_adapter *adapter, u32 addr)
+{
+	u8 r_val = 0x00;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	u8 (*_sd_f0_read8)(struct intf_hdl *pintfhdl, u32 addr);
+
+	_func_enter_;
+	_sd_f0_read8 = pintfhdl->io_ops._sd_f0_read8;
+
+	if (_sd_f0_read8)
+		r_val = _sd_f0_read8(pintfhdl, addr);
+	else
+		DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" _sd_f0_read8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	_func_exit_;
+	return r_val;
+}
+
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+u8 _rtw_sd_iread8(_adapter *adapter, u32 addr)
+{
+	u8 r_val = 0x00;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	u8 (*_sd_iread8)(struct intf_hdl *pintfhdl, u32 addr);
+
+	_sd_iread8 = pintfhdl->io_ops._sd_iread8;
+
+	if (_sd_iread8)
+		r_val = _sd_iread8(pintfhdl, addr);
+	else
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" _sd_iread8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	return r_val;
+}
+
+u16 _rtw_sd_iread16(_adapter *adapter, u32 addr)
+{
+	u16 r_val = 0x00;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	u16 (*_sd_iread16)(struct intf_hdl *pintfhdl, u32 addr);
+
+	_sd_iread16 = pintfhdl->io_ops._sd_iread16;
+
+	if (_sd_iread16)
+		r_val = _sd_iread16(pintfhdl, addr);
+	else
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" _sd_iread16 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	return r_val;
+}
+
+u32 _rtw_sd_iread32(_adapter *adapter, u32 addr)
+{
+	u32 r_val = 0x00;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	u32 (*_sd_iread32)(struct intf_hdl *pintfhdl, u32 addr);
+
+	_sd_iread32 = pintfhdl->io_ops._sd_iread32;
+
+	if (_sd_iread32)
+		r_val = _sd_iread32(pintfhdl, addr);
+	else
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" _sd_iread32 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	return r_val;
+}
+
+int _rtw_sd_iwrite8(_adapter *adapter, u32 addr, u8 val)
+{
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	int (*_sd_iwrite8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+	int ret = -1;
+
+	_sd_iwrite8 = pintfhdl->io_ops._sd_iwrite8;
+
+	if (_sd_iwrite8)
+		ret = _sd_iwrite8(pintfhdl, addr, val);
+	else
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" _sd_iwrite8 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	return RTW_STATUS_CODE(ret);
+}
+
+int _rtw_sd_iwrite16(_adapter *adapter, u32 addr, u16 val)
+{
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	int (*_sd_iwrite16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+	int ret = -1;
+
+	_sd_iwrite16 = pintfhdl->io_ops._sd_iwrite16;
+
+	if (_sd_iwrite16)
+		ret = _sd_iwrite16(pintfhdl, addr, val);
+	else
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" _sd_iwrite16 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	return RTW_STATUS_CODE(ret);
+}
+int _rtw_sd_iwrite32(_adapter *adapter, u32 addr, u32 val)
+{
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+	int (*_sd_iwrite32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+	int ret = -1;
+
+	_sd_iwrite32 = pintfhdl->io_ops._sd_iwrite32;
+
+	if (_sd_iwrite32)
+		ret = _sd_iwrite32(pintfhdl, addr, val);
+	else
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" _sd_iwrite32 callback is NULL\n", FUNC_ADPT_ARG(adapter));
+
+	return RTW_STATUS_CODE(ret);
+}
+
+#endif /* CONFIG_SDIO_INDIRECT_ACCESS */
+
+#endif /* CONFIG_SDIO_HCI */
+
+int _rtw_write8_async(_adapter *adapter, u32 addr, u8 val)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	int (*_write8_async)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
+	int ret;
+	_func_enter_;
+	_write8_async = pintfhdl->io_ops._write8_async;
+
+	ret = _write8_async(pintfhdl, addr, val);
+	_func_exit_;
+
+	return RTW_STATUS_CODE(ret);
+}
+int _rtw_write16_async(_adapter *adapter, u32 addr, u16 val)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	int (*_write16_async)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
+	int ret;
+	_func_enter_;
+	_write16_async = pintfhdl->io_ops._write16_async;
+	val = rtw_cpu_to_le16(val);
+	ret = _write16_async(pintfhdl, addr, val);
+	_func_exit_;
+
+	return RTW_STATUS_CODE(ret);
+}
+int _rtw_write32_async(_adapter *adapter, u32 addr, u32 val)
+{
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	int (*_write32_async)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
+	int ret;
+	_func_enter_;
+	_write32_async = pintfhdl->io_ops._write32_async;
+	val = rtw_cpu_to_le32(val);
+	ret = _write32_async(pintfhdl, addr, val);
+	_func_exit_;
+
+	return RTW_STATUS_CODE(ret);
+}
+
+void _rtw_read_mem(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+	void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+
+	_func_enter_;
+
+	if (RTW_CANNOT_RUN(adapter)) {
+		RT_TRACE(_module_rtl871x_io_c_, _drv_info_, ("rtw_read_mem:bDriverStopped(%s) OR bSurpriseRemoved(%s)"
+			, rtw_is_drv_stopped(adapter)?"True":"False"
+			, rtw_is_surprise_removed(adapter)?"True":"False"));
+		return;
+	}
+
+	_read_mem = pintfhdl->io_ops._read_mem;
+
+	_read_mem(pintfhdl, addr, cnt, pmem);
+
+	_func_exit_;
+
+}
+
+void _rtw_write_mem(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+	void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+
+	_func_enter_;
+
+	_write_mem = pintfhdl->io_ops._write_mem;
+
+	_write_mem(pintfhdl, addr, cnt, pmem);
+
+	_func_exit_;
+
+}
+
+void _rtw_read_port(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+	u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+
+	_func_enter_;
+
+	if (RTW_CANNOT_RUN(adapter)) {
+		RT_TRACE(_module_rtl871x_io_c_, _drv_info_, ("rtw_read_port:bDriverStopped(%s) OR bSurpriseRemoved(%s)"
+			, rtw_is_drv_stopped(adapter)?"True":"False"
+			, rtw_is_surprise_removed(adapter)?"True":"False"));	    
+	     return;
+	}
+
+	_read_port = pintfhdl->io_ops._read_port;
+
+	_read_port(pintfhdl, addr, cnt, pmem);
+
+	_func_exit_;
+
+}
+
+void _rtw_read_port_cancel(_adapter *adapter)
+{
+	void (*_read_port_cancel)(struct intf_hdl *pintfhdl);
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+
+	_read_port_cancel = pintfhdl->io_ops._read_port_cancel;
+
+	RTW_DISABLE_FUNC(adapter, DF_RX_BIT);
+
+	if(_read_port_cancel)
+		_read_port_cancel(pintfhdl);
+}
+
+u32 _rtw_write_port(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
+{
+	u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+	//struct	io_queue  	*pio_queue = (struct io_queue *)adapter->pio_queue;
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct	intf_hdl		*pintfhdl = &(pio_priv->intf);
+	u32 ret = _SUCCESS;
+
+	_func_enter_;
+
+	_write_port = pintfhdl->io_ops._write_port;
+	
+	ret = _write_port(pintfhdl, addr, cnt, pmem);
+
+	 _func_exit_;
+
+	return ret;
+}
+
+u32 _rtw_write_port_and_wait(_adapter *adapter, u32 addr, u32 cnt, u8 *pmem, int timeout_ms)
+{
+	int ret = _SUCCESS;
+	struct xmit_buf *pxmitbuf = (struct xmit_buf *)pmem;
+	struct submit_ctx sctx;
+
+	rtw_sctx_init(&sctx, timeout_ms);
+	pxmitbuf->sctx = &sctx;
+
+	ret = _rtw_write_port(adapter, addr, cnt, pmem);
+
+	if (ret == _SUCCESS)
+		ret = rtw_sctx_wait(&sctx, __func__);
+
+	 return ret;
+}
+
+void _rtw_write_port_cancel(_adapter *adapter)
+{
+	void (*_write_port_cancel)(struct intf_hdl *pintfhdl);
+	struct io_priv *pio_priv = &adapter->iopriv;
+	struct intf_hdl *pintfhdl = &(pio_priv->intf);
+
+	_write_port_cancel = pintfhdl->io_ops._write_port_cancel;
+
+	RTW_DISABLE_FUNC(adapter, DF_TX_BIT);
+
+	if(_write_port_cancel)
+		_write_port_cancel(pintfhdl);
+}
+int rtw_init_io_priv(_adapter *padapter, void (*set_intf_ops)(_adapter *padapter,struct _io_ops *pops))
+{
+	struct io_priv	*piopriv = &padapter->iopriv;
+	struct intf_hdl *pintf = &piopriv->intf;
+
+	if (set_intf_ops == NULL)
+		return _FAIL;
+
+	piopriv->padapter = padapter;
+	pintf->padapter = padapter;
+	pintf->pintf_dev = adapter_to_dvobj(padapter);
+		
+	set_intf_ops(padapter,&pintf->io_ops);	
+
+	return _SUCCESS;
+}
+
+/*
+* Increase and check if the continual_io_error of this @param dvobjprive is larger than MAX_CONTINUAL_IO_ERR
+* @return _TRUE:
+* @return _FALSE:
+*/
+int rtw_inc_and_chk_continual_io_error(struct dvobj_priv *dvobj)
+{
+	int ret = _FALSE;
+	int value;
+	if( (value=ATOMIC_INC_RETURN(&dvobj->continual_io_error)) > MAX_CONTINUAL_IO_ERR) {
+		DBG_871X("[dvobj:%p][ERROR] continual_io_error:%d > %d\n", dvobj, value, MAX_CONTINUAL_IO_ERR);
+		ret = _TRUE;
+	} else {
+		//DBG_871X("[dvobj:%p] continual_io_error:%d\n", dvobj, value);
+	}
+	return ret;
+}
+
+/*
+* Set the continual_io_error of this @param dvobjprive to 0
+*/
+void rtw_reset_continual_io_error(struct dvobj_priv *dvobj)
+{
+	ATOMIC_SET(&dvobj->continual_io_error, 0);	
+}
+
+#ifdef DBG_IO
+
+u32 read_sniff_ranges[][2] = {
+	//{0x520, 0x523},
+}; 
+
+u32 write_sniff_ranges[][2] = {
+	//{0x520, 0x523},
+	//{0x4c, 0x4c},
+}; 
+
+int read_sniff_num = sizeof(read_sniff_ranges)/sizeof(u32)/2;
+int write_sniff_num = sizeof(write_sniff_ranges)/sizeof(u32)/2;
+
+bool match_read_sniff_ranges(u32 addr, u16 len)
+{
+	int i;
+	for (i = 0; i<read_sniff_num; i++) {
+		if (addr + len > read_sniff_ranges[i][0] && addr <= read_sniff_ranges[i][1])
+			return _TRUE;
+	}
+	
+	return _FALSE;
+}
+
+bool match_write_sniff_ranges(u32 addr, u16 len)
+{
+	int i;
+	for (i = 0; i<write_sniff_num; i++) {
+		if (addr + len > write_sniff_ranges[i][0] && addr <= write_sniff_ranges[i][1])
+			return _TRUE;
+	}
+	
+	return _FALSE;
+}
+
+struct rf_sniff_ent {
+	u8 path;
+	u16 reg;
+	u32 mask;
+};
+
+struct rf_sniff_ent rf_read_sniff_ranges[] = {
+	/* example for all path addr 0x55 with all RF Reg mask */
+	/* {MAX_RF_PATH, 0x55, bRFRegOffsetMask}, */
+};
+
+struct rf_sniff_ent rf_write_sniff_ranges[] = {
+	/* example for all path addr 0x55 with all RF Reg mask */
+	/* {MAX_RF_PATH, 0x55, bRFRegOffsetMask}, */
+};
+
+int rf_read_sniff_num = sizeof(rf_read_sniff_ranges)/sizeof(struct rf_sniff_ent);
+int rf_write_sniff_num = sizeof(rf_write_sniff_ranges)/sizeof(struct rf_sniff_ent);
+
+bool match_rf_read_sniff_ranges(u8 path, u32 addr, u32 mask)
+{
+	int i;
+
+	for (i = 0; i < rf_read_sniff_num; i++) {
+		if (rf_read_sniff_ranges[i].path == MAX_RF_PATH || rf_read_sniff_ranges[i].path == path)
+			if (addr == rf_read_sniff_ranges[i].reg && (mask & rf_read_sniff_ranges[i].mask))
+				return _TRUE;
+	}
+
+	return _FALSE;
+}
+
+bool match_rf_write_sniff_ranges(u8 path, u32 addr, u32 mask)
+{
+	int i;
+
+	for (i = 0; i < rf_write_sniff_num; i++) {
+		if (rf_write_sniff_ranges[i].path == MAX_RF_PATH || rf_write_sniff_ranges[i].path == path)
+			if (addr == rf_write_sniff_ranges[i].reg && (mask & rf_write_sniff_ranges[i].mask))
+				return _TRUE;
+	}
+
+	return _FALSE;
+}
+
+u8 dbg_rtw_read8(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u8 val = _rtw_read8(adapter, addr);
+
+	if (match_read_sniff_ranges(addr, 1))
+		DBG_871X("DBG_IO %s:%d rtw_read8(0x%04x) return 0x%02x\n", caller, line, addr, val);
+
+	return val;
+}
+
+u16 dbg_rtw_read16(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u16 val = _rtw_read16(adapter, addr);
+	
+	if (match_read_sniff_ranges(addr, 2))
+		DBG_871X("DBG_IO %s:%d rtw_read16(0x%04x) return 0x%04x\n", caller, line, addr, val);
+
+	return val;
+}
+
+u32 dbg_rtw_read32(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u32 val = _rtw_read32(adapter, addr);
+	
+	if (match_read_sniff_ranges(addr, 4))
+		DBG_871X("DBG_IO %s:%d rtw_read32(0x%04x) return 0x%08x\n", caller, line, addr, val);
+
+	return val;
+}
+
+int dbg_rtw_write8(_adapter *adapter, u32 addr, u8 val, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 1))
+		DBG_871X("DBG_IO %s:%d rtw_write8(0x%04x, 0x%02x)\n", caller, line, addr, val);
+	
+	return _rtw_write8(adapter, addr, val);
+}
+int dbg_rtw_write16(_adapter *adapter, u32 addr, u16 val, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 2))
+		DBG_871X("DBG_IO %s:%d rtw_write16(0x%04x, 0x%04x)\n", caller, line, addr, val);
+	
+	return _rtw_write16(adapter, addr, val);
+}
+int dbg_rtw_write32(_adapter *adapter, u32 addr, u32 val, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 4))
+		DBG_871X("DBG_IO %s:%d rtw_write32(0x%04x, 0x%08x)\n", caller, line, addr, val);
+	
+	return _rtw_write32(adapter, addr, val);
+}
+int dbg_rtw_writeN(_adapter *adapter, u32 addr ,u32 length , u8 *data, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, length))
+		DBG_871X("DBG_IO %s:%d rtw_writeN(0x%04x, %u)\n", caller, line, addr, length);
+
+	return _rtw_writeN(adapter, addr, length, data);
+}
+
+#ifdef CONFIG_SDIO_HCI
+u8 dbg_rtw_sd_f0_read8(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u8 val = _rtw_sd_f0_read8(adapter, addr);
+
+	#if 0
+	if (match_read_sniff_ranges(addr, 1))
+		DBG_871X("DBG_IO %s:%d rtw_sd_f0_read8(0x%04x) return 0x%02x\n", caller, line, addr, val);
+	#endif
+
+	return val;
+}
+
+#ifdef CONFIG_SDIO_INDIRECT_ACCESS
+u8 dbg_rtw_sd_iread8(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u8 val = rtw_sd_iread8(adapter, addr);
+
+	if (match_read_sniff_ranges(addr, 1))
+		DBG_871X("DBG_IO %s:%d rtw_sd_iread8(0x%04x) return 0x%02x\n", caller, line, addr, val);
+
+	return val;
+}
+
+u16 dbg_rtw_sd_iread16(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u16 val = _rtw_sd_iread16(adapter, addr);
+	
+	if (match_read_sniff_ranges(addr, 2))
+		DBG_871X("DBG_IO %s:%d rtw_sd_iread16(0x%04x) return 0x%04x\n", caller, line, addr, val);
+
+	return val;
+}
+
+u32 dbg_rtw_sd_iread32(_adapter *adapter, u32 addr, const char *caller, const int line)
+{
+	u32 val = _rtw_sd_iread32(adapter, addr);
+	
+	if (match_read_sniff_ranges(addr, 4))
+		DBG_871X("DBG_IO %s:%d rtw_sd_iread32(0x%04x) return 0x%08x\n", caller, line, addr, val);
+
+	return val;
+}
+
+int dbg_rtw_sd_iwrite8(_adapter *adapter, u32 addr, u8 val, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 1))
+		DBG_871X("DBG_IO %s:%d rtw_sd_iwrite8(0x%04x, 0x%02x)\n", caller, line, addr, val);
+	
+	return _rtw_sd_iwrite8(adapter, addr, val);
+}
+int dbg_rtw_sd_iwrite16(_adapter *adapter, u32 addr, u16 val, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 2))
+		DBG_871X("DBG_IO %s:%d rtw_sd_iwrite16(0x%04x, 0x%04x)\n", caller, line, addr, val);
+	
+	return _rtw_sd_iwrite16(adapter, addr, val);
+}
+int dbg_rtw_sd_iwrite32(_adapter *adapter, u32 addr, u32 val, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 4))
+		DBG_871X("DBG_IO %s:%d rtw_sd_iwrite32(0x%04x, 0x%08x)\n", caller, line, addr, val);
+	
+	return _rtw_sd_iwrite32(adapter, addr, val);
+}
+
+#endif /* CONFIG_SDIO_INDIRECT_ACCESS */
+
+#endif /* CONFIG_SDIO_HCI */
+
+#endif
+
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_query.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_query.c
new file mode 100644
index 000000000..d7cd88590
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_query.c
@@ -0,0 +1,192 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_IOCTL_QUERY_C_
+
+#include <drv_types.h>
+
+
+#ifdef PLATFORM_WINDOWS
+//
+// Added for WPA2-PSK, by Annie, 2005-09-20.
+//
+u8
+query_802_11_capability(
+	_adapter*		Adapter,
+	u8*			pucBuf,
+	u32 *		pulOutLen
+)
+{
+	static NDIS_802_11_AUTHENTICATION_ENCRYPTION szAuthEnc[] = 
+	{
+		{Ndis802_11AuthModeOpen, Ndis802_11EncryptionDisabled}, 
+		{Ndis802_11AuthModeOpen, Ndis802_11Encryption1Enabled},
+		{Ndis802_11AuthModeShared, Ndis802_11EncryptionDisabled}, 
+		{Ndis802_11AuthModeShared, Ndis802_11Encryption1Enabled},
+		{Ndis802_11AuthModeWPA, Ndis802_11Encryption2Enabled}, 
+		{Ndis802_11AuthModeWPA, Ndis802_11Encryption3Enabled},
+		{Ndis802_11AuthModeWPAPSK, Ndis802_11Encryption2Enabled}, 
+		{Ndis802_11AuthModeWPAPSK, Ndis802_11Encryption3Enabled},
+		{Ndis802_11AuthModeWPANone, Ndis802_11Encryption2Enabled}, 
+		{Ndis802_11AuthModeWPANone, Ndis802_11Encryption3Enabled},
+		{Ndis802_11AuthModeWPA2, Ndis802_11Encryption2Enabled}, 
+		{Ndis802_11AuthModeWPA2, Ndis802_11Encryption3Enabled},
+		{Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption2Enabled}, 
+		{Ndis802_11AuthModeWPA2PSK, Ndis802_11Encryption3Enabled}
+	};	
+	static ULONG	ulNumOfPairSupported = sizeof(szAuthEnc)/sizeof(NDIS_802_11_AUTHENTICATION_ENCRYPTION);
+	NDIS_802_11_CAPABILITY * pCap = (NDIS_802_11_CAPABILITY *)pucBuf;
+	u8*	pucAuthEncryptionSupported = (u8*) pCap->AuthenticationEncryptionSupported;
+
+
+	pCap->Length = sizeof(NDIS_802_11_CAPABILITY);
+	if(ulNumOfPairSupported > 1 )
+		pCap->Length += 	(ulNumOfPairSupported-1) * sizeof(NDIS_802_11_AUTHENTICATION_ENCRYPTION);
+	
+	pCap->Version = 2;	
+	pCap->NoOfPMKIDs = NUM_PMKID_CACHE;	
+	pCap->NoOfAuthEncryptPairsSupported = ulNumOfPairSupported;
+
+	if( sizeof (szAuthEnc) <= 240 )		// 240 = 256 - 4*4	// SecurityInfo.szCapability: only 256 bytes in size.
+	{
+		_rtw_memcpy( pucAuthEncryptionSupported, (u8*)szAuthEnc,  sizeof (szAuthEnc) );
+		*pulOutLen = pCap->Length;
+		return _TRUE;
+	}
+	else
+	{
+		*pulOutLen = 0;
+		RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("_query_802_11_capability(): szAuthEnc size is too large.\n"));
+		return _FALSE;
+	}
+}
+
+u8 query_802_11_association_information(	_adapter *padapter,PNDIS_802_11_ASSOCIATION_INFORMATION	pAssocInfo)
+{
+	struct wlan_network *tgt_network;
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct	security_priv  *psecuritypriv=&(padapter->securitypriv);
+	WLAN_BSSID_EX	*psecnetwork = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;					
+	u8 *	pDest = (u8 *)pAssocInfo + sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+	unsigned char i,*auth_ie,*supp_ie;
+
+	//NdisZeroMemory(pAssocInfo, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION));
+	_rtw_memset(pAssocInfo, 0, sizeof(NDIS_802_11_ASSOCIATION_INFORMATION));
+	//pAssocInfo->Length = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+
+	//------------------------------------------------------
+	// Association Request related information
+	//------------------------------------------------------
+	// Req_1. AvailableRequestFixedIEs
+	if(psecnetwork!=NULL){
+		
+	pAssocInfo->AvailableRequestFixedIEs |= NDIS_802_11_AI_REQFI_CAPABILITIES|NDIS_802_11_AI_REQFI_CURRENTAPADDRESS;
+	pAssocInfo->RequestFixedIEs.Capabilities = (unsigned short)* & psecnetwork->IEs[10];
+	_rtw_memcpy(pAssocInfo->RequestFixedIEs.CurrentAPAddress,
+		& psecnetwork->MacAddress, 6);
+
+	pAssocInfo->OffsetRequestIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION);
+
+	if(check_fwstate( pmlmepriv, _FW_UNDER_LINKING|_FW_LINKED)==_TRUE)
+	{
+		
+		if(psecuritypriv->ndisauthtype>=Ndis802_11AuthModeWPA2)
+			pDest[0] =48;		//RSN Information Element
+		else 
+			pDest[0] =221;	//WPA(SSN) Information Element
+		
+		RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("\n Adapter->ndisauthtype==Ndis802_11AuthModeWPA)?0xdd:0x30 [%d]",pDest[0]));
+		supp_ie=&psecuritypriv->supplicant_ie[0];
+		for(i=0;i<supp_ie[0];i++)
+		{
+			RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("IEs [%d] = 0x%x \n\n", i,supp_ie[i]));
+		}
+
+		i=13;	//0~11 is fixed information element		
+		RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("i= %d tgt_network->network.IELength=%d\n\n", i,(int)psecnetwork->IELength));
+		while((i<supp_ie[0]) && (i<256)){
+			if((unsigned char)supp_ie[i]==pDest[0]){
+						_rtw_memcpy((u8 *)(pDest),
+							&supp_ie[i], 
+							supp_ie[1+i]+2);
+			
+				break;
+			}
+			
+			i=i+supp_ie[i+1]+2;
+			if(supp_ie[1+i]==0)
+				i=i+1;
+			RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("iteration i=%d IEs [%d] = 0x%x \n\n", i,i,supp_ie[i+1]));
+			
+		}
+		
+
+		pAssocInfo->RequestIELength += (2 + supp_ie[1+i]);// (2 + psecnetwork->IEs[1+i]+4);
+
+	}
+	
+
+		RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("\n psecnetwork != NULL,fwstate==_FW_UNDER_LINKING \n"));
+
+	}
+	
+
+	//------------------------------------------------------
+	// Association Response related information
+	//------------------------------------------------------
+
+	if(check_fwstate( pmlmepriv, _FW_LINKED)==_TRUE)
+	{
+		tgt_network =&(pmlmepriv->cur_network);
+		if(tgt_network!=NULL){
+		pAssocInfo->AvailableResponseFixedIEs =
+				NDIS_802_11_AI_RESFI_CAPABILITIES
+				|NDIS_802_11_AI_RESFI_ASSOCIATIONID
+				;
+
+		pAssocInfo->ResponseFixedIEs.Capabilities =(unsigned short)* & tgt_network->network.IEs[10];
+		pAssocInfo->ResponseFixedIEs.StatusCode = 0;
+		pAssocInfo->ResponseFixedIEs.AssociationId =(unsigned short) tgt_network->aid;
+
+		pDest = (u8 *)pAssocInfo + sizeof(NDIS_802_11_ASSOCIATION_INFORMATION)+pAssocInfo->RequestIELength;
+		auth_ie=&psecuritypriv->authenticator_ie[0];
+
+		for(i=0;i<auth_ie[0];i++)
+			RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("IEs [%d] = 0x%x \n\n", i,auth_ie[i]));
+
+		i=auth_ie[0]-12;
+		if(i>0){
+			_rtw_memcpy((u8 *)&pDest[0],&auth_ie[1],i);
+			pAssocInfo->ResponseIELength =i; 
+		}
+
+
+		pAssocInfo->OffsetResponseIEs = sizeof(NDIS_802_11_ASSOCIATION_INFORMATION) + pAssocInfo->RequestIELength;  
+
+
+		RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("\n tgt_network != NULL,fwstate==_FW_LINKED \n"));
+		}
+	}												  	
+	RT_TRACE(_module_rtl871x_ioctl_query_c_,_drv_info_,("\n exit query_802_11_association_information \n"));
+_func_exit_;
+
+	return _TRUE;
+}
+#endif
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_rtl.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_rtl.c
new file mode 100644
index 000000000..998965975
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_rtl.c
@@ -0,0 +1,1021 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define  _RTW_IOCTL_RTL_C_
+
+#include <drv_types.h>
+
+#ifdef CONFIG_MP_INCLUDED
+#include <rtw_mp_ioctl.h>
+#endif
+
+struct oid_obj_priv oid_rtl_seg_01_01[] =
+{
+	{1, &oid_null_function},										//0x80
+	{1, &oid_null_function},										//0x81
+	{1, &oid_null_function},										//0x82
+	{1, &oid_null_function},										//0x83//OID_RT_SET_SNIFFER_MODE
+	{1, &oid_rt_get_signal_quality_hdl},							//0x84
+	{1, &oid_rt_get_small_packet_crc_hdl},						//0x85
+	{1, &oid_rt_get_middle_packet_crc_hdl},						//0x86
+	{1, &oid_rt_get_large_packet_crc_hdl},						//0x87
+	{1, &oid_rt_get_tx_retry_hdl},								//0x88
+	{1, &oid_rt_get_rx_retry_hdl},								//0x89
+	{1, &oid_rt_pro_set_fw_dig_state_hdl},						//0x8A
+	{1, &oid_rt_pro_set_fw_ra_state_hdl}	,						//0x8B
+	{1, &oid_null_function},										//0x8C
+	{1, &oid_null_function},										//0x8D
+	{1, &oid_null_function},										//0x8E
+	{1, &oid_null_function},										//0x8F
+	{1, &oid_rt_get_rx_total_packet_hdl},							//0x90
+	{1, &oid_rt_get_tx_beacon_ok_hdl},							//0x91
+	{1, &oid_rt_get_tx_beacon_err_hdl},							//0x92
+	{1, &oid_rt_get_rx_icv_err_hdl},								//0x93
+	{1, &oid_rt_set_encryption_algorithm_hdl},					//0x94
+	{1, &oid_null_function},										//0x95
+	{1, &oid_rt_get_preamble_mode_hdl},							//0x96
+	{1, &oid_null_function},										//0x97
+	{1, &oid_rt_get_ap_ip_hdl},									//0x98
+	{1, &oid_rt_get_channelplan_hdl},							//0x99	
+	{1, &oid_rt_set_preamble_mode_hdl},	 						//0x9A
+	{1, &oid_rt_set_bcn_intvl_hdl},								//0x9B
+	{1, &oid_null_function},										//0x9C
+	{1, &oid_rt_dedicate_probe_hdl},								//0x9D
+	{1, &oid_null_function},										//0x9E
+	{1, &oid_null_function},										//0x9F
+	{1, &oid_null_function},										//0xA0
+	{1, &oid_null_function},										//0xA1
+	{1, &oid_null_function},										//0xA2
+	{1, &oid_null_function},										//0xA3
+	{1, &oid_null_function},										//0xA4
+	{1, &oid_null_function},										//0xA5
+	{1, &oid_null_function},										//0xA6
+	{1, &oid_rt_get_total_tx_bytes_hdl},							//0xA7
+	{1, &oid_rt_get_total_rx_bytes_hdl},							//0xA8
+	{1, &oid_rt_current_tx_power_level_hdl},						//0xA9	
+	{1, &oid_rt_get_enc_key_mismatch_count_hdl},	 			//0xAA
+	{1, &oid_rt_get_enc_key_match_count_hdl},					//0xAB
+	{1, &oid_rt_get_channel_hdl},								//0xAC
+	{1, &oid_rt_set_channelplan_hdl},								//0xAD
+	{1, &oid_rt_get_hardware_radio_off_hdl},						//0xAE
+	{1, &oid_null_function},										//0xAF
+	{1, &oid_null_function},										//0xB0
+	{1, &oid_null_function},										//0xB1
+	{1, &oid_null_function},										//0xB2
+	{1, &oid_null_function},										//0xB3
+	{1, &oid_rt_get_key_mismatch_hdl},							//0xB4
+	{1, &oid_null_function},										//0xB5
+	{1, &oid_null_function},										//0xB6
+	{1, &oid_null_function},										//0xB7
+	{1, &oid_null_function},										//0xB8
+	{1, &oid_null_function},										//0xB9	
+	{1, &oid_null_function},	 									//0xBA
+	{1, &oid_rt_supported_wireless_mode_hdl},					//0xBB
+	{1, &oid_rt_get_channel_list_hdl},							//0xBC
+	{1, &oid_rt_get_scan_in_progress_hdl},						//0xBD
+	{1, &oid_null_function},										//0xBE
+	{1, &oid_null_function},										//0xBF
+	{1, &oid_null_function},										//0xC0
+	{1, &oid_rt_forced_data_rate_hdl},							//0xC1
+	{1, &oid_rt_wireless_mode_for_scan_list_hdl},					//0xC2
+	{1, &oid_rt_get_bss_wireless_mode_hdl},						//0xC3
+	{1, &oid_rt_scan_with_magic_packet_hdl},					//0xC4
+	{1, &oid_null_function},										//0xC5
+	{1, &oid_null_function},										//0xC6
+	{1, &oid_null_function},										//0xC7
+	{1, &oid_null_function},										//0xC8
+	{1, &oid_null_function},										//0xC9	
+	{1, &oid_null_function},	 									//0xCA
+	{1, &oid_null_function},										//0xCB
+	{1, &oid_null_function},										//0xCC
+	{1, &oid_null_function},										//0xCD
+	{1, &oid_null_function},										//0xCE
+	{1, &oid_null_function},										//0xCF
+	
+};
+
+struct oid_obj_priv oid_rtl_seg_01_03[] =
+{
+	{1, &oid_rt_ap_get_associated_station_list_hdl},				//0x00
+	{1, &oid_null_function},										//0x01
+	{1, &oid_rt_ap_switch_into_ap_mode_hdl},					//0x02
+	{1, &oid_null_function},										//0x03
+	{1, &oid_rt_ap_supported_hdl},								//0x04
+	{1, &oid_rt_ap_set_passphrase_hdl},							//0x05
+
+};
+
+struct oid_obj_priv oid_rtl_seg_01_11[] =
+{
+	{1, &oid_null_function},					//0xC0	OID_RT_PRO_RX_FILTER	
+	{1, &oid_null_function},					//0xC1	OID_CE_USB_WRITE_REGISTRY
+	{1, &oid_null_function},					//0xC2	OID_CE_USB_READ_REGISTRY
+	{1, &oid_null_function},					//0xC3	OID_RT_PRO_SET_INITIAL_GAIN
+	{1, &oid_null_function},					//0xC4	OID_RT_PRO_SET_BB_RF_STANDBY_MODE
+	{1, &oid_null_function},					//0xC5	OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE
+	{1, &oid_null_function},					//0xC6	OID_RT_PRO_SET_TX_CHARGE_PUMP
+	{1, &oid_null_function},					//0xC7	OID_RT_PRO_SET_RX_CHARGE_PUMP
+	{1, &oid_rt_pro_rf_write_registry_hdl},	//0xC8	
+	{1, &oid_rt_pro_rf_read_registry_hdl},	//0xC9	
+	{1, &oid_null_function}					//0xCA	OID_RT_PRO_QUERY_RF_TYPE
+	
+};
+
+struct oid_obj_priv oid_rtl_seg_03_00[] =
+{
+	{1, &oid_null_function},										//0x00
+	{1, &oid_rt_get_connect_state_hdl},							//0x01
+	{1, &oid_null_function},										//0x02
+	{1, &oid_null_function},										//0x03
+	{1, &oid_rt_set_default_key_id_hdl},							//0x04
+
+	
+};
+
+
+//**************  oid_rtl_seg_01_01 section start ************** 
+
+NDIS_STATUS oid_rt_pro_set_fw_dig_state_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+#if 0
+	PADAPTER		Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	_irqL			oldirql;
+	
+	_func_enter_;
+	
+	if(poid_par_priv->type_of_oid != SET_OID) 
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+			
+	_irqlevel_changed_(&oldirql,LOWER);
+	if(poid_par_priv->information_buf_len >= sizeof(struct setdig_parm))
+	{
+		//DEBUG_ERR(("===> oid_rt_pro_set_fw_dig_state_hdl. type:0x%02x.\n",*((unsigned char*)poid_par_priv->information_buf )));	
+		if(!rtw_setfwdig_cmd(Adapter,*((unsigned char*)poid_par_priv->information_buf )))			
+		{
+			status = NDIS_STATUS_NOT_ACCEPTED;
+		}
+		                   
+	}
+	else{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+	}  
+	_irqlevel_changed_(&oldirql,RAISE);
+	_func_exit_;
+#endif
+	return status;
+}
+//-----------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_fw_ra_state_hdl(struct oid_par_priv* poid_par_priv)
+{
+
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+#if 0
+	PADAPTER		Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	_irqL			oldirql;
+	
+	_func_enter_;	
+	if(poid_par_priv->type_of_oid != SET_OID) 
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+					
+	_irqlevel_changed_(&oldirql,LOWER);
+	
+	if(poid_par_priv->information_buf_len >= sizeof(struct setra_parm))
+	{
+		//DEBUG_ERR(("===> oid_rt_pro_set_fw_ra_state_hdl. type:0x%02x.\n",*((unsigned char*)poid_par_priv->information_buf )));	
+		if(!rtw_setfwra_cmd(Adapter,*((unsigned char*)poid_par_priv->information_buf )))			
+		{
+			status = NDIS_STATUS_NOT_ACCEPTED;
+		}
+		                   
+	}
+	else{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+	}  
+	_irqlevel_changed_(&oldirql,RAISE);
+	_func_exit_;
+#endif
+	return status;
+}
+//-----------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_signal_quality_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	//DEBUG_ERR(("<**********************oid_rt_get_signal_quality_hdl \n"));
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+#if 0
+		if(pMgntInfo->mAssoc || pMgntInfo->mIbss)
+		{
+			ulInfo = pAdapter->RxStats.SignalQuality;
+			*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+		}
+		else
+		{
+			ulInfo = 0xffffffff; // It stands for -1 in 4-byte integer.
+		}
+		break;
+#endif
+
+	return status;
+}
+
+//------------------------------------------------------------------------------
+
+NDIS_STATUS oid_rt_get_small_packet_crc_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+		
+	if(poid_par_priv->information_buf_len >=  sizeof(ULONG) )
+	{		
+		*(ULONG *)poid_par_priv->information_buf = padapter->recvpriv.rx_smallpacket_crcerr;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;		
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	if(poid_par_priv->information_buf_len >=  sizeof(ULONG) )
+	{		
+		*(ULONG *)poid_par_priv->information_buf = padapter->recvpriv.rx_middlepacket_crcerr;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;		
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_large_packet_crc_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}	
+
+	if(poid_par_priv->information_buf_len >=  sizeof(ULONG) )
+	{		
+		*(ULONG *)poid_par_priv->information_buf = padapter->recvpriv.rx_largepacket_crcerr;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;		
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+
+	return status;
+}
+
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_tx_retry_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_rx_retry_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_rx_total_packet_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}	
+	if(poid_par_priv->information_buf_len >=  sizeof(ULONG) )
+	{		
+		*(u64 *)poid_par_priv->information_buf = padapter->recvpriv.rx_pkts + padapter->recvpriv.rx_drop;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;		
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_rx_icv_err_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	if(poid_par_priv->information_buf_len>= sizeof(u32))
+	{
+		//_rtw_memcpy(*(uint *)poid_par_priv->information_buf,padapter->recvpriv.rx_icv_err,sizeof(u32));
+		*(uint *)poid_par_priv->information_buf = padapter->recvpriv.rx_icv_err;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH ;
+	}
+	
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}	
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_preamble_mode_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+	ULONG			preamblemode = 0 ;			
+		
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+	if(poid_par_priv->information_buf_len>= sizeof(ULONG))
+	{		
+		if(padapter->registrypriv.preamble == PREAMBLE_LONG)
+			preamblemode = 0;
+		else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
+			preamblemode = 1;
+		else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
+			preamblemode = 2;
+		
+			
+		*(ULONG *)poid_par_priv->information_buf = preamblemode ;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH ;
+	}
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_ap_ip_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_get_channelplan_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	*(u16 *)poid_par_priv->information_buf = padapter->mlmepriv.ChannelPlan ;
+
+	return status;
+}
+NDIS_STATUS oid_rt_set_channelplan_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+	
+	if(poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+	
+	padapter->mlmepriv.ChannelPlan  = *(u16 *)poid_par_priv->information_buf ;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_set_preamble_mode_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+	ULONG			preamblemode = 0;
+	if(poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	 
+	if(poid_par_priv->information_buf_len>= sizeof(ULONG))
+	{		
+		preamblemode = *(ULONG *)poid_par_priv->information_buf ;
+		if( preamblemode == 0)
+			padapter->registrypriv.preamble = PREAMBLE_LONG;
+		else if (preamblemode==1 )
+			padapter->registrypriv.preamble = PREAMBLE_AUTO;
+		else if ( preamblemode==2 )
+			padapter->registrypriv.preamble = PREAMBLE_SHORT;		
+			
+		*(ULONG *)poid_par_priv->information_buf = preamblemode ;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH ;
+	}	
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_set_bcn_intvl_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+	return status;
+}
+NDIS_STATUS oid_rt_dedicate_probe_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}	
+	if(poid_par_priv->information_buf_len>= sizeof(ULONG))
+	{		
+		*(u64 *)poid_par_priv->information_buf = padapter->xmitpriv.tx_bytes;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH ;
+	}
+	
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	if(poid_par_priv->information_buf_len>= sizeof(ULONG))
+	{
+		//_rtw_memcpy(*(uint *)poid_par_priv->information_buf,padapter->recvpriv.rx_icv_err,sizeof(u32));
+		*(u64 *)poid_par_priv->information_buf = padapter->recvpriv.rx_bytes;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	}
+	else
+	{
+		status = NDIS_STATUS_INVALID_LENGTH ;
+	}
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_current_tx_power_level_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_channel_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+	struct	mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	NDIS_802_11_CONFIGURATION		*pnic_Config;
+
+	ULONG   channelnum;
+
+	_func_enter_;
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	if ( (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) ||
+		(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
+		pnic_Config = &pmlmepriv->cur_network.network.Configuration;
+	else
+		pnic_Config = &padapter->registrypriv.dev_network.Configuration;
+
+	channelnum = pnic_Config->DSConfig;
+	*(ULONG *)poid_par_priv->information_buf = channelnum;
+	
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	_func_exit_;
+
+
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_key_mismatch_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_supported_wireless_mode_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+	ULONG 			ulInfo = 0 ;
+	//DEBUG_ERR(("<**********************oid_rt_supported_wireless_mode_hdl \n"));	
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+	if(poid_par_priv->information_buf_len >= sizeof(ULONG)){
+		ulInfo |= 0x0100; //WIRELESS_MODE_B
+		ulInfo |= 0x0200; //WIRELESS_MODE_G
+		ulInfo |= 0x0400; //WIRELESS_MODE_A
+
+		*(ULONG *) poid_par_priv->information_buf = ulInfo;		
+		//DEBUG_ERR(("<===oid_rt_supported_wireless_mode %x\n",ulInfo));	
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	}
+	else{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_channel_list_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_scan_in_progress_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+
+
+NDIS_STATUS oid_rt_forced_data_rate_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+NDIS_STATUS oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+NDIS_STATUS oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+//**************  oid_rtl_seg_01_01 section end ************** 
+
+//**************  oid_rtl_seg_01_03 section start ************** 
+NDIS_STATUS oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+NDIS_STATUS oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+NDIS_STATUS oid_rt_ap_supported_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	return status;
+}
+NDIS_STATUS oid_rt_ap_set_passphrase_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	return status;
+}
+
+//**************  oid_rtl_seg_01_03 section end ************** 
+
+//****************  oid_rtl_seg_01_11   section start ****************
+NDIS_STATUS oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+	PADAPTER		Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	_irqL			oldirql;
+	_func_enter_;
+	//DEBUG_ERR(("<**********************oid_rt_pro_rf_write_registry_hdl \n"));
+	if(poid_par_priv->type_of_oid != SET_OID) //QUERY_OID
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	
+	_irqlevel_changed_(&oldirql,LOWER);
+	if(poid_par_priv->information_buf_len== (sizeof(unsigned long)*3))
+	{      
+		//RegOffsetValue	- The offset of RF register to write.
+		//RegDataWidth	- The data width of RF register to write.
+		//RegDataValue	- The value to write. 
+		//RegOffsetValue = *((unsigned long*)InformationBuffer);
+		//RegDataWidth = *((unsigned long*)InformationBuffer+1);	   
+		//RegDataValue =  *((unsigned long*)InformationBuffer+2);	
+		if(!rtw_setrfreg_cmd(Adapter, 
+						*(unsigned char*)poid_par_priv->information_buf, 
+						(unsigned long)(*((unsigned long*)poid_par_priv->information_buf+2))))
+		{
+			status = NDIS_STATUS_NOT_ACCEPTED;
+		}
+	                   
+	}
+	else{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}   
+	_irqlevel_changed_(&oldirql,RAISE);
+	_func_exit_;
+
+	return status;
+}
+
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+#if 0
+	PADAPTER		Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	_irqL	oldirql;
+	_func_enter_;
+
+	//DEBUG_ERR(("<**********************oid_rt_pro_rf_read_registry_hdl \n"));
+	if(poid_par_priv->type_of_oid != SET_OID) //QUERY_OID
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}	
+	
+	_irqlevel_changed_(&oldirql,LOWER);
+	if(poid_par_priv->information_buf_len== (sizeof(unsigned long)*3))
+	{
+		if(Adapter->mppriv.act_in_progress == _TRUE)
+		{
+			status = NDIS_STATUS_NOT_ACCEPTED;
+		}
+		else
+		{
+			//init workparam
+			Adapter->mppriv.act_in_progress = _TRUE;
+			Adapter->mppriv.workparam.bcompleted= _FALSE;
+			Adapter->mppriv.workparam.act_type = MPT_READ_RF;
+			Adapter->mppriv.workparam.io_offset = *(unsigned long*)poid_par_priv->information_buf;		
+			Adapter->mppriv.workparam.io_value = 0xcccccccc;
+				       
+			//RegOffsetValue	- The offset of RF register to read.
+			//RegDataWidth	- The data width of RF register to read.
+			//RegDataValue	- The value to read. 
+			//RegOffsetValue = *((unsigned long*)InformationBuffer);
+			//RegDataWidth = *((unsigned long*)InformationBuffer+1);	   
+			//RegDataValue =  *((unsigned long*)InformationBuffer+2);	   	 	                   
+			if(!rtw_getrfreg_cmd(Adapter, 
+							*(unsigned char*)poid_par_priv->information_buf, 
+							(unsigned char*)&Adapter->mppriv.workparam.io_value))
+			{
+				status = NDIS_STATUS_NOT_ACCEPTED;
+			}
+		}
+				      		   
+		                   
+	}
+	else	{
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+	_irqlevel_changed_(&oldirql,RAISE);
+	_func_exit_;
+#endif
+	return status;
+}
+
+//****************  oid_rtl_seg_01_11   section end****************	
+
+
+//**************  oid_rtl_seg_03_00 section start **************  
+enum _CONNECT_STATE_{
+	CHECKINGSTATUS,
+	ASSOCIATED,
+	ADHOCMODE,
+	NOTASSOCIATED
+};
+
+NDIS_STATUS oid_rt_get_connect_state_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+
+	ULONG ulInfo;
+		
+	if(poid_par_priv->type_of_oid != QUERY_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}		
+
+	// nStatus==0	CheckingStatus
+	// nStatus==1	Associated
+	// nStatus==2	AdHocMode
+	// nStatus==3	NotAssociated
+	
+	if(check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE)
+		ulInfo = CHECKINGSTATUS;
+	else if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)	
+		ulInfo = ASSOCIATED;
+	else if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)== _TRUE)
+		ulInfo = ADHOCMODE;
+	else
+		ulInfo = NOTASSOCIATED ;
+
+	*(ULONG *)poid_par_priv->information_buf = ulInfo;
+	*poid_par_priv->bytes_rw =  poid_par_priv->information_buf_len;
+
+#if 0
+	// Rearrange the order to let the UI still shows connection when scan is in progress
+	RT_TRACE(COMP_OID_QUERY, DBG_LOUD, ("===> Query OID_RT_GET_CONNECT_STATE.\n"));
+	if(pMgntInfo->mAssoc)
+		ulInfo = 1;
+	else if(pMgntInfo->mIbss)
+		ulInfo = 2;
+	else if(pMgntInfo->bScanInProgress)
+		ulInfo = 0;
+	else
+		ulInfo = 3;
+	ulInfoLen = sizeof(ULONG);
+	RT_TRACE(COMP_OID_QUERY, DBG_LOUD, ("<=== Query OID_RT_GET_CONNECT_STATE: %d\n", ulInfo));
+#endif
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_set_default_key_id_hdl(struct oid_par_priv* poid_par_priv)
+{
+	NDIS_STATUS	 	status = NDIS_STATUS_SUCCESS;
+	PADAPTER		padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	if(poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	
+	return status;
+}
+//**************  oid_rtl_seg_03_00 section end **************  
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_set.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_set.c
new file mode 100644
index 000000000..93f064115
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_ioctl_set.c
@@ -0,0 +1,1483 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_IOCTL_SET_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+
+extern void indicate_wx_scan_complete_event(_adapter *padapter);
+
+#define IS_MAC_ADDRESS_BROADCAST(addr) \
+( \
+	( (addr[0] == 0xff) && (addr[1] == 0xff) && \
+		(addr[2] == 0xff) && (addr[3] == 0xff) && \
+		(addr[4] == 0xff) && (addr[5] == 0xff) )  ? _TRUE : _FALSE \
+)
+
+u8 rtw_validate_bssid(u8 *bssid)
+{
+	u8 ret = _TRUE;
+
+	if (is_zero_mac_addr(bssid)
+		|| is_broadcast_mac_addr(bssid)
+		|| is_multicast_mac_addr(bssid)
+	) { 
+		ret = _FALSE;
+	}
+
+	return ret;
+}
+
+u8 rtw_validate_ssid(NDIS_802_11_SSID *ssid)
+{
+	u8	 i;
+	u8	ret=_TRUE;
+
+_func_enter_;	
+
+	if (ssid->SsidLength > 32) {
+		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid length >32\n"));
+		ret= _FALSE;
+		goto exit;
+	}
+
+#ifdef CONFIG_VALIDATE_SSID
+	for(i = 0; i < ssid->SsidLength; i++)
+	{
+		//wifi, printable ascii code must be supported
+		if(!( (ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e) )){
+			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("ssid has nonprintabl ascii\n"));
+			ret= _FALSE;
+			break;
+		}
+	}
+#endif /* CONFIG_VALIDATE_SSID */
+
+exit:	
+
+_func_exit_;
+
+	return ret;
+}
+
+u8 rtw_do_join(_adapter * padapter);
+u8 rtw_do_join(_adapter * padapter)
+{
+	_irqL	irqL;
+	_list	*plist, *phead;
+	u8* pibss = NULL;
+	struct	mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	_queue	*queue	= &(pmlmepriv->scanned_queue);
+	u8 ret=_SUCCESS;
+
+_func_enter_;
+
+	_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+	phead = get_list_head(queue);
+	plist = get_next(phead);
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("\n rtw_do_join: phead = %p; plist = %p \n\n\n", phead, plist));
+
+	pmlmepriv->cur_network.join_res = -2;
+		
+	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+	pmlmepriv->pscanned = plist;
+
+	pmlmepriv->to_join = _TRUE;
+
+	if(_rtw_queue_empty(queue)== _TRUE)
+	{	
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+            		
+		//when set_ssid/set_bssid for rtw_do_join(), but scanning queue is empty
+		//we try to issue sitesurvey firstly	
+            		
+		if (pmlmepriv->LinkDetectInfo.bBusyTraffic ==_FALSE
+			|| rtw_to_roam(padapter) > 0
+		)
+		{
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_do_join(): site survey if scanned_queue is empty\n."));
+			// submit site_survey_cmd
+			if(_SUCCESS!=(ret=rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) ) {
+				pmlmepriv->to_join = _FALSE;
+				RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_do_join(): site survey return error\n."));
+			}
+		}
+		else
+		{
+			pmlmepriv->to_join = _FALSE;
+			ret = _FAIL;
+		}
+		
+		goto exit;
+	}	
+	else 	
+	{
+		int select_ret;
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		if((select_ret=rtw_select_and_join_from_scanned_queue(pmlmepriv))==_SUCCESS)
+		{
+			pmlmepriv->to_join = _FALSE;
+			_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+		}
+		else	
+		{
+			if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE)
+			{
+				// submit createbss_cmd to change to a ADHOC_MASTER
+
+ 				//pmlmepriv->lock has been acquired by caller...
+				WLAN_BSSID_EX    *pdev_network = &(padapter->registrypriv.dev_network);
+
+				pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+				
+				pibss = padapter->registrypriv.dev_network.MacAddress;
+
+				_rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
+				_rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
+	
+				rtw_update_registrypriv_dev_network(padapter);
+
+				rtw_generate_random_ibss(pibss);
+					
+				if (rtw_create_ibss_cmd(padapter, 0) != _SUCCESS) {
+					RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error=>do_goin: rtw_create_ibss_cmd status FAIL***\n"));						
+					ret =  _FALSE;
+					goto exit;
+				}
+
+			     	pmlmepriv->to_join = _FALSE;
+
+				RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("***Error=> rtw_select_and_join_from_scanned_queue FAIL under STA_Mode*** \n "));						
+
+			}			
+			else
+			{ 
+				// can't associate ; reset under-linking			
+				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+
+#if 0	
+				if((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE))
+				{
+					if(_rtw_memcmp(pmlmepriv->cur_network.network.Ssid.Ssid, pmlmepriv->assoc_ssid.Ssid, pmlmepriv->assoc_ssid.SsidLength))
+					{ 
+						// for funk to do roaming
+						// funk will reconnect, but funk will not sitesurvey before reconnect
+						RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("for funk to do roaming"));
+						if(pmlmepriv->sitesurveyctrl.traffic_busy==_FALSE)
+							rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0);
+					}
+				
+				}				
+#endif
+
+				//when set_ssid/set_bssid for rtw_do_join(), but there are no desired bss in scanning queue
+				//we try to issue sitesurvey firstly			
+				if(pmlmepriv->LinkDetectInfo.bBusyTraffic==_FALSE
+					|| rtw_to_roam(padapter) > 0
+				)
+				{
+					//DBG_871X("rtw_do_join() when   no desired bss in scanning queue \n");
+					if( _SUCCESS!=(ret=rtw_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)) ){
+						pmlmepriv->to_join = _FALSE;
+						RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("do_join(): site survey return error\n."));
+					}
+				}				
+				else
+				{
+					ret = _FAIL;
+					pmlmepriv->to_join = _FALSE;
+				}
+			}
+
+		}
+
+	}
+	
+exit:
+	
+_func_exit_;	
+
+	return ret;	
+}
+
+#ifdef PLATFORM_WINDOWS
+u8 rtw_pnp_set_power_wakeup(_adapter* padapter)
+{
+	u8 res=_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("==>rtw_pnp_set_power_wakeup!!!\n"));
+	
+	res = rtw_setstandby_cmd(padapter, 0);
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("<==rtw_pnp_set_power_wakeup!!!\n"));
+
+_func_exit_;
+	
+	return res;
+}
+
+u8 rtw_pnp_set_power_sleep(_adapter* padapter)
+{
+	u8 res=_SUCCESS;	
+	
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("==>rtw_pnp_set_power_sleep!!!\n"));
+	//DbgPrint("+rtw_pnp_set_power_sleep\n");
+
+	res = rtw_setstandby_cmd(padapter, 1);
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("<==rtw_pnp_set_power_sleep!!!\n"));
+
+_func_exit_;
+
+	return res;
+}
+
+u8 rtw_set_802_11_reload_defaults(_adapter * padapter, NDIS_802_11_RELOAD_DEFAULTS reloadDefaults)
+{
+_func_enter_;
+
+	switch( reloadDefaults)
+	{
+		case Ndis802_11ReloadWEPKeys:
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("SetInfo OID_802_11_RELOAD_DEFAULTS : Ndis802_11ReloadWEPKeys\n"));
+			break;
+	}
+
+	// SecClearAllKeys(Adapter);
+	// 8711 CAM was not for En/Decrypt only
+	// so, we can't clear all keys.
+	// should we disable WPAcfg (ox0088) bit 1-2, instead of clear all CAM
+	
+	//TO DO...
+
+_func_exit_;
+	
+	return _TRUE;
+}
+
+u8 set_802_11_test(_adapter* padapter, NDIS_802_11_TEST *test)
+{
+	u8 ret=_TRUE;
+	
+_func_enter_;
+
+	switch(test->Type)
+	{
+		case 1:
+			NdisMIndicateStatus(padapter->hndis_adapter, NDIS_STATUS_MEDIA_SPECIFIC_INDICATION, (PVOID)&test->AuthenticationEvent, test->Length - 8);
+			NdisMIndicateStatusComplete(padapter->hndis_adapter);
+			break;
+
+		case 2:
+			NdisMIndicateStatus(padapter->hndis_adapter, NDIS_STATUS_MEDIA_SPECIFIC_INDICATION, (PVOID)&test->RssiTrigger, sizeof(NDIS_802_11_RSSI));
+			NdisMIndicateStatusComplete(padapter->hndis_adapter);
+			break;
+
+		default:
+			ret=_FALSE;
+			break;
+	}
+
+_func_exit_;
+
+	return ret;	
+}
+
+u8	rtw_set_802_11_pmkid(_adapter*	padapter, NDIS_802_11_PMKID *pmkid)
+{
+	u8	ret=_SUCCESS;
+
+	return ret;
+}
+
+#endif
+
+u8 rtw_set_802_11_bssid(_adapter* padapter, u8 *bssid)
+{	
+	_irqL irqL;	
+	u8 status=_SUCCESS;
+
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	
+_func_enter_;
+	
+	DBG_871X_LEVEL(_drv_always_, "set bssid:%pM\n", bssid);
+
+	if ((bssid[0]==0x00 && bssid[1]==0x00 && bssid[2]==0x00 && bssid[3]==0x00 && bssid[4]==0x00 &&bssid[5]==0x00) ||
+	    (bssid[0]==0xFF && bssid[1]==0xFF && bssid[2]==0xFF && bssid[3]==0xFF && bssid[4]==0xFF &&bssid[5]==0xFF))
+	{
+		status = _FAIL;
+		goto exit;
+	}
+		
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+
+	DBG_871X("Set BSSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
+		goto handle_tkip_countermeasure;
+	} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {
+		goto release_mlme_lock;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_, ("set_bssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
+
+		if (_rtw_memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid, ETH_ALEN) == _TRUE)
+		{		
+			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE)
+				goto release_mlme_lock;//it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again.
+		} else {
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("Set BSSID not the same bssid\n"));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("set_bssid="MAC_FMT"\n", MAC_ARG(bssid) ));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("cur_bssid="MAC_FMT"\n", MAC_ARG(pmlmepriv->cur_network.network.MacAddress) ));
+
+			rtw_disassoc_cmd(padapter, 0, _TRUE);
+
+			if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+				rtw_indicate_disconnect(padapter);
+
+			rtw_free_assoc_resources(padapter, 1);
+
+			if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
+				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+			}		
+		}
+	}
+
+handle_tkip_countermeasure:
+	if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
+		status = _FAIL;
+		goto release_mlme_lock;
+	}
+
+	_rtw_memset(&pmlmepriv->assoc_ssid, 0, sizeof(NDIS_802_11_SSID));
+	_rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
+	pmlmepriv->assoc_by_bssid=_TRUE;
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
+		pmlmepriv->to_join = _TRUE;	
+	}
+	else {
+		status = rtw_do_join(padapter);
+	}
+
+release_mlme_lock:
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+		
+exit:
+	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+		("rtw_set_802_11_bssid: status=%d\n", status));
+	
+_func_exit_;
+
+	return status;
+}
+
+u8 rtw_set_802_11_ssid(_adapter* padapter, NDIS_802_11_SSID *ssid)
+{	
+	_irqL irqL;
+	u8 status = _SUCCESS;
+	u32 cur_time = 0;
+
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network *pnetwork = &pmlmepriv->cur_network;
+	
+_func_enter_;
+	
+	DBG_871X_LEVEL(_drv_always_, "set ssid [%s] fw_state=0x%08x\n",
+		       	ssid->Ssid, get_fwstate(pmlmepriv));
+
+	if (!rtw_is_hw_init_completed(padapter)) {
+		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+			 ("set_ssid: hw_init_completed==_FALSE=>exit!!!\n"));
+		status = _FAIL;
+		goto exit;
+	}
+		
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	DBG_871X("Set SSID under fw_state=0x%08x\n", get_fwstate(pmlmepriv));
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {	
+		goto handle_tkip_countermeasure;
+	} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {
+		goto release_mlme_lock;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED|WIFI_ADHOC_MASTER_STATE) == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_info_,
+			 ("set_ssid: _FW_LINKED||WIFI_ADHOC_MASTER_STATE\n"));
+
+		if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
+		    (_rtw_memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid, ssid->SsidLength) == _TRUE))
+		{			
+			if((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _FALSE))
+			{
+				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+					 ("Set SSID is the same ssid, fw_state=0x%08x\n",
+					  get_fwstate(pmlmepriv)));
+
+				if(rtw_is_same_ibss(padapter, pnetwork) == _FALSE)
+				{				
+					//if in WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE, create bss or rejoin again
+					rtw_disassoc_cmd(padapter, 0, _TRUE);
+
+					if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+						rtw_indicate_disconnect(padapter);
+						
+					rtw_free_assoc_resources(padapter, 1);
+
+					if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) {
+						_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+						set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+					}
+				}
+				else
+				{
+					goto release_mlme_lock;//it means driver is in WIFI_ADHOC_MASTER_STATE, we needn't create bss again.
+				}
+			}
+#ifdef CONFIG_LPS
+			else {
+				rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_JOINBSS, 1);
+			}
+#endif
+		}
+		else
+		{
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("Set SSID not the same ssid\n"));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("set_ssid=[%s] len=0x%x\n", ssid->Ssid, (unsigned int)ssid->SsidLength));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("assoc_ssid=[%s] len=0x%x\n", pmlmepriv->assoc_ssid.Ssid, (unsigned int)pmlmepriv->assoc_ssid.SsidLength));
+
+			rtw_disassoc_cmd(padapter, 0, _TRUE);
+
+			if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+				rtw_indicate_disconnect(padapter);
+			
+			rtw_free_assoc_resources(padapter, 1);
+
+			if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE) {
+				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+			}
+		}		
+	}
+
+handle_tkip_countermeasure:
+	if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
+		status = _FAIL;
+		goto release_mlme_lock;
+	}
+
+	if (rtw_validate_ssid(ssid) == _FALSE) {
+		status = _FAIL;
+		goto release_mlme_lock;
+	}
+
+	_rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID));
+	pmlmepriv->assoc_by_bssid=_FALSE;
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
+		pmlmepriv->to_join = _TRUE;	
+	}
+	else {
+		status = rtw_do_join(padapter);
+	}
+
+release_mlme_lock:
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+exit:
+	RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+		("-rtw_set_802_11_ssid: status=%d\n", status));
+	
+_func_exit_;
+
+	return status;
+	
+}
+
+u8 rtw_set_802_11_connect(_adapter* padapter, u8 *bssid, NDIS_802_11_SSID *ssid)
+{
+	_irqL irqL;
+	u8 status = _SUCCESS;
+	u32 cur_time = 0;
+	bool bssid_valid = _TRUE;
+	bool ssid_valid = _TRUE;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+_func_enter_;
+
+	if (!ssid || rtw_validate_ssid(ssid) == _FALSE)
+		ssid_valid = _FALSE;
+
+	if (!bssid || rtw_validate_bssid(bssid) == _FALSE)
+		bssid_valid = _FALSE;
+
+	if (ssid_valid == _FALSE && bssid_valid == _FALSE) {
+		DBG_871X(FUNC_ADPT_FMT" ssid:%p, ssid_valid:%d, bssid:%p, bssid_valid:%d\n",
+			FUNC_ADPT_ARG(padapter), ssid, ssid_valid, bssid, bssid_valid);
+		status = _FAIL;
+		goto exit;
+	}
+
+	if (!rtw_is_hw_init_completed(padapter)) {
+		RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_,
+			 ("set_ssid: hw_init_completed==_FALSE=>exit!!!\n"));
+		status = _FAIL;
+		goto exit;
+	}
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT"  fw_state=0x%08x\n",
+		FUNC_ADPT_ARG(padapter), get_fwstate(pmlmepriv));
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
+		goto handle_tkip_countermeasure;
+	} else if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE) {
+		goto release_mlme_lock;
+	}
+
+handle_tkip_countermeasure:
+	if (rtw_handle_tkip_countermeasure(padapter, __func__) == _FAIL) {
+		status = _FAIL;
+		goto release_mlme_lock;
+	}
+
+	if (ssid && ssid_valid)
+		_rtw_memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(NDIS_802_11_SSID));
+	else
+		_rtw_memset(&pmlmepriv->assoc_ssid, 0, sizeof(NDIS_802_11_SSID));
+
+	if (bssid && bssid_valid) {
+		_rtw_memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
+		pmlmepriv->assoc_by_bssid = _TRUE;
+	} else {
+		pmlmepriv->assoc_by_bssid = _FALSE;
+	}
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY) == _TRUE) {
+		pmlmepriv->to_join = _TRUE;	
+	}
+	else {
+		status = rtw_do_join(padapter);
+	}
+
+release_mlme_lock:
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+exit:
+	
+_func_exit_;
+
+	return status;
+}
+
+u8 rtw_set_802_11_infrastructure_mode(_adapter* padapter, 
+	NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
+{
+	_irqL irqL;
+	struct	mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct	wlan_network	*cur_network = &pmlmepriv->cur_network;
+	NDIS_802_11_NETWORK_INFRASTRUCTURE* pold_state = &(cur_network->network.InfrastructureMode);
+	
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_notice_,
+		 ("+rtw_set_802_11_infrastructure_mode: old=%d new=%d fw_state=0x%08x\n",
+		  *pold_state, networktype, get_fwstate(pmlmepriv)));
+	
+	if(*pold_state != networktype)
+	{
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,(" change mode!"));
+		//DBG_871X("change mode, old_mode=%d, new_mode=%d, fw_state=0x%x\n", *pold_state, networktype, get_fwstate(pmlmepriv));
+
+		if(*pold_state==Ndis802_11APMode)
+		{		
+			//change to other mode from Ndis802_11APMode			
+			cur_network->join_res = -1;
+			
+#ifdef CONFIG_NATIVEAP_MLME
+			stop_ap_mode(padapter);
+#endif
+		}
+
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);
+		
+		if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) ||(*pold_state==Ndis802_11IBSS))
+			rtw_disassoc_cmd(padapter, 0, _TRUE);
+
+		if((check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) ||
+			(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)== _TRUE) )
+			rtw_free_assoc_resources(padapter, 1);
+
+		if((*pold_state == Ndis802_11Infrastructure) ||(*pold_state == Ndis802_11IBSS))
+	       {
+			if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+			{		
+				rtw_indicate_disconnect(padapter); //will clr Linked_state; before this function, we must have chked whether  issue dis-assoc_cmd or not
+			}
+	       }
+		
+		*pold_state = networktype;
+
+		_clr_fwstate_(pmlmepriv, ~WIFI_NULL_STATE);
+				
+		switch(networktype)
+		{
+			case Ndis802_11IBSS:
+				set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
+				break;
+				
+			case Ndis802_11Infrastructure:
+				set_fwstate(pmlmepriv, WIFI_STATION_STATE);
+				break;
+				
+			case Ndis802_11APMode:
+				set_fwstate(pmlmepriv, WIFI_AP_STATE);
+#ifdef CONFIG_NATIVEAP_MLME
+				start_ap_mode(padapter);
+				//rtw_indicate_connect(padapter);
+#endif				
+				
+				break;
+
+			case Ndis802_11AutoUnknown:
+			case Ndis802_11InfrastructureMax:
+				break;
+			case Ndis802_11Monitor:
+				set_fwstate(pmlmepriv, WIFI_MONITOR_STATE);
+				break;
+		}
+
+		//SecClearAllKeys(adapter);
+		
+		//RT_TRACE(COMP_OID_SET, DBG_LOUD, ("set_infrastructure: fw_state:%x after changing mode\n",
+		//									get_fwstate(pmlmepriv) ));
+
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	}
+
+_func_exit_;
+
+	return _TRUE;
+}
+
+
+u8 rtw_set_802_11_disassociate(_adapter *padapter)
+{
+	_irqL irqL;
+	struct mlme_priv * pmlmepriv = &padapter->mlmepriv;
+
+_func_enter_;
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("MgntActrtw_set_802_11_disassociate: rtw_indicate_disconnect\n"));
+
+		rtw_disassoc_cmd(padapter, 0, _TRUE);
+		rtw_indicate_disconnect(padapter);
+		//modify for CONFIG_IEEE80211W, none 11w can use it
+		rtw_free_assoc_resources_cmd(padapter);
+		if (_FAIL == rtw_pwr_wakeup(padapter))
+			DBG_871X("%s(): rtw_pwr_wakeup fail !!!\n",__FUNCTION__);
+	}
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	
+_func_exit_;
+
+	return _TRUE;	
+}
+
+u8 rtw_set_802_11_bssid_list_scan(_adapter* padapter, NDIS_802_11_SSID *pssid, int ssid_max_num)
+{	
+	_irqL	irqL;
+	struct	mlme_priv		*pmlmepriv= &padapter->mlmepriv;
+	u8	res=_TRUE;
+	
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("+rtw_set_802_11_bssid_list_scan(), fw_state=%x\n", get_fwstate(pmlmepriv)));
+
+	if (padapter == NULL) {
+		res=_FALSE;
+		goto exit;
+	}
+	if (!rtw_is_hw_init_completed(padapter)) {
+		res = _FALSE;
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n===rtw_set_802_11_bssid_list_scan:hw_init_completed==_FALSE===\n"));
+		goto exit;
+	}
+	
+	if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == _TRUE) ||
+		(pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE))
+	{
+		// Scan or linking is in progress, do nothing.
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_bssid_list_scan fail since fw_state = %x\n", get_fwstate(pmlmepriv)));
+		res = _TRUE;
+
+		if(check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY|_FW_UNDER_LINKING))== _TRUE){
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n###_FW_UNDER_SURVEY|_FW_UNDER_LINKING\n\n"));
+		} else {
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n###pmlmepriv->sitesurveyctrl.traffic_busy==_TRUE\n\n"));
+		}
+	} else {		
+		if (rtw_is_scan_deny(padapter)) {
+			DBG_871X(FUNC_ADPT_FMT": scan deny\n", FUNC_ADPT_ARG(padapter));
+			indicate_wx_scan_complete_event(padapter);
+			return _SUCCESS;
+		}
+		
+		_enter_critical_bh(&pmlmepriv->lock, &irqL);		
+		
+		res = rtw_sitesurvey_cmd(padapter, pssid, ssid_max_num, NULL, 0);
+		
+		_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	}
+exit:
+	
+_func_exit_;
+
+	return res;	
+}
+
+u8 rtw_set_802_11_authentication_mode(_adapter* padapter, NDIS_802_11_AUTHENTICATION_MODE authmode) 
+{
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	int res;
+	u8 ret;
+	
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("set_802_11_auth.mode(): mode=%x\n", authmode));
+
+	psecuritypriv->ndisauthtype=authmode;
+	
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_authentication_mode:psecuritypriv->ndisauthtype=%d", psecuritypriv->ndisauthtype));
+	
+	if(psecuritypriv->ndisauthtype>3)
+		psecuritypriv->dot11AuthAlgrthm=dot11AuthAlgrthm_8021X;
+	
+#ifdef CONFIG_WAPI_SUPPORT
+	if(psecuritypriv->ndisauthtype == 6)
+		psecuritypriv->dot11AuthAlgrthm=dot11AuthAlgrthm_WAPI;
+#endif
+
+	res=rtw_set_auth(padapter,psecuritypriv);
+	
+	if(res==_SUCCESS)
+		ret=_TRUE;
+	else
+		ret=_FALSE;
+	
+_func_exit_;
+
+	return ret;
+}
+
+u8 rtw_set_802_11_add_wep(_adapter* padapter, NDIS_802_11_WEP *wep){
+
+	u8		bdefaultkey;
+	u8		btransmitkey;
+	sint		keyid,res;
+	struct security_priv* psecuritypriv=&(padapter->securitypriv);
+	u8		ret=_SUCCESS;
+
+_func_enter_;
+
+	bdefaultkey=(wep->KeyIndex & 0x40000000) > 0 ? _FALSE : _TRUE;   //for ???
+	btransmitkey= (wep->KeyIndex & 0x80000000) > 0 ? _TRUE  : _FALSE;	//for ???
+	keyid=wep->KeyIndex & 0x3fffffff;
+
+	if(keyid>=4)
+	{
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("MgntActrtw_set_802_11_add_wep:keyid>4=>fail\n"));
+		ret=_FALSE;
+		goto exit;
+	}
+	
+	switch(wep->KeyLength)
+	{
+		case 5:
+			psecuritypriv->dot11PrivacyAlgrthm=_WEP40_;
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("MgntActrtw_set_802_11_add_wep:wep->KeyLength=5\n"));
+			break;
+		case 13:
+			psecuritypriv->dot11PrivacyAlgrthm=_WEP104_;
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("MgntActrtw_set_802_11_add_wep:wep->KeyLength=13\n"));
+			break;
+		default:
+			psecuritypriv->dot11PrivacyAlgrthm=_NO_PRIVACY_;
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("MgntActrtw_set_802_11_add_wep:wep->KeyLength!=5 or 13\n"));
+			break;
+	}
+	
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_wep:befor memcpy, wep->KeyLength=0x%x wep->KeyIndex=0x%x  keyid =%x\n",wep->KeyLength,wep->KeyIndex,keyid));
+
+	_rtw_memcpy(&(psecuritypriv->dot11DefKey[keyid].skey[0]),&(wep->KeyMaterial),wep->KeyLength);
+
+	psecuritypriv->dot11DefKeylen[keyid]=wep->KeyLength;
+
+	psecuritypriv->dot11PrivacyKeyIndex=keyid;
+
+	RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_wep:security key material : %x %x %x %x %x %x %x %x %x %x %x %x %x \n",
+		psecuritypriv->dot11DefKey[keyid].skey[0],psecuritypriv->dot11DefKey[keyid].skey[1],psecuritypriv->dot11DefKey[keyid].skey[2],
+		psecuritypriv->dot11DefKey[keyid].skey[3],psecuritypriv->dot11DefKey[keyid].skey[4],psecuritypriv->dot11DefKey[keyid].skey[5],
+		psecuritypriv->dot11DefKey[keyid].skey[6],psecuritypriv->dot11DefKey[keyid].skey[7],psecuritypriv->dot11DefKey[keyid].skey[8],
+		psecuritypriv->dot11DefKey[keyid].skey[9],psecuritypriv->dot11DefKey[keyid].skey[10],psecuritypriv->dot11DefKey[keyid].skey[11],
+		psecuritypriv->dot11DefKey[keyid].skey[12]));
+
+	res=rtw_set_key(padapter,psecuritypriv, keyid, 1, _TRUE);
+	
+	if(res==_FAIL)
+		ret= _FALSE;
+exit:
+	
+_func_exit_;
+
+	return ret;
+	
+}
+
+u8 rtw_set_802_11_remove_wep(_adapter* padapter, u32 keyindex){
+	
+	u8 ret=_SUCCESS;
+	
+_func_enter_;
+
+	if (keyindex >= 0x80000000 || padapter == NULL){
+		
+		ret=_FALSE;
+		goto exit;
+
+	}
+	else 
+	{
+		int res;
+		struct security_priv* psecuritypriv=&(padapter->securitypriv);
+		if( keyindex < 4 ){
+			
+			_rtw_memset(&psecuritypriv->dot11DefKey[keyindex], 0, 16);
+			
+			res=rtw_set_key(padapter,psecuritypriv,keyindex, 0, _TRUE);
+			
+			psecuritypriv->dot11DefKeylen[keyindex]=0;
+			
+			if(res==_FAIL)
+				ret=_FAIL;
+			
+		}
+		else
+		{			
+			ret=_FAIL;
+		}
+		
+	}
+	
+exit:	
+	
+_func_exit_;
+
+	return ret;
+	
+}
+
+u8 rtw_set_802_11_add_key(_adapter* padapter, NDIS_802_11_KEY *key){
+
+	uint	encryptionalgo;
+	u8 * pbssid;
+	struct sta_info *stainfo;
+	u8	bgroup = _FALSE;
+	u8	bgrouptkey = _FALSE;//can be remove later
+	u8	ret=_SUCCESS;
+	
+_func_enter_;
+
+	if (((key->KeyIndex & 0x80000000) == 0) && ((key->KeyIndex & 0x40000000) > 0)){
+
+		// It is invalid to clear bit 31 and set bit 30. If the miniport driver encounters this combination, 
+		// it must fail the request and return NDIS_STATUS_INVALID_DATA.
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_key: ((key->KeyIndex & 0x80000000) == 0)[=%d] ",(int)(key->KeyIndex & 0x80000000) == 0));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_key:((key->KeyIndex & 0x40000000) > 0)[=%d]" , (int)(key->KeyIndex & 0x40000000) > 0));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_info_,("rtw_set_802_11_add_key: key->KeyIndex=%d \n" ,(int)key->KeyIndex));
+		ret= _FAIL;
+		goto exit;
+	}
+
+	if(key->KeyIndex & 0x40000000)
+	{ 
+		// Pairwise key
+
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ Pairwise key +++++\n"));
+	
+		pbssid=get_bssid(&padapter->mlmepriv);
+		stainfo=rtw_get_stainfo(&padapter->stapriv, pbssid);
+
+		if((stainfo!=NULL)&&(padapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)){
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY:( stainfo!=NULL)&&(Adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)\n"));
+			encryptionalgo=stainfo->dot118021XPrivacy;
+		}
+		else{
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: stainfo==NULL)||(Adapter->securitypriv.dot11AuthAlgrthm!=dot11AuthAlgrthm_8021X)\n"));
+			encryptionalgo=padapter->securitypriv.dot11PrivacyAlgrthm;
+		}
+
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (encryptionalgo ==%d)!\n",encryptionalgo ));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11PrivacyAlgrthm ==%d)!\n",padapter->securitypriv.dot11PrivacyAlgrthm));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (Adapter->securitypriv.dot11AuthAlgrthm ==%d)!\n",padapter->securitypriv.dot11AuthAlgrthm));
+
+		if((stainfo!=NULL)){
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("rtw_set_802_11_add_key: (stainfo->dot118021XPrivacy ==%d)!\n", stainfo->dot118021XPrivacy));
+		}
+		
+		if(key->KeyIndex & 0x000000FF){
+			// The key index is specified in the lower 8 bits by values of zero to 255.
+			// The key index should be set to zero for a Pairwise key, and the driver should fail with
+			// NDIS_STATUS_INVALID_DATA if the lower 8 bits is not zero
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" key->KeyIndex & 0x000000FF.\n"));
+			ret= _FAIL;
+			goto exit;
+		}
+
+		// check BSSID
+		if (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == _TRUE){
+
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("MacAddr_isBcst(key->BSSID)\n"));
+			ret= _FALSE;
+			goto exit;
+		}
+
+		// Check key length for TKIP.
+		//if(encryptionAlgorithm == RT_ENC_TKIP_ENCRYPTION && key->KeyLength != 32)
+		if((encryptionalgo== _TKIP_)&& (key->KeyLength != 32)){
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("TKIP KeyLength:0x%x != 32\n", key->KeyLength));
+			ret=_FAIL;
+			goto exit;
+
+		}
+
+		// Check key length for AES.
+		if((encryptionalgo== _AES_)&& (key->KeyLength != 16)) {
+			// For our supplicant, EAPPkt9x.vxd, cannot differentiate TKIP and AES case.
+			if(key->KeyLength == 32) {
+				key->KeyLength = 16; 
+			} else {
+				ret= _FAIL;
+				goto exit;
+			}
+		}
+
+		/* Check key length for WEP. For NDTEST, 2005.01.27, by rcnjko. -> modify checking condition*/
+		if (((encryptionalgo == _WEP40_) && (key->KeyLength != 5)) || ((encryptionalgo == _WEP104_) && (key->KeyLength != 13))) {
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("WEP KeyLength:0x%x != 5 or 13\n", key->KeyLength));
+			ret=_FAIL;
+			goto exit;
+		}
+
+		bgroup = _FALSE;
+
+		// Check the pairwise key. Added by Annie, 2005-07-06.
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("[Pairwise Key set]\n"));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key index: 0x%8x(0x%8x)\n", key->KeyIndex,(key->KeyIndex&0x3)));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key Length: %d\n", key->KeyLength));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+	
+	}
+	else 
+	{	
+		// Group key - KeyIndex(BIT30==0)
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ Group key +++++\n"));
+
+
+		// when add wep key through add key and didn't assigned encryption type before
+		if((padapter->securitypriv.ndisauthtype<=3)&&(padapter->securitypriv.dot118021XGrpPrivacy==0))
+		{
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("keylen=%d( Adapter->securitypriv.dot11PrivacyAlgrthm=%x  )padapter->securitypriv.dot118021XGrpPrivacy(%x)\n", key->KeyLength,padapter->securitypriv.dot11PrivacyAlgrthm,padapter->securitypriv.dot118021XGrpPrivacy));
+
+			switch(key->KeyLength)
+			{
+				case 5:
+					padapter->securitypriv.dot11PrivacyAlgrthm=_WEP40_;
+					RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("Adapter->securitypriv.dot11PrivacyAlgrthm= %x key->KeyLength=%u\n", padapter->securitypriv.dot11PrivacyAlgrthm,key->KeyLength));
+					break;
+				case 13:
+					padapter->securitypriv.dot11PrivacyAlgrthm=_WEP104_;
+					RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("Adapter->securitypriv.dot11PrivacyAlgrthm= %x key->KeyLength=%u\n", padapter->securitypriv.dot11PrivacyAlgrthm,key->KeyLength));
+					break;
+				default:
+					padapter->securitypriv.dot11PrivacyAlgrthm=_NO_PRIVACY_;
+					RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("Adapter->securitypriv.dot11PrivacyAlgrthm= %x key->KeyLength=%u \n", padapter->securitypriv.dot11PrivacyAlgrthm,key->KeyLength));
+					break;
+			}
+			
+			encryptionalgo=padapter->securitypriv.dot11PrivacyAlgrthm;
+			
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" Adapter->securitypriv.dot11PrivacyAlgrthm=%x\n", padapter->securitypriv.dot11PrivacyAlgrthm));
+			
+		}
+		else 
+		{
+			encryptionalgo=padapter->securitypriv.dot118021XGrpPrivacy;
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("( Adapter->securitypriv.dot11PrivacyAlgrthm=%x  )encryptionalgo(%x)=padapter->securitypriv.dot118021XGrpPrivacy(%x)keylen=%d\n", padapter->securitypriv.dot11PrivacyAlgrthm,encryptionalgo,padapter->securitypriv.dot118021XGrpPrivacy,key->KeyLength));
+
+		}
+		
+		if((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)==_TRUE) && (IS_MAC_ADDRESS_BROADCAST(key->BSSID) == _FALSE)) {
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" IBSS but BSSID is not Broadcast Address.\n"));
+			ret= _FAIL;
+			goto exit;
+		}
+
+		// Check key length for TKIP
+		if((encryptionalgo== _TKIP_) && (key->KeyLength != 32)) {
+
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,(" TKIP GTK KeyLength:%u != 32\n", key->KeyLength));
+			ret= _FAIL;
+			goto exit;
+
+		} else if(encryptionalgo== _AES_ && (key->KeyLength != 16 && key->KeyLength != 32) ) {
+			
+			// Check key length for AES
+			// For NDTEST, we allow keylen=32 in this case. 2005.01.27, by rcnjko.
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("<=== SetInfo, OID_802_11_ADD_KEY: AES GTK KeyLength:%u != 16 or 32\n", key->KeyLength));
+			ret= _FAIL;
+			goto exit;
+		}
+
+		// Change the key length for EAPPkt9x.vxd. Added by Annie, 2005-11-03.
+		if((encryptionalgo==  _AES_) && (key->KeyLength == 32) ) {
+			key->KeyLength = 16; 
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("AES key length changed: %u\n", key->KeyLength) );
+		}
+
+		if(key->KeyIndex & 0x8000000) {//error ??? 0x8000_0000
+			bgrouptkey = _TRUE;
+		}
+
+		if((check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE)==_TRUE)&&(check_fwstate(&padapter->mlmepriv, _FW_LINKED)==_TRUE))
+		{
+			bgrouptkey = _TRUE;
+		}
+
+		bgroup = _TRUE;
+
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n") );
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("[Group Key set]\n") );
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n")) ;
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key index: 0x%8x(0x%8x)\n", key->KeyIndex,(key->KeyIndex&0x3)));
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("key Length: %d\n", key->KeyLength)) ;
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("------------------------------------------\n"));
+		
+	}	
+
+	// If WEP encryption algorithm, just call rtw_set_802_11_add_wep().
+	if((padapter->securitypriv.dot11AuthAlgrthm !=dot11AuthAlgrthm_8021X)&&(encryptionalgo== _WEP40_  || encryptionalgo== _WEP104_))
+	{
+		u8 ret;		
+		u32 keyindex;		
+		u32 len = FIELD_OFFSET(NDIS_802_11_KEY, KeyMaterial) + key->KeyLength;
+		NDIS_802_11_WEP *wep = &padapter->securitypriv.ndiswep;
+				
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ WEP key +++++\n"));
+
+		wep->Length = len;
+		keyindex = key->KeyIndex&0x7fffffff;
+		wep->KeyIndex = keyindex ;
+		wep->KeyLength = key->KeyLength;
+		
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY:Before memcpy \n"));
+
+		_rtw_memcpy(wep->KeyMaterial, key->KeyMaterial, key->KeyLength);	
+		_rtw_memcpy(&(padapter->securitypriv.dot11DefKey[keyindex].skey[0]), key->KeyMaterial, key->KeyLength);
+
+		padapter->securitypriv.dot11DefKeylen[keyindex]=key->KeyLength;		
+		padapter->securitypriv.dot11PrivacyKeyIndex=keyindex;
+		
+		ret = rtw_set_802_11_add_wep(padapter, wep);
+	
+		goto exit;
+		
+	}
+
+	if(key->KeyIndex & 0x20000000){
+		// SetRSC
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("OID_802_11_ADD_KEY: +++++ SetRSC+++++\n"));
+		if(bgroup == _TRUE)
+		{
+			NDIS_802_11_KEY_RSC keysrc=key->KeyRSC & 0x00FFFFFFFFFFFFULL;
+			_rtw_memcpy(&padapter->securitypriv.dot11Grprxpn, &keysrc, 8);			
+		} 
+		else 
+		{		
+			NDIS_802_11_KEY_RSC keysrc=key->KeyRSC & 0x00FFFFFFFFFFFFULL;	
+			_rtw_memcpy(&padapter->securitypriv.dot11Grptxpn, &keysrc, 8);			
+		}
+			
+	}
+
+	// Indicate this key idx is used for TX
+	// Save the key in KeyMaterial
+	if(bgroup == _TRUE) // Group transmit key
+	{
+		int res;
+		
+		if(bgrouptkey == _TRUE)
+		{		
+			padapter->securitypriv.dot118021XGrpKeyid=(u8)key->KeyIndex;
+		}
+		
+		if((key->KeyIndex&0x3) == 0){
+			ret = _FAIL;
+			goto exit;
+		}		
+		
+		_rtw_memset(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+		_rtw_memset(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+		_rtw_memset(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], 0, 16);
+		
+		if((key->KeyIndex & 0x10000000))
+		{
+			_rtw_memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
+			_rtw_memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
+			
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
+
+		}
+		else
+		{
+			_rtw_memcpy(&padapter->securitypriv.dot118021XGrptxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 24, 8);
+			_rtw_memcpy(&padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial + 16, 8);
+			
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rx mic :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[0],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[1],
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[2],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[3],
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[4],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[5],
+				padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex) & 0x03)].skey[6],padapter->securitypriv.dot118021XGrprxmickey[(u8)((key->KeyIndex-1) & 0x03)].skey[7]));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:set Group mic key!!!!!!!!\n"));
+		
+		}
+
+		//set group key by index
+		_rtw_memcpy(&padapter->securitypriv.dot118021XGrpKey[(u8)((key->KeyIndex) & 0x03)], key->KeyMaterial, key->KeyLength);
+		
+		key->KeyIndex=key->KeyIndex & 0x03;
+		
+		padapter->securitypriv.binstallGrpkey=_TRUE;
+		
+		padapter->securitypriv.bcheck_grpkey=_FALSE;
+		
+		RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("reset group key"));
+		
+		res=rtw_set_key(padapter,&padapter->securitypriv, key->KeyIndex, 1, _TRUE);
+
+		if(res==_FAIL)
+			ret= _FAIL;
+
+		goto exit;
+			
+	}
+	else // Pairwise Key
+	{
+		u8 res;
+		
+		pbssid=get_bssid(&padapter->mlmepriv);
+		stainfo=rtw_get_stainfo(&padapter->stapriv , pbssid );
+		
+		if(stainfo!=NULL)
+		{			
+			_rtw_memset( &stainfo->dot118021x_UncstKey, 0, 16);// clear keybuffer
+			
+			_rtw_memcpy(&stainfo->dot118021x_UncstKey, key->KeyMaterial, 16);
+			
+			if(encryptionalgo== _TKIP_)
+			{
+				padapter->securitypriv.busetkipkey=_FALSE;
+				
+				//_set_timer(&padapter->securitypriv.tkip_timer, 50);
+				
+				RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n ==========_set_timer\n"));
+				
+				// if TKIP, save the Receive/Transmit MIC key in KeyMaterial[128-255]
+				if((key->KeyIndex & 0x10000000)){
+					_rtw_memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 16, 8);
+					_rtw_memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 24, 8);
+
+				} else {
+					_rtw_memcpy(&stainfo->dot11tkiptxmickey, key->KeyMaterial + 24, 8);
+					_rtw_memcpy(&stainfo->dot11tkiprxmickey, key->KeyMaterial + 16, 8);
+
+				}
+		
+			}
+			else if(encryptionalgo == _AES_)
+			{		
+	
+			}
+
+		
+			//Set key to CAM through H2C command
+			#if 0
+			if(bgrouptkey)//never go to here
+			{
+				res=rtw_setstakey_cmd(padapter, stainfo, GROUP_KEY, _TRUE);
+				RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(group)\n"));
+			}
+			else{
+				res=rtw_setstakey_cmd(padapter, stainfo, UNICAST_KEY, _TRUE);
+				RT_TRACE(_module_rtl871x_ioctl_set_c_,_drv_err_,("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(unicast)\n"));
+			}
+			#else
+			
+			res = rtw_setstakey_cmd(padapter, stainfo, UNICAST_KEY, _TRUE);
+			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("\n rtw_set_802_11_add_key:rtw_setstakey_cmd(unicast)\n"));
+			#endif
+
+			if(res ==_FALSE)
+				ret= _FAIL;
+			
+		}
+
+	}
+
+exit:
+	
+_func_exit_;
+
+	return ret;	
+}
+
+u8 rtw_set_802_11_remove_key(_adapter*	padapter, NDIS_802_11_REMOVE_KEY *key){
+	
+	uint				encryptionalgo;
+	u8 * pbssid;
+	struct sta_info *stainfo;
+	u8	bgroup = (key->KeyIndex & 0x4000000) > 0 ? _FALSE: _TRUE;
+	u8	keyIndex = (u8)key->KeyIndex & 0x03;
+	u8	ret=_SUCCESS;
+	
+_func_enter_;
+
+	if ((key->KeyIndex & 0xbffffffc) > 0) {
+		ret=_FAIL;
+		goto exit;
+	}
+
+	if (bgroup == _TRUE) {
+		encryptionalgo= padapter->securitypriv.dot118021XGrpPrivacy;
+		// clear group key by index
+		//NdisZeroMemory(Adapter->MgntInfo.SecurityInfo.KeyBuf[keyIndex], MAX_WEP_KEY_LEN);
+		//Adapter->MgntInfo.SecurityInfo.KeyLen[keyIndex] = 0;
+		
+		_rtw_memset(&padapter->securitypriv.dot118021XGrpKey[keyIndex], 0, 16);
+		
+		//! \todo Send a H2C Command to Firmware for removing this Key in CAM Entry.
+	
+	} else {
+	
+		pbssid=get_bssid(&padapter->mlmepriv);
+		stainfo=rtw_get_stainfo(&padapter->stapriv , pbssid );
+		if(stainfo !=NULL){
+			encryptionalgo=stainfo->dot118021XPrivacy;
+
+		// clear key by BSSID
+		_rtw_memset(&stainfo->dot118021x_UncstKey, 0, 16);
+		
+		//! \todo Send a H2C Command to Firmware for disable this Key in CAM Entry.
+
+		}
+		else{
+			ret= _FAIL;
+			goto exit;
+		}
+	}
+
+exit:
+	
+_func_exit_;
+
+	return _TRUE;
+	
+}
+
+/*
+* rtw_get_cur_max_rate - 
+* @adapter: pointer to _adapter structure
+* 
+* Return 0 or 100Kbps
+*/
+u16 rtw_get_cur_max_rate(_adapter *adapter)
+{
+	int	i = 0;
+	u16	rate = 0, max_rate = 0;
+	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+	WLAN_BSSID_EX	*pcur_bss = &pmlmepriv->cur_network.network;
+	struct sta_info *psta = NULL;
+	u8	short_GI=0;
+#ifdef CONFIG_80211N_HT
+	u8	rf_type = 0;
+#endif
+
+#ifdef CONFIG_MP_INCLUDED
+	if (adapter->registrypriv.mp_mode == 1)
+	{	
+		if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+			return 0;
+	}
+#endif
+
+	if((check_fwstate(pmlmepriv, _FW_LINKED) != _TRUE) 
+		&& (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) != _TRUE))
+		return 0;
+
+	psta = rtw_get_stainfo(&adapter->stapriv, get_bssid(pmlmepriv));
+	if (psta == NULL)
+		return 0;
+
+	short_GI = query_ra_short_GI(psta);
+
+#ifdef CONFIG_80211N_HT
+	if (IsSupportedHT(psta->wireless_mode)) {
+		rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+		max_rate = rtw_mcs_rate(
+			rf_type,
+			((psta->bw_mode == CHANNEL_WIDTH_40)?1:0),
+			short_GI,
+			psta->htpriv.ht_cap.supp_mcs_set
+		);
+	}
+#ifdef CONFIG_80211AC_VHT
+	else if (IsSupportedVHT(psta->wireless_mode)) {
+		max_rate = ((rtw_vht_mcs_to_data_rate(psta->bw_mode, short_GI, pmlmepriv->vhtpriv.vht_highest_rate) + 1) >> 1) * 10;
+	}
+#endif //CONFIG_80211AC_VHT
+	else 
+#endif //CONFIG_80211N_HT
+	{
+		while( (pcur_bss->SupportedRates[i]!=0) && (pcur_bss->SupportedRates[i]!=0xFF))
+		{
+			rate = pcur_bss->SupportedRates[i]&0x7F;
+			if(rate>max_rate)
+				max_rate = rate;
+			i++;
+		}
+	
+		max_rate = max_rate*10/2;
+	}
+
+	return max_rate;
+}
+
+/*
+* rtw_set_scan_mode - 
+* @adapter: pointer to _adapter structure
+* @scan_mode: 
+* 
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_scan_mode(_adapter *adapter, RT_SCAN_TYPE scan_mode)
+{
+	if(scan_mode != SCAN_ACTIVE && scan_mode != SCAN_PASSIVE)
+		return _FAIL;
+	
+	adapter->mlmepriv.scan_mode = scan_mode;
+
+	return _SUCCESS;
+}
+
+/*
+* rtw_set_channel_plan - 
+* @adapter: pointer to _adapter structure
+* @channel_plan: 
+* 
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_channel_plan(_adapter *adapter, u8 channel_plan)
+{
+	struct registry_priv *pregistrypriv = &adapter->registrypriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+	//handle by cmd_thread to sync with scan operation
+	return rtw_set_chplan_cmd(adapter, RTW_CMDF_WAIT_ACK, channel_plan, 1);
+}
+
+/*
+* rtw_set_country - 
+* @adapter: pointer to _adapter structure
+* @country_code: string of country code
+* 
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_country(_adapter *adapter, const char *country_code)
+{
+	int channel_plan;
+
+	channel_plan = rtw_get_chplan_from_country(country_code);
+
+	if (channel_plan == -1) {
+		DBG_871X_LEVEL(_drv_always_, "%s unsupported country_code:%s\n", __func__, country_code);
+		return _FAIL;
+	}
+
+	DBG_871X_LEVEL(_drv_always_, "%s country_code:%s mapping to chplan:0x%02x\n", __func__, country_code, channel_plan);
+	return rtw_set_channel_plan(adapter, channel_plan);
+}
+
+/*
+* rtw_set_band - 
+* @adapter: pointer to _adapter structure
+* @band: band to set
+* 
+* Return _SUCCESS or _FAIL
+*/
+int rtw_set_band(_adapter *adapter, u8 band)
+{
+	if (rtw_band_valid(band)) {
+		DBG_871X(FUNC_ADPT_FMT" band:%d\n", FUNC_ADPT_ARG(adapter), band);
+		adapter->setband = band;
+		return _SUCCESS;
+	}
+
+	DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" band:%d fail\n", FUNC_ADPT_ARG(adapter), band);
+	return _FAIL;
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_iol.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_iol.c
new file mode 100644
index 000000000..3524e1c5a
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_iol.c
@@ -0,0 +1,390 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+
+#ifdef CONFIG_IOL
+struct xmit_frame	*rtw_IOL_accquire_xmit_frame(ADAPTER *adapter)
+{
+	struct xmit_frame	*xmit_frame;
+	struct xmit_buf	*xmitbuf;
+	struct pkt_attrib	*pattrib;
+	struct xmit_priv	*pxmitpriv = &(adapter->xmitpriv);
+
+#if 1
+	if ((xmit_frame = rtw_alloc_xmitframe(pxmitpriv)) == NULL)
+	{
+		DBG_871X("%s rtw_alloc_xmitframe return null\n", __FUNCTION__);
+		goto exit;
+	}
+	
+	if ((xmitbuf = rtw_alloc_xmitbuf(pxmitpriv)) == NULL)
+	{
+		DBG_871X("%s rtw_alloc_xmitbuf return null\n", __FUNCTION__);
+		rtw_free_xmitframe(pxmitpriv, xmit_frame);
+		xmit_frame=NULL;
+		goto exit;
+	}
+	
+	xmit_frame->frame_tag = MGNT_FRAMETAG;
+	xmit_frame->pxmitbuf = xmitbuf;
+	xmit_frame->buf_addr = xmitbuf->pbuf;
+	xmitbuf->priv_data = xmit_frame;
+
+	pattrib = &xmit_frame->attrib;
+	update_mgntframe_attrib(adapter, pattrib);
+	pattrib->qsel = QSLT_BEACON;//Beacon	
+	pattrib->subtype = WIFI_BEACON;	
+	pattrib->pktlen = pattrib->last_txcmdsz = 0;
+
+#else
+	if ((xmit_frame = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		DBG_871X("%s alloc_mgtxmitframe return null\n", __FUNCTION__);
+	}
+	else {
+		pattrib = &xmit_frame->attrib;
+		update_mgntframe_attrib(adapter, pattrib);
+		pattrib->qsel = QSLT_BEACON;
+		pattrib->pktlen = pattrib->last_txcmdsz = 0;
+	}
+#endif
+
+exit:
+	return xmit_frame;
+}
+
+
+int rtw_IOL_append_cmds(struct xmit_frame *xmit_frame, u8 *IOL_cmds, u32 cmd_len)
+{
+	struct pkt_attrib	*pattrib = &xmit_frame->attrib;
+	u16 buf_offset;
+	u32 ori_len;
+
+	buf_offset = TXDESC_OFFSET;
+	ori_len = buf_offset+pattrib->pktlen;
+
+	//check if the io_buf can accommodate new cmds
+	if(ori_len + cmd_len + 8 > MAX_XMITBUF_SZ) {
+		DBG_871X("%s %u is large than MAX_XMITBUF_SZ:%u, can't accommodate new cmds\n", __FUNCTION__
+			, ori_len + cmd_len + 8, MAX_XMITBUF_SZ);
+		return _FAIL;
+	}
+
+	_rtw_memcpy(xmit_frame->buf_addr + buf_offset + pattrib->pktlen, IOL_cmds, cmd_len);
+	pattrib->pktlen += cmd_len;
+	pattrib->last_txcmdsz += cmd_len;
+
+	//DBG_871X("%s ori:%u + cmd_len:%u = %u\n", __FUNCTION__, ori_len, cmd_len, buf_offset+pattrib->pktlen);
+	
+	return _SUCCESS;
+}
+
+bool rtw_IOL_applied(ADAPTER *adapter)
+{	
+	if(1 == adapter->registrypriv.fw_iol)
+		return _TRUE;
+
+#ifdef CONFIG_USB_HCI
+	if((2 == adapter->registrypriv.fw_iol) && (IS_FULL_SPEED_USB(adapter)))
+		return _TRUE;
+#endif
+
+	return _FALSE;
+}
+
+int rtw_IOL_exec_cmds_sync(ADAPTER *adapter, struct xmit_frame *xmit_frame, u32 max_wating_ms, u32 bndy_cnt)
+{
+	return rtw_hal_iol_cmd(adapter, xmit_frame, max_wating_ms,bndy_cnt);
+}
+
+#ifdef CONFIG_IOL_NEW_GENERATION
+int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
+{
+	return _SUCCESS;
+}
+int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, u8 mask)
+{
+	struct ioreg_cfg cmd = {8,IOREG_CMD_WB_REG,0x0, 0x0,0x0};
+
+	//RTW_PUT_LE16((u8*)&cmd.address, addr);	
+	//RTW_PUT_LE32((u8*)&cmd.value, (u32)value);	
+	cmd.address = cpu_to_le16(addr);	
+	cmd.data = cpu_to_le32(value);
+	
+	if(mask!=0xFF)
+	{
+		cmd.length = 12;
+		//RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask);	
+		cmd.mask = cpu_to_le32(mask);
+	}	
+		
+	//DBG_871X("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, cmd.length);
+
+}
+int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, u16 mask)
+{
+	struct ioreg_cfg cmd = {8,IOREG_CMD_WW_REG,0x0, 0x0,0x0};
+
+	//RTW_PUT_LE16((u8*)&cmd.address, addr);	
+	//RTW_PUT_LE32((u8*)&cmd.value, (u32)value);	
+	cmd.address = cpu_to_le16(addr);	
+	cmd.data = cpu_to_le32(value);
+	
+	if(mask!=0xFFFF)
+	{
+		cmd.length = 12;
+		//RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask);	
+		cmd.mask =  cpu_to_le32(mask);
+	}	
+		
+	//DBG_871X("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FUNCTION__, addr,value,mask);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, cmd.length);
+	
+}
+int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, u32 mask)
+{
+	struct ioreg_cfg cmd = {8,IOREG_CMD_WD_REG,0x0, 0x0,0x0};
+
+	//RTW_PUT_LE16((u8*)&cmd.address, addr);	
+	//RTW_PUT_LE32((u8*)&cmd.value, (u32)value);	
+	cmd.address = cpu_to_le16(addr);	
+	cmd.data = cpu_to_le32(value);
+	
+	if(mask!=0xFFFFFFFF)
+	{
+		cmd.length = 12;
+		//RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask);	
+		cmd.mask =  cpu_to_le32(mask);
+	}	
+		
+	//DBG_871X("%s addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__, addr,value,mask);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, cmd.length);
+	
+}
+
+int _rtw_IOL_append_WRF_cmd(struct xmit_frame *xmit_frame, u8 rf_path, u16 addr, u32 value, u32 mask)
+{
+	struct ioreg_cfg cmd = {8,IOREG_CMD_W_RF,0x0, 0x0,0x0};
+
+	//RTW_PUT_LE16((u8*)&cmd.address, addr);	
+	//RTW_PUT_LE32((u8*)&cmd.value, (u32)value);	
+	cmd.address = (rf_path<<8) |((addr) &0xFF);	
+	cmd.data = cpu_to_le32(value);
+	
+	if(mask!=0x000FFFFF)
+	{
+		cmd.length = 12;
+		//RTW_PUT_LE32((u8*)&cmd.mask, (u32)mask);	
+		cmd.mask =  cpu_to_le32(mask);
+	}	
+		
+	//DBG_871X("%s rf_path:0x%02x addr:0x%04x,value:0x%08x,mask:0x%08x\n", __FU2NCTION__,rf_path, addr,value,mask);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, cmd.length);
+	
+}
+
+
+
+int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
+{
+	struct ioreg_cfg cmd = {4,IOREG_CMD_DELAY_US,0x0, 0x0,0x0};
+	//RTW_PUT_LE16((u8*)&cmd.address, us);	
+	cmd.address = cpu_to_le16(us);	
+
+	//DBG_871X("%s %u\n", __FUNCTION__, us);
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 4);
+}
+
+int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
+{
+	struct ioreg_cfg cmd = {4,IOREG_CMD_DELAY_US,0x0, 0x0,0x0};
+
+	//RTW_PUT_LE16((u8*)&cmd.address, ms);	
+	cmd.address = cpu_to_le16(ms);	
+
+	//DBG_871X("%s %u\n", __FUNCTION__, ms);
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 4);
+}
+int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
+{	
+	struct ioreg_cfg cmd = {4,IOREG_CMD_END,0xFFFF, 0xFF,0x0};
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 4);
+
+}
+
+u8 rtw_IOL_cmd_boundary_handle(struct xmit_frame *pxmit_frame)
+{	
+	u8 is_cmd_bndy = _FALSE;
+	if(((pxmit_frame->attrib.pktlen+32)%256) + 8 >= 256){
+		rtw_IOL_append_END_cmd(pxmit_frame);
+		pxmit_frame->attrib.pktlen = ((((pxmit_frame->attrib.pktlen+32)/256)+1)*256 );
+		
+		//printk("==> %s, pktlen(%d)\n",__FUNCTION__,pxmit_frame->attrib.pktlen);
+		pxmit_frame->attrib.last_txcmdsz = pxmit_frame->attrib.pktlen;
+		is_cmd_bndy = _TRUE;	
+	}
+	return is_cmd_bndy;
+}
+
+void rtw_IOL_cmd_buf_dump(ADAPTER *Adapter,int buf_len,u8 *pbuf)
+{
+	int i;
+	int j=1;
+	
+	printk("###### %s ######\n",__FUNCTION__);
+	for(i=0;i< buf_len;i++){
+		printk("%02x-",*(pbuf+i));
+			
+		if(j%32 ==0) printk("\n");j++;				
+	}
+	printk("\n");
+	printk("============= ioreg_cmd len = %d =============== \n",buf_len);	
+}
+
+
+#else //CONFIG_IOL_NEW_GENERATION
+int rtw_IOL_append_LLT_cmd(struct xmit_frame *xmit_frame, u8 page_boundary)
+{	
+	IOL_CMD cmd = {0x0, IOL_CMD_LLT, 0x0, 0x0};
+	
+	RTW_PUT_BE32((u8*)&cmd.value, (u32)page_boundary);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8);
+}
+
+int _rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value)
+{
+	IOL_CMD cmd = {0x0, IOL_CMD_WB_REG, 0x0, 0x0};
+	
+	RTW_PUT_BE16((u8*)&cmd.address, (u16)addr);
+	RTW_PUT_BE32((u8*)&cmd.value, (u32)value);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8);
+}
+
+int _rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value)
+{
+	IOL_CMD cmd = {0x0, IOL_CMD_WW_REG, 0x0, 0x0};
+	
+	RTW_PUT_BE16((u8*)&cmd.address, (u16)addr);
+	RTW_PUT_BE32((u8*)&cmd.value, (u32)value);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8);
+}
+
+int _rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value)
+{
+	IOL_CMD cmd = {0x0, IOL_CMD_WD_REG, 0x0, 0x0};
+	u8* pos = (u8 *)&cmd;
+	
+	RTW_PUT_BE16((u8*)&cmd.address, (u16)addr);
+	RTW_PUT_BE32((u8*)&cmd.value, (u32)value);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8);
+}
+
+#ifdef DBG_IO
+int dbg_rtw_IOL_append_WB_cmd(struct xmit_frame *xmit_frame, u16 addr, u8 value, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 1))
+		DBG_871X("DBG_IO %s:%d IOL_WB(0x%04x, 0x%02x)\n", caller, line, addr, value);
+
+	return _rtw_IOL_append_WB_cmd(xmit_frame, addr, value);
+}
+
+int dbg_rtw_IOL_append_WW_cmd(struct xmit_frame *xmit_frame, u16 addr, u16 value, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 2))
+		DBG_871X("DBG_IO %s:%d IOL_WW(0x%04x, 0x%04x)\n", caller, line, addr, value);
+
+	return _rtw_IOL_append_WW_cmd(xmit_frame, addr, value);
+}
+
+int dbg_rtw_IOL_append_WD_cmd(struct xmit_frame *xmit_frame, u16 addr, u32 value, const char *caller, const int line)
+{
+	if (match_write_sniff_ranges(addr, 4))
+		DBG_871X("DBG_IO %s:%d IOL_WD(0x%04x, 0x%08x)\n", caller, line, addr, value);
+
+	return _rtw_IOL_append_WD_cmd(xmit_frame, addr, value);
+}
+#endif
+
+int rtw_IOL_append_DELAY_US_cmd(struct xmit_frame *xmit_frame, u16 us)
+{
+	IOL_CMD cmd = {0x0, IOL_CMD_DELAY_US, 0x0, 0x0};
+	
+	RTW_PUT_BE32((u8*)&cmd.value, (u32)us);
+
+	//DBG_871X("%s %u\n", __FUNCTION__, us);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8);
+}
+
+int rtw_IOL_append_DELAY_MS_cmd(struct xmit_frame *xmit_frame, u16 ms)
+{
+	IOL_CMD cmd = {0x0, IOL_CMD_DELAY_MS, 0x0, 0x0};
+	
+	RTW_PUT_BE32((u8*)&cmd.value, (u32)ms);
+
+	//DBG_871X("%s %u\n", __FUNCTION__, ms);
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&cmd, 8);
+}
+
+int rtw_IOL_append_END_cmd(struct xmit_frame *xmit_frame)
+{	
+	IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
+
+
+	return rtw_IOL_append_cmds(xmit_frame, (u8*)&end_cmd, 8);
+
+}
+
+int rtw_IOL_exec_cmd_array_sync(PADAPTER adapter, u8 *IOL_cmds, u32 cmd_num, u32 max_wating_ms)
+{
+	struct xmit_frame	*xmit_frame;
+
+	if((xmit_frame=rtw_IOL_accquire_xmit_frame(adapter)) == NULL)
+		return _FAIL;
+
+	if(rtw_IOL_append_cmds(xmit_frame, IOL_cmds, cmd_num<<3) == _FAIL)
+		return _FAIL;
+
+	return rtw_IOL_exec_cmds_sync(adapter, xmit_frame, max_wating_ms,0);
+}
+
+int rtw_IOL_exec_empty_cmds_sync(ADAPTER *adapter, u32 max_wating_ms)
+{
+	IOL_CMD end_cmd = {0x0, IOL_CMD_END, 0x0, 0x0};
+	return rtw_IOL_exec_cmd_array_sync(adapter, (u8*)&end_cmd, 1, max_wating_ms);
+}
+#endif //CONFIG_IOL_NEW_GENERATION
+
+
+
+
+#endif //CONFIG_IOL
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mem.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mem.c
new file mode 100644
index 000000000..45ccd9d4d
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mem.c
@@ -0,0 +1,122 @@
+
+#include <drv_types.h>
+#include <rtw_mem.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek Wireless Lan Driver");
+MODULE_AUTHOR("Realtek Semiconductor Corp.");
+MODULE_VERSION("DRIVERVERSION");
+
+struct sk_buff_head rtk_skb_mem_q;
+struct u8* rtk_buf_mem[NR_RECVBUFF];
+
+struct u8	* rtw_get_buf_premem(int index)
+{
+	printk("%s, rtk_buf_mem index : %d\n", __func__, index);
+	return rtk_buf_mem[index];
+}
+
+u16 rtw_rtkm_get_buff_size(void)
+{
+	return MAX_RTKM_RECVBUF_SZ;
+}
+EXPORT_SYMBOL(rtw_rtkm_get_buff_size);
+
+u8 rtw_rtkm_get_nr_recv_skb(void)
+{
+	return MAX_RTKM_NR_PREALLOC_RECV_SKB;
+}
+EXPORT_SYMBOL(rtw_rtkm_get_nr_recv_skb);
+
+struct sk_buff *rtw_alloc_skb_premem(u16 in_size)
+{
+	struct sk_buff *skb = NULL;
+
+	if (in_size > MAX_RTKM_RECVBUF_SZ) {
+		pr_info("warning %s: driver buffer size(%d) > rtkm buffer size(%d)\n", __func__, in_size, MAX_RTKM_RECVBUF_SZ);
+		WARN_ON(1);
+		return skb;
+	}
+
+	skb = skb_dequeue(&rtk_skb_mem_q);
+
+	printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
+
+	return skb;	
+}
+EXPORT_SYMBOL(rtw_alloc_skb_premem);
+
+int rtw_free_skb_premem(struct sk_buff *pskb)
+{
+	if(!pskb)
+		return -1;
+
+	if (skb_queue_len(&rtk_skb_mem_q) >= MAX_RTKM_NR_PREALLOC_RECV_SKB)	
+		return -1;
+	
+	skb_queue_tail(&rtk_skb_mem_q, pskb);
+	
+	printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
+
+	return 0;
+}
+EXPORT_SYMBOL(rtw_free_skb_premem);
+
+static int __init rtw_mem_init(void)
+{
+	int i;
+	SIZE_PTR tmpaddr=0;
+	SIZE_PTR alignment=0;
+	struct sk_buff *pskb=NULL;
+
+	printk("%s\n", __func__);
+	pr_info("MAX_RTKM_NR_PREALLOC_RECV_SKB: %d\n", MAX_RTKM_NR_PREALLOC_RECV_SKB);
+	pr_info("MAX_RTKM_RECVBUF_SZ: %d\n", MAX_RTKM_RECVBUF_SZ);
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+	for(i=0; i<NR_RECVBUFF; i++)
+	{
+		rtk_buf_mem[i] = usb_buffer_alloc(dev, size, (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL), dma);
+	}
+#endif //CONFIG_USE_USB_BUFFER_ALLOC_RX
+
+	skb_queue_head_init(&rtk_skb_mem_q);
+
+	for(i=0; i<MAX_RTKM_NR_PREALLOC_RECV_SKB; i++)
+	{
+		pskb = __dev_alloc_skb(MAX_RTKM_RECVBUF_SZ + RECVBUFF_ALIGN_SZ, in_interrupt() ? GFP_ATOMIC : GFP_KERNEL);
+		if(pskb)
+		{		
+			tmpaddr = (SIZE_PTR)pskb->data;
+			alignment = tmpaddr & (RECVBUFF_ALIGN_SZ-1);
+			skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
+
+			skb_queue_tail(&rtk_skb_mem_q, pskb);
+		}
+		else
+		{
+			printk("%s, alloc skb memory fail!\n", __func__);
+		}
+
+		pskb=NULL;
+	}
+
+	printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
+
+	return 0;
+	
+}
+
+static void __exit rtw_mem_exit(void)
+{
+	if (skb_queue_len(&rtk_skb_mem_q)) {
+		printk("%s, rtk_skb_mem_q len : %d\n", __func__, skb_queue_len(&rtk_skb_mem_q));
+	}
+
+	skb_queue_purge(&rtk_skb_mem_q);
+
+	printk("%s\n", __func__);
+}
+
+module_init(rtw_mem_init);
+module_exit(rtw_mem_exit);
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme.c
new file mode 100644
index 000000000..dc1d3c0d4
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme.c
@@ -0,0 +1,4935 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_MLME_C_
+
+#include <hal_data.h>
+
+extern void indicate_wx_scan_complete_event(_adapter *padapter);
+extern u8 rtw_do_join(_adapter * padapter);
+
+
+sint	_rtw_init_mlme_priv (_adapter* padapter)
+{
+	sint	i;
+	u8	*pbuf;
+	struct wlan_network	*pnetwork;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	sint	res = _SUCCESS;
+
+_func_enter_;
+
+	// We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
+	//_rtw_memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
+
+	pmlmepriv->nic_hdl = (u8 *)padapter;
+
+	pmlmepriv->pscanned = NULL;
+	pmlmepriv->fw_state = WIFI_STATION_STATE; // Must sync with rtw_wdev_alloc() 
+	                                          // wdev->iftype = NL80211_IFTYPE_STATION
+	pmlmepriv->cur_network.network.InfrastructureMode = Ndis802_11AutoUnknown;
+	pmlmepriv->scan_mode=SCAN_ACTIVE;// 1: active, 0: pasive. Maybe someday we should rename this varable to "active_mode" (Jeff)
+
+	_rtw_spinlock_init(&(pmlmepriv->lock));	
+	_rtw_init_queue(&(pmlmepriv->free_bss_pool));
+	_rtw_init_queue(&(pmlmepriv->scanned_queue));
+
+	set_scanned_network_val(pmlmepriv, 0);
+	
+	_rtw_memset(&pmlmepriv->assoc_ssid,0,sizeof(NDIS_802_11_SSID));
+
+	pbuf = rtw_zvmalloc(MAX_BSS_CNT * (sizeof(struct wlan_network)));
+	
+	if (pbuf == NULL){
+		res=_FAIL;
+		goto exit;
+	}
+	pmlmepriv->free_bss_buf = pbuf;
+		
+	pnetwork = (struct wlan_network *)pbuf;
+	
+	for(i = 0; i < MAX_BSS_CNT; i++)
+	{		
+		_rtw_init_listhead(&(pnetwork->list));
+
+		rtw_list_insert_tail(&(pnetwork->list), &(pmlmepriv->free_bss_pool.queue));
+
+		pnetwork++;
+	}
+
+	//allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf
+
+	rtw_clear_scan_deny(padapter);
+#ifdef CONFIG_ARP_KEEP_ALIVE
+	pmlmepriv->bGetGateway = 0;
+#endif
+
+#ifdef CONFIG_LAYER2_ROAMING
+	#define RTW_ROAM_SCAN_RESULT_EXP_MS 5*1000
+	#define RTW_ROAM_RSSI_DIFF_TH 10
+	#define RTW_ROAM_SCAN_INTERVAL_MS 10*1000
+
+	pmlmepriv->roam_flags = 0
+		| RTW_ROAM_ON_EXPIRED
+		#ifdef CONFIG_LAYER2_ROAMING_RESUME
+		| RTW_ROAM_ON_RESUME
+		#endif
+		#ifdef CONFIG_LAYER2_ROAMING_ACTIVE
+		| RTW_ROAM_ACTIVE
+		#endif
+		;
+
+	pmlmepriv->roam_scanr_exp_ms = RTW_ROAM_SCAN_RESULT_EXP_MS;
+	pmlmepriv->roam_rssi_diff_th = RTW_ROAM_RSSI_DIFF_TH;
+	pmlmepriv->roam_scan_int_ms = RTW_ROAM_SCAN_INTERVAL_MS;
+#endif /* CONFIG_LAYER2_ROAMING */
+
+	rtw_init_mlme_timer(padapter);
+
+exit:
+
+_func_exit_;
+
+	return res;
+}	
+
+void rtw_mfree_mlme_priv_lock (struct mlme_priv *pmlmepriv);
+void rtw_mfree_mlme_priv_lock (struct mlme_priv *pmlmepriv)
+{
+	_rtw_spinlock_free(&pmlmepriv->lock);
+	_rtw_spinlock_free(&(pmlmepriv->free_bss_pool.lock));
+	_rtw_spinlock_free(&(pmlmepriv->scanned_queue.lock));
+}
+
+static void rtw_free_mlme_ie_data(u8 **ppie, u32 *plen)
+{
+	if(*ppie)
+	{		
+		rtw_mfree(*ppie, *plen);
+		*plen = 0;
+		*ppie=NULL;
+	}	
+}
+
+void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv)
+{
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
+	rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_beacon_ie, &pmlmepriv->wps_beacon_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_req_ie, &pmlmepriv->wps_probe_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_probe_resp_ie, &pmlmepriv->wps_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wps_assoc_resp_ie, &pmlmepriv->wps_assoc_resp_ie_len);
+	
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_beacon_ie, &pmlmepriv->p2p_beacon_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_req_ie, &pmlmepriv->p2p_probe_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_probe_resp_ie, &pmlmepriv->p2p_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_go_probe_resp_ie, &pmlmepriv->p2p_go_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_req_ie, &pmlmepriv->p2p_assoc_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->p2p_assoc_resp_ie, &pmlmepriv->p2p_assoc_resp_ie_len);
+#endif
+
+#if defined(CONFIG_WFD) && defined(CONFIG_IOCTL_CFG80211)	
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_beacon_ie, &pmlmepriv->wfd_beacon_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_req_ie, &pmlmepriv->wfd_probe_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_probe_resp_ie, &pmlmepriv->wfd_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_go_probe_resp_ie, &pmlmepriv->wfd_go_probe_resp_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_req_ie, &pmlmepriv->wfd_assoc_req_ie_len);
+	rtw_free_mlme_ie_data(&pmlmepriv->wfd_assoc_resp_ie, &pmlmepriv->wfd_assoc_resp_ie_len);
+#endif
+
+}
+
+#if defined(CONFIG_WFD) && defined(CONFIG_IOCTL_CFG80211)
+int rtw_mlme_update_wfd_ie_data(struct mlme_priv *mlme, u8 type, u8 *ie, u32 ie_len)
+{
+	_adapter *adapter = mlme_to_adapter(mlme);
+	struct wifi_display_info *wfd_info = &adapter->wfd_info;
+	u8 clear = 0;
+	u8 **t_ie = NULL;
+	u32 *t_ie_len = NULL;
+	int ret = _FAIL;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		goto success;
+
+	if (wfd_info->wfd_enable == _TRUE)
+		goto success; /* WFD IE is build by self */
+
+	if (!ie && !ie_len) {
+		clear = 1;
+	} else if (!ie || !ie_len) {
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" type:%u, ie:%p, ie_len:%u"
+			, FUNC_ADPT_ARG(adapter), type, ie, ie_len);
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	switch (type) {
+	case MLME_BEACON_IE:
+		t_ie = &mlme->wfd_beacon_ie;
+		t_ie_len = &mlme->wfd_beacon_ie_len;
+		break;
+	case MLME_PROBE_REQ_IE:
+		t_ie = &mlme->wfd_probe_req_ie;
+		t_ie_len = &mlme->wfd_probe_req_ie_len;
+		break;
+	case MLME_PROBE_RESP_IE:
+		t_ie = &mlme->wfd_probe_resp_ie;
+		t_ie_len = &mlme->wfd_probe_resp_ie_len;
+		break;
+	case MLME_GO_PROBE_RESP_IE:
+		t_ie = &mlme->wfd_go_probe_resp_ie;
+		t_ie_len = &mlme->wfd_go_probe_resp_ie_len;
+		break;
+	case MLME_ASSOC_REQ_IE:
+		t_ie = &mlme->wfd_assoc_req_ie;
+		t_ie_len = &mlme->wfd_assoc_req_ie_len;
+		break;
+	case MLME_ASSOC_RESP_IE:
+		t_ie = &mlme->wfd_assoc_resp_ie;
+		t_ie_len = &mlme->wfd_assoc_resp_ie_len;
+		break;
+	default:
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" unsupported type:%u"
+			, FUNC_ADPT_ARG(adapter), type);
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (*t_ie) {
+		u32 free_len = *t_ie_len;
+		*t_ie_len = 0;
+		rtw_mfree(*t_ie, free_len);
+		*t_ie = NULL;
+	}
+
+	if (!clear) {
+		*t_ie = rtw_malloc(ie_len);
+		if (*t_ie == NULL) {
+			DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" type:%u, rtw_malloc() fail\n"
+				, FUNC_ADPT_ARG(adapter), type);
+			goto exit;
+		}
+		_rtw_memcpy(*t_ie, ie, ie_len);
+		*t_ie_len = ie_len;
+	}
+
+	if (*t_ie && *t_ie_len) {
+		u8 *attr_content;
+		u32 attr_contentlen = 0;
+
+		attr_content = rtw_get_wfd_attr_content(*t_ie, *t_ie_len, WFD_ATTR_DEVICE_INFO, NULL, &attr_contentlen);
+		if (attr_content && attr_contentlen) {
+			if (RTW_GET_BE16(attr_content + 2) != wfd_info->rtsp_ctrlport) {
+				wfd_info->rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);
+				DBG_871X(FUNC_ADPT_FMT" type:%u, RTSP CTRL port = %u\n"
+					, FUNC_ADPT_ARG(adapter), type, wfd_info->rtsp_ctrlport);
+			}
+		}
+	}
+
+success:
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+#endif /* defined(CONFIG_WFD) && defined(CONFIG_IOCTL_CFG80211) */
+
+void _rtw_free_mlme_priv (struct mlme_priv *pmlmepriv)
+{
+_func_enter_;
+	if (NULL == pmlmepriv){
+		rtw_warn_on(1);
+		goto exit;
+	}
+	rtw_free_mlme_priv_ie_data(pmlmepriv);
+
+	if(pmlmepriv){
+		rtw_mfree_mlme_priv_lock (pmlmepriv);
+
+		if (pmlmepriv->free_bss_buf) {
+			rtw_vmfree(pmlmepriv->free_bss_buf, MAX_BSS_CNT * sizeof(struct wlan_network));
+		}
+	}
+exit:
+_func_exit_;	
+}
+
+sint	_rtw_enqueue_network(_queue *queue, struct wlan_network *pnetwork)
+{
+	_irqL irqL;
+
+_func_enter_;	
+
+	if (pnetwork == NULL)
+		goto exit;
+	
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	rtw_list_insert_tail(&pnetwork->list, &queue->queue);
+
+	_exit_critical_bh(&queue->lock, &irqL);
+
+exit:	
+
+_func_exit_;		
+
+	return _SUCCESS;
+}
+
+/*
+struct	wlan_network *_rtw_dequeue_network(_queue *queue)
+{
+	_irqL irqL;
+
+	struct wlan_network *pnetwork;
+
+_func_enter_;	
+
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	if (_rtw_queue_empty(queue) == _TRUE)
+
+		pnetwork = NULL;
+	
+	else
+	{
+		pnetwork = LIST_CONTAINOR(get_next(&queue->queue), struct wlan_network, list);
+		
+		rtw_list_delete(&(pnetwork->list));
+	}
+	
+	_exit_critical_bh(&queue->lock, &irqL);
+
+_func_exit_;		
+
+	return pnetwork;
+}
+*/
+
+struct	wlan_network *_rtw_alloc_network(struct	mlme_priv *pmlmepriv )//(_queue *free_queue)
+{
+	_irqL	irqL;
+	struct	wlan_network	*pnetwork;	
+	_queue *free_queue = &pmlmepriv->free_bss_pool;
+	_list* plist = NULL;
+	
+_func_enter_;	
+
+	_enter_critical_bh(&free_queue->lock, &irqL);
+	
+	if (_rtw_queue_empty(free_queue) == _TRUE) {
+		pnetwork=NULL;
+		goto exit;
+	}
+	plist = get_next(&(free_queue->queue));
+	
+	pnetwork = LIST_CONTAINOR(plist , struct wlan_network, list);
+	
+	rtw_list_delete(&pnetwork->list);
+	
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("_rtw_alloc_network: ptr=%p\n", plist));
+	pnetwork->network_type = 0;
+	pnetwork->fixed = _FALSE;
+	pnetwork->last_scanned = rtw_get_current_time();
+	pnetwork->aid=0;	
+	pnetwork->join_res=0;
+
+	pmlmepriv->num_of_scanned ++;
+	
+exit:
+	_exit_critical_bh(&free_queue->lock, &irqL);
+
+_func_exit_;		
+
+	return pnetwork;	
+}
+
+void _rtw_free_network(struct	mlme_priv *pmlmepriv ,struct wlan_network *pnetwork, u8 isfreeall)
+{
+	u32 delta_time;
+	u32 lifetime = SCANQUEUE_LIFETIME;
+	_irqL irqL;	
+	_queue *free_queue = &(pmlmepriv->free_bss_pool);
+	
+_func_enter_;		
+
+	if (pnetwork == NULL)
+		goto exit;
+
+	if (pnetwork->fixed == _TRUE)
+		goto exit;
+
+	if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==_TRUE ) || 
+		(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE ) )
+		lifetime = 1;
+
+	if(!isfreeall)
+	{
+		delta_time = (u32) rtw_get_passing_time_ms(pnetwork->last_scanned);
+		if(delta_time < lifetime)// unit:msec
+			goto exit;
+	}
+
+	_enter_critical_bh(&free_queue->lock, &irqL);
+	
+	rtw_list_delete(&(pnetwork->list));
+
+	rtw_list_insert_tail(&(pnetwork->list),&(free_queue->queue));
+		
+	pmlmepriv->num_of_scanned --;
+	
+
+	//DBG_871X("_rtw_free_network:SSID=%s\n", pnetwork->network.Ssid.Ssid);
+	
+	_exit_critical_bh(&free_queue->lock, &irqL);
+	
+exit:		
+	
+_func_exit_;			
+
+}
+
+void _rtw_free_network_nolock(struct	mlme_priv *pmlmepriv, struct wlan_network *pnetwork)
+{
+
+	_queue *free_queue = &(pmlmepriv->free_bss_pool);
+
+_func_enter_;		
+
+	if (pnetwork == NULL)
+		goto exit;
+
+	if (pnetwork->fixed == _TRUE)
+		goto exit;
+
+	//_enter_critical(&free_queue->lock, &irqL);
+	
+	rtw_list_delete(&(pnetwork->list));
+
+	rtw_list_insert_tail(&(pnetwork->list), get_list_head(free_queue));
+		
+	pmlmepriv->num_of_scanned --;
+	
+	//_exit_critical(&free_queue->lock, &irqL);
+	
+exit:		
+
+_func_exit_;			
+
+}
+
+
+/*
+	return the wlan_network with the matching addr
+
+	Shall be calle under atomic context... to avoid possible racing condition...
+*/
+struct wlan_network *_rtw_find_network(_queue *scanned_queue, u8 *addr)
+{
+
+	//_irqL irqL;
+	_list	*phead, *plist;
+	struct	wlan_network *pnetwork = NULL;
+	u8 zero_addr[ETH_ALEN] = {0,0,0,0,0,0};
+	
+_func_enter_;	
+
+	if(_rtw_memcmp(zero_addr, addr, ETH_ALEN)){
+		pnetwork=NULL;
+		goto exit;
+	}
+	
+	//_enter_critical_bh(&scanned_queue->lock, &irqL);
+	
+	phead = get_list_head(scanned_queue);
+	plist = get_next(phead);
+	 
+	while (plist != phead)
+       {
+                pnetwork = LIST_CONTAINOR(plist, struct wlan_network ,list);
+
+		if (_rtw_memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN) == _TRUE)
+                        break;
+		
+		plist = get_next(plist);
+        }
+
+	if(plist == phead)
+		pnetwork = NULL;
+
+	//_exit_critical_bh(&scanned_queue->lock, &irqL);
+	
+exit:		
+	
+_func_exit_;		
+
+	return pnetwork;
+	
+}
+
+
+void _rtw_free_network_queue(_adapter *padapter, u8 isfreeall)
+{
+	_irqL irqL;
+	_list *phead, *plist;
+	struct wlan_network *pnetwork;
+	struct mlme_priv* pmlmepriv = &padapter->mlmepriv;
+	_queue *scanned_queue = &pmlmepriv->scanned_queue;
+
+_func_enter_;	
+	
+
+	_enter_critical_bh(&scanned_queue->lock, &irqL);
+
+	phead = get_list_head(scanned_queue);
+	plist = get_next(phead);
+
+	while (rtw_end_of_queue_search(phead, plist) == _FALSE)
+	{
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		plist = get_next(plist);
+
+		_rtw_free_network(pmlmepriv,pnetwork, isfreeall);
+		
+	}
+
+	_exit_critical_bh(&scanned_queue->lock, &irqL);
+	
+_func_exit_;		
+
+}
+
+
+
+
+sint rtw_if_up(_adapter *padapter)	{
+
+	sint res;
+_func_enter_;		
+
+	if (RTW_CANNOT_RUN(padapter) ||
+		(check_fwstate(&padapter->mlmepriv, _FW_LINKED) == _FALSE)) {
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("rtw_if_up:bDriverStopped(%s) OR bSurpriseRemoved(%s)"
+			, rtw_is_drv_stopped(padapter)?"True":"False"
+			, rtw_is_surprise_removed(padapter)?"True":"False"));
+		res=_FALSE;
+	}
+	else
+		res=  _TRUE;
+	
+_func_exit_;
+	return res;
+}
+
+
+void rtw_generate_random_ibss(u8* pibss)
+{
+	u32	curtime = rtw_get_current_time();
+
+_func_enter_;
+	pibss[0] = 0x02;  //in ad-hoc mode bit1 must set to 1
+	pibss[1] = 0x11;
+	pibss[2] = 0x87;
+	pibss[3] = (u8)(curtime & 0xff) ;//p[0];
+	pibss[4] = (u8)((curtime>>8) & 0xff) ;//p[1];
+	pibss[5] = (u8)((curtime>>16) & 0xff) ;//p[2];
+_func_exit_;
+	return;
+}
+
+u8 *rtw_get_capability_from_ie(u8 *ie)
+{
+	return (ie + 8 + 2);
+}
+
+
+u16 rtw_get_capability(WLAN_BSSID_EX *bss)
+{
+	u16	val;
+_func_enter_;	
+
+	_rtw_memcpy((u8 *)&val, rtw_get_capability_from_ie(bss->IEs), 2); 
+
+_func_exit_;		
+	return le16_to_cpu(val);
+}
+
+u8 *rtw_get_timestampe_from_ie(u8 *ie)
+{
+	return (ie + 0);	
+}
+
+u8 *rtw_get_beacon_interval_from_ie(u8 *ie)
+{
+	return (ie + 8);	
+}
+
+
+int	rtw_init_mlme_priv (_adapter *padapter)//(struct	mlme_priv *pmlmepriv)
+{
+	int	res;
+_func_enter_;	
+	res = _rtw_init_mlme_priv(padapter);// (pmlmepriv);
+_func_exit_;	
+	return res;
+}
+
+void rtw_free_mlme_priv (struct mlme_priv *pmlmepriv)
+{
+_func_enter_;
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_mlme_priv\n"));
+	_rtw_free_mlme_priv (pmlmepriv);
+_func_exit_;	
+}
+
+int	rtw_enqueue_network(_queue *queue, struct wlan_network *pnetwork);
+int	rtw_enqueue_network(_queue *queue, struct wlan_network *pnetwork)
+{
+	int	res;
+_func_enter_;		
+	res = _rtw_enqueue_network(queue, pnetwork);
+_func_exit_;		
+	return res;
+}
+
+/*
+static struct	wlan_network *rtw_dequeue_network(_queue *queue)
+{
+	struct wlan_network *pnetwork;
+_func_enter_;		
+	pnetwork = _rtw_dequeue_network(queue);
+_func_exit_;		
+	return pnetwork;
+}
+*/
+
+struct	wlan_network *rtw_alloc_network(struct	mlme_priv *pmlmepriv );
+struct	wlan_network *rtw_alloc_network(struct	mlme_priv *pmlmepriv )//(_queue	*free_queue)
+{
+	struct	wlan_network	*pnetwork;
+_func_enter_;			
+	pnetwork = _rtw_alloc_network(pmlmepriv);
+_func_exit_;			
+	return pnetwork;
+}
+
+void rtw_free_network(struct mlme_priv *pmlmepriv, struct	wlan_network *pnetwork, u8 is_freeall);
+void rtw_free_network(struct mlme_priv *pmlmepriv, struct	wlan_network *pnetwork, u8 is_freeall)//(struct	wlan_network *pnetwork, _queue	*free_queue)
+{
+_func_enter_;		
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_network==> ssid = %s \n\n" , pnetwork->network.Ssid.Ssid));
+	_rtw_free_network(pmlmepriv, pnetwork, is_freeall);
+_func_exit_;
+}
+
+void rtw_free_network_nolock(_adapter * padapter, struct wlan_network *pnetwork );
+void rtw_free_network_nolock(_adapter * padapter, struct wlan_network *pnetwork )
+{
+_func_enter_;		
+	//RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_network==> ssid = %s \n\n" , pnetwork->network.Ssid.Ssid));
+	_rtw_free_network_nolock(&(padapter->mlmepriv), pnetwork);
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_unlink_bss(padapter, pnetwork);
+#endif //CONFIG_IOCTL_CFG80211
+_func_exit_;		
+}
+
+
+void rtw_free_network_queue(_adapter* dev, u8 isfreeall)
+{
+_func_enter_;		
+	_rtw_free_network_queue(dev, isfreeall);
+_func_exit_;			
+}
+
+/*
+	return the wlan_network with the matching addr
+
+	Shall be calle under atomic context... to avoid possible racing condition...
+*/
+struct	wlan_network *rtw_find_network(_queue *scanned_queue, u8 *addr)
+{
+	struct	wlan_network *pnetwork = _rtw_find_network(scanned_queue, addr);
+
+	return pnetwork;
+}
+
+int rtw_is_same_ibss(_adapter *adapter, struct wlan_network *pnetwork)
+{
+	int ret=_TRUE;
+	struct security_priv *psecuritypriv = &adapter->securitypriv;
+
+	if ( (psecuritypriv->dot11PrivacyAlgrthm != _NO_PRIVACY_ ) &&
+		    ( pnetwork->network.Privacy == 0 ) )
+	{
+		ret=_FALSE;
+	}
+	else if((psecuritypriv->dot11PrivacyAlgrthm == _NO_PRIVACY_ ) &&
+		 ( pnetwork->network.Privacy == 1 ) )
+	{
+		ret=_FALSE;
+	}
+	else
+	{
+		ret=_TRUE;
+	}
+	
+	return ret;
+	
+}
+
+inline int is_same_ess(WLAN_BSSID_EX *a, WLAN_BSSID_EX *b)
+{
+	//RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("(%s,%d)(%s,%d)\n",
+	//		a->Ssid.Ssid,a->Ssid.SsidLength,b->Ssid.Ssid,b->Ssid.SsidLength));
+	return (a->Ssid.SsidLength == b->Ssid.SsidLength) 
+		&&  _rtw_memcmp(a->Ssid.Ssid, b->Ssid.Ssid, a->Ssid.SsidLength)==_TRUE;
+}
+
+int is_same_network(WLAN_BSSID_EX *src, WLAN_BSSID_EX *dst, u8 feature)
+{
+	 u16 s_cap, d_cap;
+	 
+_func_enter_;	
+
+	if(rtw_bug_check(dst, src, &s_cap, &d_cap)==_FALSE)
+			return _FALSE;
+
+	_rtw_memcpy((u8 *)&s_cap, rtw_get_capability_from_ie(src->IEs), 2);
+	_rtw_memcpy((u8 *)&d_cap, rtw_get_capability_from_ie(dst->IEs), 2);
+
+	
+	s_cap = le16_to_cpu(s_cap);
+	d_cap = le16_to_cpu(d_cap);
+	
+_func_exit_;			
+
+#ifdef CONFIG_P2P
+	if ((feature == 1) && // 1: P2P supported
+		(_rtw_memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN) == _TRUE)
+		) {
+		return _TRUE;
+	}
+#endif
+
+	return ((src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
+		//	(src->Configuration.DSConfig == dst->Configuration.DSConfig) &&
+			( (_rtw_memcmp(src->MacAddress, dst->MacAddress, ETH_ALEN)) == _TRUE) &&
+			( (_rtw_memcmp(src->Ssid.Ssid, dst->Ssid.Ssid, src->Ssid.SsidLength)) == _TRUE) &&
+			((s_cap & WLAN_CAPABILITY_IBSS) == 
+			(d_cap & WLAN_CAPABILITY_IBSS)) &&
+			((s_cap & WLAN_CAPABILITY_BSS) == 
+			(d_cap & WLAN_CAPABILITY_BSS)));
+	
+}
+
+struct wlan_network *_rtw_find_same_network(_queue *scanned_queue, struct wlan_network *network)
+{
+	_list *phead, *plist;
+	struct wlan_network *found = NULL;
+
+	phead = get_list_head(scanned_queue);
+	plist = get_next(phead);
+
+	while (plist != phead) {
+		found = LIST_CONTAINOR(plist, struct wlan_network ,list);
+
+		if (is_same_network(&network->network, &found->network,0))
+			break;
+
+		plist = get_next(plist);
+	}
+
+	if(plist == phead)
+		found = NULL;
+exit:		
+	return found;
+}
+
+struct wlan_network *rtw_find_same_network(_queue *scanned_queue, struct wlan_network *network)
+{
+	_irqL irqL;
+	struct wlan_network *found = NULL;
+
+	if (scanned_queue == NULL || network == NULL)
+		goto exit;	
+
+	_enter_critical_bh(&scanned_queue->lock, &irqL);
+	found = _rtw_find_same_network(scanned_queue, network);
+	_exit_critical_bh(&scanned_queue->lock, &irqL);
+
+exit:
+	return found;
+}
+
+struct	wlan_network	* rtw_get_oldest_wlan_network(_queue *scanned_queue)
+{
+	_list	*plist, *phead;
+
+	
+	struct	wlan_network	*pwlan = NULL;
+	struct	wlan_network	*oldest = NULL;
+_func_enter_;		
+	phead = get_list_head(scanned_queue);
+	
+	plist = get_next(phead);
+
+	while(1)
+	{
+		
+		if (rtw_end_of_queue_search(phead,plist)== _TRUE)
+			break;
+		
+		pwlan= LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		if(pwlan->fixed!=_TRUE)
+		{		
+			if (oldest == NULL ||time_after(oldest->last_scanned, pwlan->last_scanned))
+				oldest = pwlan;
+		}
+		
+		plist = get_next(plist);
+	}
+_func_exit_;		
+	return oldest;
+	
+}
+
+void update_network(WLAN_BSSID_EX *dst, WLAN_BSSID_EX *src,
+	_adapter * padapter, bool update_ie)
+{
+	u8 ss_ori = dst->PhyInfo.SignalStrength;
+	u8 sq_ori = dst->PhyInfo.SignalQuality;
+	long rssi_ori = dst->Rssi;
+
+	u8 ss_smp = src->PhyInfo.SignalStrength;
+	u8 sq_smp = src->PhyInfo.SignalQuality;
+	long rssi_smp = src->Rssi;
+
+	u8 ss_final;
+	u8 sq_final;
+	long rssi_final;
+
+_func_enter_;		
+
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	rtw_hal_antdiv_rssi_compared(padapter, dst, src); //this will update src.Rssi, need consider again
+#endif
+
+	#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1
+	if(strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
+		DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT", ch%u) ss_ori:%3u, sq_ori:%3u, rssi_ori:%3ld, ss_smp:%3u, sq_smp:%3u, rssi_smp:%3ld\n"
+			, FUNC_ADPT_ARG(padapter)
+			, src->Ssid.Ssid, MAC_ARG(src->MacAddress), src->Configuration.DSConfig
+			,ss_ori, sq_ori, rssi_ori
+			,ss_smp, sq_smp, rssi_smp
+		);
+	}
+	#endif
+
+	/* The rule below is 1/5 for sample value, 4/5 for history value */
+	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src, 0)) {
+		/* Take the recvpriv's value for the connected AP*/
+		ss_final = padapter->recvpriv.signal_strength;
+		sq_final = padapter->recvpriv.signal_qual;
+		/* the rssi value here is undecorated, and will be used for antenna diversity */
+		if(sq_smp != 101) /* from the right channel */
+			rssi_final = (src->Rssi+dst->Rssi*4)/5;
+		else
+			rssi_final = rssi_ori;
+	}
+	else {
+		if(sq_smp != 101) { /* from the right channel */
+			ss_final = ((u32)(src->PhyInfo.SignalStrength)+(u32)(dst->PhyInfo.SignalStrength)*4)/5;
+			sq_final = ((u32)(src->PhyInfo.SignalQuality)+(u32)(dst->PhyInfo.SignalQuality)*4)/5;
+			rssi_final = (src->Rssi+dst->Rssi*4)/5;
+		} else {
+			/* bss info not receving from the right channel, use the original RX signal infos */
+			ss_final = dst->PhyInfo.SignalStrength;
+			sq_final = dst->PhyInfo.SignalQuality;
+			rssi_final = dst->Rssi;
+		}
+		
+	}
+
+	if (update_ie) {
+		dst->Reserved[0] = src->Reserved[0];
+		dst->Reserved[1] = src->Reserved[1];
+		_rtw_memcpy((u8 *)dst, (u8 *)src, get_WLAN_BSSID_EX_sz(src));
+	}
+
+	dst->PhyInfo.SignalStrength = ss_final;
+	dst->PhyInfo.SignalQuality = sq_final;
+	dst->Rssi = rssi_final;
+
+	#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) && 1
+	if(strcmp(dst->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
+		DBG_871X(FUNC_ADPT_FMT" %s("MAC_FMT"), SignalStrength:%u, SignalQuality:%u, RawRSSI:%ld\n"
+			, FUNC_ADPT_ARG(padapter)
+			, dst->Ssid.Ssid, MAC_ARG(dst->MacAddress), dst->PhyInfo.SignalStrength, dst->PhyInfo.SignalQuality, dst->Rssi);
+	}
+	#endif
+
+#if 0 // old codes, may be useful one day...
+//	DBG_871X("update_network: rssi=0x%lx dst->Rssi=%d ,dst->Rssi=0x%lx , src->Rssi=0x%lx",(dst->Rssi+src->Rssi)/2,dst->Rssi,dst->Rssi,src->Rssi);
+	if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) && is_same_network(&(padapter->mlmepriv.cur_network.network), src))
+	{
+	
+		//DBG_871X("b:ssid=%s update_network: src->rssi=0x%d padapter->recvpriv.ui_rssi=%d\n",src->Ssid.Ssid,src->Rssi,padapter->recvpriv.signal);
+		if(padapter->recvpriv.signal_qual_data.total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX)
+	        {
+	              padapter->recvpriv.signal_qual_data.total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
+	              last_evm = padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index];
+	              padapter->recvpriv.signal_qual_data.total_val -= last_evm;
+	        }
+               	padapter->recvpriv.signal_qual_data.total_val += query_rx_pwr_percentage(src->Rssi);
+
+              	padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index++] = query_rx_pwr_percentage(src->Rssi);
+                if(padapter->recvpriv.signal_qual_data.index >= PHY_LINKQUALITY_SLID_WIN_MAX)
+                       padapter->recvpriv.signal_qual_data.index = 0;
+
+		//DBG_871X("Total SQ=%d  pattrib->signal_qual= %d\n", padapter->recvpriv.signal_qual_data.total_val, src->Rssi);
+
+		// <1> Showed on UI for user,in percentage.
+		tmpVal = padapter->recvpriv.signal_qual_data.total_val/padapter->recvpriv.signal_qual_data.total_num;
+                padapter->recvpriv.signal=(u8)tmpVal;//Link quality
+
+		src->Rssi= translate_percentage_to_dbm(padapter->recvpriv.signal) ;
+	}
+	else{
+//	DBG_871X("ELSE:ssid=%s update_network: src->rssi=0x%d dst->rssi=%d\n",src->Ssid.Ssid,src->Rssi,dst->Rssi);
+		src->Rssi=(src->Rssi +dst->Rssi)/2;//dBM
+	}	
+
+//	DBG_871X("a:update_network: src->rssi=0x%d padapter->recvpriv.ui_rssi=%d\n",src->Rssi,padapter->recvpriv.signal);
+
+#endif
+
+_func_exit_;		
+}
+
+static void update_current_network(_adapter *adapter, WLAN_BSSID_EX *pnetwork)
+{
+	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+	
+_func_enter_;		
+
+	rtw_bug_check(&(pmlmepriv->cur_network.network), 
+		&(pmlmepriv->cur_network.network), 
+		&(pmlmepriv->cur_network.network), 
+		&(pmlmepriv->cur_network.network));
+
+	if ( (check_fwstate(pmlmepriv, _FW_LINKED)== _TRUE) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork, 0)))
+	{
+		//RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"Same Network\n");
+
+		//if(pmlmepriv->cur_network.network.IELength<= pnetwork->IELength)
+		{
+			update_network(&(pmlmepriv->cur_network.network), pnetwork,adapter, _TRUE);
+			rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof (NDIS_802_11_FIXED_IEs), 
+									pmlmepriv->cur_network.network.IELength);
+		}
+	}
+
+_func_exit_;			
+
+}
+
+
+/*
+
+Caller must hold pmlmepriv->lock first.
+
+
+*/
+void rtw_update_scanned_network(_adapter *adapter, WLAN_BSSID_EX *target)
+{
+	_irqL irqL;
+	_list	*plist, *phead;
+	ULONG	bssid_ex_sz;
+	struct mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(adapter->mlmeextpriv);
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo= &(adapter->wdinfo);
+#endif // CONFIG_P2P
+	_queue	*queue	= &(pmlmepriv->scanned_queue);
+	struct wlan_network	*pnetwork = NULL;
+	struct wlan_network	*oldest = NULL;
+	int target_find = 0;
+	u8 feature = 0;    
+
+_func_enter_;
+
+	_enter_critical_bh(&queue->lock, &irqL);
+	phead = get_list_head(queue);
+	plist = get_next(phead);
+
+#ifdef CONFIG_P2P
+	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		feature = 1; // p2p enable
+#endif
+
+	while(1)
+	{
+		if (rtw_end_of_queue_search(phead,plist)== _TRUE)
+			break;
+
+		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
+
+		rtw_bug_check(pnetwork, pnetwork, pnetwork, pnetwork);
+
+#ifdef CONFIG_P2P
+		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) &&
+			(_rtw_memcmp(pnetwork->network.MacAddress, target->MacAddress, ETH_ALEN) == _TRUE))
+		{
+			target_find = 1;
+			break;
+		}
+#endif
+
+		if (is_same_network(&(pnetwork->network), target, feature))
+		{
+			target_find = 1;
+			break;
+		}
+
+		if (rtw_roam_flags(adapter)) {
+			/* TODO: don't  select netowrk in the same ess as oldest if it's new enough*/
+		}
+
+		if (oldest == NULL || time_after(oldest->last_scanned, pnetwork->last_scanned))
+			oldest = pnetwork;
+
+		plist = get_next(plist);
+
+	}
+	
+	
+	/* If we didn't find a match, then get a new network slot to initialize
+	 * with this beacon's information */
+	//if (rtw_end_of_queue_search(phead,plist)== _TRUE) {
+	if (!target_find) {		
+		if (_rtw_queue_empty(&(pmlmepriv->free_bss_pool)) == _TRUE) {
+			/* If there are no more slots, expire the oldest */
+			//list_del_init(&oldest->list);
+			pnetwork = oldest;
+			if(pnetwork==NULL){ 
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n\nsomething wrong here\n\n\n"));
+				goto exit;
+			}
+#ifdef CONFIG_ANTENNA_DIVERSITY
+			//target->PhyInfo.Optimum_antenna = pHalData->CurAntenna;//optimum_antenna=>For antenna diversity
+			rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(target->PhyInfo.Optimum_antenna));
+#endif
+			_rtw_memcpy(&(pnetwork->network), target,  get_WLAN_BSSID_EX_sz(target));
+			//pnetwork->last_scanned = rtw_get_current_time();
+			// variable initialize
+			pnetwork->fixed = _FALSE;
+			pnetwork->last_scanned = rtw_get_current_time();
+
+			pnetwork->network_type = 0;	
+			pnetwork->aid=0;		
+			pnetwork->join_res=0;
+
+			/* bss info not receving from the right channel */
+			if (pnetwork->network.PhyInfo.SignalQuality == 101)
+				pnetwork->network.PhyInfo.SignalQuality = 0;
+		}
+		else {
+			/* Otherwise just pull from the free list */
+
+			pnetwork = rtw_alloc_network(pmlmepriv); // will update scan_time
+
+			if(pnetwork==NULL){ 
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n\nsomething wrong here\n\n\n"));
+				goto exit;
+			}
+
+			bssid_ex_sz = get_WLAN_BSSID_EX_sz(target);
+			target->Length = bssid_ex_sz;
+#ifdef CONFIG_ANTENNA_DIVERSITY
+			//target->PhyInfo.Optimum_antenna = pHalData->CurAntenna;
+			rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(target->PhyInfo.Optimum_antenna));
+#endif
+			_rtw_memcpy(&(pnetwork->network), target, bssid_ex_sz );
+
+			pnetwork->last_scanned = rtw_get_current_time();
+
+			/* bss info not receving from the right channel */
+			if (pnetwork->network.PhyInfo.SignalQuality == 101)
+				pnetwork->network.PhyInfo.SignalQuality = 0;
+
+			rtw_list_insert_tail(&(pnetwork->list),&(queue->queue)); 
+
+		}
+	}
+	else {
+		/* we have an entry and we are going to update it. But this entry may
+		 * be already expired. In this case we do the same as we found a new 
+		 * net and call the new_net handler
+		 */
+		bool update_ie = _TRUE;
+
+		pnetwork->last_scanned = rtw_get_current_time();
+
+		//target.Reserved[0]==1, means that scaned network is a bcn frame.
+		if((pnetwork->network.IELength>target->IELength) && (target->Reserved[0]==1))
+			update_ie = _FALSE;
+
+		// probe resp(3) > beacon(1) > probe req(2)
+		if ((target->Reserved[0] != 2) &&
+			(target->Reserved[0] >= pnetwork->network.Reserved[0])
+			) {
+			update_ie = _TRUE;
+		}
+		else {
+			update_ie = _FALSE;
+		}
+
+		update_network(&(pnetwork->network), target,adapter, update_ie);
+	}
+
+exit:
+	_exit_critical_bh(&queue->lock, &irqL);
+
+_func_exit_;
+}
+
+void rtw_add_network(_adapter *adapter, WLAN_BSSID_EX *pnetwork);
+void rtw_add_network(_adapter *adapter, WLAN_BSSID_EX *pnetwork)
+{
+	_irqL irqL;
+	struct	mlme_priv	*pmlmepriv = &(((_adapter *)adapter)->mlmepriv);
+	//_queue	*queue	= &(pmlmepriv->scanned_queue);
+
+_func_enter_;		
+
+	//_enter_critical_bh(&queue->lock, &irqL);
+
+	#if defined(CONFIG_P2P) && defined(CONFIG_P2P_REMOVE_GROUP_INFO)
+	if (adapter->registrypriv.wifi_spec == 0)
+		rtw_bss_ex_del_p2p_attr(pnetwork, P2P_ATTR_GROUP_INFO);
+	#endif
+	
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		rtw_bss_ex_del_wfd_ie(pnetwork);
+
+	update_current_network(adapter, pnetwork);
+	
+	rtw_update_scanned_network(adapter, pnetwork);
+
+	//_exit_critical_bh(&queue->lock, &irqL);
+	
+_func_exit_;		
+}
+
+//select the desired network based on the capability of the (i)bss.
+// check items: (1) security
+//			   (2) network_type
+//			   (3) WMM
+//			   (4) HT
+//                     (5) others
+int rtw_is_desired_network(_adapter *adapter, struct wlan_network *pnetwork);
+int rtw_is_desired_network(_adapter *adapter, struct wlan_network *pnetwork)
+{
+	struct security_priv *psecuritypriv = &adapter->securitypriv;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	u32 desired_encmode;
+	u32 privacy;
+
+	//u8 wps_ie[512];
+	uint wps_ielen;
+
+	int bselected = _TRUE;
+	
+	desired_encmode = psecuritypriv->ndisencryptstatus;
+	privacy = pnetwork->network.Privacy;
+
+	if(check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
+	{
+		if(rtw_get_wps_ie(pnetwork->network.IEs+_FIXED_IE_LENGTH_, pnetwork->network.IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen)!=NULL)
+		{
+			return _TRUE;
+		}
+		else
+		{	
+			return _FALSE;
+		}	
+	}
+	if (adapter->registrypriv.wifi_spec == 1) //for  correct flow of 8021X  to do....
+	{
+		u8 *p=NULL;
+		uint ie_len=0;
+
+		if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
+	            bselected = _FALSE;
+
+		if ( psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
+			p = rtw_get_ie(pnetwork->network.IEs + _BEACON_IE_OFFSET_, _RSN_IE_2_, &ie_len, (pnetwork->network.IELength - _BEACON_IE_OFFSET_));
+			if (p && ie_len>0) {
+				bselected = _TRUE;
+			} else {
+				bselected = _FALSE;
+			}
+		}
+	}
+	
+
+ 	if ((desired_encmode != Ndis802_11EncryptionDisabled) && (privacy == 0)) {
+		DBG_871X("desired_encmode: %d, privacy: %d\n", desired_encmode, privacy);
+		bselected = _FALSE;
+ 	}
+
+	if(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)
+	{
+		if(pnetwork->network.InfrastructureMode != pmlmepriv->cur_network.network.InfrastructureMode)
+			bselected = _FALSE;
+	}	
+		
+
+	return bselected;
+}
+
+/* TODO: Perry : For Power Management */
+void rtw_atimdone_event_callback(_adapter	*adapter , u8 *pbuf)
+{
+
+_func_enter_;		
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("receive atimdone_evet\n"));	
+_func_exit_;			
+	return;	
+}
+
+
+void rtw_survey_event_callback(_adapter	*adapter, u8 *pbuf)
+{
+	_irqL  irqL;
+	u32 len;
+	WLAN_BSSID_EX *pnetwork;
+	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+
+_func_enter_;		
+
+	pnetwork = (WLAN_BSSID_EX *)pbuf;
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_survey_event_callback, ssid=%s\n",  pnetwork->Ssid.Ssid));
+
+#ifdef CONFIG_RTL8712
+        //endian_convert
+ 	pnetwork->Length = le32_to_cpu(pnetwork->Length);
+  	pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);	
+	pnetwork->Privacy =le32_to_cpu( pnetwork->Privacy);
+	pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
+	pnetwork->NetworkTypeInUse =le32_to_cpu(pnetwork->NetworkTypeInUse);	
+	pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->Configuration.ATIMWindow);
+	pnetwork->Configuration.BeaconPeriod = le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
+	pnetwork->Configuration.DSConfig =le32_to_cpu(pnetwork->Configuration.DSConfig);
+	pnetwork->Configuration.FHConfig.DwellTime=le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
+	pnetwork->Configuration.FHConfig.HopPattern=le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
+	pnetwork->Configuration.FHConfig.HopSet=le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
+	pnetwork->Configuration.FHConfig.Length=le32_to_cpu(pnetwork->Configuration.FHConfig.Length);	
+	pnetwork->Configuration.Length = le32_to_cpu(pnetwork->Configuration.Length);
+	pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->InfrastructureMode);
+	pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
+#endif	
+
+	len = get_WLAN_BSSID_EX_sz(pnetwork);
+	if(len > (sizeof(WLAN_BSSID_EX)))
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n ****rtw_survey_event_callback: return a wrong bss ***\n"));
+		return;
+	}
+
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	// update IBSS_network 's timestamp
+	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE)
+	{
+		//RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"rtw_survey_event_callback : WIFI_ADHOC_MASTER_STATE \n\n");
+		if(_rtw_memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN))
+		{
+			struct wlan_network* ibss_wlan = NULL;
+			_irqL	irqL;
+			
+			_rtw_memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
+			_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			ibss_wlan = rtw_find_network(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
+			if(ibss_wlan)
+			{
+				_rtw_memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);			
+				_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);		
+				goto exit;
+			}
+			_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		}
+	}
+
+	// lock pmlmepriv->lock when you accessing network_q
+	if ((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == _FALSE)
+	{		
+   	        if( pnetwork->Ssid.Ssid[0] == 0 )
+		{
+			pnetwork->Ssid.SsidLength = 0;
+		}	
+		rtw_add_network(adapter, pnetwork);
+	}	
+
+exit:	
+		
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+_func_exit_;		
+
+	return;	
+}
+
+void rtw_surveydone_event_callback(_adapter	*adapter, u8 *pbuf)
+{
+	_irqL  irqL;
+	u8 timer_cancelled;
+	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+
+#ifdef CONFIG_MLME_EXT
+	mlmeext_surveydone_event_callback(adapter);
+#endif
+
+_func_enter_;
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	if (pmlmepriv->wps_probe_req_ie) {
+		u32 free_len = pmlmepriv->wps_probe_req_ie_len;
+		pmlmepriv->wps_probe_req_ie_len = 0;
+		rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
+		pmlmepriv->wps_probe_req_ie = NULL;
+	}
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("rtw_surveydone_event_callback: fw_state:%x\n\n", get_fwstate(pmlmepriv)));
+
+	if (check_fwstate(pmlmepriv,_FW_UNDER_SURVEY) == _FALSE) {
+		DBG_871X(FUNC_ADPT_FMT" fw_state:0x%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
+		//rtw_warn_on(1);
+	}
+
+	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+	_cancel_timer(&pmlmepriv->scan_to_timer, &timer_cancelled);
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	rtw_set_signal_stat_timer(&adapter->recvpriv);
+	#endif
+
+	if(pmlmepriv->to_join == _TRUE)
+	{
+		if((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE) )
+		{
+			if(check_fwstate(pmlmepriv, _FW_LINKED)==_FALSE)
+			{
+				set_fwstate(pmlmepriv, _FW_UNDER_LINKING);	
+				
+				if(rtw_select_and_join_from_scanned_queue(pmlmepriv)==_SUCCESS)
+				{
+					_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+				}
+				else
+				{
+					WLAN_BSSID_EX    *pdev_network = &(adapter->registrypriv.dev_network); 			
+					u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
+
+					//pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;//because don't set assoc_timer
+					_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+
+					RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("switching to adhoc master\n"));
+				
+					_rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
+					_rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
+	
+					rtw_update_registrypriv_dev_network(adapter);
+					rtw_generate_random_ibss(pibss);
+
+	
+					pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
+			
+					if (rtw_create_ibss_cmd(adapter, 0) != _SUCCESS)
+						RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("Error=>rtw_create_ibss_cmd status FAIL\n"));
+
+			     		pmlmepriv->to_join = _FALSE;
+		   		}
+		 	}
+		}
+		else
+		{
+			int s_ret;
+			set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+			pmlmepriv->to_join = _FALSE;
+			if(_SUCCESS == (s_ret=rtw_select_and_join_from_scanned_queue(pmlmepriv)))
+			{
+	     		     _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);	 
+			}
+			else if(s_ret == 2)//there is no need to wait for join
+			{
+				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+				rtw_indicate_connect(adapter);
+			}
+			else
+			{
+				DBG_871X("try_to_join, but select scanning queue fail, to_roam:%d\n", rtw_to_roam(adapter));
+
+				if (rtw_to_roam(adapter) != 0) {
+					if(rtw_dec_to_roam(adapter) == 0
+						|| _SUCCESS != rtw_sitesurvey_cmd(adapter, &pmlmepriv->assoc_ssid, 1, NULL, 0)
+					) {
+						rtw_set_to_roam(adapter, 0);
+#ifdef CONFIG_INTEL_WIDI
+						if(adapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING)
+						{
+							_rtw_memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
+							intel_widi_wk_cmd(adapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
+							DBG_871X("change to widi listen\n");
+						}
+#endif // CONFIG_INTEL_WIDI
+						rtw_free_assoc_resources(adapter, 1);
+						rtw_indicate_disconnect(adapter);
+					} else {
+						pmlmepriv->to_join = _TRUE;
+					}
+				}
+				else
+				{
+					rtw_indicate_disconnect(adapter);
+				}
+				_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+			}
+		}
+	} else {
+		if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
+			if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
+				&& check_fwstate(pmlmepriv, _FW_LINKED))
+			{
+				if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
+					receive_disconnect(adapter, pmlmepriv->cur_network.network.MacAddress
+						, WLAN_REASON_ACTIVE_ROAM);
+				}
+			}
+		}
+	}
+	
+	//DBG_871X("scan complete in %dms\n",rtw_get_passing_time_ms(pmlmepriv->scan_start_time));
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+#ifdef CONFIG_P2P_PS
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
+		p2p_ps_wk_cmd(adapter, P2P_PS_SCAN_DONE, 0);
+	}
+#endif // CONFIG_P2P_PS
+
+	rtw_os_xmit_schedule(adapter);
+#ifdef CONFIG_CONCURRENT_MODE	
+	rtw_os_xmit_schedule(adapter->pbuddy_adapter);
+#endif
+
+#ifdef CONFIG_DRVEXT_MODULE_WSC
+	drvext_surveydone_callback(&adapter->drvextpriv);
+#endif
+
+#ifdef DBG_CONFIG_ERROR_DETECT
+	{
+		struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;		
+		if(pmlmeext->sitesurvey_res.bss_cnt == 0){
+			//rtw_hal_sreset_reset(adapter);
+		}
+	}
+#endif
+
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_surveydone_event_callback(adapter);
+#endif //CONFIG_IOCTL_CFG80211
+
+	rtw_indicate_scan_done(adapter, _FALSE);
+
+#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_IOCTL_CFG80211)
+	if (adapter->pbuddy_adapter) {
+		_adapter *buddy_adapter = adapter->pbuddy_adapter;
+		struct mlme_priv *buddy_mlme = &(buddy_adapter->mlmepriv);
+		struct rtw_wdev_priv *buddy_wdev_priv = adapter_wdev_data(buddy_adapter);
+		bool indicate_buddy_scan = _FALSE;
+
+		_enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
+		if (buddy_wdev_priv->scan_request && buddy_mlme->scanning_via_buddy_intf == _TRUE) {
+			buddy_mlme->scanning_via_buddy_intf = _FALSE;
+			clr_fwstate(buddy_mlme, _FW_UNDER_SURVEY);
+			indicate_buddy_scan = _TRUE;
+		}
+		_exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
+
+		if (indicate_buddy_scan == _TRUE) {
+			#ifdef CONFIG_IOCTL_CFG80211
+			rtw_cfg80211_surveydone_event_callback(buddy_adapter);
+			#endif
+			rtw_indicate_scan_done(buddy_adapter, _FALSE);
+		}
+	}
+#endif /* CONFIG_CONCURRENT_MODE */
+
+_func_exit_;	
+
+}
+
+void rtw_dummy_event_callback(_adapter *adapter , u8 *pbuf)
+{
+
+}
+
+void rtw_fwdbg_event_callback(_adapter *adapter , u8 *pbuf)
+{
+
+}
+
+static void free_scanqueue(struct	mlme_priv *pmlmepriv)
+{
+	_irqL irqL, irqL0;
+	_queue *free_queue = &pmlmepriv->free_bss_pool;
+	_queue *scan_queue = &pmlmepriv->scanned_queue;
+	_list	*plist, *phead, *ptemp;
+	
+_func_enter_;		
+	
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+free_scanqueue\n"));
+	_enter_critical_bh(&scan_queue->lock, &irqL0);
+	_enter_critical_bh(&free_queue->lock, &irqL);
+
+	phead = get_list_head(scan_queue);
+	plist = get_next(phead);
+
+	while (plist != phead)
+       {
+		ptemp = get_next(plist);
+		rtw_list_delete(plist);
+		rtw_list_insert_tail(plist, &free_queue->queue);
+		plist =ptemp;
+		pmlmepriv->num_of_scanned --;
+        }
+	
+	_exit_critical_bh(&free_queue->lock, &irqL);
+	_exit_critical_bh(&scan_queue->lock, &irqL0);
+	
+_func_exit_;
+}
+
+void rtw_reset_rx_info(struct debug_priv *pdbgpriv){
+	pdbgpriv->dbg_rx_ampdu_drop_count = 0;
+	pdbgpriv->dbg_rx_ampdu_forced_indicate_count = 0;
+	pdbgpriv->dbg_rx_ampdu_loss_count = 0;
+	pdbgpriv->dbg_rx_dup_mgt_frame_drop_count = 0;
+	pdbgpriv->dbg_rx_ampdu_window_shift_cnt = 0;
+}
+	
+/*
+*rtw_free_assoc_resources: the caller has to lock pmlmepriv->lock
+*/
+void rtw_free_assoc_resources(_adapter *adapter, int lock_scanned_queue)
+{
+	_irqL irqL;
+	struct wlan_network* pwlan = NULL;
+	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct	sta_priv *pstapriv = &adapter->stapriv;
+	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+	struct dvobj_priv *psdpriv = adapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;	
+
+	
+#ifdef CONFIG_TDLS
+	struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+#endif //CONFIG_TDLS
+_func_enter_;			
+
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_, ("+rtw_free_assoc_resources\n"));
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_, ("tgt_network->network.MacAddress="MAC_FMT" ssid=%s\n",
+		MAC_ARG(tgt_network->network.MacAddress), tgt_network->network.Ssid.Ssid));
+
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+		struct sta_info* psta;
+		
+		psta = rtw_get_stainfo(&adapter->stapriv, tgt_network->network.MacAddress);
+
+#ifdef CONFIG_TDLS
+		if (ptdlsinfo->link_established == _TRUE) {
+			rtw_tdls_cmd(adapter, NULL, TDLS_RS_RCR);
+			rtw_reset_tdls_info(adapter);
+			rtw_free_all_stainfo(adapter);
+			//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+		}
+		else
+#endif //CONFIG_TDLS
+		{
+			//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+			rtw_free_stainfo(adapter,  psta);
+		}
+
+		//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+		
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE)) {
+		struct sta_info* psta;
+	
+		rtw_free_all_stainfo(adapter);
+
+		psta = rtw_get_bcmc_stainfo(adapter);
+		//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+		rtw_free_stainfo(adapter, psta);
+		//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+
+		rtw_init_bcmc_stainfo(adapter);	
+	}
+
+	if(lock_scanned_queue)
+		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+	
+	pwlan = _rtw_find_same_network(&pmlmepriv->scanned_queue, tgt_network);
+	if(pwlan)		
+	{
+		pwlan->fixed = _FALSE;
+
+                DBG_871X("free disconnecting network\n");
+		rtw_free_network_nolock(adapter, pwlan);
+#ifdef CONFIG_P2P
+		if(!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE))
+		{
+			rtw_set_scan_deny(adapter, 2000);
+			//rtw_clear_scan_deny(adapter);			
+		}
+#endif //CONFIG_P2P
+	}	
+	else
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_free_assoc_resources : pwlan== NULL \n\n"));
+	}
+
+
+	if((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) && (adapter->stapriv.asoc_sta_count== 1))
+		/*||check_fwstate(pmlmepriv, WIFI_STATION_STATE)*/)
+	{
+		if (pwlan)
+			rtw_free_network_nolock(adapter, pwlan);
+	}
+
+	if(lock_scanned_queue)
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+	
+	adapter->securitypriv.key_mask = 0;
+
+	rtw_reset_rx_info(pdbgpriv);
+
+_func_exit_;	
+	
+}
+
+/*
+*rtw_indicate_connect: the caller has to lock pmlmepriv->lock
+*/
+void rtw_indicate_connect(_adapter *padapter)
+{
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_connect\n"));
+ 
+	pmlmepriv->to_join = _FALSE;
+
+	if(!check_fwstate(&padapter->mlmepriv, _FW_LINKED)) 
+	{
+
+		set_fwstate(pmlmepriv, _FW_LINKED);
+
+		rtw_led_control(padapter, LED_CTL_LINK);
+
+	
+#ifdef CONFIG_DRVEXT_MODULE
+		if(padapter->drvextpriv.enable_wpa)
+		{
+			indicate_l2_connect(padapter);
+		}
+		else
+#endif
+		{
+			rtw_os_indicate_connect(padapter);
+		}
+
+	}
+
+	rtw_set_to_roam(padapter, 0);
+#ifdef CONFIG_INTEL_WIDI
+	if(padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING)
+	{
+		_rtw_memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
+		intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
+		DBG_871X("change to widi listen\n");
+	}
+#endif // CONFIG_INTEL_WIDI
+
+	rtw_set_scan_deny(padapter, 3000);
+
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("-rtw_indicate_connect: fw_state=0x%08x\n", get_fwstate(pmlmepriv)));
+ 
+_func_exit_;
+
+}
+
+
+/*
+*rtw_indicate_disconnect: the caller has to lock pmlmepriv->lock
+*/
+void rtw_indicate_disconnect( _adapter *padapter )
+{
+	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;	
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX	*cur_network = &(pmlmeinfo->network);
+	struct sta_info *psta;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *wps_ie=NULL;
+	uint wpsie_len=0;
+
+_func_enter_;	
+	
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("+rtw_indicate_disconnect\n"));
+
+	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING|WIFI_UNDER_WPS);
+
+	// force to clear cur_network_scanned's SELECTED REGISTRAR
+	if (pmlmepriv->cur_network_scanned) {
+		WLAN_BSSID_EX	*current_joined_bss = &(pmlmepriv->cur_network_scanned->network);
+		if (current_joined_bss) {
+			wps_ie=rtw_get_wps_ie(current_joined_bss->IEs +_FIXED_IE_LENGTH_,
+				current_joined_bss->IELength-_FIXED_IE_LENGTH_, NULL, &wpsie_len);
+			if (wps_ie && wpsie_len>0) {
+				u8 *attr = NULL;
+				u32 attr_len;
+				attr=rtw_get_wps_attr(wps_ie, wpsie_len, WPS_ATTR_SELECTED_REGISTRAR,
+						       NULL, &attr_len);
+				if (attr)
+					*(attr + 4) = 0;
+			}
+		}
+	}
+        //DBG_871X("clear wps when %s\n", __func__);
+
+	if(rtw_to_roam(padapter) > 0)
+		_clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+#ifdef CONFIG_WAPI_SUPPORT
+	psta = rtw_get_stainfo(pstapriv,cur_network->MacAddress);
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+	{
+		rtw_wapi_return_one_sta_info(padapter, psta->hwaddr);
+	}
+	else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
+		check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+	{
+		rtw_wapi_return_all_sta_info(padapter);
+	}
+#endif
+
+	if(check_fwstate(&padapter->mlmepriv, _FW_LINKED) 
+		|| (rtw_to_roam(padapter) <= 0)
+	)
+	{
+		rtw_os_indicate_disconnect(padapter);
+
+		//set ips_deny_time to avoid enter IPS before LPS leave
+		rtw_set_ips_deny(padapter, 3000);
+
+	      _clr_fwstate_(pmlmepriv, _FW_LINKED);
+
+		rtw_led_control(padapter, LED_CTL_NO_LINK);
+
+		rtw_clear_scan_deny(padapter);
+	}
+
+#ifdef CONFIG_P2P_PS
+	p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
+#endif // CONFIG_P2P_PS
+
+#ifdef CONFIG_LPS
+	rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_DISCONNECT, 1);
+#endif
+
+#ifdef CONFIG_BEAMFORMING
+	beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_LEAVE, cur_network->MacAddress, ETH_ALEN, 1);
+#endif /*CONFIG_BEAMFORMING*/
+
+_func_exit_;	
+}
+
+inline void rtw_indicate_scan_done( _adapter *padapter, bool aborted)
+{
+	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+	rtw_os_indicate_scan_done(padapter, aborted);
+
+#ifdef CONFIG_IPS
+	if (is_primary_adapter(padapter)
+		&& (_FALSE == adapter_to_pwrctl(padapter)->bInSuspend)
+		&& (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE|WIFI_UNDER_LINKING) == _FALSE))
+	{
+		struct pwrctrl_priv *pwrpriv;
+
+		pwrpriv = adapter_to_pwrctl(padapter);
+		rtw_set_ips_deny(padapter, 0);
+#ifdef CONFIG_IPS_CHECK_IN_WD
+		_set_timer(&padapter->mlmepriv.dynamic_chk_timer, 1);
+#else // !CONFIG_IPS_CHECK_IN_WD
+		_rtw_set_pwr_state_check_timer(pwrpriv, 1);
+#endif // !CONFIG_IPS_CHECK_IN_WD
+	}
+#endif // CONFIG_IPS
+}
+
+static u32 _rtw_wait_scan_done(_adapter *adapter, u8 abort, u32 timeout_ms)
+{
+	u32 start;
+	u32 pass_ms;
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
+
+	start = rtw_get_current_time();
+	
+	pmlmeext->scan_abort = abort;
+	
+	while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)
+		&& rtw_get_passing_time_ms(start) <= timeout_ms) {
+
+		if (RTW_CANNOT_RUN(adapter))
+			break;
+
+		DBG_871X(FUNC_NDEV_FMT"fw_state=_FW_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
+		rtw_msleep_os(20);
+	}
+
+	if (_TRUE == abort) {
+		if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
+			if (!RTW_CANNOT_RUN(adapter))
+				DBG_871X(FUNC_NDEV_FMT"waiting for scan_abort time out!\n", FUNC_NDEV_ARG(adapter->pnetdev));
+			#ifdef CONFIG_PLATFORM_MSTAR
+			/*_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);*/
+			set_survey_timer(pmlmeext, 0);
+			mlme_set_scan_to_timer(pmlmepriv, 50);
+			#endif
+			rtw_indicate_scan_done(adapter, _TRUE);
+		}
+	}
+	
+	pmlmeext->scan_abort = _FALSE;
+	pass_ms = rtw_get_passing_time_ms(start);
+
+	return pass_ms;
+
+}
+
+void rtw_scan_wait_completed(_adapter *adapter)
+{
+	u32 scan_to = SCANNING_TIMEOUT;
+
+#ifdef CONFIG_SCAN_BACKOP
+	if (IsSupported5G(adapter->registrypriv.wireless_mode) 
+		&& IsSupported24G(adapter->registrypriv.wireless_mode)) /*dual band*/
+		scan_to = CONC_SCANNING_TIMEOUT_DUAL_BAND;
+	else /*single band*/
+		scan_to = CONC_SCANNING_TIMEOUT_SINGLE_BAND;
+#endif /* CONFIG_SCAN_BACKOP */
+
+	_rtw_wait_scan_done(adapter, _FALSE, scan_to);
+}
+
+u32 rtw_scan_abort_timeout(_adapter *adapter, u32 timeout_ms)
+{
+	return _rtw_wait_scan_done(adapter, _TRUE, timeout_ms);
+}
+
+void rtw_scan_abort_no_wait(_adapter *adapter)
+{
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+		pmlmeext->scan_abort = _TRUE;
+}
+
+void rtw_scan_abort(_adapter *adapter)
+{
+	rtw_scan_abort_timeout(adapter, 200);
+}
+
+static struct sta_info *rtw_joinbss_update_stainfo(_adapter *padapter, struct wlan_network *pnetwork)
+{
+	int i;
+	struct sta_info *bmc_sta, *psta=NULL;
+	struct recv_reorder_ctrl *preorder_ctrl;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	psta = rtw_get_stainfo(pstapriv, pnetwork->network.MacAddress);
+	if(psta==NULL) {
+		psta = rtw_alloc_stainfo(pstapriv, pnetwork->network.MacAddress);
+	}
+
+	if(psta) //update ptarget_sta
+	{
+		DBG_871X("%s\n", __FUNCTION__);
+	
+		psta->aid  = pnetwork->join_res;
+
+#if 0 //alloc macid when call rtw_alloc_stainfo(), and release macid when call rtw_free_stainfo()
+#ifdef CONFIG_CONCURRENT_MODE	
+
+		if(PRIMARY_ADAPTER == padapter->adapter_type)
+			psta->mac_id=0;
+		else
+			psta->mac_id=2;
+#else
+		psta->mac_id=0;
+#endif
+#endif //removed
+
+		update_sta_info(padapter, psta);
+
+		//update station supportRate
+		psta->bssratelen = rtw_get_rateset_len(pnetwork->network.SupportedRates);
+		_rtw_memcpy(psta->bssrateset, pnetwork->network.SupportedRates, psta->bssratelen);
+		rtw_hal_update_sta_rate_mask(padapter, psta);
+
+		psta->wireless_mode = pmlmeext->cur_wireless_mode;
+		psta->raid = rtw_hal_networktype_to_raid(padapter,psta);
+
+
+		//sta mode
+		rtw_hal_set_odm_var(padapter,HAL_ODM_STA_INFO,psta,_TRUE);
+
+		//security related
+		if(padapter->securitypriv.dot11AuthAlgrthm== dot11AuthAlgrthm_8021X)
+		{						
+			padapter->securitypriv.binstallGrpkey=_FALSE;
+			padapter->securitypriv.busetkipkey=_FALSE;						
+			padapter->securitypriv.bgrpkey_handshake=_FALSE;
+
+			psta->ieee8021x_blocked=_TRUE;
+			psta->dot118021XPrivacy=padapter->securitypriv.dot11PrivacyAlgrthm;
+						
+			_rtw_memset((u8 *)&psta->dot118021x_UncstKey, 0, sizeof (union Keytype));
+						
+			_rtw_memset((u8 *)&psta->dot11tkiprxmickey, 0, sizeof (union Keytype));
+			_rtw_memset((u8 *)&psta->dot11tkiptxmickey, 0, sizeof (union Keytype));
+						
+			_rtw_memset((u8 *)&psta->dot11txpn, 0, sizeof (union pn48));
+			psta->dot11txpn.val = psta->dot11txpn.val + 1;
+#ifdef CONFIG_IEEE80211W
+			_rtw_memset((u8 *)&psta->dot11wtxpn, 0, sizeof (union pn48));
+#endif //CONFIG_IEEE80211W
+			_rtw_memset((u8 *)&psta->dot11rxpn, 0, sizeof (union pn48));	
+		}
+
+		//	Commented by Albert 2012/07/21
+		//	When doing the WPS, the wps_ie_len won't equal to 0
+		//	And the Wi-Fi driver shouldn't allow the data packet to be tramsmitted.
+		if ( padapter->securitypriv.wps_ie_len != 0 )
+		{
+			psta->ieee8021x_blocked=_TRUE;
+			padapter->securitypriv.wps_ie_len = 0;
+		}
+
+
+		//for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
+		//if A-MPDU Rx is enabled, reseting  rx_ordering_ctrl wstart_b(indicate_seq) to default value=0xffff
+		//todo: check if AP can send A-MPDU packets
+		for(i=0; i < 16 ; i++)
+		{
+			//preorder_ctrl = &precvpriv->recvreorder_ctrl[i];
+			preorder_ctrl = &psta->recvreorder_ctrl[i];
+			preorder_ctrl->enable = _FALSE;
+			preorder_ctrl->indicate_seq = 0xffff;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq);
+			#endif
+			preorder_ctrl->wend_b= 0xffff;
+			preorder_ctrl->wsize_b = 64;//max_ampdu_sz;//ex. 32(kbytes) -> wsize_b=32
+			preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
+		}
+
+		
+		bmc_sta = rtw_get_bcmc_stainfo(padapter);
+		if(bmc_sta)
+		{
+			for(i=0; i < 16 ; i++)
+			{
+				//preorder_ctrl = &precvpriv->recvreorder_ctrl[i];
+				preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
+				preorder_ctrl->enable = _FALSE;
+				preorder_ctrl->indicate_seq = 0xffff;
+				#ifdef DBG_RX_SEQ
+				DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
+					preorder_ctrl->indicate_seq);
+				#endif
+				preorder_ctrl->wend_b= 0xffff;
+				preorder_ctrl->wsize_b = 64;//max_ampdu_sz;//ex. 32(kbytes) -> wsize_b=32
+				preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
+			}
+		}
+	}
+					
+	return psta;
+	
+}
+
+//pnetwork : returns from rtw_joinbss_event_callback
+//ptarget_wlan: found from scanned_queue
+static void rtw_joinbss_update_network(_adapter *padapter, struct wlan_network *ptarget_wlan, struct wlan_network  *pnetwork)
+{
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);	
+	struct wlan_network  *cur_network = &(pmlmepriv->cur_network);
+
+	DBG_871X("%s\n", __FUNCTION__);
+	
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\nfw_state:%x, BSSID:"MAC_FMT"\n"
+		,get_fwstate(pmlmepriv), MAC_ARG(pnetwork->network.MacAddress)));
+
+				
+	// why not use ptarget_wlan??
+	_rtw_memcpy(&cur_network->network, &pnetwork->network, pnetwork->network.Length);
+	// some IEs in pnetwork is wrong, so we should use ptarget_wlan IEs
+	cur_network->network.IELength = ptarget_wlan->network.IELength;
+	_rtw_memcpy(&cur_network->network.IEs[0], &ptarget_wlan->network.IEs[0], MAX_IE_SZ);
+
+	cur_network->aid = pnetwork->join_res;
+
+				
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	rtw_set_signal_stat_timer(&padapter->recvpriv);
+#endif
+	padapter->recvpriv.signal_strength = ptarget_wlan->network.PhyInfo.SignalStrength;
+	padapter->recvpriv.signal_qual = ptarget_wlan->network.PhyInfo.SignalQuality;
+	//the ptarget_wlan->network.Rssi is raw data, we use ptarget_wlan->network.PhyInfo.SignalStrength instead (has scaled)
+	padapter->recvpriv.rssi = translate_percentage_to_dbm(ptarget_wlan->network.PhyInfo.SignalStrength);
+	#if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
+		DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"
+			"\n"
+			, FUNC_ADPT_ARG(padapter)
+			, padapter->recvpriv.signal_strength
+			, padapter->recvpriv.rssi
+			, padapter->recvpriv.signal_qual
+	);
+	#endif
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	rtw_set_signal_stat_timer(&padapter->recvpriv);
+#endif
+				
+	//update fw_state //will clr _FW_UNDER_LINKING here indirectly
+	switch(pnetwork->network.InfrastructureMode)
+	{	
+		case Ndis802_11Infrastructure:						
+			
+				if(pmlmepriv->fw_state&WIFI_UNDER_WPS)
+					pmlmepriv->fw_state = WIFI_STATION_STATE|WIFI_UNDER_WPS;
+				else
+					pmlmepriv->fw_state = WIFI_STATION_STATE;
+				
+				break;
+		case Ndis802_11IBSS:		
+				pmlmepriv->fw_state = WIFI_ADHOC_STATE;
+				break;
+		default:
+				pmlmepriv->fw_state = WIFI_NULL_STATE;
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Invalid network_mode\n"));
+				break;
+	}
+
+	rtw_update_protection(padapter, (cur_network->network.IEs) + sizeof (NDIS_802_11_FIXED_IEs), 
+									(cur_network->network.IELength));
+
+#ifdef CONFIG_80211N_HT			
+	rtw_update_ht_cap(padapter, cur_network->network.IEs, cur_network->network.IELength, (u8) cur_network->network.Configuration.DSConfig);
+#endif
+}
+
+//Notes: the fucntion could be > passive_level (the same context as Rx tasklet)
+//pnetwork : returns from rtw_joinbss_event_callback
+//ptarget_wlan: found from scanned_queue
+//if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if  "ptarget_sta" & "ptarget_wlan" exist.	
+//if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check if "ptarget_wlan" exist.
+//if join_res > 0, update "cur_network->network" from "pnetwork->network" if (ptarget_wlan !=NULL).
+//
+//#define REJOIN
+void rtw_joinbss_event_prehandle(_adapter *adapter, u8 *pbuf)
+{
+	_irqL irqL,irqL2;
+	static u8 retry=0;
+	u8 timer_cancelled;
+	struct sta_info *ptarget_sta= NULL, *pcur_sta = NULL;
+   	struct	sta_priv *pstapriv = &adapter->stapriv;
+	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+	struct wlan_network 	*pnetwork	= (struct wlan_network *)pbuf;
+	struct wlan_network 	*cur_network = &(pmlmepriv->cur_network);
+	struct wlan_network	*pcur_wlan = NULL, *ptarget_wlan = NULL;
+	unsigned int 		the_same_macaddr = _FALSE;	
+
+_func_enter_;	
+
+#ifdef CONFIG_RTL8712
+       //endian_convert
+	pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
+	pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
+	pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
+	pnetwork->network.Ssid.SsidLength = le32_to_cpu(pnetwork->network.Ssid.SsidLength);
+	pnetwork->network.Privacy =le32_to_cpu( pnetwork->network.Privacy);
+	pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
+	pnetwork->network.NetworkTypeInUse =le32_to_cpu(pnetwork->network.NetworkTypeInUse) ;	
+	pnetwork->network.Configuration.ATIMWindow = le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
+	pnetwork->network.Configuration.BeaconPeriod = le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
+	pnetwork->network.Configuration.DSConfig = le32_to_cpu(pnetwork->network.Configuration.DSConfig);
+	pnetwork->network.Configuration.FHConfig.DwellTime=le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime);
+	pnetwork->network.Configuration.FHConfig.HopPattern=le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern);
+	pnetwork->network.Configuration.FHConfig.HopSet=le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
+	pnetwork->network.Configuration.FHConfig.Length=le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);	
+	pnetwork->network.Configuration.Length = le32_to_cpu(pnetwork->network.Configuration.Length);
+	pnetwork->network.InfrastructureMode = le32_to_cpu(pnetwork->network.InfrastructureMode);
+	pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength );
+#endif
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("joinbss event call back received with res=%d\n", pnetwork->join_res));
+
+	rtw_get_encrypt_decrypt_from_registrypriv(adapter);
+	
+
+	if (pmlmepriv->assoc_ssid.SsidLength == 0)
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("@@@@@   joinbss event call back  for Any SSid\n"));		
+	}
+	else
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("@@@@@   rtw_joinbss_event_callback for SSid:%s\n", pmlmepriv->assoc_ssid.Ssid));
+	}
+	
+	the_same_macaddr = _rtw_memcmp(pnetwork->network.MacAddress, cur_network->network.MacAddress, ETH_ALEN);
+
+	pnetwork->network.Length = get_WLAN_BSSID_EX_sz(&pnetwork->network);
+	if(pnetwork->network.Length > sizeof(WLAN_BSSID_EX))
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n\n ***joinbss_evt_callback return a wrong bss ***\n\n"));
+		goto ignore_joinbss_callback;
+	}
+		
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	
+	pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
+	pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
+	
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("\n rtw_joinbss_event_callback !! _enter_critical \n"));
+
+	if(pnetwork->join_res > 0)
+	{
+		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		retry = 0;
+		if (check_fwstate(pmlmepriv,_FW_UNDER_LINKING) )
+		{
+			//s1. find ptarget_wlan
+			if(check_fwstate(pmlmepriv, _FW_LINKED) )
+			{
+				if(the_same_macaddr == _TRUE)
+				{
+					ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);					
+				}
+				else
+				{
+					pcur_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+					if(pcur_wlan)	pcur_wlan->fixed = _FALSE;
+
+					pcur_sta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
+					if(pcur_sta){
+						//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+						rtw_free_stainfo(adapter,  pcur_sta);
+						//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+					}
+
+					ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, pnetwork->network.MacAddress);
+					if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE){
+						if(ptarget_wlan)	ptarget_wlan->fixed = _TRUE;			
+					}
+				}
+
+			}
+			else
+			{
+				ptarget_wlan = _rtw_find_same_network(&pmlmepriv->scanned_queue, pnetwork);
+				if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE){
+					if(ptarget_wlan)	ptarget_wlan->fixed = _TRUE;			
+				}
+			}
+		
+			//s2. update cur_network 
+			if(ptarget_wlan)
+			{			
+				rtw_joinbss_update_network(adapter, ptarget_wlan, pnetwork);
+			}
+			else
+			{			
+				DBG_871X_LEVEL(_drv_always_, "Can't find ptarget_wlan when joinbss_event callback\n");
+				_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+				goto ignore_joinbss_callback;
+			}
+					
+			
+			//s3. find ptarget_sta & update ptarget_sta after update cur_network only for station mode 
+			if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+			{ 
+				ptarget_sta = rtw_joinbss_update_stainfo(adapter, pnetwork);
+				if(ptarget_sta==NULL)
+				{
+					RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't update stainfo when joinbss_event callback\n"));
+					_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+					goto ignore_joinbss_callback;
+				}
+			}
+
+			//s4. indicate connect			
+			if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+			{
+				pmlmepriv->cur_network_scanned = ptarget_wlan;
+				rtw_indicate_connect(adapter);
+			}
+			else
+			{
+				//adhoc mode will rtw_indicate_connect when rtw_stassoc_event_callback
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("adhoc mode, fw_state:%x", get_fwstate(pmlmepriv)));
+			}
+
+				
+			//s5. Cancle assoc_timer					
+			_cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
+		
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("Cancle assoc_timer \n"));		
+		
+		}
+		else
+		{
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_joinbss_event_callback err: fw_state:%x", get_fwstate(pmlmepriv)));	
+			_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			goto ignore_joinbss_callback;
+		}
+		
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);	
+				
+	}
+	else if(pnetwork->join_res == -4) 
+	{
+		rtw_reset_securitypriv(adapter);
+		_set_timer(&pmlmepriv->assoc_timer, 1);					
+
+		//rtw_free_assoc_resources(adapter, 1);
+
+		if((check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) == _TRUE)
+		{		
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("fail! clear _FW_UNDER_LINKING ^^^fw_state=%x\n", get_fwstate(pmlmepriv)));
+			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+		}	
+		
+	}
+	else //if join_res < 0 (join fails), then try again
+	{
+	
+		#ifdef REJOIN
+		res = _FAIL;
+		if(retry < 2) {
+			res = rtw_select_and_join_from_scanned_queue(pmlmepriv);
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("rtw_select_and_join_from_scanned_queue again! res:%d\n",res));
+		}
+
+		 if(res == _SUCCESS)
+		{
+			//extend time of assoc_timer
+			_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+			retry++;
+		}
+		else if(res == 2)//there is no need to wait for join
+		{
+			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+			rtw_indicate_connect(adapter);
+		}	
+		else
+		{
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Set Assoc_Timer = 1; can't find match ssid in scanned_q \n"));
+		#endif
+			
+			_set_timer(&pmlmepriv->assoc_timer, 1);
+			//rtw_free_assoc_resources(adapter, 1);
+			_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+			
+		#ifdef REJOIN
+			retry = 0;	
+		}
+		#endif
+	}
+
+ignore_joinbss_callback:
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	_func_exit_;	
+}
+
+void rtw_joinbss_event_callback(_adapter *adapter, u8 *pbuf)
+{
+	struct wlan_network 	*pnetwork	= (struct wlan_network *)pbuf;
+
+_func_enter_;
+
+	mlmeext_joinbss_event_callback(adapter, pnetwork->join_res);
+
+	rtw_os_xmit_schedule(adapter);
+
+#ifdef CONFIG_CONCURRENT_MODE	
+	rtw_os_xmit_schedule(adapter->pbuddy_adapter);
+#endif	
+
+_func_exit_;
+}
+
+#if 0
+//#if (RATE_ADAPTIVE_SUPPORT==1)	//for 88E RA		
+u8 search_max_mac_id(_adapter *padapter)
+{
+	u8 mac_id, aid;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)	
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE)){		
+		
+#if 1
+		_irqL irqL;
+		struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
+
+		_enter_critical_bh(&pdvobj->lock, &irqL);
+		for(mac_id=(NUM_STA-1); mac_id>0; mac_id--)
+			if(pdvobj->macid[mac_id] == _TRUE)
+				break;
+		_exit_critical_bh(&pdvobj->lock, &irqL);
+
+#else
+		for (aid = (pstapriv->max_num_sta); aid > 0; aid--)
+		{
+			if (pstapriv->sta_aid[aid-1] != NULL)
+			{
+				psta = pstapriv->sta_aid[aid-1];
+				break;
+			}	
+		}
+/*
+		for (mac_id = (pstapriv->max_num_sta-1); mac_id >= 0; mac_id--)
+		{
+			if (pstapriv->sta_aid[mac_id] != NULL)
+				break;
+		}	
+*/
+		mac_id = aid + 1;
+#endif
+	}
+	else
+#endif
+	{//adhoc  id =  31~2
+		for (mac_id = (NUM_STA-1); mac_id >= IBSS_START_MAC_ID ; mac_id--)
+		{
+			if (pmlmeinfo->FW_sta_info[mac_id].status == 1)
+			{
+				break;
+			}
+		}
+	}
+
+	DBG_871X("max mac_id=%d\n", mac_id);
+
+	return mac_id;
+
+}		
+#endif	
+
+void rtw_sta_media_status_rpt(_adapter *adapter, struct sta_info *sta, bool connected)
+{
+	struct macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl;
+	bool miracast_enabled = 0;
+	bool miracast_sink = 0;
+	u8 role = H2C_MSR_ROLE_RSVD;
+
+	if (sta == NULL) {
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" sta is NULL\n"
+			, FUNC_ADPT_ARG(adapter));
+		rtw_warn_on(1);
+		return;
+	}
+
+	if (sta->mac_id >= macid_ctl->num) {
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" invalid macid:%u\n"
+			, FUNC_ADPT_ARG(adapter), sta->mac_id);
+		rtw_warn_on(1);
+		return;
+	}
+
+	if (!rtw_macid_is_used(macid_ctl, sta->mac_id)) {
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" macid:%u not is used, set connected to 0\n"
+			, FUNC_ADPT_ARG(adapter), sta->mac_id);
+		connected = 0;
+		rtw_warn_on(1);
+	}
+
+	if (connected && !rtw_macid_is_bmc(macid_ctl, sta->mac_id)) {
+		miracast_enabled = STA_OP_WFD_MODE(sta) != 0 && is_miracast_enabled(adapter);
+		miracast_sink = miracast_enabled && (STA_OP_WFD_MODE(sta) & MIRACAST_SINK);
+
+		#ifdef CONFIG_TDLS
+		if (sta->tdls_sta_state & TDLS_LINKED_STATE)
+			role = H2C_MSR_ROLE_TDLS;
+		else
+		#endif
+		if (MLME_IS_STA(adapter)) {
+			if (MLME_IS_GC(adapter))
+				role = H2C_MSR_ROLE_GO;
+			else
+				role = H2C_MSR_ROLE_AP;
+		} else if (MLME_IS_AP(adapter)) {
+			if (MLME_IS_GO(adapter))
+				role = H2C_MSR_ROLE_GC;
+			else
+				role = H2C_MSR_ROLE_STA;
+		}
+
+		#ifdef CONFIG_WFD
+		if (role == H2C_MSR_ROLE_GC
+			|| role == H2C_MSR_ROLE_GO
+			|| role == H2C_MSR_ROLE_TDLS
+		) {
+			if (adapter->wfd_info.rtsp_ctrlport
+				|| adapter->wfd_info.tdls_rtsp_ctrlport
+				|| adapter->wfd_info.peer_rtsp_ctrlport)
+				rtw_wfd_st_switch(sta, 1);
+		}
+		#endif
+	}
+
+	rtw_hal_set_FwMediaStatusRpt_single_cmd(adapter
+		, connected
+		, miracast_enabled
+		, miracast_sink
+		, role
+		, sta->mac_id
+	);
+}
+
+u8 rtw_sta_media_status_rpt_cmd(_adapter *adapter, struct sta_info *sta, bool connected)
+{
+	struct cmd_priv	*cmdpriv = &adapter->cmdpriv;
+	struct cmd_obj *cmdobj;
+	struct drvextra_cmd_parm *cmd_parm;
+	struct sta_media_status_rpt_cmd_parm *rpt_parm;
+	u8	res = _SUCCESS;
+
+	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (cmdobj == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
+	if (cmd_parm == NULL) {
+		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
+		res = _FAIL;
+		goto exit;
+	}
+
+	rpt_parm = (struct sta_media_status_rpt_cmd_parm *)rtw_zmalloc(sizeof(struct sta_media_status_rpt_cmd_parm));
+	if (rpt_parm == NULL) {
+		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
+		rtw_mfree((u8 *)cmd_parm, sizeof(struct drvextra_cmd_parm));
+		res = _FAIL;
+		goto exit;
+	}
+
+	rpt_parm->sta = sta;
+	rpt_parm->connected = connected;
+
+	cmd_parm->ec_id = STA_MSTATUS_RPT_WK_CID;
+	cmd_parm->type = 0;
+	cmd_parm->size = sizeof(struct sta_media_status_rpt_cmd_parm);
+	cmd_parm->pbuf = (u8 *)rpt_parm;
+	init_h2fwcmd_w_parm_no_rsp(cmdobj, cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+	res = rtw_enqueue_cmd(cmdpriv, cmdobj);
+
+exit:
+	return res;
+}
+
+inline void rtw_sta_media_status_rpt_cmd_hdl(_adapter *adapter, struct sta_media_status_rpt_cmd_parm *parm)
+{
+	rtw_sta_media_status_rpt(adapter, parm->sta, parm->connected);
+}
+
+void rtw_stassoc_event_callback(_adapter *adapter, u8 *pbuf)
+{
+	_irqL irqL;	
+	struct sta_info *psta;
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+	struct stassoc_event	*pstassoc	= (struct stassoc_event*)pbuf;
+	struct wlan_network 	*cur_network = &(pmlmepriv->cur_network);
+	struct wlan_network	*ptarget_wlan = NULL;
+	
+_func_enter_;	
+	
+	if(rtw_access_ctrl(adapter, pstassoc->macaddr) == _FALSE)
+		return;
+
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
+	{
+		psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);	
+		if(psta)
+		{		
+			u8 *passoc_req = NULL;
+			u32 assoc_req_len = 0;
+		
+			rtw_sta_media_status_rpt(adapter, psta, 1);
+		
+#ifndef CONFIG_AUTO_AP_MODE
+
+			ap_sta_info_defer_update(adapter, psta);
+
+			//report to upper layer 
+			DBG_871X("indicate_sta_assoc_event to upper layer - hostapd\n");
+#ifdef CONFIG_IOCTL_CFG80211
+			_enter_critical_bh(&psta->lock, &irqL);
+			if(psta->passoc_req && psta->assoc_req_len>0)
+			{				
+				passoc_req = rtw_zmalloc(psta->assoc_req_len);
+				if(passoc_req)
+				{
+					assoc_req_len = psta->assoc_req_len;
+					_rtw_memcpy(passoc_req, psta->passoc_req, assoc_req_len);
+					
+					rtw_mfree(psta->passoc_req , psta->assoc_req_len);
+					psta->passoc_req = NULL;
+					psta->assoc_req_len = 0;
+				}
+			}			
+			_exit_critical_bh(&psta->lock, &irqL);
+
+			if(passoc_req && assoc_req_len>0)
+			{
+				rtw_cfg80211_indicate_sta_assoc(adapter, passoc_req, assoc_req_len);
+
+				rtw_mfree(passoc_req, assoc_req_len);
+			}			
+#else //!CONFIG_IOCTL_CFG80211	
+			rtw_indicate_sta_assoc_event(adapter, psta);
+#endif //!CONFIG_IOCTL_CFG80211
+#endif //!CONFIG_AUTO_AP_MODE
+
+#ifdef CONFIG_BEAMFORMING
+			beamforming_wk_cmd(adapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0);
+#endif/*CONFIG_BEAMFORMING*/
+		}		
+		goto exit;
+	}	
+#endif //defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+
+	//for AD-HOC mode
+	psta = rtw_get_stainfo(&adapter->stapriv, pstassoc->macaddr);	
+	if( psta != NULL)
+	{
+		//the sta have been in sta_info_queue => do nothing 
+		
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Error: rtw_stassoc_event_callback: sta has been in sta_hash_queue \n"));
+		
+		goto exit; //(between drv has received this event before and  fw have not yet to set key to CAM_ENTRY)
+	}
+
+	psta = rtw_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);	
+	if (psta == NULL) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Can't alloc sta_info when rtw_stassoc_event_callback\n"));
+		goto exit;
+	}	
+	
+	//to do : init sta_info variable
+	psta->qos_option = 0;
+	psta->mac_id = (uint)pstassoc->cam_id;
+	//psta->aid = (uint)pstassoc->cam_id;
+	DBG_871X("%s\n",__FUNCTION__);
+	//for ad-hoc mode
+	rtw_hal_set_odm_var(adapter,HAL_ODM_STA_INFO,psta,_TRUE);
+
+	rtw_sta_media_status_rpt(adapter, psta, 1);
+	
+	if(adapter->securitypriv.dot11AuthAlgrthm==dot11AuthAlgrthm_8021X)
+		psta->dot118021XPrivacy = adapter->securitypriv.dot11PrivacyAlgrthm;
+	
+
+	psta->ieee8021x_blocked = _FALSE;		
+	
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	if ( (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)==_TRUE ) || 
+		(check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)==_TRUE ) )
+	{
+		if(adapter->stapriv.asoc_sta_count== 2)
+		{
+			_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			ptarget_wlan = rtw_find_network(&pmlmepriv->scanned_queue, cur_network->network.MacAddress);
+			pmlmepriv->cur_network_scanned = ptarget_wlan;
+			if(ptarget_wlan)	ptarget_wlan->fixed = _TRUE;
+			_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			// a sta + bc/mc_stainfo (not Ibss_stainfo)
+			rtw_indicate_connect(adapter);
+		}
+	}
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+
+	mlmeext_sta_add_event_callback(adapter, psta);
+	
+#ifdef CONFIG_RTL8711
+	//submit SetStaKey_cmd to tell fw, fw will allocate an CAM entry for this sta	
+	rtw_setstakey_cmd(adapter, psta, GROUP_KEY, _TRUE);
+#endif
+		
+exit:
+	
+_func_exit_;	
+
+}
+
+#ifdef CONFIG_IEEE80211W
+void rtw_sta_timeout_event_callback(_adapter *adapter, u8 *pbuf)
+{
+	_irqL irqL;
+	struct sta_info *psta;
+	struct stadel_event *pstadel = (struct stadel_event *)pbuf;
+	struct sta_priv *pstapriv = &adapter->stapriv;
+	
+_func_enter_;
+	
+	psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
+
+	if (psta) {
+		u8 updated = _FALSE;
+		
+		_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+		if (rtw_is_list_empty(&psta->asoc_list) == _FALSE) {
+			rtw_list_delete(&psta->asoc_list);
+			pstapriv->asoc_list_cnt--;
+			updated = ap_free_sta(adapter, psta, _TRUE, WLAN_REASON_PREV_AUTH_NOT_VALID, _TRUE);
+		}
+		_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+		associated_clients_update(adapter, updated, STA_INFO_UPDATE_ALL);
+	}
+
+	
+_func_exit_;	
+
+}
+#endif /* CONFIG_IEEE80211W */
+
+void rtw_stadel_event_callback(_adapter *adapter, u8 *pbuf)
+{
+	_irqL irqL,irqL2;
+	int mac_id = (-1);
+	struct sta_info *psta;
+	struct wlan_network* pwlan = NULL;
+	WLAN_BSSID_EX    *pdev_network=NULL;
+	u8* pibss = NULL;
+	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+	struct 	stadel_event *pstadel	= (struct stadel_event*)pbuf;
+   	struct	sta_priv *pstapriv = &adapter->stapriv;
+	struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct macid_ctl_t *macid_ctl = &adapter->dvobj->macid_ctl;
+
+_func_enter_;	
+	
+	psta = rtw_get_stainfo(&adapter->stapriv, pstadel->macaddr);
+	if(psta)
+		mac_id = psta->mac_id;
+	else
+		mac_id = pstadel->mac_id;
+
+	DBG_871X("%s(mac_id=%d)=" MAC_FMT "\n", __func__, mac_id, MAC_ARG(pstadel->macaddr));
+
+	if (mac_id >= 0 && mac_id < macid_ctl->num) {
+		rtw_hal_set_FwMediaStatusRpt_single_cmd(adapter, 0, 0, 0, 0, mac_id);
+		if (psta)
+			rtw_wfd_st_switch(psta, 0);
+	} else {
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" invalid macid:%u\n"
+			, FUNC_ADPT_ARG(adapter), mac_id);
+		rtw_warn_on(1);
+	}
+
+	//if(check_fwstate(pmlmepriv, WIFI_AP_STATE))
+	if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	{
+#ifdef CONFIG_IOCTL_CFG80211
+		#ifdef COMPAT_KERNEL_RELEASE
+
+		#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) || defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+		rtw_cfg80211_indicate_sta_disassoc(adapter, pstadel->macaddr, *(u16*)pstadel->rsvd);
+		#endif //(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37)) || defined(CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER)
+#endif //CONFIG_IOCTL_CFG80211
+
+		return;
+	}
+
+
+	mlmeext_sta_del_event_callback(adapter);
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL2);
+
+	if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) )
+	{
+		u16 reason = *((unsigned short *)(pstadel->rsvd));
+		bool roam = _FALSE;
+		struct wlan_network *roam_target = NULL;
+
+		#ifdef CONFIG_LAYER2_ROAMING
+		if(adapter->registrypriv.wifi_spec==1) {
+			roam = _FALSE;
+		} else if (reason == WLAN_REASON_EXPIRATION_CHK && rtw_chk_roam_flags(adapter, RTW_ROAM_ON_EXPIRED)) {
+			roam = _TRUE;
+		} else if (reason == WLAN_REASON_ACTIVE_ROAM && rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
+			roam = _TRUE;
+			roam_target = pmlmepriv->roam_network;
+		}
+#ifdef CONFIG_INTEL_WIDI
+		else if (adapter->mlmepriv.widi_state == INTEL_WIDI_STATE_CONNECTED) {
+			roam = _TRUE;
+		}
+#endif // CONFIG_INTEL_WIDI
+
+		if (roam == _TRUE) {
+			if (rtw_to_roam(adapter) > 0)
+				rtw_dec_to_roam(adapter); /* this stadel_event is caused by roaming, decrease to_roam */
+			else if (rtw_to_roam(adapter) == 0)
+				rtw_set_to_roam(adapter, adapter->registrypriv.max_roaming_times);
+		} else {
+			rtw_set_to_roam(adapter, 0);
+		}
+		#endif /* CONFIG_LAYER2_ROAMING */
+
+		rtw_free_uc_swdec_pending_queue(adapter);
+
+		rtw_free_assoc_resources(adapter, 1);
+		rtw_indicate_disconnect(adapter);
+		rtw_free_mlme_priv_ie_data(pmlmepriv);
+
+		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+		// remove the network entry in scanned_queue
+		pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);	
+		if (pwlan) {			
+			pwlan->fixed = _FALSE;
+			rtw_free_network_nolock(adapter, pwlan);
+		}
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+#ifdef CONFIG_INTEL_WIDI
+		if (!rtw_to_roam(adapter))
+			process_intel_widi_disconnect(adapter, 1);
+#endif // CONFIG_INTEL_WIDI
+
+		_rtw_roaming(adapter, roam_target);
+	}
+
+	if ( check_fwstate(pmlmepriv,WIFI_ADHOC_MASTER_STATE) || 
+	      check_fwstate(pmlmepriv,WIFI_ADHOC_STATE))
+	{
+		
+		//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+		rtw_free_stainfo(adapter,  psta);
+		//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+		
+		if(adapter->stapriv.asoc_sta_count== 1) //a sta + bc/mc_stainfo (not Ibss_stainfo)
+		{ 
+			//rtw_indicate_disconnect(adapter);//removed@20091105
+			_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			//free old ibss network
+			//pwlan = rtw_find_network(&pmlmepriv->scanned_queue, pstadel->macaddr);
+			pwlan = rtw_find_network(&pmlmepriv->scanned_queue, tgt_network->network.MacAddress);
+			if(pwlan)	
+			{
+				pwlan->fixed = _FALSE;
+				rtw_free_network_nolock(adapter, pwlan); 
+			}
+			_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+			//re-create ibss
+			pdev_network = &(adapter->registrypriv.dev_network);			
+			pibss = adapter->registrypriv.dev_network.MacAddress;
+
+			_rtw_memcpy(pdev_network, &tgt_network->network, get_WLAN_BSSID_EX_sz(&tgt_network->network));
+			
+			_rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
+			_rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
+	
+			rtw_update_registrypriv_dev_network(adapter);			
+
+			rtw_generate_random_ibss(pibss);
+			
+			if(check_fwstate(pmlmepriv,WIFI_ADHOC_STATE))
+			{
+				set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
+				_clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
+			}
+
+			if (rtw_create_ibss_cmd(adapter, 0) != _SUCCESS)
+				RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_err_, ("***Error=>stadel_event_callback: rtw_create_ibss_cmd status FAIL***\n"));
+
+		}
+		
+	}
+	
+	_exit_critical_bh(&pmlmepriv->lock, &irqL2);
+	
+_func_exit_;	
+
+}
+
+
+void rtw_cpwm_event_callback(PADAPTER padapter, u8 *pbuf)
+{
+#ifdef CONFIG_LPS_LCLK
+	struct reportpwrstate_parm *preportpwrstate;
+#endif
+
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("+rtw_cpwm_event_callback !!!\n"));
+#ifdef CONFIG_LPS_LCLK
+	preportpwrstate = (struct reportpwrstate_parm*)pbuf;
+	preportpwrstate->state |= (u8)(adapter_to_pwrctl(padapter)->cpwm_tog + 0x80);
+	cpwm_int_hdl(padapter, preportpwrstate);
+#endif
+
+_func_exit_;
+
+}
+
+
+void rtw_wmm_event_callback(PADAPTER padapter, u8 *pbuf)
+{
+_func_enter_;
+
+	WMMOnAssocRsp(padapter);
+
+_func_exit_;
+
+}
+
+/*
+* _rtw_join_timeout_handler - Timeout/faliure handler for CMD JoinBss
+* @adapter: pointer to _adapter structure
+*/
+void _rtw_join_timeout_handler(struct timer_list *t)
+{
+	_adapter *adapter = from_timer(adapter, t,
+						  mlmepriv.assoc_timer);
+	_irqL irqL;
+	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+#if 0
+	if (rtw_is_drv_stopped(adapter)) {
+		_rtw_up_sema(&pmlmepriv->assoc_terminate);
+		return;
+	}
+#endif	
+
+_func_enter_;		
+
+
+	DBG_871X("%s, fw_state=%x\n", __FUNCTION__, get_fwstate(pmlmepriv));
+	
+	if (RTW_CANNOT_RUN(adapter))
+		return;
+
+	
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	#ifdef CONFIG_LAYER2_ROAMING
+	if (rtw_to_roam(adapter) > 0) { /* join timeout caused by roaming */
+		while(1) {
+			rtw_dec_to_roam(adapter);
+			if (rtw_to_roam(adapter) != 0) { /* try another */
+				int do_join_r;
+				DBG_871X("%s try another roaming\n", __FUNCTION__);
+				if( _SUCCESS!=(do_join_r=rtw_do_join(adapter)) ) {
+					DBG_871X("%s roaming do_join return %d\n", __FUNCTION__ ,do_join_r);
+					continue;
+				}
+				break;
+			} else {
+#ifdef CONFIG_INTEL_WIDI
+				if(adapter->mlmepriv.widi_state == INTEL_WIDI_STATE_ROAMING)
+				{
+					_rtw_memset(pmlmepriv->sa_ext, 0x00, L2SDTA_SERVICE_VE_LEN);
+					intel_widi_wk_cmd(adapter, INTEL_WIDI_LISTEN_WK, NULL, 0);
+					DBG_871X("change to widi listen\n");
+				}
+#endif // CONFIG_INTEL_WIDI
+				DBG_871X("%s We've try roaming but fail\n", __FUNCTION__);
+				rtw_indicate_disconnect(adapter);
+				break;
+			}
+		}
+		
+	} else 
+	#endif
+	{
+		rtw_indicate_disconnect(adapter);
+		free_scanqueue(pmlmepriv);//???
+
+#ifdef CONFIG_IOCTL_CFG80211
+		//indicate disconnect for the case that join_timeout and check_fwstate != FW_LINKED
+		rtw_cfg80211_indicate_disconnect(adapter);
+#endif //CONFIG_IOCTL_CFG80211
+
+ 	}
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	
+
+#ifdef CONFIG_DRVEXT_MODULE_WSC	
+	drvext_assoc_fail_indicate(&adapter->drvextpriv);	
+#endif	
+
+	
+_func_exit_;
+
+}
+
+/*
+* rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
+* @adapter: pointer to _adapter structure
+*/
+void rtw_scan_timeout_handler(struct timer_list *t)
+{	
+	_adapter *adapter = from_timer(adapter, t,
+						  mlmepriv.scan_to_timer);
+	_irqL irqL;
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	DBG_871X(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	
+	_clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
+	
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+	
+#ifdef CONFIG_IOCTL_CFG80211
+	rtw_cfg80211_surveydone_event_callback(adapter);
+#endif //CONFIG_IOCTL_CFG80211
+	
+	rtw_indicate_scan_done(adapter, _TRUE);
+
+#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_IOCTL_CFG80211)
+	if (adapter->pbuddy_adapter) {
+		_adapter *buddy_adapter = adapter->pbuddy_adapter;
+		struct mlme_priv *buddy_mlme = &(buddy_adapter->mlmepriv);
+		struct rtw_wdev_priv *buddy_wdev_priv = adapter_wdev_data(buddy_adapter);
+		bool indicate_buddy_scan = _FALSE;
+
+		_enter_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
+		if (buddy_wdev_priv->scan_request && buddy_mlme->scanning_via_buddy_intf == _TRUE) {
+			buddy_mlme->scanning_via_buddy_intf = _FALSE;
+			clr_fwstate(buddy_mlme, _FW_UNDER_SURVEY);
+			indicate_buddy_scan = _TRUE;
+		}
+		_exit_critical_bh(&buddy_wdev_priv->scan_req_lock, &irqL);
+
+		if (indicate_buddy_scan == _TRUE) {
+			rtw_indicate_scan_done(buddy_adapter, _TRUE);
+		}
+	}
+#endif /* CONFIG_CONCURRENT_MODE */
+}
+
+void rtw_mlme_reset_auto_scan_int(_adapter *adapter)
+{
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+#ifdef CONFIG_P2P
+	if(!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) {
+		mlme->auto_scan_int_ms = 0; /* disabled */
+		goto exit;
+	}
+#endif	
+	if(pmlmeinfo->VHT_enable) //disable auto scan when connect to 11AC AP
+	{
+		mlme->auto_scan_int_ms = 0;
+	}
+	else if(adapter->registrypriv.wifi_spec && is_client_associated_to_ap(adapter) == _TRUE) {
+		mlme->auto_scan_int_ms = 60*1000;
+#ifdef CONFIG_LAYER2_ROAMING
+	} else if(rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)) {
+		if (check_fwstate(mlme, WIFI_STATION_STATE) && check_fwstate(mlme, _FW_LINKED))
+			mlme->auto_scan_int_ms = mlme->roam_scan_int_ms;
+#endif
+	} else {
+		mlme->auto_scan_int_ms = 0; /* disabled */
+	}
+exit:
+	return;
+}
+
+void rtw_drv_scan_by_self(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	if (!padapter->registrypriv.wifi_spec) {
+		if (check_fwstate(pmlmepriv, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING)) == _TRUE) {
+			DBG_871X(FUNC_ADPT_FMT" _FW_UNDER_SURVEY|_FW_UNDER_LINKING\n", FUNC_ADPT_ARG(padapter));
+			goto exit;
+		}
+			
+		if (pmlmepriv->LinkDetectInfo.bBusyTraffic == _TRUE) {
+			DBG_871X(FUNC_ADPT_FMT" exit BusyTraffic\n", FUNC_ADPT_ARG(padapter));
+			goto exit;
+		}
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (rtw_buddy_adapter_up(padapter)) {
+		if ((check_buddy_fwstate(padapter, (_FW_UNDER_SURVEY | _FW_UNDER_LINKING)) == _TRUE) ||
+			(padapter->pbuddy_adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)) {		
+				DBG_871X(FUNC_ADPT_FMT", but buddy_intf is under scanning or linking or BusyTraffic\n", FUNC_ADPT_ARG(padapter));
+				goto exit;
+		}
+	}
+#endif
+
+	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+	rtw_set_802_11_bssid_list_scan(padapter, NULL, 0);
+
+exit:
+	return;	
+}
+
+static void rtw_auto_scan_handler(_adapter *padapter)
+{
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	rtw_mlme_reset_auto_scan_int(padapter);
+
+	if (pmlmepriv->auto_scan_int_ms != 0
+		&& rtw_get_passing_time_ms(pmlmepriv->scan_start_time) > pmlmepriv->auto_scan_int_ms) 
+		rtw_drv_scan_by_self(padapter);
+	
+}
+
+void rtw_dynamic_check_timer_handler(_adapter *adapter)
+{
+#ifdef CONFIG_AP_MODE
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+#endif //CONFIG_AP_MODE
+	struct registry_priv *pregistrypriv = &adapter->registrypriv;
+#ifdef CONFIG_CONCURRENT_MODE	
+	PADAPTER pbuddy_adapter = adapter->pbuddy_adapter;
+#endif
+
+	if(!adapter)
+		return;	
+
+	if (!rtw_is_hw_init_completed(adapter))
+		return;
+
+	if (RTW_CANNOT_RUN(adapter))
+		return;
+
+	
+#ifdef CONFIG_CONCURRENT_MODE
+	if(pbuddy_adapter)
+	{
+		if(adapter->net_closed == _TRUE && pbuddy_adapter->net_closed == _TRUE)
+		{
+			return;
+		}		
+	}
+	else
+#endif //CONFIG_CONCURRENT_MODE
+	if(adapter->net_closed == _TRUE)
+	{
+		return;
+	}	
+
+#ifdef CONFIG_BT_COEXIST
+	if (is_primary_adapter(adapter)) {
+		if (GET_HAL_DATA(adapter)->EEPROMBluetoothCoexist == 1)
+			DBG_871X("IsBtDisabled=%d, IsBtControlLps=%d\n" , rtw_btcoex_IsBtDisabled(adapter) , rtw_btcoex_IsBtControlLps(adapter));
+	}
+#endif
+
+#ifdef CONFIG_LPS_LCLK_WD_TIMER /* to avoid leaving lps 32k frequently*/
+	if ((adapter_to_pwrctl(adapter)->bFwCurrentInPSMode ==_TRUE )
+#ifdef CONFIG_BT_COEXIST
+		&& (rtw_btcoex_IsBtControlLps(adapter) == _FALSE)
+#endif		
+		) 
+	{
+		u8 bEnterPS;	
+		
+		linked_status_chk(adapter, 1);	
+			
+		bEnterPS = traffic_status_watchdog(adapter, 1);
+		if(bEnterPS)
+		{
+			//rtw_lps_ctrl_wk_cmd(adapter, LPS_CTRL_ENTER, 1);
+			rtw_hal_dm_watchdog_in_lps(adapter);
+		}
+		else
+		{
+			//call rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1) in traffic_status_watchdog()
+		}
+			
+	}
+	else
+#endif //CONFIG_LPS_LCLK_WD_TIMER	
+	{
+		if(is_primary_adapter(adapter))
+		{	
+			rtw_dynamic_chk_wk_cmd(adapter);		
+		}	
+	}	
+
+	/* auto site survey */
+	rtw_auto_scan_handler(adapter);
+
+#ifndef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+#ifdef CONFIG_AP_MODE
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{
+		expire_timeout_chk(adapter);
+	}	
+#endif
+#endif //!CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+
+#ifdef CONFIG_BR_EXT
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+	rcu_read_lock();
+#endif	// (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35)) 
+	if( adapter->pnetdev->br_port 
+#else	// (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+	if( rcu_dereference(adapter->pnetdev->rx_handler_data)
+#endif	// (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+		&& (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE) )
+	{
+		// expire NAT2.5 entry
+		void nat25_db_expire(_adapter *priv);
+		nat25_db_expire(adapter);
+
+		if (adapter->pppoe_connection_in_progress > 0) {
+			adapter->pppoe_connection_in_progress--;
+		}
+		
+		// due to rtw_dynamic_check_timer_handlder() is called every 2 seconds
+		if (adapter->pppoe_connection_in_progress > 0) {
+			adapter->pppoe_connection_in_progress--;
+		}
+	}
+
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+	rcu_read_unlock();
+#endif	// (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35))
+
+#endif	// CONFIG_BR_EXT
+	
+}
+
+
+#ifdef CONFIG_SET_SCAN_DENY_TIMER
+inline bool rtw_is_scan_deny(_adapter *adapter)
+{
+	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
+	return (ATOMIC_READ(&mlmepriv->set_scan_deny) != 0) ? _TRUE : _FALSE;
+}
+
+inline void rtw_clear_scan_deny(_adapter *adapter)
+{
+	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
+	ATOMIC_SET(&mlmepriv->set_scan_deny, 0);
+	if (0)
+		DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
+}
+
+void rtw_set_scan_deny_timer_hdl(_adapter *adapter)
+{
+	rtw_clear_scan_deny(adapter);
+}
+
+void rtw_set_scan_deny(_adapter *adapter, u32 ms)
+{
+	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
+#ifdef CONFIG_CONCURRENT_MODE
+	struct mlme_priv *b_mlmepriv;
+#endif
+
+	if (0)
+		DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
+	ATOMIC_SET(&mlmepriv->set_scan_deny, 1);
+	_set_timer(&mlmepriv->set_scan_deny_timer, ms);
+	
+#ifdef CONFIG_CONCURRENT_MODE
+	if (!adapter->pbuddy_adapter)
+		return;
+
+	if (0)
+		DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter->pbuddy_adapter));
+ 	b_mlmepriv = &adapter->pbuddy_adapter->mlmepriv;
+	ATOMIC_SET(&b_mlmepriv->set_scan_deny, 1);
+	_set_timer(&b_mlmepriv->set_scan_deny_timer, ms);	
+#endif
+	
+}
+#endif
+
+#ifdef CONFIG_LAYER2_ROAMING
+/*
+* Select a new roaming candidate from the original @param candidate and @param competitor
+* @return _TRUE: candidate is updated
+* @return _FALSE: candidate is not updated
+*/
+static int rtw_check_roaming_candidate(struct mlme_priv *mlme
+	, struct wlan_network **candidate, struct wlan_network *competitor)
+{
+	int updated = _FALSE;
+	_adapter *adapter = container_of(mlme, _adapter, mlmepriv);
+
+	if(is_same_ess(&competitor->network, &mlme->cur_network.network) == _FALSE)
+		goto exit;
+
+	if(rtw_is_desired_network(adapter, competitor) == _FALSE)
+		goto exit;
+
+	DBG_871X("roam candidate:%s %s("MAC_FMT", ch%3u) rssi:%d, age:%5d\n",
+		(competitor == mlme->cur_network_scanned)?"*":" " ,
+		competitor->network.Ssid.Ssid,
+		MAC_ARG(competitor->network.MacAddress),
+		competitor->network.Configuration.DSConfig,
+		(int)competitor->network.Rssi,
+		rtw_get_passing_time_ms(competitor->last_scanned)
+	);
+
+	/* got specific addr to roam */
+	if (!is_zero_mac_addr(mlme->roam_tgt_addr)) {
+		if(_rtw_memcmp(mlme->roam_tgt_addr, competitor->network.MacAddress, ETH_ALEN) == _TRUE)
+			goto update;
+		else
+			goto exit;
+	}
+	#if 1
+	if(rtw_get_passing_time_ms((u32)competitor->last_scanned) >= mlme->roam_scanr_exp_ms)
+		goto exit;
+
+	if (competitor->network.Rssi - mlme->cur_network_scanned->network.Rssi < mlme->roam_rssi_diff_th)
+		goto exit;
+
+	if(*candidate != NULL && (*candidate)->network.Rssi>=competitor->network.Rssi)
+		goto exit;
+	#else
+	goto exit;
+	#endif
+
+update:
+	*candidate = competitor;
+	updated = _TRUE;
+
+exit:
+	return updated;
+}
+
+int rtw_select_roaming_candidate(struct mlme_priv *mlme)
+{
+	_irqL	irqL;
+	int ret = _FAIL;
+	_list	*phead;
+	_adapter *adapter;	
+	_queue	*queue	= &(mlme->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	struct	wlan_network	*candidate = NULL;
+	u8 		bSupportAntDiv = _FALSE;
+
+_func_enter_;
+
+	if (mlme->cur_network_scanned == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	_enter_critical_bh(&(mlme->scanned_queue.lock), &irqL);
+	phead = get_list_head(queue);		
+	adapter = (_adapter *)mlme->nic_hdl;
+
+	mlme->pscanned = get_next(phead);
+
+	while (!rtw_end_of_queue_search(phead, mlme->pscanned)) {
+
+		pnetwork = LIST_CONTAINOR(mlme->pscanned, struct wlan_network, list);
+		if(pnetwork==NULL){
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s return _FAIL:(pnetwork==NULL)\n", __FUNCTION__));
+			ret = _FAIL;
+			goto exit;
+		}
+		
+		mlme->pscanned = get_next(mlme->pscanned);
+
+		if (0)
+			DBG_871X("%s("MAC_FMT", ch%u) rssi:%d\n"
+				, pnetwork->network.Ssid.Ssid
+				, MAC_ARG(pnetwork->network.MacAddress)
+				, pnetwork->network.Configuration.DSConfig
+				, (int)pnetwork->network.Rssi);
+
+		rtw_check_roaming_candidate(mlme, &candidate, pnetwork);
+ 
+ 	}
+
+	if(candidate == NULL) {
+		DBG_871X("%s: return _FAIL(candidate == NULL)\n", __FUNCTION__);
+		ret = _FAIL;
+		goto exit;
+	} else {
+		DBG_871X("%s: candidate: %s("MAC_FMT", ch:%u)\n", __FUNCTION__,
+			candidate->network.Ssid.Ssid, MAC_ARG(candidate->network.MacAddress),
+			candidate->network.Configuration.DSConfig);
+
+		mlme->roam_network = candidate;
+
+		if (_rtw_memcmp(candidate->network.MacAddress, mlme->roam_tgt_addr, ETH_ALEN) == _TRUE)
+			_rtw_memset(mlme->roam_tgt_addr,0, ETH_ALEN);
+	}
+
+	ret = _SUCCESS;
+exit:
+	_exit_critical_bh(&(mlme->scanned_queue.lock), &irqL);
+
+	return ret;
+}
+#endif /* CONFIG_LAYER2_ROAMING */
+
+/*
+* Select a new join candidate from the original @param candidate and @param competitor
+* @return _TRUE: candidate is updated
+* @return _FALSE: candidate is not updated
+*/
+static int rtw_check_join_candidate(struct mlme_priv *mlme
+	, struct wlan_network **candidate, struct wlan_network *competitor)
+{
+	int updated = _FALSE;
+	_adapter *adapter = container_of(mlme, _adapter, mlmepriv);
+
+
+	//check bssid, if needed
+	if(mlme->assoc_by_bssid==_TRUE) {
+		if(_rtw_memcmp(competitor->network.MacAddress, mlme->assoc_bssid, ETH_ALEN) ==_FALSE)
+			goto exit;
+	}
+
+	//check ssid, if needed
+	if(mlme->assoc_ssid.Ssid[0] && mlme->assoc_ssid.SsidLength) {
+		if(	competitor->network.Ssid.SsidLength != mlme->assoc_ssid.SsidLength
+			|| _rtw_memcmp(competitor->network.Ssid.Ssid, mlme->assoc_ssid.Ssid, mlme->assoc_ssid.SsidLength) == _FALSE
+		)
+			goto exit;
+	}
+
+	if(rtw_is_desired_network(adapter, competitor)  == _FALSE)
+		goto exit;
+
+#ifdef  CONFIG_LAYER2_ROAMING
+	if(rtw_to_roam(adapter) > 0) {
+		if(	rtw_get_passing_time_ms((u32)competitor->last_scanned) >= mlme->roam_scanr_exp_ms
+			|| is_same_ess(&competitor->network, &mlme->cur_network.network) == _FALSE
+		)
+			goto exit;
+	}
+#endif
+	
+	if(*candidate == NULL ||(*candidate)->network.Rssi<competitor->network.Rssi )
+	{
+		*candidate = competitor;
+		updated = _TRUE;
+	}
+
+	if(updated){
+		DBG_871X("[by_bssid:%u][assoc_ssid:%s][to_roam:%u] "
+			"new candidate: %s("MAC_FMT", ch%u) rssi:%d\n",
+			mlme->assoc_by_bssid,
+			mlme->assoc_ssid.Ssid,
+			rtw_to_roam(adapter),
+			(*candidate)->network.Ssid.Ssid,
+			MAC_ARG((*candidate)->network.MacAddress),
+			(*candidate)->network.Configuration.DSConfig,
+			(int)(*candidate)->network.Rssi
+		);
+	}
+
+exit:
+	return updated;
+}
+
+/*
+Calling context:
+The caller of the sub-routine will be in critical section...
+
+The caller must hold the following spinlock
+
+pmlmepriv->lock
+
+
+*/
+
+int rtw_select_and_join_from_scanned_queue(struct mlme_priv *pmlmepriv )
+{
+	_irqL	irqL;
+	int ret;
+	_list	*phead;
+	_adapter *adapter;	
+	_queue	*queue	= &(pmlmepriv->scanned_queue);
+	struct	wlan_network	*pnetwork = NULL;
+	struct	wlan_network	*candidate = NULL;
+	u8 		bSupportAntDiv = _FALSE;
+
+_func_enter_;
+
+	adapter = (_adapter *)pmlmepriv->nic_hdl;
+
+	_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+	#ifdef CONFIG_LAYER2_ROAMING
+	if (pmlmepriv->roam_network) {
+		candidate = pmlmepriv->roam_network;
+		pmlmepriv->roam_network = NULL;
+		goto candidate_exist;
+	}
+	#endif
+
+	phead = get_list_head(queue);
+	pmlmepriv->pscanned = get_next(phead);
+
+	while (!rtw_end_of_queue_search(phead, pmlmepriv->pscanned)) {
+
+		pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned, struct wlan_network, list);
+		if(pnetwork==NULL){
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("%s return _FAIL:(pnetwork==NULL)\n", __FUNCTION__));
+			ret = _FAIL;
+			goto exit;
+		}
+		
+		pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
+
+		if (0)
+			DBG_871X("%s("MAC_FMT", ch%u) rssi:%d\n"
+				, pnetwork->network.Ssid.Ssid
+				, MAC_ARG(pnetwork->network.MacAddress)
+				, pnetwork->network.Configuration.DSConfig
+				, (int)pnetwork->network.Rssi);
+
+		rtw_check_join_candidate(pmlmepriv, &candidate, pnetwork);
+ 
+ 	}
+
+	if(candidate == NULL) {
+		DBG_871X("%s: return _FAIL(candidate == NULL)\n", __FUNCTION__);
+#ifdef CONFIG_WOWLAN
+		_clr_fwstate_(pmlmepriv, _FW_LINKED|_FW_UNDER_LINKING);
+#endif
+		ret = _FAIL;
+		goto exit;
+	} else {
+		DBG_871X("%s: candidate: %s("MAC_FMT", ch:%u)\n", __FUNCTION__,
+			candidate->network.Ssid.Ssid, MAC_ARG(candidate->network.MacAddress),
+			candidate->network.Configuration.DSConfig);
+		goto candidate_exist;
+	}
+	
+candidate_exist:
+
+	// check for situation of  _FW_LINKED 
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+	{
+		DBG_871X("%s: _FW_LINKED while ask_for_joinbss!!!\n", __FUNCTION__);
+
+		#if 0 // for WPA/WPA2 authentication, wpa_supplicant will expect authentication from AP, it is needed to reconnect AP...
+		if(is_same_network(&pmlmepriv->cur_network.network, &candidate->network))
+		{
+			DBG_871X("%s: _FW_LINKED and is same network, it needn't join again\n", __FUNCTION__);
+
+			rtw_indicate_connect(adapter);//rtw_indicate_connect again
+				
+			ret = 2;
+			goto exit;
+		}
+		else
+		#endif
+		{
+			rtw_disassoc_cmd(adapter, 0, _TRUE);
+			rtw_indicate_disconnect(adapter);
+			rtw_free_assoc_resources(adapter, 0);
+		}
+	}
+	
+	#ifdef CONFIG_ANTENNA_DIVERSITY
+	rtw_hal_get_def_var(adapter, HAL_DEF_IS_SUPPORT_ANT_DIV, &(bSupportAntDiv));
+	if(_TRUE == bSupportAntDiv)	
+	{
+		u8 CurrentAntenna;
+		rtw_hal_get_def_var(adapter, HAL_DEF_CURRENT_ANTENNA, &(CurrentAntenna));			
+		DBG_871X("#### Opt_Ant_(%s) , cur_Ant(%s)\n",
+			(2==candidate->network.PhyInfo.Optimum_antenna)?"A":"B",
+			(2==CurrentAntenna)?"A":"B"
+		);
+	}
+	#endif
+	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+	ret = rtw_joinbss_cmd(adapter, candidate);
+	
+exit:
+	_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+_func_exit_;
+
+	return ret;
+}
+
+sint rtw_set_auth(_adapter * adapter,struct security_priv *psecuritypriv)
+{
+	struct	cmd_obj* pcmd;
+	struct 	setauth_parm *psetauthparm;
+	struct	cmd_priv	*pcmdpriv=&(adapter->cmdpriv);
+	sint		res=_SUCCESS;
+	
+_func_enter_;	
+
+	pcmd = (struct	cmd_obj*)rtw_zmalloc(sizeof(struct	cmd_obj));
+	if(pcmd==NULL){
+		res= _FAIL;  //try again
+		goto exit;
+	}
+	
+	psetauthparm=(struct setauth_parm*)rtw_zmalloc(sizeof(struct setauth_parm));
+	if(psetauthparm==NULL){
+		rtw_mfree((unsigned char *)pcmd, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	_rtw_memset(psetauthparm, 0, sizeof(struct setauth_parm));
+	psetauthparm->mode=(unsigned char)psecuritypriv->dot11AuthAlgrthm;
+	
+	pcmd->cmdcode = _SetAuth_CMD_;
+	pcmd->parmbuf = (unsigned char *)psetauthparm;   
+	pcmd->cmdsz =  (sizeof(struct setauth_parm));  
+	pcmd->rsp = NULL;
+	pcmd->rspsz = 0;
+
+
+	_rtw_init_listhead(&pcmd->list);
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("after enqueue set_auth_cmd, auth_mode=%x\n", psecuritypriv->dot11AuthAlgrthm));
+
+	res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+
+exit:
+
+_func_exit_;
+
+	return res;
+
+}
+
+
+sint rtw_set_key(_adapter * adapter,struct security_priv *psecuritypriv,sint keyid, u8 set_tx, bool enqueue)
+{
+	u8	keylen;
+	struct cmd_obj		*pcmd;
+	struct setkey_parm	*psetkeyparm;
+	struct cmd_priv		*pcmdpriv = &(adapter->cmdpriv);
+	struct mlme_priv		*pmlmepriv = &(adapter->mlmepriv);
+	sint	res=_SUCCESS;
+	
+_func_enter_;
+
+	psetkeyparm=(struct setkey_parm*)rtw_zmalloc(sizeof(struct setkey_parm));
+	if(psetkeyparm==NULL){		
+		res= _FAIL;
+		goto exit;
+	}
+	_rtw_memset(psetkeyparm, 0, sizeof(struct setkey_parm));
+
+	if(psecuritypriv->dot11AuthAlgrthm ==dot11AuthAlgrthm_8021X){		
+		psetkeyparm->algorithm=(unsigned char)psecuritypriv->dot118021XGrpPrivacy;	
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n rtw_set_key: psetkeyparm->algorithm=(unsigned char)psecuritypriv->dot118021XGrpPrivacy=%d \n", psetkeyparm->algorithm));
+	}	
+	else{
+		psetkeyparm->algorithm=(u8)psecuritypriv->dot11PrivacyAlgrthm;
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n rtw_set_key: psetkeyparm->algorithm=(u8)psecuritypriv->dot11PrivacyAlgrthm=%d \n", psetkeyparm->algorithm));
+
+	}
+	psetkeyparm->keyid = (u8)keyid;//0~3
+	psetkeyparm->set_tx = set_tx;
+	if (is_wep_enc(psetkeyparm->algorithm))
+		adapter->securitypriv.key_mask |= BIT(psetkeyparm->keyid);
+
+	DBG_871X("==> rtw_set_key algorithm(%x),keyid(%x),key_mask(%x)\n",psetkeyparm->algorithm,psetkeyparm->keyid, adapter->securitypriv.key_mask);
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n rtw_set_key: psetkeyparm->algorithm=%d psetkeyparm->keyid=(u8)keyid=%d \n",psetkeyparm->algorithm, keyid));
+
+	switch(psetkeyparm->algorithm){
+			
+		case _WEP40_:
+			keylen=5;
+			_rtw_memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
+			break;
+		case _WEP104_:
+			keylen=13;
+			_rtw_memcpy(&(psetkeyparm->key[0]), &(psecuritypriv->dot11DefKey[keyid].skey[0]), keylen);
+			break;
+		case _TKIP_:
+			keylen=16;			
+			_rtw_memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
+			psetkeyparm->grpkey=1;
+			break;
+		case _AES_:
+			keylen=16;			
+			_rtw_memcpy(&psetkeyparm->key, &psecuritypriv->dot118021XGrpKey[keyid], keylen);
+			psetkeyparm->grpkey=1;
+			break;
+		default:
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("\n rtw_set_key:psecuritypriv->dot11PrivacyAlgrthm = %x (must be 1 or 2 or 4 or 5)\n",psecuritypriv->dot11PrivacyAlgrthm));
+			res= _FAIL;
+			rtw_mfree((unsigned char *)psetkeyparm, sizeof(struct setkey_parm));
+			goto exit;
+	}
+		
+		
+	if(enqueue){
+		pcmd = (struct	cmd_obj*)rtw_zmalloc(sizeof(struct	cmd_obj));
+		if(pcmd==NULL){
+			rtw_mfree((unsigned char *)psetkeyparm, sizeof(struct setkey_parm));
+			res= _FAIL;  //try again
+			goto exit;
+		}
+		
+		pcmd->cmdcode = _SetKey_CMD_;
+		pcmd->parmbuf = (u8 *)psetkeyparm;   
+		pcmd->cmdsz =  (sizeof(struct setkey_parm));  
+		pcmd->rsp = NULL;
+		pcmd->rspsz = 0;
+
+		_rtw_init_listhead(&pcmd->list);
+
+		//_rtw_init_sema(&(pcmd->cmd_sem), 0);
+
+		res = rtw_enqueue_cmd(pcmdpriv, pcmd);
+	}
+	else{
+		setkey_hdl(adapter, (u8 *)psetkeyparm);
+		rtw_mfree((u8 *) psetkeyparm, sizeof(struct setkey_parm));
+	}
+exit:
+_func_exit_;
+	return res;
+
+}
+
+
+//adjust IEs for rtw_joinbss_cmd in WMM
+int rtw_restruct_wmm_ie(_adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_len, uint initial_out_len)
+{
+	unsigned	int ielength=0;
+	unsigned int i, j;
+
+	i = 12; //after the fixed IE
+	while(i<in_len)
+	{
+		ielength = initial_out_len;		
+		
+		if(in_ie[i] == 0xDD && in_ie[i+2] == 0x00 && in_ie[i+3] == 0x50  && in_ie[i+4] == 0xF2 && in_ie[i+5] == 0x02 && i+5 < in_len) //WMM element ID and OUI
+		{
+
+			//Append WMM IE to the last index of out_ie
+			/*
+			for(j=i; j< i+(in_ie[i+1]+2); j++)
+			{
+				out_ie[ielength] = in_ie[j];				
+				ielength++;
+			}
+			out_ie[initial_out_len+8] = 0x00; //force the QoS Info Field to be zero
+	                */
+                       
+                        for ( j = i; j < i + 9; j++ )
+                        {
+                            out_ie[ ielength] = in_ie[ j ];
+                            ielength++;
+                        } 
+                        out_ie[ initial_out_len + 1 ] = 0x07;
+                        out_ie[ initial_out_len + 6 ] = 0x00;
+                        out_ie[ initial_out_len + 8 ] = 0x00;
+	
+			break;
+		}
+
+		i+=(in_ie[i+1]+2); // to the next IE element
+	}
+	
+	return ielength;
+	
+}
+
+
+//
+// Ported from 8185: IsInPreAuthKeyList(). (Renamed from SecIsInPreAuthKeyList(), 2006-10-13.)
+// Added by Annie, 2006-05-07.
+//
+// Search by BSSID,
+// Return Value:
+//		-1 		:if there is no pre-auth key in the  table
+//		>=0		:if there is pre-auth key, and   return the entry id
+//
+//
+
+static int SecIsInPMKIDList(_adapter *Adapter, u8 *bssid)
+{
+	struct security_priv *psecuritypriv=&Adapter->securitypriv;
+	int i=0;
+
+	do
+	{
+		if( ( psecuritypriv->PMKIDList[i].bUsed ) && 
+                    (  _rtw_memcmp( psecuritypriv->PMKIDList[i].Bssid, bssid, ETH_ALEN ) == _TRUE ) )
+		{
+			break;
+		}
+		else
+		{	
+			i++;
+			//continue;
+		}
+		
+	}while(i<NUM_PMKID_CACHE);
+
+	if( i == NUM_PMKID_CACHE )
+	{ 
+		i = -1;// Could not find.
+	}
+	else
+	{ 
+		// There is one Pre-Authentication Key for the specific BSSID.
+	}
+
+	return (i);
+	
+}
+
+//
+// Check the RSN IE length
+// If the RSN IE length <= 20, the RSN IE didn't include the PMKID information
+// 0-11th element in the array are the fixed IE
+// 12th element in the array is the IE
+// 13th element in the array is the IE length  
+//
+
+static int rtw_append_pmkid(_adapter *adapter,int iEntry, u8 *ie, uint ie_len)
+{
+	struct security_priv *sec=&adapter->securitypriv;
+
+	if (ie[13] > 20) {
+		int i;
+		u16 pmkid_cnt = RTW_GET_LE16(ie+14+20);
+		if (pmkid_cnt == 1 && _rtw_memcmp(ie+14+20+2, &sec->PMKIDList[iEntry].PMKID, 16)) {
+			DBG_871X(FUNC_ADPT_FMT" has carried the same PMKID:"KEY_FMT"\n"
+				, FUNC_ADPT_ARG(adapter), KEY_ARG(&sec->PMKIDList[iEntry].PMKID));
+			goto exit;
+		}
+
+		DBG_871X(FUNC_ADPT_FMT" remove original PMKID, count:%u\n"
+			, FUNC_ADPT_ARG(adapter), pmkid_cnt);
+
+		for (i=0;i<pmkid_cnt;i++)
+			DBG_871X("    "KEY_FMT"\n", KEY_ARG(ie+14+20+2+i*16));
+
+		ie_len -= 2+pmkid_cnt*16;
+		ie[13] = 20;
+	}
+
+	if (ie[13] <= 20) {	
+		/* The RSN IE didn't include the PMK ID, append the PMK information */
+
+		DBG_871X(FUNC_ADPT_FMT" append PMKID:"KEY_FMT"\n"
+				, FUNC_ADPT_ARG(adapter), KEY_ARG(&sec->PMKIDList[iEntry].PMKID));
+
+		RTW_PUT_LE16(&ie[ie_len], 1);
+		ie_len += 2;
+
+		_rtw_memcpy(&ie[ie_len], &sec->PMKIDList[iEntry].PMKID, 16);
+		ie_len += 16;
+
+		ie[13] += 18;//PMKID length = 2+16
+	}
+
+exit:
+	return (ie_len);
+}
+
+static int rtw_remove_pmkid(_adapter *adapter, u8 *ie, uint ie_len)
+{
+	struct security_priv *sec=&adapter->securitypriv;
+	int i;
+	u16 pmkid_cnt = RTW_GET_LE16(ie+14+20);
+
+	if (ie[13] <= 20)
+		goto exit;
+
+	DBG_871X(FUNC_ADPT_FMT" remove original PMKID, count:%u\n"
+		, FUNC_ADPT_ARG(adapter), pmkid_cnt);
+
+	for (i=0;i<pmkid_cnt;i++)
+		DBG_871X("    "KEY_FMT"\n", KEY_ARG(ie+14+20+2+i*16));
+
+	ie_len -= 2+pmkid_cnt*16;
+	ie[13] = 20;
+
+exit:
+	return (ie_len);
+}
+
+sint rtw_restruct_sec_ie(_adapter *adapter,u8 *in_ie, u8 *out_ie, uint in_len)
+{
+	u8 authmode=0x0, securitytype, match;
+	u8 sec_ie[255], uncst_oui[4], bkup_ie[255];
+	u8 wpa_oui[4]={0x0, 0x50, 0xf2, 0x01};
+	uint 	ielength, cnt, remove_cnt;
+	int iEntry;
+
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct security_priv *psecuritypriv=&adapter->securitypriv;
+	uint 	ndisauthmode=psecuritypriv->ndisauthtype;
+	uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
+	
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+		 ("+rtw_restruct_sec_ie: ndisauthmode=%d ndissecuritytype=%d\n",
+		  ndisauthmode, ndissecuritytype));
+	
+	//copy fixed ie only
+	_rtw_memcpy(out_ie, in_ie,12);
+	ielength=12;
+	if((ndisauthmode==Ndis802_11AuthModeWPA)||(ndisauthmode==Ndis802_11AuthModeWPAPSK))
+			authmode=_WPA_IE_ID_;
+	if((ndisauthmode==Ndis802_11AuthModeWPA2)||(ndisauthmode==Ndis802_11AuthModeWPA2PSK))
+			authmode=_WPA2_IE_ID_;
+
+	if(check_fwstate(pmlmepriv, WIFI_UNDER_WPS))
+	{
+		_rtw_memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
+		
+		ielength += psecuritypriv->wps_ie_len;
+	}
+	else if((authmode==_WPA_IE_ID_)||(authmode==_WPA2_IE_ID_))
+	{		
+		//copy RSN or SSN		
+		_rtw_memcpy(&out_ie[ielength], &psecuritypriv->supplicant_ie[0], psecuritypriv->supplicant_ie[1]+2);
+		/* debug for CONFIG_IEEE80211W
+		{
+			int jj;
+			printk("supplicant_ie_length=%d &&&&&&&&&&&&&&&&&&&\n", psecuritypriv->supplicant_ie[1]+2);
+			for(jj=0; jj < psecuritypriv->supplicant_ie[1]+2; jj++)
+				printk(" %02x ", psecuritypriv->supplicant_ie[jj]);
+			printk("\n");
+		}*/
+		ielength+=psecuritypriv->supplicant_ie[1]+2;
+		rtw_report_sec_ie(adapter, authmode, psecuritypriv->supplicant_ie);
+	
+#ifdef CONFIG_DRVEXT_MODULE
+		drvext_report_sec_ie(&adapter->drvextpriv, authmode, sec_ie);	
+#endif
+	}
+
+	iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
+	if(iEntry<0)
+	{
+		if(authmode == _WPA2_IE_ID_)
+			ielength = rtw_remove_pmkid(adapter, out_ie, ielength);
+	}
+	else
+	{
+		if(authmode == _WPA2_IE_ID_)
+			ielength=rtw_append_pmkid(adapter, iEntry, out_ie, ielength);
+	}
+
+_func_exit_;
+	
+	return ielength;	
+}
+
+void rtw_init_registrypriv_dev_network(	_adapter* adapter)
+{
+	struct registry_priv* pregistrypriv = &adapter->registrypriv;
+	WLAN_BSSID_EX    *pdev_network = &pregistrypriv->dev_network;
+	u8 *myhwaddr = adapter_mac_addr(adapter);
+	
+_func_enter_;
+
+	_rtw_memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
+
+	_rtw_memcpy(&pdev_network->Ssid, &pregistrypriv->ssid, sizeof(NDIS_802_11_SSID));
+	
+	pdev_network->Configuration.Length=sizeof(NDIS_802_11_CONFIGURATION);
+	pdev_network->Configuration.BeaconPeriod = 100;	
+	pdev_network->Configuration.FHConfig.Length = 0;
+	pdev_network->Configuration.FHConfig.HopPattern = 0;
+	pdev_network->Configuration.FHConfig.HopSet = 0;
+	pdev_network->Configuration.FHConfig.DwellTime = 0;
+	
+	
+_func_exit_;	
+	
+}
+
+void rtw_update_registrypriv_dev_network(_adapter* adapter) 
+{
+	int sz=0;
+	struct registry_priv* pregistrypriv = &adapter->registrypriv;	
+	WLAN_BSSID_EX    *pdev_network = &pregistrypriv->dev_network;
+	struct	security_priv*	psecuritypriv = &adapter->securitypriv;
+	struct	wlan_network	*cur_network = &adapter->mlmepriv.cur_network;
+	//struct	xmit_priv	*pxmitpriv = &adapter->xmitpriv;
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+
+_func_enter_;
+
+#if 0
+	pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
+	pxmitpriv->vcs = pregistrypriv->vcs_type;
+	pxmitpriv->vcs_type = pregistrypriv->vcs_type;
+	//pxmitpriv->rts_thresh = pregistrypriv->rts_thresh;
+	pxmitpriv->frag_len = pregistrypriv->frag_thresh;
+	
+	adapter->qospriv.qos_option = pregistrypriv->wmm_enable;
+#endif	
+
+	pdev_network->Privacy = (psecuritypriv->dot11PrivacyAlgrthm > 0 ? 1 : 0) ; // adhoc no 802.1x
+
+	pdev_network->Rssi = 0;
+
+	switch(pregistrypriv->wireless_mode)
+	{
+		case WIRELESS_11B:
+			pdev_network->NetworkTypeInUse = (Ndis802_11DS);
+			break;	
+		case WIRELESS_11G:
+		case WIRELESS_11BG:
+		case WIRELESS_11_24N:
+		case WIRELESS_11G_24N:
+		case WIRELESS_11BG_24N:
+			pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
+			break;
+		case WIRELESS_11A:
+		case WIRELESS_11A_5N:
+			pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
+			break;
+		case WIRELESS_11ABGN:
+			if(pregistrypriv->channel > 14)
+				pdev_network->NetworkTypeInUse = (Ndis802_11OFDM5);
+			else
+				pdev_network->NetworkTypeInUse = (Ndis802_11OFDM24);
+			break;
+		default :
+			// TODO
+			break;
+	}
+	
+	pdev_network->Configuration.DSConfig = (pregistrypriv->channel);
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("pregistrypriv->channel=%d, pdev_network->Configuration.DSConfig=0x%x\n", pregistrypriv->channel, pdev_network->Configuration.DSConfig));	
+
+	if (cur_network->network.InfrastructureMode == Ndis802_11IBSS) {
+		pdev_network->Configuration.ATIMWindow = (0);
+
+		if (pmlmeext->cur_channel != 0)
+			pdev_network->Configuration.DSConfig = pmlmeext->cur_channel;
+		else 
+			pdev_network->Configuration.DSConfig = 1;
+	}
+
+	pdev_network->InfrastructureMode = (cur_network->network.InfrastructureMode);
+
+	// 1. Supported rates
+	// 2. IE
+
+	//rtw_set_supported_rate(pdev_network->SupportedRates, pregistrypriv->wireless_mode) ; // will be called in rtw_generate_ie
+	sz = rtw_generate_ie(pregistrypriv);
+
+	pdev_network->IELength = sz;
+
+	pdev_network->Length = get_WLAN_BSSID_EX_sz((WLAN_BSSID_EX  *)pdev_network);
+
+	//notes: translate IELength & Length after assign the Length to cmdsz in createbss_cmd();
+	//pdev_network->IELength = cpu_to_le32(sz);
+		
+_func_exit_;	
+
+}
+
+void rtw_get_encrypt_decrypt_from_registrypriv(_adapter* adapter)
+{
+_func_enter_;
+
+
+_func_exit_;	
+	
+}
+
+//the fucntion is at passive_level 
+void rtw_joinbss_reset(_adapter *padapter)
+{
+	u8	threshold;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	//todo: if you want to do something io/reg/hw setting before join_bss, please add code here
+	
+#ifdef CONFIG_80211N_HT	
+	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;	
+
+	pmlmepriv->num_FortyMHzIntolerant = 0;
+
+	pmlmepriv->num_sta_no_ht = 0;
+
+	phtpriv->ampdu_enable = _FALSE;//reset to disabled
+
+#if defined( CONFIG_USB_HCI) || defined (CONFIG_SDIO_HCI)
+	// TH=1 => means that invalidate usb rx aggregation
+	// TH=0 => means that validate usb rx aggregation, use init value.
+	if(phtpriv->ht_option)
+	{
+		if(padapter->registrypriv.wifi_spec==1)		
+			threshold = 1;
+		else
+			threshold = 0;		
+		rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+	}
+	else
+	{
+		threshold = 1;
+		rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+	}
+#endif//#if defined( CONFIG_USB_HCI) || defined (CONFIG_SDIO_HCI)
+
+#endif//#ifdef CONFIG_80211N_HT
+
+}
+
+
+#ifdef CONFIG_80211N_HT
+void	rtw_ht_use_default_setting(_adapter *padapter)
+{
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	BOOLEAN		bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
+	BOOLEAN		bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
+
+	if (pregistrypriv->wifi_spec)
+		phtpriv->bss_coexist = 1;
+	else
+		phtpriv->bss_coexist = 0;
+
+	phtpriv->sgi_40m = TEST_FLAG(pregistrypriv->short_gi, BIT1) ? _TRUE : _FALSE;
+	phtpriv->sgi_20m = TEST_FLAG(pregistrypriv->short_gi, BIT0) ? _TRUE : _FALSE;
+
+	// LDPC support
+	rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
+	CLEAR_FLAGS(phtpriv->ldpc_cap);
+	if(bHwLDPCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->ldpc_cap, BIT4))
+			SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX);
+	}
+	rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
+	if(bHwLDPCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->ldpc_cap, BIT5))
+			SET_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX);
+	}
+	if (phtpriv->ldpc_cap)
+		DBG_871X("[HT] HAL Support LDPC = 0x%02X\n", phtpriv->ldpc_cap);
+
+	// STBC
+	rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
+	CLEAR_FLAGS(phtpriv->stbc_cap);
+	if(bHwSTBCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->stbc_cap, BIT5))
+			SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX);
+	}
+	rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
+	if(bHwSTBCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->stbc_cap, BIT4))
+			SET_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX);
+	}
+	if (phtpriv->stbc_cap)
+		DBG_871X("[HT] HAL Support STBC = 0x%02X\n", phtpriv->stbc_cap);
+
+	// Beamforming setting
+	rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&bHwSupportBeamformer);
+	rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&bHwSupportBeamformee);
+	CLEAR_FLAGS(phtpriv->beamform_cap);
+	if(TEST_FLAG(pregistrypriv->beamform_cap, BIT4) && bHwSupportBeamformer)
+	{
+		SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
+		DBG_871X("[HT] HAL Support Beamformer\n");
+	}
+	if(TEST_FLAG(pregistrypriv->beamform_cap, BIT5) && bHwSupportBeamformee)
+	{
+		SET_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
+		DBG_871X("[HT] HAL Support Beamformee\n");
+	}
+}
+void rtw_build_wmm_ie_ht(_adapter *padapter, u8 *out_ie, uint *pout_len)
+{
+	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
+	int out_len;
+	u8 *pframe;
+
+	if(padapter->mlmepriv.qospriv.qos_option == 0)
+	{
+		out_len = *pout_len;
+		pframe = rtw_set_ie(out_ie+out_len, _VENDOR_SPECIFIC_IE_, 
+							_WMM_IE_Length_, WMM_IE, pout_len);
+
+		padapter->mlmepriv.qospriv.qos_option = 1;
+	}
+}
+
+/* the fucntion is >= passive_level */
+unsigned int rtw_restructure_ht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len, u8 channel)
+{
+	u32 ielen, out_len;
+	HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
+	HT_CAP_AMPDU_DENSITY best_ampdu_density;
+	unsigned char *p, *pframe;
+	struct rtw_ieee80211_ht_cap ht_capie;
+	u8	cbw40_enable = 0, stbc_rx_enable = 0, rf_type = 0, operation_bw = 0, rf_num = 0;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	phtpriv->ht_option = _FALSE;
+
+	out_len = *pout_len;
+
+	_rtw_memset(&ht_capie, 0, sizeof(struct rtw_ieee80211_ht_cap));
+
+	ht_capie.cap_info = IEEE80211_HT_CAP_DSSSCCK40;
+
+	if (phtpriv->sgi_20m)
+		ht_capie.cap_info |= IEEE80211_HT_CAP_SGI_20;
+
+	/* Get HT BW */
+	if (in_ie == NULL) {
+		/* TDLS: TODO 20/40 issue */
+		if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+			operation_bw = padapter->mlmeextpriv.cur_bwmode;
+			if (operation_bw > CHANNEL_WIDTH_40)
+				operation_bw = CHANNEL_WIDTH_40;
+		} else
+			/* TDLS: TODO 40? */
+			operation_bw = CHANNEL_WIDTH_40;
+	} else {
+		p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
+		if (p && (ielen == sizeof(struct ieee80211_ht_addt_info))) {
+			struct HT_info_element *pht_info = (struct HT_info_element *)(p+2);
+			if (pht_info->infos[0] & BIT(2)) {
+				switch (pht_info->infos[0] & 0x3) {
+				case 1:
+				case 3:
+					operation_bw = CHANNEL_WIDTH_40;
+					break;
+				default:
+					operation_bw = CHANNEL_WIDTH_20;
+					break;
+				}
+			} else {
+				operation_bw = CHANNEL_WIDTH_20;
+			}
+		}
+	}
+
+	/* to disable 40M Hz support while gd_bw_40MHz_en = 0 */
+	if (hal_chk_bw_cap(padapter, BW_CAP_40M)) {
+		if (channel > 14) {
+			if (REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
+				cbw40_enable = 1;
+		} else {
+			if (REGSTY_IS_BW_2G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
+				cbw40_enable = 1;
+		}
+	}
+
+	if ((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) {
+		ht_capie.cap_info |= IEEE80211_HT_CAP_SUP_WIDTH;
+		if (phtpriv->sgi_40m)
+			ht_capie.cap_info |= IEEE80211_HT_CAP_SGI_40;
+	}
+
+	/* todo: disable SM power save mode */
+	ht_capie.cap_info |= IEEE80211_HT_CAP_SM_PS;
+
+	/* RX LDPC */
+	if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_RX)) {
+		ht_capie.cap_info |= IEEE80211_HT_CAP_LDPC_CODING;
+		DBG_871X("[HT] Declare supporting RX LDPC\n");
+	}
+
+	/* TX STBC */
+	if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX)) {
+		ht_capie.cap_info |= IEEE80211_HT_CAP_TX_STBC;
+		DBG_871X("[HT] Declare supporting TX STBC\n");
+	}
+
+	/* RX STBC */
+	if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_RX)) {
+		if((pregistrypriv->rx_stbc == 0x3) ||							/* enable for 2.4/5 GHz */
+			((channel <= 14) && (pregistrypriv->rx_stbc == 0x1)) ||		/* enable for 2.4GHz */
+			((channel > 14) && (pregistrypriv->rx_stbc == 0x2)) ||		/* enable for 5GHz */
+			(pregistrypriv->wifi_spec == 1)) {
+			stbc_rx_enable = 1;
+		}
+	}
+
+	//fill default supported_mcs_set
+	_rtw_memcpy(ht_capie.supp_mcs_set, pmlmeext->default_supported_mcs_set, 16);
+
+	//update default supported_mcs_set
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+	switch(rf_type)
+	{
+	case RF_1T1R:
+		
+		if (stbc_rx_enable) {
+			ht_capie.cap_info |= IEEE80211_HT_CAP_RX_STBC_1R;//RX STBC One spatial stream
+			DBG_871X("[HT] Declare supporting RX STBC_1R\n");
+		}
+
+	                set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_1R);			
+			break;
+
+	case RF_2T2R:
+	case RF_1T2R:
+		if (stbc_rx_enable) {
+			ht_capie.cap_info |= IEEE80211_HT_CAP_RX_STBC_1R;/* RX STBC one spatial stream */
+			DBG_871X("[HT] Declare supporting RX STBC_1R\n");
+		}
+
+		#ifdef CONFIG_DISABLE_MCS13TO15
+		if(((cbw40_enable == 1) && (operation_bw == CHANNEL_WIDTH_40)) && (pregistrypriv->wifi_spec!=1))
+				set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R_13TO15_OFF);	
+		else
+				set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R);	
+		#else //CONFIG_DISABLE_MCS13TO15
+			set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_2R);
+		#endif //CONFIG_DISABLE_MCS13TO15
+		break;
+	case RF_3T3R:
+		if (stbc_rx_enable) {
+			ht_capie.cap_info |= IEEE80211_HT_CAP_RX_STBC_1R;/* RX STBC one spatial stream */
+			DBG_871X("[HT] Declare supporting RX STBC_1R\n");
+		}
+		set_mcs_rate_by_mask(ht_capie.supp_mcs_set, MCS_RATE_3R);
+		break;
+	default:
+		if (stbc_rx_enable) {
+			ht_capie.cap_info |= IEEE80211_HT_CAP_RX_STBC_1R;/* RX STBC one spatial stream */
+			DBG_871X("[HT] Declare supporting RX STBC_1R\n");
+		}
+		DBG_871X("[warning] rf_type %d is not expected\n", rf_type);
+	}
+
+	{
+		u32 rx_packet_offset, max_recvbuf_sz;
+		rtw_hal_get_def_var(padapter, HAL_DEF_RX_PACKET_OFFSET, &rx_packet_offset);
+		rtw_hal_get_def_var(padapter, HAL_DEF_MAX_RECVBUF_SZ, &max_recvbuf_sz);
+		//if(max_recvbuf_sz-rx_packet_offset>(8191-256)) {
+		//	DBG_871X("%s IEEE80211_HT_CAP_MAX_AMSDU is set\n", __FUNCTION__);
+		//	ht_capie.cap_info = ht_capie.cap_info |IEEE80211_HT_CAP_MAX_AMSDU;
+		//}
+	}
+	/* 	
+	AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+	AMPDU_para [4:2]:Min MPDU Start Spacing	
+	*/
+
+	/*
+	#if defined(CONFIG_RTL8188E )&& defined (CONFIG_SDIO_HCI)
+	ht_capie.ampdu_params_info = 2;
+	#else
+	ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR&0x03);
+	#endif
+	*/
+
+	if(padapter->driver_rx_ampdu_factor != 0xFF)
+		max_rx_ampdu_factor = (HT_CAP_AMPDU_FACTOR)padapter->driver_rx_ampdu_factor;
+	else
+		rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+				
+	//rtw_hal_get_def_var(padapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+	ht_capie.ampdu_params_info = (max_rx_ampdu_factor&0x03);
+
+	if(padapter->driver_rx_ampdu_spacing != 0xFF) 
+	{
+		ht_capie.ampdu_params_info |= (( padapter->driver_rx_ampdu_spacing&0x07) <<2);	
+	}
+	else
+	{
+		if (padapter->securitypriv.dot11PrivacyAlgrthm == _AES_) {
+			/*
+			*	Todo : Each chip must to ask DD , this chip best ampdu_density setting
+			*	By yiwei.sun
+			*/
+			rtw_hal_get_def_var(padapter, HW_VAR_BEST_AMPDU_DENSITY, &best_ampdu_density);
+
+			ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY & (best_ampdu_density << 2));
+
+		 } else
+			ht_capie.ampdu_params_info |= (IEEE80211_HT_CAP_AMPDU_DENSITY&0x00);
+	}
+#ifdef CONFIG_BEAMFORMING
+	ht_capie.tx_BF_cap_info = 0;
+
+	/* HT Beamformer*/
+	if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE)) {
+		/* Transmit NDP Capable */
+		SET_HT_CAP_TXBF_TRANSMIT_NDP_CAP(&ht_capie, 1);
+		/* Explicit Compressed Steering Capable */
+		SET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(&ht_capie, 1);
+		/* Compressed Steering Number Antennas */
+		SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(&ht_capie, 1);
+		rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
+		SET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(&ht_capie, rf_num);
+	}
+
+	/* HT Beamformee */
+	if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE)) {
+		/* Receive NDP Capable */
+		SET_HT_CAP_TXBF_RECEIVE_NDP_CAP(&ht_capie, 1);
+		/* Explicit Compressed Beamforming Feedback Capable */
+		SET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(&ht_capie, 2);
+		rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
+		SET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(&ht_capie, rf_num);
+	}
+#endif/*CONFIG_BEAMFORMING*/
+
+	pframe = rtw_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_, 
+						sizeof(struct rtw_ieee80211_ht_cap), (unsigned char*)&ht_capie, pout_len);
+
+	phtpriv->ht_option = _TRUE;
+
+	if(in_ie!=NULL)
+	{
+		p = rtw_get_ie(in_ie, _HT_ADD_INFO_IE_, &ielen, in_len);
+		if(p && (ielen==sizeof(struct ieee80211_ht_addt_info)))
+		{
+			out_len = *pout_len;		
+			pframe = rtw_set_ie(out_ie+out_len, _HT_ADD_INFO_IE_, ielen, p+2 , pout_len);
+		}
+	}
+
+	return (phtpriv->ht_option);
+	
+}
+
+//the fucntion is > passive_level (in critical_section)
+void rtw_update_ht_cap(_adapter *padapter, u8 *pie, uint ie_len, u8 channel)
+{	
+	u8 *p, max_ampdu_sz;
+	int len;		
+	//struct sta_info *bmc_sta, *psta;
+	struct rtw_ieee80211_ht_cap *pht_capie;
+	struct ieee80211_ht_addt_info *pht_addtinfo;
+	//struct recv_reorder_ctrl *preorder_ctrl;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
+	//struct recv_priv *precvpriv = &padapter->recvpriv;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	//struct wlan_network *pcur_network = &(pmlmepriv->cur_network);;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 cbw40_enable=0;
+	
+
+	if(!phtpriv->ht_option)
+		return;
+
+	if ((!pmlmeinfo->HT_info_enable) || (!pmlmeinfo->HT_caps_enable))
+		return;
+
+	DBG_871X("+rtw_update_ht_cap()\n");
+
+	//maybe needs check if ap supports rx ampdu.
+	if((phtpriv->ampdu_enable==_FALSE) &&(pregistrypriv->ampdu_enable==1))
+	{
+		if(pregistrypriv->wifi_spec==1)
+		{
+			//remove this part because testbed AP should disable RX AMPDU
+			//phtpriv->ampdu_enable = _FALSE;
+			phtpriv->ampdu_enable = _TRUE;
+		}
+		else
+		{
+			phtpriv->ampdu_enable = _TRUE;
+		}
+	}
+	else if(pregistrypriv->ampdu_enable==2)
+	{
+		//remove this part because testbed AP should disable RX AMPDU
+		//phtpriv->ampdu_enable = _TRUE;
+	}
+
+	
+	//check Max Rx A-MPDU Size 
+	len = 0;
+	p = rtw_get_ie(pie+sizeof (NDIS_802_11_FIXED_IEs), _HT_CAPABILITY_IE_, &len, ie_len-sizeof (NDIS_802_11_FIXED_IEs));
+	if(p && len>0)	
+	{
+		pht_capie = (struct rtw_ieee80211_ht_cap *)(p+2);
+		max_ampdu_sz = (pht_capie->ampdu_params_info & IEEE80211_HT_CAP_AMPDU_FACTOR);
+		max_ampdu_sz = 1 << (max_ampdu_sz+3); // max_ampdu_sz (kbytes);
+		
+		//DBG_871X("rtw_update_ht_cap(): max_ampdu_sz=%d\n", max_ampdu_sz);
+		phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
+		
+	}
+
+
+	len=0;
+	p = rtw_get_ie(pie+sizeof (NDIS_802_11_FIXED_IEs), _HT_ADD_INFO_IE_, &len, ie_len-sizeof (NDIS_802_11_FIXED_IEs));
+	if(p && len>0)	
+	{
+		pht_addtinfo = (struct ieee80211_ht_addt_info *)(p+2);
+		//todo:
+	}
+
+	if (hal_chk_bw_cap(padapter, BW_CAP_40M)) {
+		if (channel > 14) {
+			if (REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
+				cbw40_enable = 1;
+		} else {
+			if (REGSTY_IS_BW_2G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
+				cbw40_enable = 1;
+		}
+	}
+
+	//update cur_bwmode & cur_ch_offset
+	if ((cbw40_enable) &&
+		(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1)) && 
+		(pmlmeinfo->HT_info.infos[0] & BIT(2)))
+	{
+		int i;
+		u8	rf_type = RF_1T1R;
+
+		rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+		//update the MCS set
+		for (i = 0; i < 16; i++)
+			pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
+
+		//update the MCS rates
+		switch(rf_type)
+		{
+			case RF_1T1R:
+			case RF_1T2R:
+				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);							
+				break;
+			case RF_2T2R:
+				#ifdef CONFIG_DISABLE_MCS13TO15
+				if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 && pregistrypriv->wifi_spec != 1 )				
+					set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R_13TO15_OFF);				
+				else
+					set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
+#else //CONFIG_DISABLE_MCS13TO15
+				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
+#endif //CONFIG_DISABLE_MCS13TO15
+				break;
+			case RF_3T3R:
+				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_3R);
+				break;
+			default:
+				DBG_871X("[warning] rf_type %d is not expected\n", rf_type);
+		}
+
+		//switch to the 40M Hz mode accoring to the AP
+		//pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
+		switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
+		{
+			case EXTCHNL_OFFSET_UPPER:
+				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+				break;
+			
+			case EXTCHNL_OFFSET_LOWER:
+				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+				break;
+				
+			default:
+				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+				break;
+		}		
+	}
+
+	//
+	// Config SM Power Save setting
+	//
+	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
+	if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+	{
+		/*u8 i;
+		//update the MCS rates
+		for (i = 0; i < 16; i++)
+		{
+			pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
+		}*/
+		DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);
+	}
+
+	//
+	// Config current HT Protection mode.
+	//
+	pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
+
+	
+	
+#if 0 //move to rtw_update_sta_info_client()
+	//for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
+	//if A-MPDU Rx is enabled, reseting  rx_ordering_ctrl wstart_b(indicate_seq) to default value=0xffff
+	//todo: check if AP can send A-MPDU packets
+	bmc_sta = rtw_get_bcmc_stainfo(padapter);
+	if(bmc_sta)
+	{
+		for(i=0; i < 16 ; i++)
+		{
+			//preorder_ctrl = &precvpriv->recvreorder_ctrl[i];
+			preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
+			preorder_ctrl->enable = _FALSE;
+			preorder_ctrl->indicate_seq = 0xffff;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq);
+			#endif
+			preorder_ctrl->wend_b= 0xffff;
+			preorder_ctrl->wsize_b = 64;//max_ampdu_sz;//ex. 32(kbytes) -> wsize_b=32
+		}
+	}
+
+	psta = rtw_get_stainfo(&padapter->stapriv, pcur_network->network.MacAddress);
+	if(psta)
+	{
+		for(i=0; i < 16 ; i++)
+		{
+			//preorder_ctrl = &precvpriv->recvreorder_ctrl[i];
+			preorder_ctrl = &psta->recvreorder_ctrl[i];
+			preorder_ctrl->enable = _FALSE;
+			preorder_ctrl->indicate_seq = 0xffff;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d indicate_seq:%u \n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq);
+			#endif
+			preorder_ctrl->wend_b= 0xffff;
+			preorder_ctrl->wsize_b = 64;//max_ampdu_sz;//ex. 32(kbytes) -> wsize_b=32
+		}
+	}
+#endif	
+
+}
+
+#ifdef CONFIG_TDLS
+void rtw_issue_addbareq_cmd_tdls(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	struct pkt_attrib *pattrib =&pxmitframe->attrib;
+	struct sta_info *ptdls_sta = NULL;
+	u8 issued;
+	int priority;
+	struct ht_priv	*phtpriv;
+
+	priority = pattrib->priority;
+
+	if (pattrib->direct_link == _TRUE) {
+		ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
+		if ((ptdls_sta != NULL) && (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)) {
+			phtpriv = &ptdls_sta->htpriv;
+
+			if ((phtpriv->ht_option == _TRUE) && (phtpriv->ampdu_enable == _TRUE)) {
+				issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
+				issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
+
+				if (0 == issued) {
+					DBG_871X("[%s], p=%d\n", __FUNCTION__, priority);
+					ptdls_sta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
+					rtw_addbareq_cmd(padapter,(u8)priority, pattrib->dst);
+				}
+			}
+		}
+	}
+}
+#endif //CONFIG_TDLS
+
+void rtw_issue_addbareq_cmd(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	u8 issued;
+	int priority;
+	struct sta_info *psta=NULL;
+	struct ht_priv	*phtpriv;
+	struct pkt_attrib *pattrib =&pxmitframe->attrib;
+	s32 bmcst = IS_MCAST(pattrib->ra);
+
+	//if(bmcst || (padapter->mlmepriv.LinkDetectInfo.bTxBusyTraffic == _FALSE))
+	if(bmcst || (padapter->mlmepriv.LinkDetectInfo.NumTxOkInPeriod<100))	
+		return;
+	
+	priority = pattrib->priority;
+
+#ifdef CONFIG_TDLS
+	rtw_issue_addbareq_cmd_tdls(padapter, pxmitframe);
+#endif //CONFIG_TDLS
+
+	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	if(pattrib->psta != psta)
+	{
+		DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
+		return;
+	}
+	
+	if(psta==NULL)
+	{
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return;
+	}
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return;
+	}	
+
+
+	phtpriv = &psta->htpriv;
+
+	if((phtpriv->ht_option==_TRUE) && (phtpriv->ampdu_enable==_TRUE)) 
+	{
+		issued = (phtpriv->agg_enable_bitmap>>priority)&0x1;
+		issued |= (phtpriv->candidate_tid_bitmap>>priority)&0x1;
+
+		if(0==issued)
+		{
+			DBG_871X("rtw_issue_addbareq_cmd, p=%d\n", priority);
+			psta->htpriv.candidate_tid_bitmap |= BIT((u8)priority);
+			rtw_addbareq_cmd(padapter,(u8) priority, pattrib->ra);
+		}
+	}
+
+}
+
+void rtw_append_exented_cap(_adapter *padapter, u8 *out_ie, uint *pout_len)
+{
+	struct mlme_priv 	*pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv		*phtpriv = &pmlmepriv->htpriv;
+#ifdef CONFIG_80211AC_VHT
+	struct vht_priv	*pvhtpriv = &pmlmepriv->vhtpriv;
+#endif //CONFIG_80211AC_VHT
+	u8	cap_content[8] = { 0 };
+	u8	*pframe;
+	u8   null_content[8] = {0};
+
+	if (phtpriv->bss_coexist) {
+		SET_EXT_CAPABILITY_ELE_BSS_COEXIST(cap_content, 1);
+	}
+
+#ifdef CONFIG_80211AC_VHT
+	if (pvhtpriv->vht_option) {
+		SET_EXT_CAPABILITY_ELE_OP_MODE_NOTIF(cap_content, 1);
+	}
+#endif //CONFIG_80211AC_VHT
+	/*
+		From 802.11 specification,if a STA does not support any of capabilities defined
+		in the Extended Capabilities element, then the STA is not required to 
+		transmit the Extended Capabilities element. 
+	*/
+	if (_FALSE == _rtw_memcmp(cap_content, null_content, 8))
+		pframe = rtw_set_ie(out_ie + *pout_len, EID_EXTCapability, 8, cap_content , pout_len);
+}
+#endif
+
+#ifdef CONFIG_LAYER2_ROAMING
+inline void rtw_set_to_roam(_adapter *adapter, u8 to_roam)
+{
+	if (to_roam == 0)
+		adapter->mlmepriv.to_join = _FALSE;
+	adapter->mlmepriv.to_roam = to_roam;
+}
+
+inline u8 rtw_dec_to_roam(_adapter *adapter)
+{
+	adapter->mlmepriv.to_roam--;
+	return adapter->mlmepriv.to_roam;
+}
+
+inline u8 rtw_to_roam(_adapter *adapter)
+{
+	return adapter->mlmepriv.to_roam;
+}
+
+void rtw_roaming(_adapter *padapter, struct wlan_network *tgt_network)
+{
+	_irqL irqL;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	_rtw_roaming(padapter, tgt_network);
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+}
+void _rtw_roaming(_adapter *padapter, struct wlan_network *tgt_network)
+{
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network *cur_network = &pmlmepriv->cur_network;
+	int do_join_r;
+	
+	if(0 < rtw_to_roam(padapter)) {
+		DBG_871X("roaming from %s("MAC_FMT"), length:%d\n",
+				cur_network->network.Ssid.Ssid, MAC_ARG(cur_network->network.MacAddress),
+				cur_network->network.Ssid.SsidLength);
+		_rtw_memcpy(&pmlmepriv->assoc_ssid, &cur_network->network.Ssid, sizeof(NDIS_802_11_SSID));
+
+		pmlmepriv->assoc_by_bssid = _FALSE;
+
+#ifdef CONFIG_WAPI_SUPPORT
+		rtw_wapi_return_all_sta_info(padapter);
+#endif
+
+		while(1) {
+			if( _SUCCESS==(do_join_r=rtw_do_join(padapter)) ) {
+				break;
+			} else {
+				DBG_871X("roaming do_join return %d\n", do_join_r);
+				rtw_dec_to_roam(padapter);
+				
+				if(rtw_to_roam(padapter) > 0) {
+					continue;
+				} else {
+					DBG_871X("%s(%d) -to roaming fail, indicate_disconnect\n", __FUNCTION__,__LINE__);
+					rtw_indicate_disconnect(padapter);
+					break;
+				}
+			}
+		}
+	}
+	
+}
+#endif /* CONFIG_LAYER2_ROAMING */
+
+bool rtw_adjust_chbw(_adapter *adapter, u8 req_ch, u8 *req_bw, u8 *req_offset)
+{
+	struct registry_priv *regsty = adapter_to_regsty(adapter);
+	u8 allowed_bw;
+
+	if (req_ch <= 14)
+		allowed_bw = REGSTY_BW_2G(regsty);
+	else
+		allowed_bw = REGSTY_BW_5G(regsty);
+
+	allowed_bw = hal_largest_bw(adapter, allowed_bw);
+
+	if (allowed_bw == CHANNEL_WIDTH_80 && *req_bw > CHANNEL_WIDTH_80)
+		*req_bw = CHANNEL_WIDTH_80;
+	else if (allowed_bw == CHANNEL_WIDTH_40 && *req_bw > CHANNEL_WIDTH_40)
+		*req_bw = CHANNEL_WIDTH_40;
+	else if (allowed_bw == CHANNEL_WIDTH_20 && *req_bw > CHANNEL_WIDTH_20) {
+		*req_bw = CHANNEL_WIDTH_20;
+		*req_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	} else
+		return _FALSE;
+
+	return _TRUE;
+}
+
+sint rtw_linked_check(_adapter *padapter)
+{
+	if(	(check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) ||
+			(check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE))
+	{
+		if(padapter->stapriv.asoc_sta_count > 2)
+			return _TRUE;
+	}
+	else
+	{	//Station mode
+		if(check_fwstate(&padapter->mlmepriv, _FW_LINKED)== _TRUE)
+			return _TRUE;
+	}
+	return _FALSE;
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+sint rtw_buddy_adapter_up(_adapter *padapter)
+{	
+	sint res = _FALSE;
+	
+	if(padapter == NULL)
+		return res;
+
+
+	if(padapter->pbuddy_adapter == NULL)
+		res = _FALSE;
+	else if (RTW_CANNOT_RUN(padapter) ||
+		(padapter->pbuddy_adapter->bup == _FALSE) || (!rtw_is_hw_init_completed(padapter)))
+		res = _FALSE;
+	else
+		res = _TRUE;
+
+	return res;	
+
+}
+
+sint check_buddy_fwstate(_adapter *padapter, sint state)
+{
+	if(padapter == NULL)
+		return _FALSE;	
+	
+	if(padapter->pbuddy_adapter == NULL)
+		return _FALSE;	
+		
+	if ((state == WIFI_FW_NULL_STATE) && 
+		(padapter->pbuddy_adapter->mlmepriv.fw_state == WIFI_FW_NULL_STATE))
+		return _TRUE;		
+	
+	if (padapter->pbuddy_adapter->mlmepriv.fw_state & state)
+		return _TRUE;
+
+	return _FALSE;
+}
+
+u8 rtw_get_buddy_bBusyTraffic(_adapter *padapter)
+{
+	if(padapter == NULL)
+		return _FALSE;	
+	
+	if(padapter->pbuddy_adapter == NULL)
+		return _FALSE;	
+	
+	return padapter->pbuddy_adapter->mlmepriv.LinkDetectInfo.bBusyTraffic;
+}
+
+#endif //CONFIG_CONCURRENT_MODE
+
+bool is_miracast_enabled(_adapter *adapter)
+{
+	bool enabled = 0;
+#ifdef CONFIG_WFD
+	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
+
+	enabled = (wfdinfo->stack_wfd_mode & (MIRACAST_SOURCE | MIRACAST_SINK))
+		|| (wfdinfo->op_wfd_mode & (MIRACAST_SOURCE | MIRACAST_SINK));
+#endif
+
+	return enabled;
+}
+
+bool rtw_chk_miracast_mode(_adapter *adapter, u8 mode)
+{
+	bool ret = 0;
+#ifdef CONFIG_WFD
+	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
+
+	ret = (wfdinfo->stack_wfd_mode & mode) || (wfdinfo->op_wfd_mode & mode);
+#endif
+
+	return ret;
+}
+
+const char *get_miracast_mode_str(int mode)
+{
+	if (mode == MIRACAST_SOURCE)
+		return "SOURCE";
+	else if (mode == MIRACAST_SINK)
+		return "SINK";
+	else if (mode == (MIRACAST_SOURCE | MIRACAST_SINK))
+		return "SOURCE&SINK";
+	else if (mode == MIRACAST_DISABLED)
+		return "DISABLED";
+	else
+		return "INVALID";
+}
+
+#ifdef CONFIG_WFD
+static bool wfd_st_match_rule(_adapter *adapter, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
+{
+	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
+
+	if (ntohs(*((u16 *)local_port)) == wfdinfo->rtsp_ctrlport
+		|| ntohs(*((u16 *)local_port)) == wfdinfo->tdls_rtsp_ctrlport
+		|| ntohs(*((u16 *)remote_port)) == wfdinfo->peer_rtsp_ctrlport)
+		return _TRUE;
+	return _FALSE;
+}
+
+static struct st_register wfd_st_reg = {
+	.s_proto = 0x06,
+	.rule = wfd_st_match_rule,
+};
+#endif /* CONFIG_WFD */
+
+inline void rtw_wfd_st_switch(struct sta_info *sta, bool on)
+{
+#ifdef CONFIG_WFD
+	if (on)
+		rtw_st_ctl_register(&sta->st_ctl, SESSION_TRACKER_REG_ID_WFD, &wfd_st_reg);
+	else
+		rtw_st_ctl_unregister(&sta->st_ctl, SESSION_TRACKER_REG_ID_WFD);
+#endif
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme_ext.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme_ext.c
new file mode 100644
index 000000000..750a86bd4
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mlme_ext.c
@@ -0,0 +1,15417 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_MLME_EXT_C_
+
+#include <drv_types.h>
+#ifdef CONFIG_IOCTL_CFG80211
+#include <rtw_wifi_regd.h>
+#endif //CONFIG_IOCTL_CFG80211
+#include <hal_data.h>
+
+
+struct mlme_handler mlme_sta_tbl[]={
+	{WIFI_ASSOCREQ,		"OnAssocReq",	&OnAssocReq},
+	{WIFI_ASSOCRSP,		"OnAssocRsp",	&OnAssocRsp},
+	{WIFI_REASSOCREQ,	"OnReAssocReq",	&OnAssocReq},
+	{WIFI_REASSOCRSP,	"OnReAssocRsp",	&OnAssocRsp},
+	{WIFI_PROBEREQ,		"OnProbeReq",	&OnProbeReq},
+	{WIFI_PROBERSP,		"OnProbeRsp",		&OnProbeRsp},
+
+	/*----------------------------------------------------------
+					below 2 are reserved
+	-----------------------------------------------------------*/
+	{0,					"DoReserved",		&DoReserved},
+	{0,					"DoReserved",		&DoReserved},
+	{WIFI_BEACON,		"OnBeacon",		&OnBeacon},
+	{WIFI_ATIM,			"OnATIM",		&OnAtim},
+	{WIFI_DISASSOC,		"OnDisassoc",		&OnDisassoc},
+	{WIFI_AUTH,			"OnAuth",		&OnAuthClient},
+	{WIFI_DEAUTH,		"OnDeAuth",		&OnDeAuth},
+	{WIFI_ACTION,		"OnAction",		&OnAction},
+	{WIFI_ACTION_NOACK,"OnActionNoAck",	&OnAction},
+};
+
+#ifdef _CONFIG_NATIVEAP_MLME_
+struct mlme_handler mlme_ap_tbl[]={
+	{WIFI_ASSOCREQ,		"OnAssocReq",	&OnAssocReq},
+	{WIFI_ASSOCRSP,		"OnAssocRsp",	&OnAssocRsp},
+	{WIFI_REASSOCREQ,	"OnReAssocReq",	&OnAssocReq},
+	{WIFI_REASSOCRSP,	"OnReAssocRsp",	&OnAssocRsp},
+	{WIFI_PROBEREQ,		"OnProbeReq",	&OnProbeReq},
+	{WIFI_PROBERSP,		"OnProbeRsp",		&OnProbeRsp},
+
+	/*----------------------------------------------------------
+					below 2 are reserved
+	-----------------------------------------------------------*/
+	{0,					"DoReserved",		&DoReserved},
+	{0,					"DoReserved",		&DoReserved},
+	{WIFI_BEACON,		"OnBeacon",		&OnBeacon},
+	{WIFI_ATIM,			"OnATIM",		&OnAtim},
+	{WIFI_DISASSOC,		"OnDisassoc",		&OnDisassoc},
+	{WIFI_AUTH,			"OnAuth",		&OnAuth},
+	{WIFI_DEAUTH,		"OnDeAuth",		&OnDeAuth},
+	{WIFI_ACTION,		"OnAction",		&OnAction},
+	{WIFI_ACTION_NOACK,"OnActionNoAck",	&OnAction},
+};
+#endif
+
+struct action_handler OnAction_tbl[]={
+	{RTW_WLAN_CATEGORY_SPECTRUM_MGMT,	 "ACTION_SPECTRUM_MGMT", on_action_spct},
+	{RTW_WLAN_CATEGORY_QOS, "ACTION_QOS", &OnAction_qos},
+	{RTW_WLAN_CATEGORY_DLS, "ACTION_DLS", &OnAction_dls},
+	{RTW_WLAN_CATEGORY_BACK, "ACTION_BACK", &OnAction_back},
+	{RTW_WLAN_CATEGORY_PUBLIC, "ACTION_PUBLIC", on_action_public},
+	{RTW_WLAN_CATEGORY_RADIO_MEASUREMENT, "ACTION_RADIO_MEASUREMENT", &DoReserved},
+	{RTW_WLAN_CATEGORY_FT, "ACTION_FT",	&DoReserved},
+	{RTW_WLAN_CATEGORY_HT,	"ACTION_HT",	&OnAction_ht},
+#ifdef CONFIG_IEEE80211W
+	{RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &OnAction_sa_query},
+#else
+	{RTW_WLAN_CATEGORY_SA_QUERY, "ACTION_SA_QUERY", &DoReserved},
+#endif //CONFIG_IEEE80211W
+	//add for CONFIG_IEEE80211W
+	{RTW_WLAN_CATEGORY_UNPROTECTED_WNM, "ACTION_UNPROTECTED_WNM", &DoReserved},
+	{RTW_WLAN_CATEGORY_SELF_PROTECTED, "ACTION_SELF_PROTECTED", &DoReserved},
+	{RTW_WLAN_CATEGORY_WMM, "ACTION_WMM", &OnAction_wmm},
+	{RTW_WLAN_CATEGORY_VHT, "ACTION_VHT", &OnAction_vht},
+	{RTW_WLAN_CATEGORY_P2P, "ACTION_P2P", &OnAction_p2p},	
+};
+
+
+u8	null_addr[ETH_ALEN]= {0,0,0,0,0,0};
+
+/**************************************************
+OUI definitions for the vendor specific IE
+***************************************************/
+unsigned char	RTW_WPA_OUI[] = {0x00, 0x50, 0xf2, 0x01};
+unsigned char WMM_OUI[] = {0x00, 0x50, 0xf2, 0x02};
+unsigned char	WPS_OUI[] = {0x00, 0x50, 0xf2, 0x04};
+unsigned char	P2P_OUI[] = {0x50,0x6F,0x9A,0x09};
+unsigned char	WFD_OUI[] = {0x50,0x6F,0x9A,0x0A};
+
+unsigned char	WMM_INFO_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+unsigned char	WMM_PARA_OUI[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};
+
+unsigned char WPA_TKIP_CIPHER[4] = {0x00, 0x50, 0xf2, 0x02};
+unsigned char RSN_TKIP_CIPHER[4] = {0x00, 0x0f, 0xac, 0x02};
+
+extern unsigned char REALTEK_96B_IE[];
+
+#ifdef LEGACY_CHANNEL_PLAN_REF
+/********************************************************
+ChannelPlan definitions
+*********************************************************/
+static RT_CHANNEL_PLAN legacy_channel_plan[] = {
+	/* 0x00, RTW_CHPLAN_FCC */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 32},
+	/* 0x01, RTW_CHPLAN_IC */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 31},
+	/* 0x02, RTW_CHPLAN_ETSI */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 32},
+	/* 0x03, RTW_CHPLAN_SPAIN */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 0x04, RTW_CHPLAN_FRANCE */					{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 0x05, RTW_CHPLAN_MKK */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 0x06, RTW_CHPLAN_MKK1 */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 0x07, RTW_CHPLAN_ISRAEL */					{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},
+	/* 0x08, RTW_CHPLAN_TELEC */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},
+	/* 0x09, RTW_CHPLAN_GLOBAL_DOAMIN */			{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+	/* 0x0A, RTW_CHPLAN_WORLD_WIDE_13 */			{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 0x0B, RTW_CHPLAN_TAIWAN */					{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 26},
+	/* 0x0C, RTW_CHPLAN_CHINA */					{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 149, 153, 157, 161, 165}, 18},
+	/* 0x0D, RTW_CHPLAN_SINGAPORE_INDIA_MEXICO */	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 24},
+	/* 0x0E, RTW_CHPLAN_KOREA */					{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 31},
+	/* 0x0F, RTW_CHPLAN_TURKEY */					{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19},
+	/* 0x10, RTW_CHPLAN_JAPAN */						{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 32},
+	/* 0x11, RTW_CHPLAN_FCC_NO_DFS */				{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 149, 153, 157, 161, 165}, 20},
+	/* 0x12, RTW_CHPLAN_JAPAN_NO_DFS */				{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48}, 17},
+	/* 0x13, RTW_CHPLAN_WORLD_WIDE_5G */			{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 37},
+	/* 0x14, RTW_CHPLAN_TAIWAN_NO_DFS */			{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 56, 60, 64, 149, 153, 157, 161, 165}, 19},
+};
+#endif
+
+static RT_CHANNEL_PLAN_2G RTW_ChannelPlan2G[] = {
+	/* 0, RTW_RD_2G_NULL */		{{}, 0},
+	/* 1, RTW_RD_2G_WORLD */	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 2, RTW_RD_2G_ETSI1 */		{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+	/* 3, RTW_RD_2G_FCC1 */		{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},
+	/* 4, RTW_RD_2G_MKK1 */		{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+	/* 5, RTW_RD_2G_ETSI2 */		{{10, 11, 12, 13}, 4},
+	/* 6, RTW_RD_2G_GLOBAL */	{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14},
+	/* 7, RTW_RD_2G_MKK2 */		{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13},
+};
+
+static RT_CHANNEL_PLAN_5G RTW_ChannelPlan5G[] = {
+	/* 0, RTW_RD_5G_NULL */		{{}, 0},
+	/* 1, RTW_RD_5G_ETSI1 */		{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19},
+	/* 2, RTW_RD_5G_ETSI2 */		{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
+	/* 3, RTW_RD_5G_ETSI3 */		{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 149, 153, 157, 161, 165}, 22},
+	/* 4, RTW_RD_5G_FCC1 */		{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165}, 24},
+	/* 5, RTW_RD_5G_FCC2 */		{{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
+	/* 6, RTW_RD_5G_FCC3 */		{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
+	/* 7, RTW_RD_5G_FCC4 */		{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161}, 12},
+	/* 8, RTW_RD_5G_FCC5 */		{{149, 153, 157, 161, 165}, 5},
+	/* 9, RTW_RD_5G_FCC6 */		{{36, 40, 44, 48, 52, 56, 60, 64}, 8},
+	/* 10, RTW_RD_5G_FCC7 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
+	/* 11, RTW_RD_5G_KCC1 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161}, 19},
+	/* 12, RTW_RD_5G_MKK1 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 19},
+	/* 13, RTW_RD_5G_MKK2 */	{{36, 40, 44, 48, 52, 56, 60, 64}, 8},
+	/* 14, RTW_RD_5G_MKK3 */	{{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
+	/* 15, RTW_RD_5G_NCC1 */	{{56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 16},
+	/* 16, RTW_RD_5G_NCC2 */	{{56, 60, 64, 149, 153, 157, 161, 165}, 8},
+	/* 17, RTW_RD_5G_NCC3 */	{{149, 153, 157, 161, 165}, 5},
+	/* 18, RTW_RD_5G_ETSI4 */	{{36, 40, 44, 48}, 4},
+	/* 19, RTW_RD_5G_ETSI5 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
+	/* 20, RTW_RD_5G_FCC8 */	{{149, 153, 157, 161}, 4},
+	/* 21, RTW_RD_5G_ETSI6 */	{{36, 40, 44, 48, 52, 56, 60, 64}, 8},
+	/* 22, RTW_RD_5G_ETSI7 */	{{36, 40, 44, 48, 52, 56, 60, 64, 149, 153, 157, 161, 165}, 13},
+	/* 23, RTW_RD_5G_ETSI8 */	{{36, 40, 44, 48, 149, 153, 157, 161, 165}, 9},
+	/* 24, RTW_RD_5G_ETSI9 */	{{100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140}, 11},
+	/* 25, RTW_RD_5G_ETSI10 */	{{149, 153, 157, 161, 165}, 5},
+	/* 26, RTW_RD_5G_ETSI11 */	{{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140, 149, 153, 157, 161, 165}, 16},
+	/* 27, RTW_RD_5G_NCC4 */	{{52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 17},
+	/* 28, RTW_RD_5G_ETSI12 */	{{149, 153, 157, 161}, 4},
+	/* 29, RTW_RD_5G_FCC9 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161, 165}, 21},
+	/* 30, RTW_RD_5G_ETSI13 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140}, 16},
+	/* 31, RTW_RD_5G_FCC10 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 132, 136, 140, 149, 153, 157, 161}, 20},
+	/* 32, RTW_RD_5G_MKK4 */	{{36, 40, 44, 48}, 4},
+	/* 33, RTW_RD_5G_ETSI14 */	{{36, 40, 44, 48, 52, 56, 60, 64, 132, 136, 140}, 11},
+
+	/* === Below are driver defined for legacy channel plan compatible, NO static index assigned ==== */
+	/* RTW_RD_5G_OLD_FCC1 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 20},
+	/* RTW_RD_5G_OLD_NCC1 */	{{56, 60, 64, 100, 104, 108, 112, 116, 136, 140, 149, 153, 157, 161, 165}, 15},
+	/* RTW_RD_5G_OLD_KCC1 */	{{36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 149, 153, 157, 161, 165}, 20},
+};
+
+static RT_CHANNEL_PLAN_MAP	RTW_ChannelPlanMap[] = {
+	/* ===== 0x00 ~ 0x1F, legacy channel plan ===== */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_KCC1,		TXPWR_LMT_FCC},		/* 0x00, RTW_CHPLAN_FCC */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_OLD_FCC1,	TXPWR_LMT_FCC},		/* 0x01, RTW_CHPLAN_IC */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_ETSI1,	TXPWR_LMT_ETSI},	/* 0x02, RTW_CHPLAN_ETSI */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_NULL,		TXPWR_LMT_ETSI},	/* 0x03, RTW_CHPLAN_SPAIN */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_NULL,		TXPWR_LMT_ETSI},	/* 0x04, RTW_CHPLAN_FRANCE */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_NULL,		TXPWR_LMT_MKK},		/* 0x05, RTW_CHPLAN_MKK */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_NULL,		TXPWR_LMT_MKK},		/* 0x06, RTW_CHPLAN_MKK1 */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_FCC6,		TXPWR_LMT_ETSI},	/* 0x07, RTW_CHPLAN_ISRAEL */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_FCC6,		TXPWR_LMT_MKK},		/* 0x08, RTW_CHPLAN_TELEC */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x09, RTW_CHPLAN_GLOBAL_DOAMIN */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x0A, RTW_CHPLAN_WORLD_WIDE_13 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_OLD_NCC1,	TXPWR_LMT_FCC},		/* 0x0B, RTW_CHPLAN_TAIWAN */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_FCC5,		TXPWR_LMT_ETSI},	/* 0x0C, RTW_CHPLAN_CHINA */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC3,		TXPWR_LMT_WW},		/* 0x0D, RTW_CHPLAN_SINGAPORE_INDIA_MEXICO */ /* ETSI:Singapore, India. FCC:Mexico => WW */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_OLD_KCC1,	TXPWR_LMT_ETSI},	/* 0x0E, RTW_CHPLAN_KOREA */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC6,		TXPWR_LMT_ETSI},	/* 0x0F, RTW_CHPLAN_TURKEY */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_ETSI1,	TXPWR_LMT_MKK},		/* 0x10, RTW_CHPLAN_JAPAN */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC2,		TXPWR_LMT_FCC},		/* 0x11, RTW_CHPLAN_FCC_NO_DFS */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_FCC7,		TXPWR_LMT_MKK},		/* 0x12, RTW_CHPLAN_JAPAN_NO_DFS */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC1,		TXPWR_LMT_WW},		/* 0x13, RTW_CHPLAN_WORLD_WIDE_5G */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_NCC2,		TXPWR_LMT_FCC},		/* 0x14, RTW_CHPLAN_TAIWAN_NO_DFS */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC7,		TXPWR_LMT_ETSI},	/* 0x15, RTW_CHPLAN_ETSI_NO_DFS */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_NCC1,		TXPWR_LMT_ETSI},	/* 0x16, RTW_CHPLAN_KOREA_NO_DFS */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_FCC7,		TXPWR_LMT_MKK},		/* 0x17, RTW_CHPLAN_JAPAN_NO_DFS */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_FCC5,		TXPWR_LMT_ETSI},	/* 0x18, RTW_CHPLAN_PAKISTAN_NO_DFS */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC5,		TXPWR_LMT_FCC},		/* 0x19, RTW_CHPLAN_TAIWAN2_NO_DFS */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x1A, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x1B, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x1C, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x1D, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x1E, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_FCC1,		TXPWR_LMT_WW},		/* 0x1F, RTW_CHPLAN_WORLD_WIDE_ONLY_5G */
+
+	/* ===== 0x20 ~ 0x7F, new channel plan ===== */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x20, RTW_CHPLAN_WORLD_NULL */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_NULL,		TXPWR_LMT_ETSI},	/* 0x21, RTW_CHPLAN_ETSI1_NULL */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_NULL,		TXPWR_LMT_FCC},		/* 0x22, RTW_CHPLAN_FCC1_NULL */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_NULL,		TXPWR_LMT_MKK},		/* 0x23, RTW_CHPLAN_MKK1_NULL */
+	{RTW_RD_2G_ETSI2,	RTW_RD_5G_NULL,		TXPWR_LMT_ETSI},	/* 0x24, RTW_CHPLAN_ETSI2_NULL */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC1,		TXPWR_LMT_FCC},		/* 0x25, RTW_CHPLAN_FCC1_FCC1 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI1,	TXPWR_LMT_ETSI},	/* 0x26, RTW_CHPLAN_WORLD_ETSI1 */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_MKK1,		TXPWR_LMT_MKK},		/* 0x27, RTW_CHPLAN_MKK1_MKK1 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_KCC1,		TXPWR_LMT_ETSI},	/* 0x28, RTW_CHPLAN_WORLD_KCC1 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC2,		TXPWR_LMT_FCC},		/* 0x29, RTW_CHPLAN_WORLD_FCC2 */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x2A, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x2B, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x2C, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x2D, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x2E, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x2F, */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC3,		TXPWR_LMT_FCC},		/* 0x30, RTW_CHPLAN_WORLD_FCC3 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC4,		TXPWR_LMT_FCC},		/* 0x31, RTW_CHPLAN_WORLD_FCC4 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC5,		TXPWR_LMT_FCC},		/* 0x32, RTW_CHPLAN_WORLD_FCC5 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_FCC6,		TXPWR_LMT_FCC},		/* 0x33, RTW_CHPLAN_WORLD_FCC6 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC7,		TXPWR_LMT_FCC},		/* 0x34, RTW_CHPLAN_FCC1_FCC7 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI2,	TXPWR_LMT_ETSI},	/* 0x35, RTW_CHPLAN_WORLD_ETSI2 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI3,	TXPWR_LMT_ETSI},	/* 0x36, RTW_CHPLAN_WORLD_ETSI3 */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_MKK2,		TXPWR_LMT_MKK},		/* 0x37, RTW_CHPLAN_MKK1_MKK2 */
+	{RTW_RD_2G_MKK1,	RTW_RD_5G_MKK3,		TXPWR_LMT_MKK},		/* 0x38, RTW_CHPLAN_MKK1_MKK3 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_NCC1,		TXPWR_LMT_FCC},		/* 0x39, RTW_CHPLAN_FCC1_NCC1 */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x3A, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x3B, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x3C, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x3D, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x3E, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x3F, */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_NCC2,		TXPWR_LMT_FCC},		/* 0x40, RTW_CHPLAN_FCC1_NCC2 */
+	{RTW_RD_2G_GLOBAL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x41, RTW_CHPLAN_GLOBAL_NULL */
+	{RTW_RD_2G_ETSI1,	RTW_RD_5G_ETSI4,	TXPWR_LMT_ETSI},	/* 0x42, RTW_CHPLAN_ETSI1_ETSI4 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC2,		TXPWR_LMT_FCC},		/* 0x43, RTW_CHPLAN_FCC1_FCC2 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_NCC3,		TXPWR_LMT_FCC},		/* 0x44, RTW_CHPLAN_FCC1_NCC3 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI5,	TXPWR_LMT_ETSI},	/* 0x45, RTW_CHPLAN_WORLD_ETSI5 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC8,		TXPWR_LMT_FCC},		/* 0x46, RTW_CHPLAN_FCC1_FCC8 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI6,	TXPWR_LMT_ETSI},	/* 0x47, RTW_CHPLAN_WORLD_ETSI6 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI7,	TXPWR_LMT_ETSI},	/* 0x48, RTW_CHPLAN_WORLD_ETSI7 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI8,	TXPWR_LMT_ETSI},	/* 0x49, RTW_CHPLAN_WORLD_ETSI8 */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x4A, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x4B, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x4C, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x4D, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x4E, */
+	{RTW_RD_2G_NULL,	RTW_RD_5G_NULL,		TXPWR_LMT_WW},		/* 0x4F, */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI9,	TXPWR_LMT_ETSI},	/* 0x50, RTW_CHPLAN_WORLD_ETSI9 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI10,	TXPWR_LMT_ETSI},	/* 0x51, RTW_CHPLAN_WORLD_ETSI10 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI11,	TXPWR_LMT_ETSI},	/* 0x52, RTW_CHPLAN_WORLD_ETSI11 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_NCC4,		TXPWR_LMT_FCC},		/* 0x53, RTW_CHPLAN_FCC1_NCC4 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI12,	TXPWR_LMT_ETSI},	/* 0x54, RTW_CHPLAN_WORLD_ETSI12 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC9,		TXPWR_LMT_FCC},		/* 0x55, RTW_CHPLAN_FCC1_FCC9 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI13,	TXPWR_LMT_ETSI},	/* 0x56, RTW_CHPLAN_WORLD_ETSI13 */
+	{RTW_RD_2G_FCC1,	RTW_RD_5G_FCC10,	TXPWR_LMT_FCC},		/* 0x57, RTW_CHPLAN_FCC1_FCC10 */
+	{RTW_RD_2G_MKK2,	RTW_RD_5G_MKK4,		TXPWR_LMT_MKK},		/* 0x58, RTW_CHPLAN_MKK2_MKK4 */
+	{RTW_RD_2G_WORLD,	RTW_RD_5G_ETSI14,	TXPWR_LMT_ETSI},	/* 0x59, RTW_CHPLAN_WORLD_ETSI14 */
+};
+
+static RT_CHANNEL_PLAN_MAP RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE = {
+	RTW_RD_2G_WORLD,	RTW_RD_5G_FCC1,		TXPWR_LMT_FCC		/* 0x7F, Realtek Define */
+};
+
+bool rtw_chplan_is_empty(u8 id)
+{
+	RT_CHANNEL_PLAN_MAP *chplan_map;
+
+	if (!rtw_is_channel_plan_valid(id)) {
+		rtw_warn_on(1);
+		return _FALSE;
+	}
+
+	if (id == RTW_CHPLAN_REALTEK_DEFINE)
+		chplan_map = &RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE;
+	else
+		chplan_map = &RTW_ChannelPlanMap[id];
+
+	if (chplan_map->Index2G == RTW_RD_2G_NULL
+		&& chplan_map->Index5G == RTW_RD_5G_NULL)
+		return _TRUE;
+
+	return _FALSE;
+}
+
+#ifdef CONFIG_DFS_MASTER
+void rtw_rfctl_reset_cac(struct rf_ctl_t *rfctl)
+{
+	if (rtw_is_long_cac_ch(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset))
+		rfctl->cac_end_time = rtw_get_current_time() + rtw_ms_to_systime(CAC_TIME_CE_MS);
+	else
+		rfctl->cac_end_time = rtw_get_current_time() + rtw_ms_to_systime(CAC_TIME_MS);
+}
+
+/*
+* check if channel coverage includes new range and the new range is in DFS range
+* called after radar_detect_ch,bw,offset is updated
+*/
+bool rtw_is_cac_reset_needed(_adapter *adapter)
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
+	bool needed = _FALSE;
+	u32 pre_hi, pre_lo, hi, lo;
+
+	if (0)
+		DBG_871X("pre_radar_detect_ch:%d, pre_radar_detect_by_sta_link:%d\n"
+			, rfctl->pre_radar_detect_ch, rfctl->pre_radar_detect_by_sta_link);
+
+	if (rfctl->pre_radar_detect_by_sta_link == _TRUE)
+		goto exit;
+
+	if (rfctl->pre_radar_detect_ch == 0) {
+		needed = _TRUE;
+		goto exit;
+	}
+
+	if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch, rfctl->radar_detect_bw, rfctl->radar_detect_offset, &hi, &lo) == _FALSE)
+		rtw_warn_on(1);
+	if (rtw_chbw_to_freq_range(rfctl->pre_radar_detect_ch, rfctl->pre_radar_detect_bw, rfctl->pre_radar_detect_offset, &pre_hi, &pre_lo) == _FALSE)
+		rtw_warn_on(1);
+
+	if (!rtw_is_range_a_in_b(hi, lo, pre_hi, pre_lo)) {
+		if (rtw_is_range_a_in_b(pre_hi, pre_lo, hi, lo)) {
+			/* currrent is supper set of previous */
+			if (rtw_is_dfs_range(hi, lo))
+				needed = _TRUE;
+		} else if (rtw_is_range_overlap(hi, lo, pre_hi, pre_lo)) {
+			/* currrent is not supper set of previous, but has overlap */
+			u32 new_hi, new_lo;
+
+			if (lo < pre_lo) {
+				new_hi = pre_lo;
+				new_lo = lo;
+				if (hi <= pre_lo || hi >= pre_hi) {
+					DBG_871X_LEVEL(_drv_err_, "hi:%u, lo:%u, pre_hi:%u, pre_lo:%u\n"
+						, hi, lo, pre_hi, pre_lo);
+					rtw_warn_on(1);
+					goto exit;
+				}
+			} else if (hi > pre_hi) {
+				new_hi = hi;
+				new_lo = pre_hi;
+				if (lo >= pre_hi && lo <= pre_lo) {
+					DBG_871X_LEVEL(_drv_err_, "hi:%u, lo:%u, pre_hi:%u, pre_lo:%u\n"
+						, hi, lo, pre_hi, pre_lo);
+					rtw_warn_on(1);
+					goto exit;
+				}
+			} else {
+				DBG_871X_LEVEL(_drv_err_, "hi:%u, lo:%u, pre_hi:%u, pre_lo:%u\n"
+					, hi, lo, pre_hi, pre_lo);
+				rtw_warn_on(1);
+				goto exit;
+			}
+
+			if (rtw_is_dfs_range(new_hi, new_lo))
+				needed = _TRUE;
+			
+		} else {
+			/* no overlap */
+			if (rtw_is_dfs_range(hi, lo))
+				needed = _TRUE;
+		}
+	}
+
+exit:
+	return needed;
+}
+
+bool _rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl, u8 ch, u8 bw, u8 offset)
+{
+	bool ret = _FALSE;
+	u32 hi = 0, lo = 0;
+	u32 r_hi = 0, r_lo = 0;
+	int i;
+
+	if (rfctl->radar_detect_ch == 0)
+		goto exit;
+
+	if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (rtw_chbw_to_freq_range(rfctl->radar_detect_ch
+			, rfctl->radar_detect_bw, rfctl->radar_detect_offset
+			, &r_hi, &r_lo) == _FALSE) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (rtw_is_range_overlap(hi, lo, r_hi, r_lo))
+		ret = _TRUE;
+
+exit:
+	return ret;
+}
+
+bool rtw_rfctl_overlap_radar_detect_ch(struct rf_ctl_t *rfctl)
+{
+	return _rtw_rfctl_overlap_radar_detect_ch(rfctl
+				, rfctl_to_dvobj(rfctl)->oper_channel
+				, rfctl_to_dvobj(rfctl)->oper_bwmode
+				, rfctl_to_dvobj(rfctl)->oper_ch_offset);
+}
+
+bool rtw_rfctl_is_tx_blocked_by_cac(struct rf_ctl_t *rfctl)
+{
+	return (rtw_rfctl_overlap_radar_detect_ch(rfctl) && IS_UNDER_CAC(rfctl));
+}
+
+bool rtw_chset_is_ch_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)
+{
+	bool ret = _FALSE;
+	u32 hi = 0, lo = 0;
+	int i;
+
+	if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
+		goto exit;
+
+	for (i = 0; ch_set[i].ChannelNum != 0; i++) {
+		if (!rtw_ch2freq(ch_set[i].ChannelNum)) {
+			rtw_warn_on(1);
+			continue;
+		}
+
+		if (!CH_IS_NON_OCP(&ch_set[i]))
+			continue;
+
+		if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)
+			&& rtw_ch2freq(ch_set[i].ChannelNum) <= hi
+		) {
+			ret = _TRUE;
+			break;
+		}
+	}
+
+exit:
+	return ret;
+}
+
+/**
+ * rtw_chset_update_non_ocp - update non_ocp_end_time according to the given @ch, @bw, @offset into @ch_set
+ * @ch_set: the given channel set
+ * @ch: channel number on which radar is detected
+ * @bw: bandwidth on which radar is detected
+ * @offset: bandwidth offset on which radar is detected
+ * @ms: ms to add from now to update non_ocp_end_time, ms < 0 means use NON_OCP_TIME_MS
+ */
+static void _rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms)
+{
+	u32 hi = 0, lo = 0;
+	int i;
+
+	if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
+		goto exit;
+
+	for (i = 0; ch_set[i].ChannelNum != 0; i++) {
+		if (!rtw_ch2freq(ch_set[i].ChannelNum)) {
+			rtw_warn_on(1);
+			continue;
+		}
+
+		if (lo <= rtw_ch2freq(ch_set[i].ChannelNum)
+			&& rtw_ch2freq(ch_set[i].ChannelNum) <= hi
+		) {
+			if (ms >= 0)
+				ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
+			else
+				ch_set[i].non_ocp_end_time = rtw_get_current_time() + rtw_ms_to_systime(NON_OCP_TIME_MS);
+		}
+	}	
+
+exit:
+	return;
+}
+
+inline void rtw_chset_update_non_ocp(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset)
+{
+	_rtw_chset_update_non_ocp(ch_set, ch, bw, offset, -1);
+}
+
+inline void rtw_chset_update_non_ocp_ms(RT_CHANNEL_INFO *ch_set, u8 ch, u8 bw, u8 offset, int ms)
+{
+	_rtw_chset_update_non_ocp(ch_set, ch, bw, offset, ms);
+}
+#endif /* CONFIG_DFS_MASTER */
+
+bool rtw_choose_available_chbw(_adapter *adapter, u8 req_bw, u8 *dec_ch, u8 *dec_bw, u8 *dec_offset, u8 d_flags)
+{
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	int i;
+
+	if (!dec_ch || !dec_bw || !dec_offset) {
+		rtw_warn_on(1);
+		return _FAIL;
+	}
+
+	for (i = 0; i < mlmeext->max_chan_nums; i++) {
+
+		*dec_ch = mlmeext->channel_set[i].ChannelNum;
+		*dec_bw = req_bw;
+		if (*dec_bw == CHANNEL_WIDTH_20)
+			*dec_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		else
+			*dec_offset = rtw_get_offset_by_ch(*dec_ch);
+
+		if ((d_flags & RTW_CHF_2G) && *dec_ch <= 14)
+			continue;
+
+		if ((d_flags & RTW_CHF_5G)  && *dec_ch > 14)
+			continue;
+
+		rtw_adjust_chbw(adapter, *dec_ch, dec_bw, dec_offset);
+
+		if ((d_flags & RTW_CHF_DFS) && rtw_is_dfs_ch(*dec_ch, *dec_bw, *dec_offset))
+			continue;
+
+		if ((d_flags & RTW_CHF_LONG_CAC) && rtw_is_long_cac_ch(*dec_ch, *dec_bw, *dec_offset))
+			continue;
+
+		if ((d_flags & RTW_CHF_NON_DFS) && !rtw_is_dfs_ch(*dec_ch, *dec_bw, *dec_offset))
+			continue;
+
+		if ((d_flags & RTW_CHF_NON_LONG_CAC) && !rtw_is_long_cac_ch(*dec_ch, *dec_bw, *dec_offset))
+			continue;
+
+		if (!rtw_chset_is_ch_non_ocp(mlmeext->channel_set, *dec_ch, *dec_bw, *dec_offset))
+			break;
+	}
+
+	return (i < mlmeext->max_chan_nums)?_TRUE:_FALSE;
+}
+
+void dump_chplan_id_list(void *sel)
+{
+	int i;
+
+	for (i = 0; i < RTW_CHPLAN_MAX; i++) {
+		if (rtw_chplan_is_empty(i))
+			continue;
+
+		DBG_871X_SEL(sel, "0x%02X ", i);
+	}
+
+	DBG_871X_SEL_NL(sel, "0x7F\n");
+}
+
+void dump_chplan_test(void *sel)
+{
+	int i, j;
+
+	/* check invalid channel */
+	for (i = 0; i < RTW_RD_2G_MAX; i++) {
+		for (j = 0; j < RTW_ChannelPlan2G[i].Len; j++) {
+			if (rtw_ch2freq(RTW_ChannelPlan2G[i].Channel[j]) == 0)
+				DBG_871X_SEL_NL(sel, "invalid ch:%u at (%d,%d)\n", RTW_ChannelPlan2G[i].Channel[j], i, j);
+		}
+	}
+
+	for (i = 0; i < RTW_RD_5G_MAX; i++) {
+		for (j = 0; j < RTW_ChannelPlan5G[i].Len; j++) {
+			if (rtw_ch2freq(RTW_ChannelPlan5G[i].Channel[j]) == 0)
+				DBG_871X_SEL_NL(sel, "invalid ch:%u at (%d,%d)\n", RTW_ChannelPlan5G[i].Channel[j], i, j);
+		}
+	}
+}
+
+void dump_chset(void *sel, RT_CHANNEL_INFO *ch_set)
+{
+	u8	i;
+
+	for (i = 0; ch_set[i].ChannelNum != 0; i++) {
+		DBG_871X_SEL_NL(sel, "ch:%3u, freq:%u, scan_type:%d"
+			, ch_set[i].ChannelNum, rtw_ch2freq(ch_set[i].ChannelNum), ch_set[i].ScanType);
+	
+		#ifdef CONFIG_FIND_BEST_CHANNEL
+		DBG_871X_SEL(sel, ", rx_count:%u", ch_set[i].rx_count);
+		#endif
+		
+		#ifdef CONFIG_DFS_MASTER
+		if (rtw_is_dfs_ch(ch_set[i].ChannelNum, CHANNEL_WIDTH_20, HAL_PRIME_CHNL_OFFSET_DONT_CARE)) {
+			if (CH_IS_NON_OCP(&ch_set[i]))
+				DBG_871X_SEL(sel, ", non_ocp:%d"
+					, rtw_systime_to_ms(ch_set[i].non_ocp_end_time - rtw_get_current_time()));
+			else
+				DBG_871X_SEL(sel, ", non_ocp:N/A");
+		}
+		#endif
+
+		DBG_871X_SEL(sel, "\n");
+	}
+
+	DBG_871X_SEL_NL(sel, "total ch number:%d\n", i);
+}
+
+void dump_cur_chset(void *sel, _adapter *adapter)
+{
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+
+	DBG_871X_SEL_NL(sel, "Channel plan ID:0x%02X, 2G_PLS:%u, 5G_PLS:%u\n"
+			, mlme->ChannelPlan, hal_data->Regulation2_4G, hal_data->Regulation5G);
+	dump_chset(sel, mlmeext->channel_set);
+}
+
+/*
+ * Search the @param ch in given @param ch_set
+ * @ch_set: the given channel set
+ * @ch: the given channel number
+ * 
+ * return the index of channel_num in channel_set, -1 if not found
+ */
+int rtw_ch_set_search_ch(RT_CHANNEL_INFO *ch_set, const u32 ch)
+{
+	int i;
+	for(i=0;ch_set[i].ChannelNum!=0;i++){
+		if(ch == ch_set[i].ChannelNum)
+			break;
+	}
+	
+	if(i >= ch_set[i].ChannelNum)
+		return -1;
+	return i;
+}
+
+/*
+ * Check the @param ch is fit with setband setting of @param adapter
+ * @adapter: the given adapter
+ * @ch: the given channel number
+ * 
+ * return _TRUE when check valid, _FALSE not valid
+ */
+bool rtw_mlme_band_check(_adapter *adapter, const u32 ch)
+{
+	if (adapter->setband == WIFI_FREQUENCY_BAND_AUTO /* 2.4G and 5G */
+		|| (adapter->setband == WIFI_FREQUENCY_BAND_2GHZ && ch < 35) /* 2.4G only */
+		|| (adapter->setband == WIFI_FREQUENCY_BAND_5GHZ && ch > 35) /* 5G only */
+	) {
+		return _TRUE;
+	}
+	return _FALSE;
+}
+
+/****************************************************************************
+
+Following are the initialization functions for WiFi MLME
+
+*****************************************************************************/
+
+int init_hw_mlme_ext(_adapter *padapter)
+{
+	struct	mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	//set_opmode_cmd(padapter, infra_client_with_mlme);//removed
+
+	set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+	return _SUCCESS;
+}
+
+void init_mlme_default_rate_set(_adapter* padapter)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	unsigned char	mixed_datarate[NumRates] = {_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_,_9M_RATE_, _12M_RATE_, _18M_RATE_, _24M_RATE_, _36M_RATE_, _48M_RATE_, _54M_RATE_, 0xff};
+	unsigned char	mixed_basicrate[NumRates] ={_1M_RATE_, _2M_RATE_, _5M_RATE_, _11M_RATE_, _6M_RATE_, _12M_RATE_, _24M_RATE_, 0xff,};
+	unsigned char	supported_mcs_set[16] = {0xff, 0xff, 0xff, 0x00, 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+
+	_rtw_memcpy(pmlmeext->datarate, mixed_datarate, NumRates);
+	_rtw_memcpy(pmlmeext->basicrate, mixed_basicrate, NumRates);
+
+	_rtw_memcpy(pmlmeext->default_supported_mcs_set, supported_mcs_set, sizeof(pmlmeext->default_supported_mcs_set));
+}
+
+static void init_mlme_ext_priv_value(_adapter* padapter)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	ATOMIC_SET(&pmlmeext->event_seq, 0);
+	pmlmeext->mgnt_seq = 0;//reset to zero when disconnect at client mode
+#ifdef CONFIG_IEEE80211W
+	pmlmeext->sa_query_seq = 0;
+	pmlmeext->mgnt_80211w_IPN=0;
+	pmlmeext->mgnt_80211w_IPN_rx=0;
+#endif //CONFIG_IEEE80211W
+	pmlmeext->cur_channel = padapter->registrypriv.channel;
+	pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
+	pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	
+	pmlmeext->retry = 0;
+
+	pmlmeext->cur_wireless_mode = padapter->registrypriv.wireless_mode;
+
+	init_mlme_default_rate_set(padapter);
+
+	if(pmlmeext->cur_channel > 14)
+		pmlmeext->tx_rate = IEEE80211_OFDM_RATE_6MB;
+	else
+		pmlmeext->tx_rate = IEEE80211_CCK_RATE_1MB;
+
+	mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
+	pmlmeext->sitesurvey_res.channel_idx = 0;
+	pmlmeext->sitesurvey_res.bss_cnt = 0;
+	pmlmeext->sitesurvey_res.scan_ch_ms = SURVEY_TO;
+	pmlmeext->sitesurvey_res.rx_ampdu_accept = RX_AMPDU_ACCEPT_INVALID;
+	pmlmeext->sitesurvey_res.rx_ampdu_size = RX_AMPDU_SIZE_INVALID;
+	#ifdef CONFIG_SCAN_BACKOP
+	mlmeext_assign_scan_backop_flags_sta(pmlmeext, /*SS_BACKOP_EN|*/SS_BACKOP_PS_ANNC|SS_BACKOP_TX_RESUME);
+	mlmeext_assign_scan_backop_flags_ap(pmlmeext, SS_BACKOP_EN|SS_BACKOP_PS_ANNC|SS_BACKOP_TX_RESUME);
+	pmlmeext->sitesurvey_res.scan_cnt = 0;
+	pmlmeext->sitesurvey_res.scan_cnt_max = RTW_SCAN_NUM_OF_CH;
+	pmlmeext->sitesurvey_res.backop_ms = RTW_BACK_OP_CH_MS;
+	#endif
+	#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
+	pmlmeext->sitesurvey_res.is_sw_antdiv_bl_scan = 0;
+	#endif
+	pmlmeext->scan_abort = _FALSE;
+
+	pmlmeinfo->state = WIFI_FW_NULL_STATE;
+	pmlmeinfo->reauth_count = 0;
+	pmlmeinfo->reassoc_count = 0;
+	pmlmeinfo->link_count = 0;
+	pmlmeinfo->auth_seq = 0;
+	pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
+	pmlmeinfo->key_index = 0;
+	pmlmeinfo->iv = 0;
+
+	pmlmeinfo->enc_algo = _NO_PRIVACY_;
+	pmlmeinfo->authModeToggle = 0;
+
+	_rtw_memset(pmlmeinfo->chg_txt, 0, 128);
+
+	pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+	pmlmeinfo->preamble_mode = PREAMBLE_AUTO;
+
+	pmlmeinfo->dialogToken = 0;
+
+	pmlmeext->action_public_rxseq = 0xffff;
+	pmlmeext->action_public_dialog_token = 0xff;
+}
+
+static int has_channel(RT_CHANNEL_INFO *channel_set,
+					   u8 chanset_size,
+					   u8 chan) {
+	int i;
+
+	for (i = 0; i < chanset_size; i++) {
+		if (channel_set[i].ChannelNum == chan) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+static void init_channel_list(_adapter *padapter, RT_CHANNEL_INFO *channel_set,
+							  u8 chanset_size,
+							  struct p2p_channels *channel_list) {
+	struct registry_priv *regsty = adapter_to_regsty(padapter);
+
+	struct p2p_oper_class_map op_class[] = {
+		{ IEEE80211G,  81,   1,  13,  1, BW20 },
+		{ IEEE80211G,  82,  14,  14,  1, BW20 },
+#if 0 /* Do not enable HT40 on 2 GHz */
+		{ IEEE80211G,  83,   1,   9,  1, BW40PLUS },
+		{ IEEE80211G,  84,   5,  13,  1, BW40MINUS },
+#endif
+		{ IEEE80211A, 115,  36,  48,  4, BW20 },
+		{ IEEE80211A, 116,  36,  44,  8, BW40PLUS },
+		{ IEEE80211A, 117,  40,  48,  8, BW40MINUS },
+		{ IEEE80211A, 124, 149, 161,  4, BW20 },
+		{ IEEE80211A, 125, 149, 169,  4, BW20 },
+		{ IEEE80211A, 126, 149, 157,  8, BW40PLUS },
+		{ IEEE80211A, 127, 153, 161,  8, BW40MINUS },
+		{ -1, 0, 0, 0, 0, BW20 }
+	};
+
+	int cla, op;
+
+	cla = 0;
+
+	for (op = 0; op_class[op].op_class; op++) {
+		u8 ch;
+		struct p2p_oper_class_map *o = &op_class[op];
+		struct p2p_reg_class *reg = NULL;
+
+		for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
+			if (!has_channel(channel_set, chanset_size, ch)) {
+				continue;
+			}
+
+			if ((0 == padapter->registrypriv.ht_enable) && (8 == o->inc))
+				continue;
+
+			if ((REGSTY_IS_BW_5G_SUPPORT(regsty, CHANNEL_WIDTH_40)) &&
+				((BW40MINUS == o->bw) || (BW40PLUS == o->bw)))
+				continue;
+
+			if (reg == NULL) {
+				reg = &channel_list->reg_class[cla];
+				cla++;
+				reg->reg_class = o->op_class;
+				reg->channels = 0;
+			}
+			reg->channel[reg->channels] = ch;
+			reg->channels++;
+		}
+	}
+	channel_list->reg_classes = cla;
+
+}
+
+static u8 init_channel_set(_adapter* padapter, u8 ChannelPlan, RT_CHANNEL_INFO *channel_set)
+{
+	u8	index,chanset_size = 0;
+	u8	b5GBand = _FALSE, b2_4GBand = _FALSE;
+	u8	Index2G = 0, Index5G=0;
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
+
+	if (!rtw_is_channel_plan_valid(ChannelPlan)) {
+		DBG_871X("ChannelPlan ID %x error !!!!!\n",ChannelPlan);
+		return chanset_size;
+	}
+
+	_rtw_memset(channel_set, 0, sizeof(RT_CHANNEL_INFO)*MAX_CHANNEL_NUM);
+
+	if (IsSupported24G(padapter->registrypriv.wireless_mode))
+		b2_4GBand = _TRUE;
+
+	if (IsSupported5G(padapter->registrypriv.wireless_mode))
+		b5GBand = _TRUE;
+
+	if (b2_4GBand) {
+		if (RTW_CHPLAN_REALTEK_DEFINE == ChannelPlan)
+			Index2G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index2G;
+		else
+			Index2G = RTW_ChannelPlanMap[ChannelPlan].Index2G;
+
+		for (index = 0; index < RTW_ChannelPlan2G[Index2G].Len; index++) {
+			channel_set[chanset_size].ChannelNum = RTW_ChannelPlan2G[Index2G].Channel[index];
+
+			if (RTW_CHPLAN_GLOBAL_DOAMIN == ChannelPlan
+				|| RTW_CHPLAN_GLOBAL_NULL == ChannelPlan
+			) {
+				/* Channel 1~11 is active, and 12~14 is passive */
+				if(channel_set[chanset_size].ChannelNum >= 1 && channel_set[chanset_size].ChannelNum <= 11)
+					channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+				else if((channel_set[chanset_size].ChannelNum  >= 12 && channel_set[chanset_size].ChannelNum  <= 14))
+					channel_set[chanset_size].ScanType  = SCAN_PASSIVE;			
+			} else if (RTW_CHPLAN_WORLD_WIDE_13 == ChannelPlan
+				|| RTW_CHPLAN_WORLD_WIDE_5G == ChannelPlan
+				|| RTW_RD_2G_WORLD == Index2G
+			) {
+				/* channel 12~13, passive scan */
+				if(channel_set[chanset_size].ChannelNum <= 11)
+					channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+				else
+					channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+			} else {
+				channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+			}
+
+			chanset_size++;
+		}
+	}
+
+	if (b5GBand) {
+		if (RTW_CHPLAN_REALTEK_DEFINE == ChannelPlan)
+			Index5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.Index5G;
+		else
+			Index5G = RTW_ChannelPlanMap[ChannelPlan].Index5G;
+
+		for (index = 0; index < RTW_ChannelPlan5G[Index5G].Len; index++) {
+#ifdef CONFIG_DFS
+			channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
+			if ( channel_set[chanset_size].ChannelNum <= 48 
+				|| channel_set[chanset_size].ChannelNum >= 149 )
+			{
+				if (RTW_CHPLAN_WORLD_WIDE_5G == ChannelPlan) /* passive scan for all 5G channels */
+					channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+				else
+					channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+			}
+			else
+			{
+				channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+			}
+			chanset_size++;
+#else /* CONFIG_DFS */
+			if (RTW_ChannelPlan5G[Index5G].Channel[index] <= 48
+				|| RTW_ChannelPlan5G[Index5G].Channel[index] >= 149
+			) {
+				channel_set[chanset_size].ChannelNum = RTW_ChannelPlan5G[Index5G].Channel[index];
+				if (RTW_CHPLAN_WORLD_WIDE_5G == ChannelPlan) /* passive scan for all 5G channels */
+					channel_set[chanset_size].ScanType = SCAN_PASSIVE;
+				else
+					channel_set[chanset_size].ScanType = SCAN_ACTIVE;
+				DBG_871X("%s(): channel_set[%d].ChannelNum = %d\n", __FUNCTION__, chanset_size, channel_set[chanset_size].ChannelNum);
+				chanset_size++;
+			}
+#endif /* CONFIG_DFS */
+		}
+	}
+
+	if (RTW_CHPLAN_REALTEK_DEFINE == ChannelPlan) {
+		hal_data->Regulation2_4G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.regd;
+		hal_data->Regulation5G = RTW_CHANNEL_PLAN_MAP_REALTEK_DEFINE.regd;
+	} else {
+		hal_data->Regulation2_4G = RTW_ChannelPlanMap[ChannelPlan].regd;
+		hal_data->Regulation5G = RTW_ChannelPlanMap[ChannelPlan].regd;
+	}
+
+	DBG_871X(FUNC_ADPT_FMT" ChannelPlan ID:0x%02x, ch num:%d\n"
+		, FUNC_ADPT_ARG(padapter), ChannelPlan, chanset_size);
+
+	return chanset_size;
+}
+
+int	init_mlme_ext_priv(_adapter* padapter)
+{
+	int	res = _SUCCESS;
+	struct registry_priv* pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	// We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
+	//_rtw_memset((u8 *)pmlmeext, 0, sizeof(struct mlme_ext_priv));
+
+	pmlmeext->padapter = padapter;
+
+	//fill_fwpriv(padapter, &(pmlmeext->fwpriv));
+
+	init_mlme_ext_priv_value(padapter);
+	pmlmeinfo->bAcceptAddbaReq = pregistrypriv->bAcceptAddbaReq;
+	
+	init_mlme_ext_timer(padapter);
+
+#ifdef CONFIG_AP_MODE
+	init_mlme_ap_info(padapter);	
+#endif
+
+	pmlmeext->max_chan_nums = init_channel_set(padapter, pmlmepriv->ChannelPlan,pmlmeext->channel_set);
+	init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);
+	pmlmeext->last_scan_time = 0;
+	pmlmeext->mlmeext_init = _TRUE;
+
+
+#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK	
+	pmlmeext->active_keep_alive_check = _TRUE;
+#else
+	pmlmeext->active_keep_alive_check = _FALSE;
+#endif
+
+#ifdef DBG_FIXED_CHAN		
+	pmlmeext->fixed_chan = 0xFF;	
+#endif
+
+	return res;
+
+}
+
+void free_mlme_ext_priv (struct mlme_ext_priv *pmlmeext)
+{
+	_adapter *padapter = pmlmeext->padapter;
+
+	if (!padapter)
+		return;
+
+	if (rtw_is_drv_stopped(padapter)) {
+		_cancel_timer_ex(&pmlmeext->survey_timer);
+		_cancel_timer_ex(&pmlmeext->link_timer);
+		//_cancel_timer_ex(&pmlmeext->ADDBA_timer);
+	}
+}
+
+static u8 cmp_pkt_chnl_diff(_adapter *padapter,u8* pframe,uint packet_len)
+{	// if the channel is same, return 0. else return channel differential	
+	uint len;
+	u8 channel;	
+	u8 *p;		
+	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_, _DSSET_IE_, &len, packet_len - _BEACON_IE_OFFSET_);	
+	if (p)	
+	{	
+		channel = *(p + 2);		
+		if(padapter->mlmeextpriv.cur_channel >= channel)		
+		{			
+			return (padapter->mlmeextpriv.cur_channel - channel);		
+		}		
+		else		
+		{			
+			return (channel-padapter->mlmeextpriv.cur_channel);		
+		}	
+	}	
+	else
+	{		
+		return 0;	
+	}
+}
+
+static void _mgt_dispatcher(_adapter *padapter, struct mlme_handler *ptable, union recv_frame *precv_frame)
+{
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 *pframe = precv_frame->u.hdr.rx_data; 
+
+	  if(ptable->func)
+        {
+       	 //receive the frames that ra(a1) is my address or ra(a1) is bc address.
+		if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) &&
+			!_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN)) 
+		{
+			return;
+		}
+		
+		ptable->func(padapter, precv_frame);
+        }
+	
+}
+
+void mgt_dispatcher(_adapter *padapter, union recv_frame *precv_frame)
+{
+	int index;
+	struct mlme_handler *ptable;
+#ifdef CONFIG_AP_MODE
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#endif //CONFIG_AP_MODE
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(pframe));
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+
+	RT_TRACE(_module_rtl871x_mlme_c_, _drv_info_,
+		 ("+mgt_dispatcher: type(0x%x) subtype(0x%x)\n",
+		  GetFrameType(pframe), GetFrameSubType(pframe)));
+
+#if 0
+	{
+		u8 *pbuf;
+		pbuf = GetAddr1Ptr(pframe);
+		DBG_871X("A1-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5));
+		pbuf = GetAddr2Ptr(pframe);
+		DBG_871X("A2-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5));
+		pbuf = GetAddr3Ptr(pframe);
+		DBG_871X("A3-%x:%x:%x:%x:%x:%x\n", *pbuf, *(pbuf+1), *(pbuf+2), *(pbuf+3), *(pbuf+4), *(pbuf+5));
+	}
+#endif
+
+	if (GetFrameType(pframe) != WIFI_MGT_TYPE)
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_err_, ("mgt_dispatcher: type(0x%x) error!\n", GetFrameType(pframe)));
+		return;
+	}
+
+	//receive the frames that ra(a1) is my address or ra(a1) is bc address.
+	if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN) &&
+		!_rtw_memcmp(GetAddr1Ptr(pframe), bc_addr, ETH_ALEN))
+	{
+		return;
+	}
+
+	ptable = mlme_sta_tbl;
+
+	index = GetFrameSubType(pframe) >> 4;
+
+#ifdef CONFIG_TDLS
+	if((index << 4)==WIFI_ACTION){
+		/* category==public (4), action==TDLS_DISCOVERY_RESPONSE */
+		if (*(pframe+24) == RTW_WLAN_CATEGORY_PUBLIC && *(pframe+25) == TDLS_DISCOVERY_RESPONSE) {
+			DBG_871X("[TDLS] Recv %s from "MAC_FMT"\n", rtw_tdls_action_txt(TDLS_DISCOVERY_RESPONSE), MAC_ARG(GetAddr2Ptr(pframe)));
+			On_TDLS_Dis_Rsp(padapter, precv_frame);
+		}
+	}
+#endif //CONFIG_TDLS
+
+	if (index >= (sizeof(mlme_sta_tbl) /sizeof(struct mlme_handler)))
+	{
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("Currently we do not support reserved sub-fr-type=%d\n", index));
+		return;
+	}
+	ptable += index;
+
+#if 1
+	if (psta != NULL)
+	{
+		if (GetRetry(pframe))
+		{
+			if (precv_frame->u.hdr.attrib.seq_num == psta->RxMgmtFrameSeqNum)
+			{
+				/* drop the duplicate management frame */
+				pdbgpriv->dbg_rx_dup_mgt_frame_drop_count++;
+				DBG_871X("Drop duplicate management frame with seq_num = %d.\n", precv_frame->u.hdr.attrib.seq_num);
+				return;
+			}
+		}
+		psta->RxMgmtFrameSeqNum = precv_frame->u.hdr.attrib.seq_num;
+	}
+#else
+
+	if(GetRetry(pframe))
+	{
+		//RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("drop due to decache!\n"));
+		//return;
+	}
+#endif
+
+#ifdef CONFIG_AP_MODE
+	switch (GetFrameSubType(pframe)) 
+	{
+		case WIFI_AUTH:
+			if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+				ptable->func = &OnAuth;
+			else
+				ptable->func = &OnAuthClient;
+			//pass through
+		case WIFI_ASSOCREQ:
+		case WIFI_REASSOCREQ:
+			_mgt_dispatcher(padapter, ptable, precv_frame);	
+#ifdef CONFIG_HOSTAPD_MLME				
+			if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+				rtw_hostapd_mlme_rx(padapter, precv_frame);
+#endif			
+			break;
+		case WIFI_PROBEREQ:
+			if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+			{
+#ifdef CONFIG_HOSTAPD_MLME		
+				rtw_hostapd_mlme_rx(padapter, precv_frame);		
+#else
+				_mgt_dispatcher(padapter, ptable, precv_frame);
+#endif
+			}
+			else
+				_mgt_dispatcher(padapter, ptable, precv_frame);
+			break;
+		case WIFI_BEACON:			
+			_mgt_dispatcher(padapter, ptable, precv_frame);
+			break;
+		case WIFI_ACTION:
+			//if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+			_mgt_dispatcher(padapter, ptable, precv_frame);		
+			break;
+		default:
+			_mgt_dispatcher(padapter, ptable, precv_frame);	
+			if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+				rtw_hostapd_mlme_rx(padapter, precv_frame);			
+			break;
+	}
+#else
+
+	_mgt_dispatcher(padapter, ptable, precv_frame);	
+	
+#endif
+
+}
+
+#ifdef CONFIG_P2P
+u32 p2p_listen_state_process(_adapter *padapter, unsigned char *da)
+{
+	bool response = _TRUE;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
+	{
+		if(padapter->cfg80211_wdinfo.is_ro_ch == _FALSE
+			|| rtw_get_oper_ch(padapter) != padapter->wdinfo.listen_channel
+			|| adapter_wdev_data(padapter)->p2p_enabled == _FALSE
+			|| padapter->mlmepriv.wps_probe_resp_ie == NULL
+			|| padapter->mlmepriv.p2p_probe_resp_ie == NULL
+		)
+		{
+#ifdef CONFIG_DEBUG_CFG80211
+			DBG_871X("DON'T issue_probersp_p2p: p2p_enabled:%d, wps_probe_resp_ie:%p, p2p_probe_resp_ie:%p, ",
+				adapter_wdev_data(padapter)->p2p_enabled,
+				padapter->mlmepriv.wps_probe_resp_ie,
+				padapter->mlmepriv.p2p_probe_resp_ie);
+			DBG_871X("is_ro_ch:%d, op_ch:%d, p2p_listen_channel:%d\n", 
+				padapter->cfg80211_wdinfo.is_ro_ch,
+				rtw_get_oper_ch(padapter),
+				padapter->wdinfo.listen_channel);
+#endif
+			response = _FALSE;
+		}
+	}
+	else
+#endif //CONFIG_IOCTL_CFG80211
+	if( padapter->wdinfo.driver_interface == DRIVER_WEXT )
+	{
+		//	do nothing if the device name is empty
+		if ( !padapter->wdinfo.device_name_len )
+		{
+			response	= _FALSE;
+		}
+	}
+
+	if (response == _TRUE)
+		issue_probersp_p2p( padapter, da);
+	
+	return _SUCCESS;
+}
+#endif //CONFIG_P2P
+
+
+/****************************************************************************
+
+Following are the callback functions for each subtype of the management frames
+
+*****************************************************************************/
+
+unsigned int OnProbeReq(_adapter *padapter, union recv_frame *precv_frame)
+{
+	unsigned int	ielen;
+	unsigned char	*p;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 	*cur = &(pmlmeinfo->network);
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint len = precv_frame->u.hdr.len;
+	u8 is_valid_p2p_probereq = _FALSE;
+
+#ifdef CONFIG_ATMEL_RC_PATCH
+	u8 *target_ie=NULL, *wps_ie=NULL;
+	u8 *start;
+	uint search_len = 0, wps_ielen = 0, target_ielen = 0;
+	struct sta_info	*psta;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+#endif
+
+
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	struct rx_pkt_attrib	*pattrib = &precv_frame->u.hdr.attrib;
+	u8 wifi_test_chk_rate = 1;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if ((pwdinfo->driver_interface == DRIVER_CFG80211)
+		&& !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
+		&& (GET_CFG80211_REPORT_MGMT(adapter_wdev_data(padapter), IEEE80211_STYPE_PROBE_REQ) == _TRUE)
+		 ) {
+		rtw_cfg80211_rx_probe_request(padapter, pframe, len);
+		return _SUCCESS;
+	}
+#endif /* CONFIG_IOCTL_CFG80211 */
+
+	if (	!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && 
+		!rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE) && 
+		!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) &&
+		!rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH) &&
+		!rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
+	   )
+	{
+		//	Commented by Albert 2011/03/17
+		//	mcs_rate = 0 -> CCK 1M rate
+		//	mcs_rate = 1 -> CCK 2M rate
+		//	mcs_rate = 2 -> CCK 5.5M rate
+		//	mcs_rate = 3 -> CCK 11M rate
+		//	In the P2P mode, the driver should not support the CCK rate
+
+		//	Commented by Kurt 2012/10/16
+		//	IOT issue: Google Nexus7 use 1M rate to send p2p_probe_req after GO nego completed and Nexus7 is client
+        if (padapter->registrypriv.wifi_spec == 1)
+        {
+            if ( pattrib->data_rate <= 3 )
+            {
+                wifi_test_chk_rate = 0;
+            }
+        }
+
+		if( wifi_test_chk_rate == 1 )
+		{
+			if((is_valid_p2p_probereq = process_probe_req_p2p_ie(pwdinfo, pframe, len)) == _TRUE)
+			{
+				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
+				{
+					// FIXME
+					if( padapter->wdinfo.driver_interface == DRIVER_WEXT )
+						report_survey_event(padapter, precv_frame);
+
+					p2p_listen_state_process( padapter,  get_sa(pframe));
+
+					return _SUCCESS;	
+				}
+
+				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+				{
+					goto _continue;
+				}
+			}
+		}
+	}
+
+_continue:
+#endif //CONFIG_P2P
+
+	if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+	{
+		return _SUCCESS;
+	}
+
+	if(check_fwstate(pmlmepriv, _FW_LINKED) == _FALSE && 
+		check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE)==_FALSE)
+	{
+		return _SUCCESS;
+	}
+
+
+	//DBG_871X("+OnProbeReq\n");
+
+
+#ifdef CONFIG_ATMEL_RC_PATCH
+		if ((wps_ie = rtw_get_wps_ie(
+			pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_,
+			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_,
+			 NULL, &wps_ielen))) {
+		
+			target_ie = rtw_get_wps_attr_content( wps_ie, wps_ielen, WPS_ATTR_MANUFACTURER, NULL, &target_ielen);
+		}
+		if ((target_ie && (target_ielen == 4)) && (_TRUE ==_rtw_memcmp((void *)target_ie, "Ozmo",4 ))) {
+			//psta->flag_atmel_rc = 1;
+			unsigned char *sa_addr = get_sa(pframe);
+			printk("%s: Find Ozmo RC -- %02x:%02x:%02x:%02x:%02x:%02x  \n\n",
+				__func__, *sa_addr, *(sa_addr+1), *(sa_addr+2), *(sa_addr+3), *(sa_addr+4), *(sa_addr+5));
+			_rtw_memcpy(  pstapriv->atmel_rc_pattern, get_sa(pframe), ETH_ALEN);
+		}
+#endif
+
+
+#ifdef CONFIG_AUTO_AP_MODE
+	if(check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE &&
+			pmlmepriv->cur_network.join_res == _TRUE)
+	{
+		_irqL	irqL;
+		struct sta_info	*psta;
+		u8 *mac_addr, *peer_addr;
+		struct sta_priv *pstapriv = &padapter->stapriv;
+		u8 RC_OUI[4]={0x00,0xE0,0x4C,0x0A};
+		//EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2]
+
+		p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _VENDOR_SPECIFIC_IE_, (int *)&ielen,
+			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+		if(!p || ielen !=14)
+			goto _non_rc_device;
+
+		if(!_rtw_memcmp(p+2, RC_OUI, sizeof(RC_OUI)))
+			goto _non_rc_device;
+
+		if(!_rtw_memcmp(p+6, get_sa(pframe), ETH_ALEN))
+		{
+			DBG_871X("%s, do rc pairing ("MAC_FMT"), but mac addr mismatch!("MAC_FMT")\n", __FUNCTION__,
+				MAC_ARG(get_sa(pframe)), MAC_ARG(p+6));
+
+			goto _non_rc_device;
+		}
+
+		DBG_871X("%s, got the pairing device("MAC_FMT")\n", __FUNCTION__,  MAC_ARG(get_sa(pframe)));
+
+		//new a station
+		psta = rtw_get_stainfo(pstapriv, get_sa(pframe));
+		if (psta == NULL)
+		{
+			// allocate a new one
+			DBG_871X("going to alloc stainfo for rc="MAC_FMT"\n",  MAC_ARG(get_sa(pframe)));
+			psta = rtw_alloc_stainfo(pstapriv, get_sa(pframe));
+			if (psta == NULL)
+			{
+				//TODO:
+				DBG_871X(" Exceed the upper limit of supported clients...\n");
+				return _SUCCESS;
+			}
+
+			_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+			if (rtw_is_list_empty(&psta->asoc_list))
+			{
+				psta->expire_to = pstapriv->expire_to;
+				rtw_list_insert_tail(&psta->asoc_list, &pstapriv->asoc_list);
+				pstapriv->asoc_list_cnt++;
+			}
+			_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+			//generate pairing ID
+			mac_addr = adapter_mac_addr(padapter);
+			peer_addr = psta->hwaddr;
+			psta->pid = (u16)(((mac_addr[4]<<8) + mac_addr[5]) + ((peer_addr[4]<<8) + peer_addr[5]));
+
+			//update peer stainfo
+			psta->isrc = _TRUE;
+			//psta->aid = 0;
+			//psta->mac_id = 2;
+
+			/* get a unique AID */
+			if (psta->aid > 0) {
+				DBG_871X("old AID %d\n", psta->aid);
+			} else {
+				for (psta->aid = 1; psta->aid <= NUM_STA; psta->aid++)
+					if (pstapriv->sta_aid[psta->aid - 1] == NULL)
+						break;
+
+				if (psta->aid > pstapriv->max_num_sta) {
+					psta->aid = 0;
+					DBG_871X("no room for more AIDs\n");
+					return _SUCCESS;
+				} else {
+					pstapriv->sta_aid[psta->aid - 1] = psta;
+					DBG_871X("allocate new AID = (%d)\n", psta->aid);
+				}
+			}
+			
+			psta->qos_option = 1;
+			psta->bw_mode = CHANNEL_WIDTH_20;
+			psta->ieee8021x_blocked = _FALSE;
+#ifdef CONFIG_80211N_HT
+			psta->htpriv.ht_option = _TRUE;
+			psta->htpriv.ampdu_enable = _FALSE;
+			psta->htpriv.sgi_20m = _FALSE;
+			psta->htpriv.sgi_40m = _FALSE;
+			psta->htpriv.ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+			psta->htpriv.agg_enable_bitmap = 0x0;//reset
+			psta->htpriv.candidate_tid_bitmap = 0x0;//reset
+#endif
+
+			rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _TRUE);
+
+			_rtw_memset((void*)&psta->sta_stats, 0, sizeof(struct stainfo_stats));
+
+			_enter_critical_bh(&psta->lock, &irqL);
+			psta->state |= _FW_LINKED;
+			_exit_critical_bh(&psta->lock, &irqL);
+
+			report_add_sta_event(padapter, psta->hwaddr, psta->aid);
+
+		}
+
+		issue_probersp(padapter, get_sa(pframe), _FALSE);
+
+		return _SUCCESS;
+
+	}
+
+_non_rc_device:
+
+	return _SUCCESS;
+
+#endif //CONFIG_AUTO_AP_MODE
+	
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
+		check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
+	{
+		//don't process probe req
+		return _SUCCESS;
+	}
+#endif	
+
+	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ielen,
+			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+
+	//check (wildcard) SSID 
+	if (p != NULL)
+	{
+		if(is_valid_p2p_probereq == _TRUE)
+		{
+			goto _issue_probersp;
+		}
+
+		if ( (ielen != 0 && _FALSE ==_rtw_memcmp((void *)(p+2), (void *)cur->Ssid.Ssid, cur->Ssid.SsidLength))
+			|| (ielen == 0 && pmlmeinfo->hidden_ssid_mode)
+		)
+		{
+			return _SUCCESS;
+		}
+
+_issue_probersp:
+		if(((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE && 
+			pmlmepriv->cur_network.join_res == _TRUE)) || check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
+		{
+			//DBG_871X("+issue_probersp during ap mode\n");
+			issue_probersp(padapter, get_sa(pframe), is_valid_p2p_probereq);		
+		}
+
+	}
+
+	return _SUCCESS;
+
+}
+
+unsigned int OnProbeRsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct sta_info		*psta;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	u8	*pframe = precv_frame->u.hdr.rx_data;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
+#endif
+
+
+#ifdef CONFIG_P2P
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
+	{
+		if ( _TRUE == pwdinfo->tx_prov_disc_info.benable )
+		{
+			if( _rtw_memcmp( pwdinfo->tx_prov_disc_info.peerIFAddr, GetAddr2Ptr(pframe), ETH_ALEN ) )
+			{
+				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT))
+				{
+					pwdinfo->tx_prov_disc_info.benable = _FALSE;
+					issue_p2p_provision_request( padapter,
+												pwdinfo->tx_prov_disc_info.ssid.Ssid, 
+												pwdinfo->tx_prov_disc_info.ssid.SsidLength,
+												pwdinfo->tx_prov_disc_info.peerDevAddr );
+				}
+				else if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
+				{
+					pwdinfo->tx_prov_disc_info.benable = _FALSE;
+					issue_p2p_provision_request( padapter,
+												NULL, 
+												0,
+												pwdinfo->tx_prov_disc_info.peerDevAddr );
+				}
+			}		
+		}
+		return _SUCCESS;
+	}
+	else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
+	{
+		if ( _TRUE == pwdinfo->nego_req_info.benable )
+		{
+			DBG_871X( "[%s] P2P State is GONEGO ING!\n", __FUNCTION__ );
+			if( _rtw_memcmp( pwdinfo->nego_req_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN ) )
+			{
+				pwdinfo->nego_req_info.benable = _FALSE;
+				issue_p2p_GO_request( padapter, pwdinfo->nego_req_info.peerDevAddr);
+			}
+		}
+	}
+	else if( rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) )
+	{
+		if ( _TRUE == pwdinfo->invitereq_info.benable )
+		{
+			DBG_871X( "[%s] P2P_STATE_TX_INVITE_REQ!\n", __FUNCTION__ );
+			if( _rtw_memcmp( pwdinfo->invitereq_info.peer_macaddr, GetAddr2Ptr(pframe), ETH_ALEN ) )
+			{
+				pwdinfo->invitereq_info.benable = _FALSE;
+				issue_p2p_invitation_request( padapter, pwdinfo->invitereq_info.peer_macaddr );
+			}
+		}
+	}
+#endif
+
+
+	if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS)) {
+		report_survey_event(padapter, precv_frame);	
+#ifdef CONFIG_CONCURRENT_MODE
+		report_survey_event(padapter->pbuddy_adapter, precv_frame);	
+#endif
+		return _SUCCESS;
+	}
+
+	#if 0 //move to validate_recv_mgnt_frame
+	if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
+	{
+		if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+		{
+			if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
+			{
+				psta->sta_stats.rx_mgnt_pkts++;
+			}
+		}
+	}
+	#endif
+	
+	return _SUCCESS;
+	
+}
+
+unsigned int OnBeacon(_adapter *padapter, union recv_frame *precv_frame)
+{
+	int cam_idx;
+	struct sta_info	*psta;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct sta_priv	*pstapriv = &padapter->stapriv;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint len = precv_frame->u.hdr.len;
+	WLAN_BSSID_EX *pbss;
+	int ret = _SUCCESS;
+	u8 *p = NULL;
+	u32 ielen = 0;
+#ifdef CONFIG_TDLS
+	struct sta_info *ptdls_sta;
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+#endif /* CONFIG_TDLS */
+
+#ifdef CONFIG_ATTEMPT_TO_FIX_AP_BEACON_ERROR
+	p = rtw_get_ie(pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_, _EXT_SUPPORTEDRATES_IE_, &ielen, precv_frame->u.hdr.len -sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_);
+	if ((p != NULL) && (ielen > 0))
+	{
+		if ((*(p + 1 + ielen) == 0x2D) && (*(p + 2 + ielen) != 0x2D))
+		{
+			/* Invalid value 0x2D is detected in Extended Supported Rates (ESR) IE. Try to fix the IE length to avoid failed Beacon parsing. */	
+		       	DBG_871X("[WIFIDBG] Error in ESR IE is detected in Beacon of BSSID:"MAC_FMT". Fix the length of ESR IE to avoid failed Beacon parsing.\n", MAC_ARG(GetAddr3Ptr(pframe)));
+		       	*(p + 1) = ielen - 1;
+		}
+	}
+#endif
+
+	if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS)) {
+		report_survey_event(padapter, precv_frame);
+#ifdef CONFIG_CONCURRENT_MODE
+		report_survey_event(padapter->pbuddy_adapter, precv_frame);	
+#endif
+		return _SUCCESS;
+	}
+
+	if (_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN))
+	{
+		if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
+		{
+			//we should update current network before auth, or some IE is wrong
+			pbss = (WLAN_BSSID_EX*)rtw_malloc(sizeof(WLAN_BSSID_EX));
+			if (pbss) {
+				if (collect_bss_info(padapter, precv_frame, pbss) == _SUCCESS) {
+					struct beacon_keys recv_beacon;
+
+					update_network(&(pmlmepriv->cur_network.network), pbss, padapter, _TRUE);
+					rtw_get_bcn_info(&(pmlmepriv->cur_network));
+
+					// update bcn keys
+					if (rtw_get_bcn_keys(padapter, pframe, len, &recv_beacon) == _TRUE) {
+						DBG_871X("%s: beacon keys ready\n", __func__);
+						_rtw_memcpy(&pmlmepriv->cur_beacon_keys,
+							&recv_beacon, sizeof(recv_beacon));
+						pmlmepriv->new_beacon_cnts = 0;
+					}
+					else {
+						DBG_871X_LEVEL(_drv_err_, "%s: get beacon keys failed\n", __func__);
+						_rtw_memset(&pmlmepriv->cur_beacon_keys, 0, sizeof(recv_beacon));
+						pmlmepriv->new_beacon_cnts = 0;
+					}
+				}
+				rtw_mfree((u8*)pbss, sizeof(WLAN_BSSID_EX));
+			}
+
+			//check the vendor of the assoc AP
+			pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pframe+sizeof(struct rtw_ieee80211_hdr_3addr), len-sizeof(struct rtw_ieee80211_hdr_3addr));				
+
+			//update TSF Value
+			update_TSF(pmlmeext, pframe, len);
+
+			//reset for adaptive_early_32k
+			pmlmeext->adaptive_tsf_done = _FALSE;
+			pmlmeext->DrvBcnEarly = 0xff;
+			pmlmeext->DrvBcnTimeOut = 0xff;
+			pmlmeext->bcn_cnt = 0;
+			_rtw_memset(pmlmeext->bcn_delay_cnt, 0, sizeof(pmlmeext->bcn_delay_cnt));
+			_rtw_memset(pmlmeext->bcn_delay_ratio, 0, sizeof(pmlmeext->bcn_delay_ratio));
+
+#ifdef CONFIG_P2P_PS
+			process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
+#endif //CONFIG_P2P_PS
+
+#if defined(CONFIG_P2P)&&defined(CONFIG_CONCURRENT_MODE)
+			if (padapter->registrypriv.wifi_spec) {
+				if (process_p2p_cross_connect_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN)) == _FALSE) {
+					if((padapter->pbuddy_adapter->mlmeextpriv.mlmext_info.state&0x03) == WIFI_FW_AP_STATE) {
+						DBG_871X_LEVEL(_drv_always_, "no issue auth, P2P cross-connect does not permit\n ");
+						return _SUCCESS;
+					}
+				}
+			}
+#endif // CONFIG_P2P CONFIG_P2P and CONFIG_CONCURRENT_MODE
+
+			//start auth
+			start_clnt_auth(padapter);
+
+			return _SUCCESS;
+		}
+
+		if(((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE) && (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+		{
+			if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
+			{
+				#ifdef CONFIG_PATCH_JOIN_WRONG_CHANNEL        
+				//Merge from 8712 FW code
+				if (cmp_pkt_chnl_diff(padapter,pframe,len) != 0)        
+				{            // join wrong channel, deauth and reconnect           
+					issue_deauth(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_DEAUTH_LEAVING);
+
+					report_del_sta_event(padapter, (&(pmlmeinfo->network))->MacAddress, WLAN_REASON_JOIN_WRONG_CHANNEL, _TRUE);
+					pmlmeinfo->state &= (~WIFI_FW_ASSOC_SUCCESS);    		
+					return _SUCCESS;
+				}        
+				#endif //CONFIG_PATCH_JOIN_WRONG_CHANNEL
+
+				ret = rtw_check_bcn_info(padapter, pframe, len);
+				if (!ret) {
+						DBG_871X_LEVEL(_drv_always_, "ap has changed, disconnect now\n ");
+						receive_disconnect(padapter, pmlmeinfo->network.MacAddress , 0);
+						return _SUCCESS;
+				}
+				//update WMM, ERP in the beacon
+				//todo: the timer is used instead of the number of the beacon received
+				if ((sta_rx_pkts(psta) & 0xf) == 0)
+				{
+					//DBG_871X("update_bcn_info\n");
+					update_beacon_info(padapter, pframe, len, psta);
+				}
+
+				adaptive_early_32k(pmlmeext, pframe, len);			 	
+				
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+				if (padapter->tdlsinfo.ch_switch_prohibited == _FALSE)
+				{
+					/* Send TDLS Channel Switch Request when receiving Beacon */
+					if ((padapter->tdlsinfo.chsw_info.ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) && (pmlmeext->cur_channel == rtw_get_oper_ch(padapter))) {
+						ptdlsinfo->chsw_info.ch_sw_state |= TDLS_WAIT_CH_RSP_STATE;
+						/* DBG_871X("[%s] issue_tdls_ch_switch_req to "MAC_FMT"\n", __FUNCTION__, MAC_ARG(padapter->tdlsinfo.chsw_info.addr)); */
+						ptdls_sta = rtw_get_stainfo(&padapter->stapriv, padapter->tdlsinfo.chsw_info.addr);
+						if (ptdls_sta != NULL) {
+							if (ptdls_sta->tdls_sta_state | TDLS_LINKED_STATE)
+								issue_tdls_ch_switch_req(padapter, ptdls_sta);
+						}
+					}
+				}
+#endif				
+#endif /* CONFIG_TDLS */
+
+#ifdef CONFIG_DFS
+				process_csa_ie(padapter, pframe, len);	//channel switch announcement
+#endif //CONFIG_DFS
+
+#ifdef CONFIG_P2P_PS
+				process_p2p_ps_ie(padapter, (pframe + WLAN_HDR_A3_LEN), (len - WLAN_HDR_A3_LEN));
+#endif //CONFIG_P2P_PS
+
+				#if 0 //move to validate_recv_mgnt_frame
+				psta->sta_stats.rx_mgnt_pkts++;
+				#endif
+			}
+		}
+		else if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
+		{
+			if ((psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe))) != NULL)
+			{
+				//update WMM, ERP in the beacon
+				//todo: the timer is used instead of the number of the beacon received
+				if ((sta_rx_pkts(psta) & 0xf) == 0)
+				{
+					//DBG_871X("update_bcn_info\n");
+					update_beacon_info(padapter, pframe, len, psta);
+				}
+
+				#if 0 //move to validate_recv_mgnt_frame
+				psta->sta_stats.rx_mgnt_pkts++;
+				#endif
+			}
+			else
+			{
+				//allocate a new CAM entry for IBSS station
+				if ((cam_idx = allocate_fw_sta_entry(padapter)) == NUM_STA)
+				{
+					goto _END_ONBEACON_;
+				}
+
+				//get supported rate
+				if (update_sta_support_rate(padapter, (pframe + WLAN_HDR_A3_LEN + _BEACON_IE_OFFSET_), (len - WLAN_HDR_A3_LEN - _BEACON_IE_OFFSET_), cam_idx) == _FAIL)
+				{
+					pmlmeinfo->FW_sta_info[cam_idx].status = 0;
+					goto _END_ONBEACON_;
+				}
+
+				//update TSF Value
+				update_TSF(pmlmeext, pframe, len);			
+
+				//report sta add event
+				report_add_sta_event(padapter, GetAddr2Ptr(pframe), cam_idx);
+			}
+		}
+	}
+
+_END_ONBEACON_:
+
+	return _SUCCESS;
+
+}
+
+unsigned int OnAuth(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_AP_MODE
+	_irqL irqL;
+	unsigned int	auth_mode, seq, ie_len;
+	unsigned char	*sa, *p;	
+	u16	algorithm;
+	int	status;
+	static struct sta_info stat;	
+	struct	sta_info	*pstat=NULL;	
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 *pframe = precv_frame->u.hdr.rx_data; 
+	uint len = precv_frame->u.hdr.len;
+	u8	offset = 0;
+
+	
+#ifdef CONFIG_CONCURRENT_MODE	
+	if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
+		check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
+	{
+		//don't process auth request;
+		return _SUCCESS;
+	}
+#endif //CONFIG_CONCURRENT_MODE
+
+	if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+		return _FAIL;
+
+	DBG_871X("+OnAuth\n");
+
+	sa = GetAddr2Ptr(pframe);
+
+	auth_mode = psecuritypriv->dot11AuthAlgrthm;
+
+	if (GetPrivacy(pframe))
+	{
+		u8	*iv;
+		struct rx_pkt_attrib	 *prxattrib = &(precv_frame->u.hdr.attrib);
+
+		prxattrib->hdrlen = WLAN_HDR_A3_LEN;
+		prxattrib->encrypt = _WEP40_;
+
+		iv = pframe+prxattrib->hdrlen;
+		prxattrib->key_index = ((iv[3]>>6)&0x3);
+
+		prxattrib->iv_len = 4;
+		prxattrib->icv_len = 4;
+
+		rtw_wep_decrypt(padapter, (u8 *)precv_frame);
+
+		offset = 4;
+	}
+
+	algorithm = le16_to_cpu(*(u16*)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
+	seq 	= le16_to_cpu(*(u16*)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
+
+	DBG_871X("auth alg=%x, seq=%X\n", algorithm, seq);
+
+	if (auth_mode == 2 &&
+			psecuritypriv->dot11PrivacyAlgrthm != _WEP40_ &&
+			psecuritypriv->dot11PrivacyAlgrthm != _WEP104_)
+		auth_mode = 0;
+
+	if ((algorithm > 0 && auth_mode == 0) ||	// rx a shared-key auth but shared not enabled
+		(algorithm == 0 && auth_mode == 1) )	// rx a open-system auth but shared-key is enabled
+	{		
+		DBG_871X("auth rejected due to bad alg [alg=%d, auth_mib=%d] %02X%02X%02X%02X%02X%02X\n",
+			algorithm, auth_mode, sa[0], sa[1], sa[2], sa[3], sa[4], sa[5]);
+		
+		status = _STATS_NO_SUPP_ALG_;
+		
+		goto auth_fail;
+	}
+	
+#if 0 //ACL control	
+	phead = &priv->wlan_acl_list;
+	plist = phead->next;
+	//check sa
+	if (acl_mode == 1)		// 1: positive check, only those on acl_list can be connected.
+		res = FAIL;
+	else
+		res = SUCCESS;
+
+	while(plist != phead)
+	{
+		paclnode = list_entry(plist, struct rtw_wlan_acl_node, list);
+		plist = plist->next;
+		if (!memcmp((void *)sa, paclnode->addr, 6)) {
+			if (paclnode->mode & 2) { // deny
+				res = FAIL;
+				break;
+			}
+			else {
+				res = SUCCESS;
+				break;
+			}
+		}
+	}
+
+	if (res != SUCCESS) {
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,"auth abort because ACL!\n");
+		return FAIL;
+	}
+#else
+	if(rtw_access_ctrl(padapter, sa) == _FALSE)
+	{
+		status = _STATS_UNABLE_HANDLE_STA_;
+		goto auth_fail;
+	}	
+#endif
+
+	pstat = rtw_get_stainfo(pstapriv, sa);
+	if (pstat == NULL)
+	{
+
+		// allocate a new one
+		DBG_871X("going to alloc stainfo for sa="MAC_FMT"\n",  MAC_ARG(sa));
+		pstat = rtw_alloc_stainfo(pstapriv, sa);
+		if (pstat == NULL)
+		{
+			DBG_871X(" Exceed the upper limit of supported clients...\n");
+			status = _STATS_UNABLE_HANDLE_STA_;
+			goto auth_fail;
+		}
+		
+		pstat->state = WIFI_FW_AUTH_NULL;
+		pstat->auth_seq = 0;
+		
+		//pstat->flags = 0;
+		//pstat->capability = 0;
+	} else {
+#ifdef CONFIG_IEEE80211W
+		if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS))
+#endif /* CONFIG_IEEE80211W */
+		{
+
+			_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+			if (rtw_is_list_empty(&pstat->asoc_list) == _FALSE) {			
+				rtw_list_delete(&pstat->asoc_list);
+				pstapriv->asoc_list_cnt--;
+				if (pstat->expire_to > 0)
+					;/* TODO: STA re_auth within expire_to */
+			}
+			_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+			if (seq == 1)
+				; /* TODO: STA re_auth and auth timeout */
+
+		}
+	}
+
+#ifdef CONFIG_IEEE80211W
+	if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) 
+#endif /* CONFIG_IEEE80211W */
+	{
+		_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+		if (rtw_is_list_empty(&pstat->auth_list)) {		
+	
+			rtw_list_insert_tail(&pstat->auth_list, &pstapriv->auth_list);
+			pstapriv->auth_list_cnt++;
+		}	
+		_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
+	}
+
+	if (pstat->auth_seq == 0)
+		pstat->expire_to = pstapriv->auth_to;
+
+
+	if ((pstat->auth_seq + 1) != seq)
+	{
+		DBG_871X("(1)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+			seq, pstat->auth_seq+1);
+		status = _STATS_OUT_OF_AUTH_SEQ_;
+		goto auth_fail;
+	}
+
+	if (algorithm==0 && (auth_mode == 0 || auth_mode == 2 || auth_mode == 3))
+	{
+		if (seq == 1)
+		{
+#ifdef CONFIG_IEEE80211W
+			if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) 
+#endif /* CONFIG_IEEE80211W */
+			{
+				pstat->state &= ~WIFI_FW_AUTH_NULL;
+				pstat->state |= WIFI_FW_AUTH_SUCCESS;
+				pstat->expire_to = pstapriv->assoc_to;
+			}
+			pstat->authalg = algorithm;
+		}
+		else
+		{
+			DBG_871X("(2)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+				seq, pstat->auth_seq+1);
+			status = _STATS_OUT_OF_AUTH_SEQ_;
+			goto auth_fail;
+		}
+	}
+	else // shared system or auto authentication
+	{
+		if (seq == 1)
+		{
+			//prepare for the challenging txt...
+
+			//get_random_bytes((void *)pstat->chg_txt, 128);//TODO:
+			_rtw_memset((void *)pstat->chg_txt, 78, 128);
+#ifdef CONFIG_IEEE80211W
+			if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) 
+#endif /* CONFIG_IEEE80211W */
+			{
+				pstat->state &= ~WIFI_FW_AUTH_NULL;
+				pstat->state |= WIFI_FW_AUTH_STATE;
+			}
+			pstat->authalg = algorithm;
+			pstat->auth_seq = 2;
+		}
+		else if (seq == 3)
+		{
+			//checking for challenging txt...
+			DBG_871X("checking for challenging txt...\n");
+			
+			p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + 4 + _AUTH_IE_OFFSET_ , _CHLGETXT_IE_, (int *)&ie_len,
+					len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_ - 4);
+
+			if((p==NULL) || (ie_len<=0))
+			{
+				DBG_871X("auth rejected because challenge failure!(1)\n");
+				status = _STATS_CHALLENGE_FAIL_;
+				goto auth_fail;
+			}
+			
+			if (_rtw_memcmp((void *)(p + 2), pstat->chg_txt, 128))
+			{
+#ifdef CONFIG_IEEE80211W
+				if (pstat->bpairwise_key_installed != _TRUE && !(pstat->state & WIFI_FW_ASSOC_SUCCESS)) 
+#endif /* CONFIG_IEEE80211W */
+				{
+					pstat->state &= (~WIFI_FW_AUTH_STATE);
+					pstat->state |= WIFI_FW_AUTH_SUCCESS;
+					/* challenging txt is correct... */
+					pstat->expire_to =  pstapriv->assoc_to;
+				}
+			}
+			else
+			{
+				DBG_871X("auth rejected because challenge failure!\n");
+				status = _STATS_CHALLENGE_FAIL_;
+				goto auth_fail;
+			}
+		}
+		else
+		{
+			DBG_871X("(3)auth rejected because out of seq [rx_seq=%d, exp_seq=%d]!\n",
+				seq, pstat->auth_seq+1);
+			status = _STATS_OUT_OF_AUTH_SEQ_;
+			goto auth_fail;
+		}
+	}
+
+
+	// Now, we are going to issue_auth...
+	pstat->auth_seq = seq + 1;	
+	
+#ifdef CONFIG_NATIVEAP_MLME
+	issue_auth(padapter, pstat, (unsigned short)(_STATS_SUCCESSFUL_));
+#endif
+
+	if ((pstat->state & WIFI_FW_AUTH_SUCCESS) || (pstat->state & WIFI_FW_ASSOC_SUCCESS))
+		pstat->auth_seq = 0;
+
+		
+	return _SUCCESS;
+
+auth_fail:
+
+	if(pstat)
+		rtw_free_stainfo(padapter , pstat);
+	
+	pstat = &stat;
+	_rtw_memset((char *)pstat, '\0', sizeof(stat));
+	pstat->auth_seq = 2;
+	_rtw_memcpy(pstat->hwaddr, sa, 6);	
+	
+#ifdef CONFIG_NATIVEAP_MLME
+	issue_auth(padapter, pstat, (unsigned short)status);	
+#endif
+
+#endif
+	return _FAIL;
+
+}
+
+unsigned int OnAuthClient(_adapter *padapter, union recv_frame *precv_frame)
+{
+	unsigned int	seq, len, status, algthm, offset;
+	unsigned char	*p;
+	unsigned int	go2asoc = 0;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint pkt_len = precv_frame->u.hdr.len;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	//check A1 matches or not
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))
+		return _SUCCESS;
+
+	if (!(pmlmeinfo->state & WIFI_FW_AUTH_STATE))
+		return _SUCCESS;
+
+	offset = (GetPrivacy(pframe))? 4: 0;
+
+	algthm 	= le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset));
+	seq 	= le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 2));
+	status 	= le16_to_cpu(*(unsigned short *)((SIZE_PTR)pframe + WLAN_HDR_A3_LEN + offset + 4));
+
+	if (status != 0)
+	{
+		DBG_871X("clnt auth fail, status: %d\n", status);
+		if(status == 13)//&& pmlmeinfo->auth_algo == dot11AuthAlgrthm_Auto)
+		{
+			if(pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+				pmlmeinfo->auth_algo = dot11AuthAlgrthm_Open;
+			else
+				pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
+			//pmlmeinfo->reauth_count = 0;
+		}
+		
+		set_link_timer(pmlmeext, 1);
+		goto authclnt_fail;
+	}
+
+	if (seq == 2)
+	{
+		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+		{
+			 // legendary shared system
+			p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _AUTH_IE_OFFSET_, _CHLGETXT_IE_, (int *)&len,
+				pkt_len - WLAN_HDR_A3_LEN - _AUTH_IE_OFFSET_);
+
+			if (p == NULL)
+			{
+				//DBG_871X("marc: no challenge text?\n");
+				goto authclnt_fail;
+			}
+
+			_rtw_memcpy((void *)(pmlmeinfo->chg_txt), (void *)(p + 2), len);
+			pmlmeinfo->auth_seq = 3;
+			issue_auth(padapter, NULL, 0);
+			set_link_timer(pmlmeext, REAUTH_TO);
+
+			return _SUCCESS;
+		}
+		else
+		{
+			// open system
+			go2asoc = 1;
+		}
+	}
+	else if (seq == 4)
+	{
+		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)
+		{
+			go2asoc = 1;
+		}
+		else
+		{
+			goto authclnt_fail;
+		}
+	}
+	else
+	{
+		// this is also illegal
+		//DBG_871X("marc: clnt auth failed due to illegal seq=%x\n", seq);
+		goto authclnt_fail;
+	}
+
+	if (go2asoc)
+	{
+		DBG_871X_LEVEL(_drv_always_, "auth success, start assoc\n");
+		start_clnt_assoc(padapter);
+		return _SUCCESS;
+	}
+
+authclnt_fail:
+
+	//pmlmeinfo->state &= ~(WIFI_FW_AUTH_STATE);
+
+	return _FAIL;
+
+}
+
+unsigned int OnAssocReq(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_AP_MODE
+	_irqL irqL;
+	u16 capab_info, listen_interval;
+	struct rtw_ieee802_11_elems elems;	
+	struct sta_info	*pstat;
+	unsigned char		reassoc, *p, *pos, *wpa_ie;
+	unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
+	int		i, ie_len, wpa_ie_len, left;
+	unsigned char		supportRate[16];
+	int					supportRateNum;
+	unsigned short		status = _STATS_SUCCESSFUL_;
+	unsigned short		frame_type, ie_offset=0;	
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);	
+	WLAN_BSSID_EX 	*cur = &(pmlmeinfo->network);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint pkt_len = precv_frame->u.hdr.len;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	u8 p2p_status_code = P2P_STATUS_SUCCESS;
+	u8 *p2pie;
+	u32 p2pielen = 0;
+#endif //CONFIG_P2P
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if(((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) &&
+		check_buddy_fwstate(padapter, _FW_UNDER_LINKING|_FW_UNDER_SURVEY))
+	{
+		//don't process assoc request;
+		return _SUCCESS;
+	}
+#endif //CONFIG_CONCURRENT_MODE
+
+	if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+		return _FAIL;
+	
+	frame_type = GetFrameSubType(pframe);
+	if (frame_type == WIFI_ASSOCREQ)
+	{
+		reassoc = 0;
+		ie_offset = _ASOCREQ_IE_OFFSET_;
+	}	
+	else // WIFI_REASSOCREQ
+	{
+		reassoc = 1;
+		ie_offset = _REASOCREQ_IE_OFFSET_;
+	}
+	
+
+	if (pkt_len < IEEE80211_3ADDR_LEN + ie_offset) {
+		DBG_871X("handle_assoc(reassoc=%d) - too short payload (len=%lu)"
+		       "\n", reassoc, (unsigned long)pkt_len);
+		return _FAIL;
+	}
+	
+	pstat = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+	if (pstat == (struct sta_info *)NULL)
+	{
+		status = _RSON_CLS2_;
+		goto asoc_class2_error;
+	}
+
+	capab_info = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN);
+	//capab_info = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));	
+	//listen_interval = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN+2));
+	listen_interval = RTW_GET_LE16(pframe + WLAN_HDR_A3_LEN+2);
+
+	left = pkt_len - (IEEE80211_3ADDR_LEN + ie_offset);
+	pos = pframe + (IEEE80211_3ADDR_LEN + ie_offset);
+	
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	// check if this stat has been successfully authenticated/assocated
+	if (!((pstat->state) & WIFI_FW_AUTH_SUCCESS))
+	{
+		if (!((pstat->state) & WIFI_FW_ASSOC_SUCCESS))
+		{
+			status = _RSON_CLS2_;
+			goto asoc_class2_error;
+		}
+		else
+		{
+			pstat->state &= (~WIFI_FW_ASSOC_SUCCESS);
+			pstat->state |= WIFI_FW_ASSOC_STATE;				
+		}
+	}
+	else
+	{
+		pstat->state &= (~WIFI_FW_AUTH_SUCCESS);
+		pstat->state |= WIFI_FW_ASSOC_STATE;
+	}
+
+
+#if 0// todo:tkip_countermeasures
+	if (hapd->tkip_countermeasures) {
+		resp = WLAN_REASON_MICHAEL_MIC_FAILURE;
+		goto fail;
+	}
+#endif
+
+	pstat->capability = capab_info;
+
+#if 0//todo:
+	//check listen_interval
+	if (listen_interval > hapd->conf->max_listen_interval) {
+		hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211,
+			       HOSTAPD_LEVEL_DEBUG,
+			       "Too large Listen Interval (%d)",
+			       listen_interval);
+		resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE;
+		goto fail;
+	}
+	
+	pstat->listen_interval = listen_interval;
+#endif
+
+	//now parse all ieee802_11 ie to point to elems
+	if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed ||
+	    !elems.ssid) {
+		DBG_871X("STA " MAC_FMT " sent invalid association request\n",
+		       MAC_ARG(pstat->hwaddr));
+		status = _STATS_FAILURE_;		
+		goto OnAssocReqFail;
+	}
+
+
+	// now we should check all the fields...
+	// checking SSID
+	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SSID_IE_, &ie_len,
+		pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+	if (p == NULL)
+	{
+		status = _STATS_FAILURE_;		
+	}
+
+	if (ie_len == 0) // broadcast ssid, however it is not allowed in assocreq
+		status = _STATS_FAILURE_;
+	else
+	{
+		// check if ssid match
+		if (!_rtw_memcmp((void *)(p+2), cur->Ssid.Ssid, cur->Ssid.SsidLength))
+			status = _STATS_FAILURE_;
+
+		if (ie_len != cur->Ssid.SsidLength)
+			status = _STATS_FAILURE_;
+	}
+
+	if(_STATS_SUCCESSFUL_ != status)
+		goto OnAssocReqFail;
+
+	// check if the supported rate is ok
+	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _SUPPORTEDRATES_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+	if (p == NULL) {
+		DBG_871X("Rx a sta assoc-req which supported rate is empty!\n");
+		// use our own rate set as statoin used
+		//_rtw_memcpy(supportRate, AP_BSSRATE, AP_BSSRATE_LEN);
+		//supportRateNum = AP_BSSRATE_LEN;
+		
+		status = _STATS_FAILURE_;
+		goto OnAssocReqFail;
+	}
+	else {
+		_rtw_memcpy(supportRate, p+2, ie_len);
+		supportRateNum = ie_len;
+
+		p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + ie_offset, _EXT_SUPPORTEDRATES_IE_ , &ie_len,
+				pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+		if (p !=  NULL) {
+			
+			if(supportRateNum<=sizeof(supportRate))
+			{
+				_rtw_memcpy(supportRate+supportRateNum, p+2, ie_len);
+				supportRateNum += ie_len;
+			}			
+		}
+	}
+
+	//todo: mask supportRate between AP & STA -> move to update raid
+	//get_matched_rate(pmlmeext, supportRate, &supportRateNum, 0);
+
+	//update station supportRate	
+	pstat->bssratelen = supportRateNum;
+	_rtw_memcpy(pstat->bssrateset, supportRate, supportRateNum);
+	UpdateBrateTblForSoftAP(pstat->bssrateset, pstat->bssratelen);
+
+	//check RSN/WPA/WPS
+	pstat->dot8021xalg = 0;
+      	pstat->wpa_psk = 0;
+	pstat->wpa_group_cipher = 0;
+	pstat->wpa2_group_cipher = 0;
+	pstat->wpa_pairwise_cipher = 0;
+	pstat->wpa2_pairwise_cipher = 0;
+	_rtw_memset(pstat->wpa_ie, 0, sizeof(pstat->wpa_ie));
+	if((psecuritypriv->wpa_psk & BIT(1)) && elems.rsn_ie) {
+
+		int group_cipher=0, pairwise_cipher=0;	
+		
+		wpa_ie = elems.rsn_ie;
+		wpa_ie_len = elems.rsn_ie_len;
+
+		if(rtw_parse_wpa2_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
+		{
+			pstat->dot8021xalg = 1;//psk,  todo:802.1x						
+			pstat->wpa_psk |= BIT(1);
+
+			pstat->wpa2_group_cipher = group_cipher&psecuritypriv->wpa2_group_cipher;				
+			pstat->wpa2_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa2_pairwise_cipher;
+			
+			if(!pstat->wpa2_group_cipher)
+				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+
+			if(!pstat->wpa2_pairwise_cipher)
+				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+		}
+		else
+		{
+			status = WLAN_STATUS_INVALID_IE;
+		}	
+			
+	} else if ((psecuritypriv->wpa_psk & BIT(0)) && elems.wpa_ie) {
+
+		int group_cipher=0, pairwise_cipher=0;	
+		
+		wpa_ie = elems.wpa_ie;
+		wpa_ie_len = elems.wpa_ie_len;
+
+		if(rtw_parse_wpa_ie(wpa_ie-2, wpa_ie_len+2, &group_cipher, &pairwise_cipher, NULL) == _SUCCESS)
+		{
+			pstat->dot8021xalg = 1;//psk,  todo:802.1x						
+			pstat->wpa_psk |= BIT(0);
+
+			pstat->wpa_group_cipher = group_cipher&psecuritypriv->wpa_group_cipher;				
+			pstat->wpa_pairwise_cipher = pairwise_cipher&psecuritypriv->wpa_pairwise_cipher;
+			
+			if(!pstat->wpa_group_cipher)
+				status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID;
+
+			if(!pstat->wpa_pairwise_cipher)
+				status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
+		
+		}
+		else
+		{
+			status = WLAN_STATUS_INVALID_IE;
+		}
+		
+	} else {
+		wpa_ie = NULL;
+		wpa_ie_len = 0;
+	}
+
+	if(_STATS_SUCCESSFUL_ != status)
+		goto OnAssocReqFail;
+
+	pstat->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS);
+	//if (hapd->conf->wps_state && wpa_ie == NULL) { //todo: to check ap if supporting WPS
+	if(wpa_ie == NULL) {
+		if (elems.wps_ie) {
+			DBG_871X("STA included WPS IE in "
+				   "(Re)Association Request - assume WPS is "
+				   "used\n");
+			pstat->flags |= WLAN_STA_WPS;
+			//wpabuf_free(sta->wps_ie);
+			//sta->wps_ie = wpabuf_alloc_copy(elems.wps_ie + 4,
+			//				elems.wps_ie_len - 4);
+		} else {
+			DBG_871X("STA did not include WPA/RSN IE "
+				   "in (Re)Association Request - possible WPS "
+				   "use\n");
+			pstat->flags |= WLAN_STA_MAYBE_WPS;
+		}
+
+
+		// AP support WPA/RSN, and sta is going to do WPS, but AP is not ready
+		// that the selected registrar of AP is _FLASE
+		if((psecuritypriv->wpa_psk >0)  
+			&& (pstat->flags & (WLAN_STA_WPS|WLAN_STA_MAYBE_WPS)))
+		{
+			if(pmlmepriv->wps_beacon_ie)
+			{	
+				u8 selected_registrar = 0;
+				
+				rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len, WPS_ATTR_SELECTED_REGISTRAR , &selected_registrar, NULL);
+
+				if(!selected_registrar)
+				{						
+					DBG_871X("selected_registrar is _FALSE , or AP is not ready to do WPS\n");
+						
+					status = _STATS_UNABLE_HANDLE_STA_;
+			
+					goto OnAssocReqFail;
+				}						
+			}			
+		}
+			
+	}
+	else
+	{
+		int copy_len;
+
+		if(psecuritypriv->wpa_psk == 0)
+		{
+			DBG_871X("STA " MAC_FMT ": WPA/RSN IE in association "
+		       	"request, but AP don't support WPA/RSN\n", MAC_ARG(pstat->hwaddr));
+			
+			status = WLAN_STATUS_INVALID_IE;
+			
+			goto OnAssocReqFail;
+
+		}
+
+		if (elems.wps_ie) {
+			DBG_871X("STA included WPS IE in "
+				   "(Re)Association Request - WPS is "
+				   "used\n");
+			pstat->flags |= WLAN_STA_WPS;
+			copy_len=0;
+		}
+		else
+		{
+			copy_len = ((wpa_ie_len+2) > sizeof(pstat->wpa_ie)) ? (sizeof(pstat->wpa_ie)):(wpa_ie_len+2);
+		}
+
+		
+		if(copy_len>0)
+			_rtw_memcpy(pstat->wpa_ie, wpa_ie-2, copy_len);
+		
+	}
+
+
+	// check if there is WMM IE & support WWM-PS
+	pstat->flags &= ~WLAN_STA_WME;
+	pstat->qos_option = 0;
+	pstat->qos_info = 0;
+	pstat->has_legacy_ac = _TRUE;
+	pstat->uapsd_vo = 0;
+	pstat->uapsd_vi = 0;
+	pstat->uapsd_be = 0;
+	pstat->uapsd_bk = 0;
+	if (pmlmepriv->qospriv.qos_option) 
+	{
+		p = pframe + WLAN_HDR_A3_LEN + ie_offset; ie_len = 0;
+		for (;;) 
+		{
+			p = rtw_get_ie(p, _VENDOR_SPECIFIC_IE_, &ie_len, pkt_len - WLAN_HDR_A3_LEN - ie_offset);
+			if (p != NULL) {
+				if (_rtw_memcmp(p+2, WMM_IE, 6)) {
+
+					pstat->flags |= WLAN_STA_WME;
+					
+					pstat->qos_option = 1;				
+					pstat->qos_info = *(p+8);
+					
+					pstat->max_sp_len = (pstat->qos_info>>5)&0x3;
+
+					if((pstat->qos_info&0xf) !=0xf)
+						pstat->has_legacy_ac = _TRUE;
+					else
+						pstat->has_legacy_ac = _FALSE;
+					
+					if(pstat->qos_info&0xf)
+					{
+						if(pstat->qos_info&BIT(0))
+							pstat->uapsd_vo = BIT(0)|BIT(1);
+						else
+							pstat->uapsd_vo = 0;
+		
+						if(pstat->qos_info&BIT(1))
+							pstat->uapsd_vi = BIT(0)|BIT(1);
+						else
+							pstat->uapsd_vi = 0;
+			
+						if(pstat->qos_info&BIT(2))
+							pstat->uapsd_bk = BIT(0)|BIT(1);
+						else
+							pstat->uapsd_bk = 0;
+			
+						if(pstat->qos_info&BIT(3))			
+							pstat->uapsd_be = BIT(0)|BIT(1);
+						else
+							pstat->uapsd_be = 0;
+		
+					}
+	
+					break;
+				}
+			}
+			else {
+				break;
+			}
+			p = p + ie_len + 2;
+		}
+	}
+
+
+#ifdef CONFIG_80211N_HT
+	/* save HT capabilities in the sta object */
+	_rtw_memset(&pstat->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
+	if (elems.ht_capabilities && elems.ht_capabilities_len >= sizeof(struct rtw_ieee80211_ht_cap)) 
+	{
+		pstat->flags |= WLAN_STA_HT;
+		
+		pstat->flags |= WLAN_STA_WME;
+		
+		_rtw_memcpy(&pstat->htpriv.ht_cap, elems.ht_capabilities, sizeof(struct rtw_ieee80211_ht_cap));			
+		
+	} else
+		pstat->flags &= ~WLAN_STA_HT;
+
+	
+	if((pmlmepriv->htpriv.ht_option == _FALSE) && (pstat->flags&WLAN_STA_HT))
+	{
+		status = _STATS_FAILURE_;
+		goto OnAssocReqFail;
+	}
+		
+#endif /* CONFIG_80211N_HT */
+
+#ifdef CONFIG_80211AC_VHT
+	_rtw_memset(&pstat->vhtpriv, 0, sizeof(struct vht_priv));
+	if (elems.vht_capabilities && elems.vht_capabilities_len == 12) {
+		pstat->flags |= WLAN_STA_VHT;
+
+		_rtw_memcpy(pstat->vhtpriv.vht_cap, elems.vht_capabilities, 12);
+
+		if (elems.vht_op_mode_notify && elems.vht_op_mode_notify_len == 1) {
+			_rtw_memcpy(&pstat->vhtpriv.vht_op_mode_notify, elems.vht_op_mode_notify, 1);
+		}
+		else // for Frame without Operating Mode notify ie; default: 80M
+		{
+			pstat->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;
+		}
+	}
+	else {
+		pstat->flags &= ~WLAN_STA_VHT;
+	}
+
+	if((pmlmepriv->vhtpriv.vht_option == _FALSE) && (pstat->flags&WLAN_STA_VHT))
+	{
+		status = _STATS_FAILURE_;
+		goto OnAssocReqFail;
+	}
+#endif /* CONFIG_80211AC_VHT */
+
+	if (((pstat->flags & WLAN_STA_HT) || (pstat->flags & WLAN_STA_VHT)) && 
+		((pstat->wpa2_pairwise_cipher & WPA_CIPHER_TKIP) || 
+		(pstat->wpa_pairwise_cipher & WPA_CIPHER_TKIP))) {
+
+		DBG_871X("(V)HT: " MAC_FMT " tried to use TKIP with (V)HT association\n", MAC_ARG(pstat->hwaddr));
+
+		pstat->flags &= ~WLAN_STA_HT;
+		pstat->flags &= ~WLAN_STA_VHT;
+		/*status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY;
+		  * goto OnAssocReqFail;
+		*/
+	}
+
+
+       //
+       //if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)//?
+	pstat->flags |= WLAN_STA_NONERP;	
+	for (i = 0; i < pstat->bssratelen; i++) {
+		if ((pstat->bssrateset[i] & 0x7f) > 22) {
+			pstat->flags &= ~WLAN_STA_NONERP;
+			break;
+		}
+	}
+
+	if (pstat->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
+		pstat->flags |= WLAN_STA_SHORT_PREAMBLE;
+	else
+		pstat->flags &= ~WLAN_STA_SHORT_PREAMBLE;
+
+	
+	
+	if (status != _STATS_SUCCESSFUL_)
+		goto OnAssocReqFail;
+
+#ifdef CONFIG_P2P
+	pstat->is_p2p_device = _FALSE;
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+	{		
+		if( (p2pie=rtw_get_p2p_ie(pframe + WLAN_HDR_A3_LEN + ie_offset , pkt_len - WLAN_HDR_A3_LEN - ie_offset , NULL, &p2pielen)))
+		{
+			pstat->is_p2p_device = _TRUE;
+			if((p2p_status_code=(u8)process_assoc_req_p2p_ie(pwdinfo, pframe, pkt_len, pstat))>0)
+			{
+				pstat->p2p_status_code = p2p_status_code;
+				status = _STATS_CAP_FAIL_;
+				goto OnAssocReqFail;
+			}
+		}
+		#ifdef CONFIG_WFD
+		rtw_process_wfd_ies(padapter, pframe + WLAN_HDR_A3_LEN + ie_offset, pkt_len - WLAN_HDR_A3_LEN - ie_offset, __func__);
+		#endif
+	}
+	pstat->p2p_status_code = p2p_status_code;
+#endif //CONFIG_P2P
+
+	//TODO: identify_proprietary_vendor_ie();
+	// Realtek proprietary IE
+	// identify if this is Broadcom sta
+	// identify if this is ralink sta
+	// Customer proprietary IE
+
+	
+
+	/* get a unique AID */
+	if (pstat->aid > 0) {
+		DBG_871X("  old AID %d\n", pstat->aid);
+	} else {
+		for (pstat->aid = 1; pstat->aid <= NUM_STA; pstat->aid++) {
+			if (pstapriv->sta_aid[pstat->aid - 1] == NULL) {
+				if (pstat->aid > pstapriv->max_num_sta) {
+					pstat->aid = 0;
+				
+					DBG_871X("  no room for more AIDs\n");
+
+					status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
+				
+					goto OnAssocReqFail;
+				
+			
+				} else {
+					pstapriv->sta_aid[pstat->aid - 1] = pstat;
+					DBG_871X("allocate new AID = (%d)\n", pstat->aid);
+					break;
+				}				
+			}
+		}	
+	}
+
+
+	pstat->state &= (~WIFI_FW_ASSOC_STATE);	
+	pstat->state |= WIFI_FW_ASSOC_SUCCESS;
+	/* DBG_871X("==================%s, %d,  (%x), bpairwise_key_installed=%d, MAC:"MAC_FMT"\n"
+	, __func__, __LINE__, pstat->state, pstat->bpairwise_key_installed, MAC_ARG(pstat->hwaddr)); */
+#ifdef CONFIG_IEEE80211W
+	if (pstat->bpairwise_key_installed != _TRUE)
+#endif /* CONFIG_IEEE80211W */
+	{
+		_enter_critical_bh(&pstapriv->auth_list_lock, &irqL);
+		if (!rtw_is_list_empty(&pstat->auth_list)) {
+			rtw_list_delete(&pstat->auth_list);
+			pstapriv->auth_list_cnt--;
+		}
+		_exit_critical_bh(&pstapriv->auth_list_lock, &irqL);
+	
+		_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);	
+		if (rtw_is_list_empty(&pstat->asoc_list)) {
+			pstat->expire_to = pstapriv->expire_to;
+			rtw_list_insert_tail(&pstat->asoc_list, &pstapriv->asoc_list);
+			pstapriv->asoc_list_cnt++;
+		}
+		_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	}
+
+	// now the station is qualified to join our BSS...	
+	if(pstat && (pstat->state & WIFI_FW_ASSOC_SUCCESS) && (_STATS_SUCCESSFUL_==status))
+	{
+#ifdef CONFIG_NATIVEAP_MLME
+#ifdef CONFIG_IEEE80211W
+		if (pstat->bpairwise_key_installed != _TRUE)
+#endif /* CONFIG_IEEE80211W */
+		{
+			/* .1 bss_cap_update & sta_info_update */
+			bss_cap_update_on_sta_join(padapter, pstat);
+			sta_info_update(padapter, pstat);
+		}
+#ifdef CONFIG_IEEE80211W
+		if (pstat->bpairwise_key_installed == _TRUE)
+			status = _STATS_REFUSED_TEMPORARILY_;
+#endif /* CONFIG_IEEE80211W */
+		//.2 issue assoc rsp before notify station join event.
+		if (frame_type == WIFI_ASSOCREQ)
+			issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+		else
+			issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+
+#ifdef CONFIG_IOCTL_CFG80211
+		_enter_critical_bh(&pstat->lock, &irqL);
+		if(pstat->passoc_req)
+		{
+			rtw_mfree(pstat->passoc_req, pstat->assoc_req_len);
+			pstat->passoc_req = NULL;
+			pstat->assoc_req_len = 0;
+		}
+
+		pstat->passoc_req =  rtw_zmalloc(pkt_len);
+		if(pstat->passoc_req)
+		{
+			_rtw_memcpy(pstat->passoc_req, pframe, pkt_len);
+			pstat->assoc_req_len = pkt_len;
+		}
+		_exit_critical_bh(&pstat->lock, &irqL);
+#endif //CONFIG_IOCTL_CFG80211
+#ifdef CONFIG_IEEE80211W
+		if (pstat->bpairwise_key_installed != _TRUE)
+#endif /* CONFIG_IEEE80211W */
+		{
+			/* .3-(1) report sta add event */
+			report_add_sta_event(padapter, pstat->hwaddr, pstat->aid);
+		}
+#ifdef CONFIG_IEEE80211W
+		if (pstat->bpairwise_key_installed == _TRUE && padapter->securitypriv.binstallBIPkey == _TRUE) {
+			DBG_871X(MAC_FMT"\n", MAC_ARG(pstat->hwaddr));
+			issue_action_SA_Query(padapter, pstat->hwaddr, 0, 0, IEEE80211W_RIGHT_KEY);
+		}
+#endif /* CONFIG_IEEE80211W */
+#endif //CONFIG_NATIVEAP_MLME
+	}
+
+	return _SUCCESS;
+
+asoc_class2_error:
+
+#ifdef CONFIG_NATIVEAP_MLME
+	issue_deauth(padapter, (void *)GetAddr2Ptr(pframe), status);
+#endif
+
+	return _FAIL;		
+
+OnAssocReqFail:
+
+
+#ifdef CONFIG_NATIVEAP_MLME
+	pstat->aid = 0;
+	if (frame_type == WIFI_ASSOCREQ)
+		issue_asocrsp(padapter, status, pstat, WIFI_ASSOCRSP);
+	else
+		issue_asocrsp(padapter, status, pstat, WIFI_REASSOCRSP);
+#endif
+
+
+#endif /* CONFIG_AP_MODE */
+
+	return _FAIL;		
+
+}
+
+unsigned int OnAssocRsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	uint i;
+	int res;
+	unsigned short	status;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	//WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint pkt_len = precv_frame->u.hdr.len;
+	PNDIS_802_11_VARIABLE_IEs	pWapiIE = NULL;
+
+	DBG_871X("%s\n", __FUNCTION__);
+	
+	//check A1 matches or not
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))
+		return _SUCCESS;
+
+	if (!(pmlmeinfo->state & (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE)))
+		return _SUCCESS;
+
+	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+		return _SUCCESS;
+
+	_cancel_timer_ex(&pmlmeext->link_timer);
+
+	//status
+	if ((status = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 2))) > 0)
+	{
+		DBG_871X("assoc reject, status code: %d\n", status);
+		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		res = -4;
+		goto report_assoc_result;
+	}
+
+	//get capabilities
+	pmlmeinfo->capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
+
+	//set slot time
+	pmlmeinfo->slotTime = (pmlmeinfo->capability & BIT(10))? 9: 20;
+
+	//AID
+	res = pmlmeinfo->aid = (int)(le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 4))&0x3fff);
+
+	//following are moved to join event callback function
+	//to handle HT, WMM, rate adaptive, update MAC reg
+	//for not to handle the synchronous IO in the tasklet
+	for (i = (6 + WLAN_HDR_A3_LEN); i < pkt_len;)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);
+
+		switch (pIE->ElementID)
+		{
+			case _VENDOR_SPECIFIC_IE_:
+				if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6))	//WMM
+				{
+					WMM_param_handler(padapter, pIE);
+				}
+#if defined(CONFIG_P2P) && defined(CONFIG_WFD)
+				else if ( _rtw_memcmp(pIE->data, WFD_OUI, 4))		//WFD
+				{
+					rtw_process_wfd_ie(padapter, (u8 *)pIE, pIE->Length, __func__);
+				}
+#endif				
+				break;
+
+#ifdef CONFIG_WAPI_SUPPORT
+			case _WAPI_IE_:
+				pWapiIE = pIE;
+				break;
+#endif
+
+			case _HT_CAPABILITY_IE_:	//HT caps
+				HT_caps_handler(padapter, pIE);
+				break;
+
+			case _HT_EXTRA_INFO_IE_:	//HT info
+				HT_info_handler(padapter, pIE);
+				break;
+
+#ifdef CONFIG_80211AC_VHT
+			case EID_VHTCapability:
+				VHT_caps_handler(padapter, pIE);
+				break;
+
+			case EID_VHTOperation:
+				VHT_operation_handler(padapter, pIE);
+				break;
+#endif
+
+			case _ERPINFO_IE_:
+				ERP_IE_handler(padapter, pIE);
+				break;
+#ifdef CONFIG_TDLS
+			case _EXT_CAP_IE_:
+				if (check_ap_tdls_prohibited(pIE->data, pIE->Length) == _TRUE)
+					padapter->tdlsinfo.ap_prohibited = _TRUE;
+				if (check_ap_tdls_ch_switching_prohibited(pIE->data, pIE->Length) == _TRUE)
+					padapter->tdlsinfo.ch_switch_prohibited = _TRUE;
+				break;
+#endif /* CONFIG_TDLS */
+			default:
+				break;
+		}
+
+		i += (pIE->Length + 2);
+	}
+
+#ifdef CONFIG_WAPI_SUPPORT
+	rtw_wapi_on_assoc_ok(padapter, pIE);
+#endif
+
+	pmlmeinfo->state &= (~WIFI_FW_ASSOC_STATE);
+	pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+
+	//Update Basic Rate Table for spec, 2010-12-28 , by thomas
+	UpdateBrateTbl(padapter, pmlmeinfo->network.SupportedRates);
+
+report_assoc_result:
+	if (res > 0) {
+		rtw_buf_update(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len, pframe, pkt_len);
+	} else {
+		rtw_buf_free(&pmlmepriv->assoc_rsp, &pmlmepriv->assoc_rsp_len);
+	}
+
+	report_join_res(padapter, res);
+
+	return _SUCCESS;
+}
+
+unsigned int OnDeAuth(_adapter *padapter, union recv_frame *precv_frame)
+{
+	unsigned short	reason;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif //CONFIG_P2P
+
+	//check A3
+	if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+		return _SUCCESS;
+
+	DBG_871X(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter));
+
+#ifdef CONFIG_P2P
+	if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
+	{
+		_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
+		_set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
+	}
+#endif //CONFIG_P2P
+
+	reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
+
+	rtw_lock_rx_suspend_timeout(8000);
+
+#ifdef CONFIG_AP_MODE
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{		
+		_irqL irqL;
+		struct sta_info *psta;
+		struct sta_priv *pstapriv = &padapter->stapriv;
+		
+		//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+		//rtw_free_stainfo(padapter, psta);
+		//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
+			, FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe));
+
+		psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));	
+		if(psta)
+		{
+			u8 updated = _FALSE;
+		
+			_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+			if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
+			{			
+				rtw_list_delete(&psta->asoc_list);
+				pstapriv->asoc_list_cnt--;
+				updated = ap_free_sta(padapter, psta, _FALSE, reason, _TRUE);
+
+			}
+			_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+			associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
+		}
+		
+
+		return _SUCCESS;
+	}
+	else
+#endif
+	{
+		int	ignore_received_deauth = 0;
+
+		//	Commented by Albert 20130604
+		//	Before sending the auth frame to start the STA/GC mode connection with AP/GO, 
+		//	we will send the deauth first.
+		//	However, the Win8.1 with BRCM Wi-Fi will send the deauth with reason code 6 to us after receieving our deauth.
+		//	Added the following code to avoid this case.
+		if ( ( pmlmeinfo->state & WIFI_FW_AUTH_STATE ) ||
+			( pmlmeinfo->state & WIFI_FW_ASSOC_STATE ) )
+		{
+			if ( reason == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA )
+			{
+				ignore_received_deauth = 1;
+			} else if (WLAN_REASON_PREV_AUTH_NOT_VALID == reason) {
+				// TODO: 802.11r
+				ignore_received_deauth = 1;
+			}
+		}
+
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM, ignore=%d\n"
+			, FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe), ignore_received_deauth);
+
+		if ( 0 == ignore_received_deauth )
+		{
+			receive_disconnect(padapter, GetAddr2Ptr(pframe), reason);
+		}
+	}	
+	pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
+	return _SUCCESS;
+
+}
+
+unsigned int OnDisassoc(_adapter *padapter, union recv_frame *precv_frame)
+{
+	unsigned short	reason;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif //CONFIG_P2P
+
+	//check A3
+	if (!(_rtw_memcmp(GetAddr3Ptr(pframe), get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+		return _SUCCESS;
+
+	DBG_871X(FUNC_ADPT_FMT" - Start to Disconnect\n", FUNC_ADPT_ARG(padapter));
+
+#ifdef CONFIG_P2P
+	if ( pwdinfo->rx_invitereq_info.scan_op_ch_only )
+	{
+		_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
+		_set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
+	}
+#endif //CONFIG_P2P
+
+	reason = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN));
+
+	rtw_lock_rx_suspend_timeout(8000);
+	
+#ifdef CONFIG_AP_MODE
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{	
+		_irqL irqL;
+		struct sta_info *psta;
+		struct sta_priv *pstapriv = &padapter->stapriv;
+		
+		//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);	
+		//rtw_free_stainfo(padapter, psta);
+		//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);		
+
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
+			, FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe));
+
+		psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));	
+		if(psta)
+		{
+			u8 updated = _FALSE;
+			
+			_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+			if(rtw_is_list_empty(&psta->asoc_list)==_FALSE)
+			{
+				rtw_list_delete(&psta->asoc_list);
+				pstapriv->asoc_list_cnt--;
+				updated = ap_free_sta(padapter, psta, _FALSE, reason, _TRUE);
+			
+			}
+			_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+			associated_clients_update(padapter, updated, STA_INFO_UPDATE_ALL);
+		}
+
+		return _SUCCESS;
+	}
+	else
+#endif
+	{
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" reason=%u, ta=%pM\n"
+			, FUNC_ADPT_ARG(padapter), reason, GetAddr2Ptr(pframe));
+
+		receive_disconnect(padapter, GetAddr2Ptr(pframe), reason);
+	}	
+	pmlmepriv->LinkDetectInfo.bBusyTraffic = _FALSE;
+	return _SUCCESS;
+
+}
+
+unsigned int OnAtim(_adapter *padapter, union recv_frame *precv_frame)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+	return _SUCCESS;
+}
+
+unsigned int on_action_spct_ch_switch(_adapter *padapter, struct sta_info *psta, u8 *ies, uint ies_len)
+{
+	unsigned int ret = _FAIL;
+	struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(mlmeext->mlmext_info);
+
+	if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
+		ret = _SUCCESS;	
+		goto exit;
+	}
+
+	if ((pmlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE) {
+		
+		int ch_switch_mode = -1, ch = -1, ch_switch_cnt = -1;
+		int ch_offset = -1;
+		u8 bwmode;
+		struct ieee80211_info_element *ie;
+
+		DBG_871X(FUNC_NDEV_FMT" from "MAC_FMT"\n",
+			FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(psta->hwaddr));
+
+		for_each_ie(ie, ies, ies_len) {
+			if (ie->id == WLAN_EID_CHANNEL_SWITCH) {
+				ch_switch_mode = ie->data[0];
+				ch = ie->data[1];
+				ch_switch_cnt = ie->data[2];
+				DBG_871X("ch_switch_mode:%d, ch:%d, ch_switch_cnt:%d\n",
+					ch_switch_mode, ch, ch_switch_cnt);
+			}
+			else if (ie->id == WLAN_EID_SECONDARY_CHANNEL_OFFSET) {
+				ch_offset = secondary_ch_offset_to_hal_ch_offset(ie->data[0]);
+				DBG_871X("ch_offset:%d\n", ch_offset);
+			}
+		}
+
+		if (ch == -1)
+			return _SUCCESS;
+
+		if (ch_offset == -1)
+			bwmode = mlmeext->cur_bwmode;
+		else
+			bwmode = (ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE) ?
+				CHANNEL_WIDTH_20 : CHANNEL_WIDTH_40;
+
+		ch_offset = (ch_offset == -1) ? mlmeext->cur_ch_offset : ch_offset;
+
+		/* todo:
+		 * 1. the decision of channel switching
+		 * 2. things after channel switching
+		 */
+
+		ret = rtw_set_ch_cmd(padapter, ch, bwmode, ch_offset, _TRUE);
+	}
+
+exit:
+	return ret;
+}
+
+unsigned int on_action_spct(_adapter *padapter, union recv_frame *precv_frame)
+{
+	unsigned int ret = _FAIL;
+	struct sta_info *psta = NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint frame_len = precv_frame->u.hdr.len;
+	u8 *frame_body = (u8 *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+	u8 category;
+	u8 action;
+
+	DBG_871X(FUNC_NDEV_FMT"\n", FUNC_NDEV_ARG(padapter->pnetdev));
+
+	psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+
+	if (!psta)
+		goto exit;
+
+	category = frame_body[0];
+	if(category != RTW_WLAN_CATEGORY_SPECTRUM_MGMT)
+		goto exit;
+
+	action = frame_body[1];
+	switch (action) {
+	case RTW_WLAN_ACTION_SPCT_MSR_REQ:
+	case RTW_WLAN_ACTION_SPCT_MSR_RPRT:
+	case RTW_WLAN_ACTION_SPCT_TPC_REQ:
+	case RTW_WLAN_ACTION_SPCT_TPC_RPRT:
+		break;
+	case RTW_WLAN_ACTION_SPCT_CHL_SWITCH:
+		#ifdef CONFIG_SPCT_CH_SWITCH
+		ret = on_action_spct_ch_switch(padapter, psta, &frame_body[2],
+			frame_len-(frame_body-pframe)-2);
+		#endif
+		break;
+	default:
+		break;
+	}
+
+exit:
+	return ret;
+}
+
+unsigned int OnAction_qos(_adapter *padapter, union recv_frame *precv_frame)
+{
+	return _SUCCESS;
+}
+
+unsigned int OnAction_dls(_adapter *padapter, union recv_frame *precv_frame)
+{
+	return _SUCCESS;
+}
+
+/**
+ * rtw_rx_ampdu_size - Get the target RX AMPDU buffer size for the specific @adapter
+ * @adapter: the adapter to get target RX AMPDU buffer size
+ *
+ * Returns: the target RX AMPDU buffer size
+ */
+u8 rtw_rx_ampdu_size(_adapter *adapter)
+{
+	u8 size;
+	HT_CAP_AMPDU_FACTOR max_rx_ampdu_factor;
+
+	if (adapter->fix_rx_ampdu_size != RX_AMPDU_SIZE_INVALID) {
+		size = adapter->fix_rx_ampdu_size;
+		goto exit;
+	}
+
+#ifdef CONFIG_BT_COEXIST
+	if (rtw_btcoex_IsBTCoexCtrlAMPDUSize(adapter) == _TRUE) {
+		size = rtw_btcoex_GetAMPDUSize(adapter);
+		goto exit;
+	}
+#endif
+
+	/* for scan */
+	if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE)
+		&& !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE)
+		&& adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size != RX_AMPDU_SIZE_INVALID
+	) {
+		size = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_size;
+		goto exit;
+	}
+
+	/* default value based on max_rx_ampdu_factor */
+	if (adapter->driver_rx_ampdu_factor != 0xFF)
+		max_rx_ampdu_factor = (HT_CAP_AMPDU_FACTOR)adapter->driver_rx_ampdu_factor;
+	else
+		rtw_hal_get_def_var(adapter, HW_VAR_MAX_RX_AMPDU_FACTOR, &max_rx_ampdu_factor);
+
+	if (MAX_AMPDU_FACTOR_64K == max_rx_ampdu_factor)
+		size = 64;
+	else if (MAX_AMPDU_FACTOR_32K == max_rx_ampdu_factor)
+		size = 32;
+	else if (MAX_AMPDU_FACTOR_16K == max_rx_ampdu_factor)
+		size = 16;
+	else if (MAX_AMPDU_FACTOR_8K == max_rx_ampdu_factor)
+		size = 8;
+	else
+		size = 64;
+
+exit:
+
+	if (size > 127)
+		size = 127;
+
+	return size;
+}
+
+/**
+ * rtw_rx_ampdu_is_accept - Get the permission if RX AMPDU should be set up for the specific @adapter
+ * @adapter: the adapter to get the permission if RX AMPDU should be set up
+ *
+ * Returns: accept or not
+ */
+bool rtw_rx_ampdu_is_accept(_adapter *adapter)
+{
+	bool accept;
+
+	if (adapter->fix_rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID) {
+		accept = adapter->fix_rx_ampdu_accept;
+		goto exit;
+	}
+
+#ifdef CONFIG_BT_COEXIST
+	if (rtw_btcoex_IsBTCoexRejectAMPDU(adapter) == _TRUE) {
+		accept = _FALSE;
+		goto exit;
+	}
+#endif
+
+	/* for scan */
+	if (!mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_DISABLE)
+		&& !mlmeext_chk_scan_state(&adapter->mlmeextpriv, SCAN_COMPLETE)
+		&& adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID
+	) {
+		accept = adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept;
+		goto exit;
+	}
+
+	/* default value for other cases */
+	accept = adapter->mlmeextpriv.mlmext_info.bAcceptAddbaReq;
+
+exit:
+	return accept;
+}
+
+/**
+ * rtw_rx_ampdu_set_size - Set the target RX AMPDU buffer size for the specific @adapter and specific @reason
+ * @adapter: the adapter to set target RX AMPDU buffer size
+ * @size: the target RX AMPDU buffer size to set
+ * @reason: reason for the target RX AMPDU buffer size setting
+ *
+ * Returns: whether the target RX AMPDU buffer size is changed
+ */
+bool rtw_rx_ampdu_set_size(_adapter *adapter, u8 size, u8 reason)
+{
+	bool is_adj = _FALSE;
+	struct mlme_ext_priv *mlmeext;
+	struct mlme_ext_info *mlmeinfo;
+
+	mlmeext = &adapter->mlmeextpriv;
+	mlmeinfo = &mlmeext->mlmext_info;
+
+	if (reason == RX_AMPDU_DRV_FIXED) {
+		if (adapter->fix_rx_ampdu_size != size) {
+			adapter->fix_rx_ampdu_size = size;
+			is_adj = _TRUE;
+			DBG_871X(FUNC_ADPT_FMT" fix_rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size);
+		}
+	} else if (reason == RX_AMPDU_DRV_SCAN) {
+		struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;
+
+		if (ss->rx_ampdu_size != size) {
+			ss->rx_ampdu_size = size;
+			is_adj = _TRUE;
+			DBG_871X(FUNC_ADPT_FMT" ss.rx_ampdu_size:%u\n", FUNC_ADPT_ARG(adapter), size);
+		}
+	}
+
+	return is_adj;
+}
+
+/**
+ * rtw_rx_ampdu_set_accept - Set the permission if RX AMPDU should be set up for the specific @adapter and specific @reason
+ * @adapter: the adapter to set if RX AMPDU should be set up
+ * @accept: if RX AMPDU should be set up
+ * @reason: reason for the permission if RX AMPDU should be set up
+ *
+ * Returns: whether the permission if RX AMPDU should be set up is changed
+ */
+bool rtw_rx_ampdu_set_accept(_adapter *adapter, u8 accept, u8 reason)
+{
+	bool is_adj = _FALSE;
+	struct mlme_ext_priv *mlmeext;
+	struct mlme_ext_info *mlmeinfo;
+
+	mlmeext = &adapter->mlmeextpriv;
+	mlmeinfo = &mlmeext->mlmext_info;
+
+	if (reason == RX_AMPDU_DRV_FIXED) {
+		if (adapter->fix_rx_ampdu_accept != accept) {
+			adapter->fix_rx_ampdu_accept = accept;
+			is_adj = _TRUE;
+			DBG_871X(FUNC_ADPT_FMT" fix_rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept);
+		}
+	} else if (reason == RX_AMPDU_DRV_SCAN) {
+		if (adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept != accept) {
+			adapter->mlmeextpriv.sitesurvey_res.rx_ampdu_accept = accept;
+			is_adj = _TRUE;
+			DBG_871X(FUNC_ADPT_FMT" ss.rx_ampdu_accept:%u\n", FUNC_ADPT_ARG(adapter), accept);
+		}
+	}
+
+	return is_adj;
+}
+
+/**
+ * rx_ampdu_apply_sta_tid - Apply RX AMPDU setting to the specific @sta and @tid
+ * @adapter: the adapter to which @sta belongs
+ * @sta: the sta to be checked
+ * @tid: the tid to be checked
+ * @accept: the target permission if RX AMPDU should be set up
+ * @size: the target RX AMPDU buffer size
+ *
+ * Returns:
+ * 0: no canceled
+ * 1: canceled by no permission
+ * 2: canceled by different buffer size
+ * 3: canceled by potential mismatched status
+ *
+ * Blocking function, may sleep
+ */
+u8 rx_ampdu_apply_sta_tid(_adapter *adapter, struct sta_info *sta, u8 tid, u8 accept, u8 size)
+{
+	u8 ret = 0;
+	struct recv_reorder_ctrl *reorder_ctl = &sta->recvreorder_ctrl[tid];
+
+	if (reorder_ctl->enable == _FALSE) {
+		if (reorder_ctl->ampdu_size != RX_AMPDU_SIZE_INVALID) {
+			send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 1);
+			ret = 3;
+		}
+		goto exit;
+	}
+
+	if (accept == _FALSE) {
+		send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0);
+		ret = 1;
+	} else if (reorder_ctl->ampdu_size != size) {
+		send_delba_sta_tid_wait_ack(adapter, 0, sta, tid, 0);
+		ret = 2;
+	}
+
+exit:
+	return ret;
+}
+
+/**
+ * rx_ampdu_apply_sta - Apply RX AMPDU setting to the specific @sta
+ * @adapter: the adapter to which @sta belongs
+ * @sta: the sta to be checked
+ * @accept: the target permission if RX AMPDU should be set up
+ * @size: the target RX AMPDU buffer size
+ *
+ * Returns: number of the RX AMPDU assciation canceled for applying current target setting
+ *
+ * Blocking function, may sleep
+ */
+u8 rx_ampdu_apply_sta(_adapter *adapter, struct sta_info *sta, u8 accept, u8 size)
+{
+	u8 change_cnt = 0;
+	int i;
+
+	for (i = 0; i < TID_NUM; i++) {
+		if (rx_ampdu_apply_sta_tid(adapter, sta, i, accept, size) != 0)
+			change_cnt++;
+	}
+
+	return change_cnt;
+}
+
+/**
+ * rtw_rx_ampdu_apply - Apply the current target RX AMPDU setting for the specific @adapter
+ * @adapter: the adapter to be applied
+ *
+ * Returns: number of the RX AMPDU assciation canceled for applying current target setting
+ */
+u16 rtw_rx_ampdu_apply(_adapter *adapter)
+{
+	u16 adj_cnt = 0;
+	struct mlme_ext_priv *mlmeext;
+	struct sta_info *sta;
+	u8 accept = rtw_rx_ampdu_is_accept(adapter);
+	u8 size = rtw_rx_ampdu_size(adapter);
+
+	mlmeext = &adapter->mlmeextpriv;
+
+	if (mlmeext_msr(mlmeext) == WIFI_FW_STATION_STATE) {
+		sta = rtw_get_stainfo(&adapter->stapriv, get_bssid(&adapter->mlmepriv));
+		if (sta)
+			adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, size);
+
+	} else if (mlmeext_msr(mlmeext) == WIFI_FW_AP_STATE) {
+		_irqL irqL;
+		_list *phead, *plist;
+		u8 peer_num = 0;
+		char peers[NUM_STA];
+		struct sta_priv *pstapriv = &adapter->stapriv;
+		int i;
+
+		_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+		phead = &pstapriv->asoc_list;
+		plist = get_next(phead);
+
+		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
+			int stainfo_offset;
+
+			sta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+			plist = get_next(plist);
+
+			stainfo_offset = rtw_stainfo_offset(pstapriv, sta);
+			if (stainfo_offset_valid(stainfo_offset))
+				peers[peer_num++] = stainfo_offset;
+		}
+
+		_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+		for (i = 0; i < peer_num; i++) {
+			sta = rtw_get_stainfo_by_offset(pstapriv, peers[i]);
+			if (sta)
+				adj_cnt += rx_ampdu_apply_sta(adapter, sta, accept, size);
+		}
+	}
+
+	return adj_cnt;
+}
+
+unsigned int OnAction_back(_adapter *padapter, union recv_frame *precv_frame)
+{
+	u8 *addr;
+	struct sta_info *psta=NULL;
+	struct recv_reorder_ctrl *preorder_ctrl;
+	unsigned char		*frame_body;
+	unsigned char		category, action;
+	unsigned short	tid, status, reason_code = 0;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+#ifdef CONFIG_80211N_HT
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	//check RA matches or not	
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
+		return _SUCCESS;
+
+/*
+	//check A1 matches or not
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), get_da(pframe), ETH_ALEN))
+		return _SUCCESS;
+*/
+
+	if((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)	
+		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+			return _SUCCESS;
+
+	addr = GetAddr2Ptr(pframe);
+	psta = rtw_get_stainfo(pstapriv, addr);
+
+	if(psta==NULL)
+		return _SUCCESS;
+
+	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+	category = frame_body[0];
+	if (category == RTW_WLAN_CATEGORY_BACK)// representing Block Ack
+	{
+#ifdef CONFIG_TDLS
+		if((psta->tdls_sta_state & TDLS_LINKED_STATE) && 
+			(psta->htpriv.ht_option==_TRUE) &&
+			(psta->htpriv.ampdu_enable==_TRUE))
+		{
+			DBG_871X("Recv [%s] from direc link\n", __FUNCTION__);
+		}
+		else
+#endif //CONFIG_TDLS
+		if (!pmlmeinfo->HT_enable)
+		{
+			return _SUCCESS;
+		}
+
+		action = frame_body[1];
+		DBG_871X("%s, action=%d\n", __FUNCTION__, action);
+		switch (action)
+		{
+			case RTW_WLAN_ACTION_ADDBA_REQ: //ADDBA request
+
+				_rtw_memcpy(&(pmlmeinfo->ADDBA_req), &(frame_body[2]), sizeof(struct ADDBA_request));
+				//process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), GetAddr3Ptr(pframe));
+				process_addba_req(padapter, (u8*)&(pmlmeinfo->ADDBA_req), addr);
+								
+				break;
+
+			case RTW_WLAN_ACTION_ADDBA_RESP: //ADDBA response
+
+				//status = frame_body[3] | (frame_body[4] << 8); //endian issue
+				status = RTW_GET_LE16(&frame_body[3]);
+				tid = ((frame_body[5] >> 2) & 0x7);
+
+				if (status == 0)
+				{	//successful					
+					DBG_871X("agg_enable for TID=%d\n", tid);
+					psta->htpriv.agg_enable_bitmap |= 1 << tid;					
+					psta->htpriv.candidate_tid_bitmap &= ~BIT(tid);				
+				}
+				else
+				{					
+					psta->htpriv.agg_enable_bitmap &= ~BIT(tid);					
+				}
+
+				if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
+				{
+					DBG_871X("%s alive check - rx ADDBA response\n", __func__);
+					psta->htpriv.agg_enable_bitmap &= ~BIT(tid);
+					psta->expire_to = pstapriv->expire_to;
+					psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+				}
+
+				//DBG_871X("marc: ADDBA RSP: %x\n", pmlmeinfo->agg_enable_bitmap);
+				break;
+
+			case RTW_WLAN_ACTION_DELBA: //DELBA
+				if ((frame_body[3] & BIT(3)) == 0)
+				{
+					psta->htpriv.agg_enable_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
+					psta->htpriv.candidate_tid_bitmap &= ~(1 << ((frame_body[3] >> 4) & 0xf));
+					
+					//reason_code = frame_body[4] | (frame_body[5] << 8);
+					reason_code = RTW_GET_LE16(&frame_body[4]);
+				}
+				else if((frame_body[3] & BIT(3)) == BIT(3))
+				{						
+					tid = (frame_body[3] >> 4) & 0x0F;
+				
+					preorder_ctrl = &psta->recvreorder_ctrl[tid];
+					preorder_ctrl->enable = _FALSE;
+					preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
+				}
+				
+				DBG_871X("%s(): DELBA: %x(%x)\n", __FUNCTION__,pmlmeinfo->agg_enable_bitmap, reason_code);
+				//todo: how to notify the host while receiving DELETE BA
+				break;
+
+			default:
+				break;
+		}
+	}
+#endif //CONFIG_80211N_HT
+	return _SUCCESS;
+}
+
+#ifdef CONFIG_P2P
+
+static int get_reg_classes_full_count(struct p2p_channels channel_list) {
+	int cnt = 0;
+	int i;
+
+	for (i = 0; i < channel_list.reg_classes; i++) {
+		cnt += channel_list.reg_class[i].channels;
+	}
+
+	return cnt;
+}
+
+static void get_channel_cnt_24g_5gl_5gh(  struct mlme_ext_priv *pmlmeext, u8* p24g_cnt, u8* p5gl_cnt, u8* p5gh_cnt )
+{
+	int	i = 0;
+
+	*p24g_cnt = 0;
+	*p5gl_cnt = 0;
+	*p5gh_cnt = 0;	
+	
+	for( i = 0; i < pmlmeext->max_chan_nums; i++ )
+	{
+		if ( pmlmeext->channel_set[ i ].ChannelNum <= 14 )
+		{
+			(*p24g_cnt)++;
+		}
+		else if ( ( pmlmeext->channel_set[ i ].ChannelNum > 14 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 48 ) )
+		{
+			//	Just include the channel 36, 40, 44, 48 channels for 5G low
+			(*p5gl_cnt)++;
+		}
+		else if ( ( pmlmeext->channel_set[ i ].ChannelNum >= 149 ) && ( pmlmeext->channel_set[ i ].ChannelNum <= 161 ) )
+		{
+			//	Just include the channel 149, 153, 157, 161 channels for 5G high
+			(*p5gh_cnt)++;
+		}
+	}
+}
+
+void issue_p2p_GO_request(_adapter *padapter, u8* raddr)
+{
+
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_GO_NEGO_REQ;
+	u8			wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
+	u8			wpsielen = 0, p2pielen = 0, i;
+	u8			channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
+	u16			len_channellist_attr = 0;
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo);
+
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	DBG_871X( "[%s] In\n", __FUNCTION__ );
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pwdinfo->negotiation_dialog_token = 1;	//	Initialize the dialog value
+	pframe = rtw_set_fixed_ie(pframe, 1, &pwdinfo->negotiation_dialog_token, &(pattrib->pktlen));
+
+	
+
+	//	WPS Section
+	wpsielen = 0;
+	//	WPS OUI
+	*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+	wpsielen += 4;
+
+	//	WPS version
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+	wpsielen += 2;
+
+	//	Value:
+	wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
+
+	//	Device Password ID
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+	wpsielen += 2;
+
+	//	Value:
+
+	if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN )
+	{
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
+	}
+	else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN )
+	{
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
+	}
+	else if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC )
+	{
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
+	}
+
+	wpsielen += 2;
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
+
+
+	//	P2P IE Section.
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20110306
+	//	According to the P2P Specification, the group negoitation request frame should contain 9 P2P attributes
+	//	1. P2P Capability
+	//	2. Group Owner Intent
+	//	3. Configuration Timeout
+	//	4. Listen Channel
+	//	5. Extended Listen Timing
+	//	6. Intended P2P Interface Address
+	//	7. Channel List
+	//	8. P2P Device Info
+	//	9. Operating Channel
+
+
+	//	P2P Capability
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Device Capability Bitmap, 1 byte
+	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+
+	//	Group Capability Bitmap, 1 byte
+	if ( pwdinfo->persistent_supported )
+	{
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
+	}
+	else
+	{
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
+	}
+
+
+	//	Group Owner Intent
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Todo the tie breaker bit.
+	p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) &  0xFE );
+
+	//	Configuration Timeout
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P GO
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P Client
+
+
+	//	Listen Channel
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Operating Class
+	p2pie[ p2pielen++ ] = 0x51;	//	Copy from SD7
+	
+	//	Channel Number
+	p2pie[ p2pielen++ ] = pwdinfo->listen_channel;	//	listening channel number
+	
+
+	//	Extended Listen Timing ATTR
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Availability Period
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+	p2pielen += 2;
+
+	//	Availability Interval
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+	p2pielen += 2;
+
+
+	//	Intended P2P Interface Address
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+	p2pielen += ETH_ALEN;
+
+
+	//	Channel List
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
+
+	// Length:
+	// Country String(3)
+	// + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
+	// + number of channels in all classes
+	len_channellist_attr = 3
+	   + (1 + 1) * (u16)(pmlmeext->channel_list.reg_classes)
+	   + get_reg_classes_full_count(pmlmeext->channel_list);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
+	}
+	else
+	{
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+	}
+#else
+
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+
+#endif
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Channel Entry List
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		_adapter *pbuddy_adapter = padapter->pbuddy_adapter;	
+		struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+		//	Operating Class
+		if ( pbuddy_mlmeext->cur_channel > 14 )
+		{
+			if ( pbuddy_mlmeext->cur_channel >= 149 )
+			{
+				p2pie[ p2pielen++ ] = 0x7c;
+			}
+			else
+			{
+				p2pie[ p2pielen++ ] = 0x73;
+			}
+		}
+		else
+		{
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+
+		//	Number of Channels
+		//	Just support 1 channel and this channel is AP's channel
+		p2pie[ p2pielen++ ] = 1;
+
+		//	Channel List
+		p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
+	}
+	else
+	{
+		int i,j;
+		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+			//	Operating Class
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+			//	Number of Channels
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+			//	Channel List
+			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+			}
+		}
+	}
+#else // CONFIG_CONCURRENT_MODE
+	{
+		int i,j;
+		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+			//	Operating Class
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+			//	Number of Channels
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+			//	Channel List
+			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+			}
+		}
+	}
+#endif // CONFIG_CONCURRENT_MODE
+
+	//	Device Info
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
+	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+	p2pielen += 2;
+
+	//	Value:
+	//	P2P Device Address
+	_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+	p2pielen += ETH_ALEN;
+
+	//	Config Method
+	//	This field should be big endian. Noted by P2P specification.
+
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
+
+	p2pielen += 2;
+
+	//	Primary Device Type
+	//	Category ID
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+	p2pielen += 2;
+
+	//	OUI
+	*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+	p2pielen += 4;
+
+	//	Sub Category ID
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+	p2pielen += 2;
+
+	//	Number of Secondary Device Types
+	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
+
+	//	Device Name
+	//	Type:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+	p2pielen += 2;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
+	p2pielen += pwdinfo->device_name_len;	
+	
+
+	//	Operating Channel
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Operating Class
+	if ( pwdinfo->operating_channel <= 14 )
+	{
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x51;
+	}
+	else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
+	{
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x73;
+	}
+	else
+	{
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x7c;
+	}
+
+	//	Channel Number
+	p2pie[ p2pielen++ ] = pwdinfo->operating_channel;	//	operating channel number
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );		
+
+#ifdef CONFIG_WFD
+	wfdielen = build_nego_req_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+
+void issue_p2p_GO_response(_adapter *padapter, u8* raddr, u8* frame_body,uint len, u8 result)
+{
+
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_GO_NEGO_RESP;
+	u8			wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
+	u8			p2pielen = 0, i;
+	uint			wpsielen = 0;
+	u16			wps_devicepassword_id = 0x0000;
+	uint			wps_devicepassword_id_len = 0;
+	u8			channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh;
+	u16			len_channellist_attr = 0;
+	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo);
+
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	DBG_871X( "[%s] In, result = %d\n", __FUNCTION__,  result );
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pwdinfo->negotiation_dialog_token = frame_body[7];	//	The Dialog Token of provisioning discovery request frame.
+	pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
+
+	//	Commented by Albert 20110328
+	//	Try to get the device password ID from the WPS IE of group negotiation request frame
+	//	WiFi Direct test plan 5.1.15
+	rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, wpsie, &wpsielen);
+	rtw_get_wps_attr_content( wpsie, wpsielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
+	wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
+
+	_rtw_memset( wpsie, 0x00, 255 );
+	wpsielen = 0;
+
+	//	WPS Section
+	wpsielen = 0;
+	//	WPS OUI
+	*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+	wpsielen += 4;
+
+	//	WPS version
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+	wpsielen += 2;
+
+	//	Value:
+	wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
+
+	//	Device Password ID
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+	wpsielen += 2;
+
+	//	Value:
+	if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
+	{
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );
+	}
+	else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
+	{
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_USER_SPEC );
+	}
+	else
+	{
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_PBC );
+	}
+	wpsielen += 2;
+
+	//	Commented by Kurt 20120113
+	//	If some device wants to do p2p handshake without sending prov_disc_req
+	//	We have to get peer_req_cm from here.
+	if(_rtw_memcmp( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3) )
+	{
+		if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
+		{
+			_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
+		}
+		else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
+		{
+			_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );	
+		}
+		else
+		{
+			_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );	
+		}
+	}
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
+
+
+	//	P2P IE Section.
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20100908
+	//	According to the P2P Specification, the group negoitation response frame should contain 9 P2P attributes
+	//	1. Status
+	//	2. P2P Capability
+	//	3. Group Owner Intent
+	//	4. Configuration Timeout
+	//	5. Operating Channel
+	//	6. Intended P2P Interface Address
+	//	7. Channel List
+	//	8. Device Info
+	//	9. Group ID	( Only GO )
+
+
+	//	ToDo:
+
+	//	P2P Status
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = result;
+	
+	//	P2P Capability
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Device Capability Bitmap, 1 byte
+
+	if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
+	{
+		//	Commented by Albert 2011/03/08
+		//	According to the P2P specification
+		//	if the sending device will be client, the P2P Capability should be reserved of group negotation response frame
+		p2pie[ p2pielen++ ] = 0;
+	}
+	else
+	{
+		//	Be group owner or meet the error case
+		p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+	}
+	
+	//	Group Capability Bitmap, 1 byte
+	if ( pwdinfo->persistent_supported )
+	{
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
+	}
+	else
+	{
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
+	}
+
+	//	Group Owner Intent
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_GO_INTENT;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
+	p2pielen += 2;
+
+	//	Value:
+	if ( pwdinfo->peer_intent & 0x01 )
+	{
+		//	Peer's tie breaker bit is 1, our tie breaker bit should be 0
+		p2pie[ p2pielen++ ] = ( pwdinfo->intent << 1 );
+	}
+	else
+	{
+		//	Peer's tie breaker bit is 0, our tie breaker bit should be 1
+		p2pie[ p2pielen++ ] = ( ( pwdinfo->intent << 1 ) | BIT(0) );
+	}
+
+
+	//	Configuration Timeout
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P GO
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P Client
+
+	//	Operating Channel
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Operating Class
+	if ( pwdinfo->operating_channel <= 14 )
+	{
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x51;
+	}
+	else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
+	{
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x73;
+	}
+	else
+	{
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x7c;
+	}
+	
+	//	Channel Number
+	p2pie[ p2pielen++ ] = pwdinfo->operating_channel;	//	operating channel number
+
+	//	Intended P2P Interface Address	
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_INTENTED_IF_ADDR;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+	p2pielen += ETH_ALEN;
+
+	//	Channel List
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
+
+	// Country String(3)
+	// + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
+	// + number of channels in all classes
+	len_channellist_attr = 3
+	   + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
+	   + get_reg_classes_full_count(pmlmeext->channel_list);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
+	}
+	else
+	{
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+	}
+#else
+
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+
+ #endif
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Channel Entry List
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		_adapter *pbuddy_adapter = padapter->pbuddy_adapter;	
+		struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+		//	Operating Class
+		if ( pbuddy_mlmeext->cur_channel > 14 )
+		{
+			if ( pbuddy_mlmeext->cur_channel >= 149 )
+			{
+				p2pie[ p2pielen++ ] = 0x7c;
+			}
+			else
+			{
+				p2pie[ p2pielen++ ] = 0x73;
+			}
+		}
+		else
+		{
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+
+		//	Number of Channels
+		//	Just support 1 channel and this channel is AP's channel
+		p2pie[ p2pielen++ ] = 1;
+
+		//	Channel List
+		p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
+	}
+	else
+	{
+		int i, j;
+		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+			//	Operating Class
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+			//	Number of Channels
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+			//	Channel List
+			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+			}
+		}
+	}
+#else // CONFIG_CONCURRENT_MODE
+	{
+		int i, j;
+		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+			//	Operating Class
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+			//	Number of Channels
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+			//	Channel List
+			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+			}
+		}
+	}
+#endif // CONFIG_CONCURRENT_MODE
+
+	
+	//	Device Info
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
+	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+	p2pielen += 2;
+
+	//	Value:
+	//	P2P Device Address
+	_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+	p2pielen += ETH_ALEN;
+
+	//	Config Method
+	//	This field should be big endian. Noted by P2P specification.
+
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
+
+	p2pielen += 2;
+
+	//	Primary Device Type
+	//	Category ID
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+	p2pielen += 2;
+
+	//	OUI
+	*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+	p2pielen += 4;
+
+	//	Sub Category ID
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+	p2pielen += 2;
+
+	//	Number of Secondary Device Types
+	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
+
+	//	Device Name
+	//	Type:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+	p2pielen += 2;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name , pwdinfo->device_name_len );
+	p2pielen += pwdinfo->device_name_len;	
+	
+	if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
+	{
+		//	Group ID Attribute
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
+
+		//	Length:
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
+		p2pielen += 2;
+
+		//	Value:
+		//	p2P Device Address
+		_rtw_memcpy( p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
+		p2pielen += ETH_ALEN;
+
+		//	SSID
+		_rtw_memcpy( p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
+		p2pielen += pwdinfo->nego_ssidlen;
+		
+	}
+	
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );	
+	
+#ifdef CONFIG_WFD
+	wfdielen = build_nego_resp_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+void issue_p2p_GO_confirm(_adapter *padapter, u8* raddr, u8 result)
+{
+
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_GO_NEGO_CONF;
+	u8			wpsie[ 255 ] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
+	u8			wpsielen = 0, p2pielen = 0;
+	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo);
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	DBG_871X( "[%s] In\n", __FUNCTION__ );
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(pwdinfo->negotiation_dialog_token), &(pattrib->pktlen));
+
+	
+
+	//	P2P IE Section.
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20110306
+	//	According to the P2P Specification, the group negoitation request frame should contain 5 P2P attributes
+	//	1. Status
+	//	2. P2P Capability
+	//	3. Operating Channel
+	//	4. Channel List
+	//	5. Group ID	( if this WiFi is GO )
+
+	//	P2P Status
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = result;
+
+	//	P2P Capability
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Device Capability Bitmap, 1 byte
+	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+	
+	//	Group Capability Bitmap, 1 byte
+	if ( pwdinfo->persistent_supported )
+	{
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN | P2P_GRPCAP_PERSISTENT_GROUP;
+	}
+	else
+	{
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_CROSS_CONN;
+	}
+
+
+	//	Operating Channel
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+
+	if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
+	{
+		if ( pwdinfo->peer_operating_ch <= 14 )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+		else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x73;
+		}
+		else
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x7c;
+		}
+		
+		p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
+	}
+	else
+	{
+		if ( pwdinfo->operating_channel <= 14 )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+		else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x73;
+		}
+		else
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x7c;
+		}
+		
+		//	Channel Number
+		p2pie[ p2pielen++ ] = pwdinfo->operating_channel;		//	Use the listen channel as the operating channel
+	}
+
+
+	//	Channel List
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
+
+	*(u16*) ( p2pie + p2pielen ) = 6;
+	p2pielen += 2;
+
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Value:
+	if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
+	{
+		if ( pwdinfo->peer_operating_ch <= 14 )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+		else if ( ( pwdinfo->peer_operating_ch >= 36 ) && ( pwdinfo->peer_operating_ch <= 48 ) )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x73;
+		}
+		else
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x7c;
+		}
+		p2pie[ p2pielen++ ] = 1;
+		p2pie[ p2pielen++ ] = pwdinfo->peer_operating_ch;
+	}
+	else
+	{
+		if ( pwdinfo->operating_channel <= 14 )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+		else if ( ( pwdinfo->operating_channel >= 36 ) && ( pwdinfo->operating_channel <= 48 ) )
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x73;
+		}
+		else
+		{
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x7c;
+		}
+		
+		//	Channel Number
+		p2pie[ p2pielen++ ] = 1;
+		p2pie[ p2pielen++ ] = pwdinfo->operating_channel;		//	Use the listen channel as the operating channel
+	}
+
+	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
+	{
+		//	Group ID Attribute
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
+
+		//	Length:
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + pwdinfo->nego_ssidlen );
+		p2pielen += 2;
+
+		//	Value:
+		//	p2P Device Address
+		_rtw_memcpy( p2pie + p2pielen , pwdinfo->device_addr, ETH_ALEN );
+		p2pielen += ETH_ALEN;
+
+		//	SSID
+		_rtw_memcpy( p2pie + p2pielen, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
+		p2pielen += pwdinfo->nego_ssidlen;
+	}
+	
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
+	
+#ifdef CONFIG_WFD
+	wfdielen = build_nego_confirm_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+void issue_p2p_invitation_request(_adapter *padapter, u8* raddr )
+{
+
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_INVIT_REQ;
+	u8			p2pie[ 255 ] = { 0x00 };
+	u8			p2pielen = 0, i;
+	u8			dialogToken = 3;
+	u8			channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
+	u16			len_channellist_attr = 0;	
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+#ifdef CONFIG_CONCURRENT_MODE
+	_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
+	struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+	struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+	struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif
+
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo);
+
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
+
+	//	P2P IE Section.
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20101011
+	//	According to the P2P Specification, the P2P Invitation request frame should contain 7 P2P attributes
+	//	1. Configuration Timeout
+	//	2. Invitation Flags
+	//	3. Operating Channel	( Only GO )
+	//	4. P2P Group BSSID	( Should be included if I am the GO )
+	//	5. Channel List
+	//	6. P2P Group ID
+	//	7. P2P Device Info
+
+	//	Configuration Timeout
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P GO
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P Client
+
+	//	Invitation Flags
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_INVITATION_FLAGS;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = P2P_INVITATION_FLAGS_PERSISTENT;
+
+
+	//	Operating Channel
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Operating Class
+	if ( pwdinfo->invitereq_info.operating_ch <= 14 )
+		p2pie[ p2pielen++ ] = 0x51;
+	else if ( ( pwdinfo->invitereq_info.operating_ch >= 36 ) && ( pwdinfo->invitereq_info.operating_ch <= 48 ) )
+		p2pie[ p2pielen++ ] = 0x73;
+	else
+		p2pie[ p2pielen++ ] = 0x7c;
+	
+	//	Channel Number
+	p2pie[ p2pielen++ ] = pwdinfo->invitereq_info.operating_ch;	//	operating channel number
+
+	if (_rtw_memcmp(adapter_mac_addr(padapter), pwdinfo->invitereq_info.go_bssid, ETH_ALEN))
+	{
+		//	P2P Group BSSID
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
+
+		//	Length:
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
+		p2pielen += 2;
+
+		//	Value:
+		//	P2P Device Address for GO
+		_rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
+		p2pielen += ETH_ALEN;
+	}
+
+	//	Channel List
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
+
+	
+	//	Length:
+	// Country String(3)
+	// + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
+	// + number of channels in all classes
+	len_channellist_attr = 3
+	   + (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
+	   + get_reg_classes_full_count(pmlmeext->channel_list);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
+	}
+	else
+	{
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+	}
+#else
+
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+
+ #endif
+	p2pielen += 2;
+
+	//	Value:
+	//	Country String
+	p2pie[ p2pielen++ ] = 'X';
+	p2pie[ p2pielen++ ] = 'X';
+	
+	//	The third byte should be set to 0x04.
+	//	Described in the "Operating Channel Attribute" section.
+	p2pie[ p2pielen++ ] = 0x04;
+
+	//	Channel Entry List
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		_adapter *pbuddy_adapter = padapter->pbuddy_adapter;	
+		struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+		//	Operating Class
+		if ( pbuddy_mlmeext->cur_channel > 14 )
+		{
+			if ( pbuddy_mlmeext->cur_channel >= 149 )
+			{
+				p2pie[ p2pielen++ ] = 0x7c;
+			}
+			else
+			{
+				p2pie[ p2pielen++ ] = 0x73;
+			}
+		}
+		else
+		{
+			p2pie[ p2pielen++ ] = 0x51;
+		}
+
+		//	Number of Channels
+		//	Just support 1 channel and this channel is AP's channel
+		p2pie[ p2pielen++ ] = 1;
+
+		//	Channel List
+		p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
+	}
+	else
+	{
+		int i, j;
+		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+			//	Operating Class
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+			//	Number of Channels
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+			//	Channel List
+			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+			}
+		}
+	}
+#else // CONFIG_CONCURRENT_MODE
+	{
+		int i, j;
+		for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+			//	Operating Class
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+			//	Number of Channels
+			p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+			//	Channel List
+			for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+			}
+		}
+	}
+#endif // CONFIG_CONCURRENT_MODE
+
+
+	//	P2P Group ID
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 6 + pwdinfo->invitereq_info.ssidlen );
+	p2pielen += 2;
+
+	//	Value:
+	//	P2P Device Address for GO
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_bssid, ETH_ALEN );
+	p2pielen += ETH_ALEN;
+
+	//	SSID
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->invitereq_info.go_ssid, pwdinfo->invitereq_info.ssidlen );
+	p2pielen += pwdinfo->invitereq_info.ssidlen;
+	
+
+	//	Device Info
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
+	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+	p2pielen += 2;
+	
+	//	Value:
+	//	P2P Device Address
+	_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+	p2pielen += ETH_ALEN;
+
+	//	Config Method
+	//	This field should be big endian. Noted by P2P specification.
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
+	p2pielen += 2;
+
+	//	Primary Device Type
+	//	Category ID
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+	p2pielen += 2;
+
+	//	OUI
+	*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+	p2pielen += 4;
+
+	//	Sub Category ID
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+	p2pielen += 2;
+
+	//	Number of Secondary Device Types
+	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
+
+	//	Device Name
+	//	Type:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+	p2pielen += 2;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
+	p2pielen += pwdinfo->device_name_len;
+		
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );	
+
+#ifdef CONFIG_WFD
+	wfdielen = build_invitation_req_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+void issue_p2p_invitation_response(_adapter *padapter, u8* raddr, u8 dialogToken, u8 status_code)
+{
+
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_INVIT_RESP;
+	u8			p2pie[ 255 ] = { 0x00 };
+	u8			p2pielen = 0, i;
+	u8			channel_cnt_24g = 0, channel_cnt_5gl = 0, channel_cnt_5gh = 0;
+	u16			len_channellist_attr = 0;
+#ifdef CONFIG_CONCURRENT_MODE
+	_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
+	struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+	struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+	struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif	
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo);
+
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, raddr,  ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));
+
+	//	P2P IE Section.
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20101005
+	//	According to the P2P Specification, the P2P Invitation response frame should contain 5 P2P attributes
+	//	1. Status
+	//	2. Configuration Timeout
+	//	3. Operating Channel	( Only GO )
+	//	4. P2P Group BSSID	( Only GO )
+	//	5. Channel List
+
+	//	P2P Status
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_STATUS;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0001 );
+	p2pielen += 2;
+
+	//	Value:
+	//	When status code is P2P_STATUS_FAIL_INFO_UNAVAILABLE.
+	//	Sent the event receiving the P2P Invitation Req frame to DMP UI.
+	//	DMP had to compare the MAC address to find out the profile.
+	//	So, the WiFi driver will send the P2P_STATUS_FAIL_INFO_UNAVAILABLE to NB.
+	//	If the UI found the corresponding profile, the WiFi driver sends the P2P Invitation Req
+	//	to NB to rebuild the persistent group.
+	p2pie[ p2pielen++ ] = status_code;
+	
+	//	Configuration Timeout
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CONF_TIMEOUT;
+
+	//	Length:
+	*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	p2pielen += 2;
+
+	//	Value:
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P GO
+	p2pie[ p2pielen++ ] = 200;	//	2 seconds needed to be the P2P Client
+
+	if( status_code == P2P_STATUS_SUCCESS )
+	{
+		if( rtw_p2p_chk_role( pwdinfo, P2P_ROLE_GO ) )
+		{
+			//	The P2P Invitation request frame asks this Wi-Fi device to be the P2P GO
+			//	In this case, the P2P Invitation response frame should carry the two more P2P attributes.
+			//	First one is operating channel attribute.
+			//	Second one is P2P Group BSSID attribute.
+
+			//	Operating Channel
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
+
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+			p2pielen += 2;
+
+			//	Value:
+			//	Country String
+			p2pie[ p2pielen++ ] = 'X';
+			p2pie[ p2pielen++ ] = 'X';
+		
+			//	The third byte should be set to 0x04.
+			//	Described in the "Operating Channel Attribute" section.
+			p2pie[ p2pielen++ ] = 0x04;
+
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x51;	//	Copy from SD7
+		
+			//	Channel Number
+			p2pie[ p2pielen++ ] = pwdinfo->operating_channel;	//	operating channel number
+			
+
+			//	P2P Group BSSID
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_BSSID;
+
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN );
+			p2pielen += 2;
+
+			//	Value:
+			//	P2P Device Address for GO
+			_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+			p2pielen += ETH_ALEN;
+
+		}
+
+		//	Channel List
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_CH_LIST;
+
+		//	Length:
+		// Country String(3)
+		// + ( Operating Class (1) + Number of Channels(1) ) * Operation Classes (?)
+		// + number of channels in all classes
+		len_channellist_attr = 3
+			+ (1 + 1) * (u16)pmlmeext->channel_list.reg_classes
+			+ get_reg_classes_full_count(pmlmeext->channel_list);
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+		{
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 5 + 1 );
+		}
+		else
+		{
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+		}
+#else
+
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( len_channellist_attr );
+
+#endif
+		p2pielen += 2;
+
+		//	Value:
+		//	Country String
+		p2pie[ p2pielen++ ] = 'X';
+		p2pie[ p2pielen++ ] = 'X';
+
+		//	The third byte should be set to 0x04.
+		//	Described in the "Operating Channel Attribute" section.
+		p2pie[ p2pielen++ ] = 0x04;
+
+		//	Channel Entry List
+#ifdef CONFIG_CONCURRENT_MODE
+		if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+		{
+			_adapter *pbuddy_adapter = padapter->pbuddy_adapter;	
+			struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+			//	Operating Class
+			if ( pbuddy_mlmeext->cur_channel > 14 )
+			{
+				if ( pbuddy_mlmeext->cur_channel >= 149 )
+				{
+					p2pie[ p2pielen++ ] = 0x7c;
+				}
+				else
+				{
+					p2pie[ p2pielen++ ] = 0x73;
+				}
+			}
+			else
+			{
+				p2pie[ p2pielen++ ] = 0x51;
+			}
+
+			//	Number of Channels
+			//	Just support 1 channel and this channel is AP's channel
+			p2pie[ p2pielen++ ] = 1;
+
+			//	Channel List
+			p2pie[ p2pielen++ ] = pbuddy_mlmeext->cur_channel;
+		}
+		else
+		{
+			int i, j;
+			for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+				//	Operating Class
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+				//	Number of Channels
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+				//	Channel List
+				for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+					p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+				}
+			}
+		}
+#else // CONFIG_CONCURRENT_MODE
+		{
+			int i, j;
+			for (j = 0; j < pmlmeext->channel_list.reg_classes; j++) {
+				//	Operating Class
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].reg_class;
+
+				//	Number of Channels
+				p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channels;
+
+				//	Channel List
+				for (i = 0; i < pmlmeext->channel_list.reg_class[j].channels; i++) {
+					p2pie[p2pielen++] = pmlmeext->channel_list.reg_class[j].channel[i];
+				}
+			}
+		}
+#endif // CONFIG_CONCURRENT_MODE
+	}
+		
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );	
+	
+#ifdef CONFIG_WFD
+	wfdielen = build_invitation_resp_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+void issue_p2p_provision_request(_adapter *padapter, u8* pssid, u8 ussidlen, u8* pdev_raddr )
+{
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u8			dialogToken = 1;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_PROVISION_DISC_REQ;
+	u8			wpsie[ 100 ] = { 0x00 };
+	u8			wpsielen = 0;
+	u32			p2pielen = 0;
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	DBG_871X( "[%s] In\n", __FUNCTION__ );
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, pdev_raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, pdev_raddr, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));		
+
+	p2pielen = build_prov_disc_request_p2p_ie( pwdinfo, pframe, pssid, ussidlen, pdev_raddr );
+
+	pframe += p2pielen;
+	pattrib->pktlen += p2pielen;
+
+	wpsielen = 0;
+	//	WPS OUI
+	*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+	wpsielen += 4;
+
+	//	WPS version
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+	wpsielen += 2;
+
+	//	Value:
+	wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
+
+	//	Config Method
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+	wpsielen += 2;
+
+	//	Value:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->tx_prov_disc_info.wps_config_method_request );
+	wpsielen += 2;
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
+
+
+#ifdef CONFIG_WFD
+	wfdielen = build_provdisc_req_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+
+u8 is_matched_in_profilelist( u8* peermacaddr, struct profile_info* profileinfo )
+{
+	u8 i, match_result = 0;
+
+	DBG_871X( "[%s] peermac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
+	  	    peermacaddr[0], peermacaddr[1],peermacaddr[2],peermacaddr[3],peermacaddr[4],peermacaddr[5]);
+	
+	for( i = 0; i < P2P_MAX_PERSISTENT_GROUP_NUM; i++, profileinfo++ )
+	{
+	       DBG_871X( "[%s] profileinfo_mac = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
+		   	    profileinfo->peermac[0], profileinfo->peermac[1],profileinfo->peermac[2],profileinfo->peermac[3],profileinfo->peermac[4],profileinfo->peermac[5]);		   
+		if ( _rtw_memcmp( peermacaddr, profileinfo->peermac, ETH_ALEN ) )
+		{
+			match_result = 1;
+			DBG_871X( "[%s] Match!\n", __FUNCTION__ );
+			break;
+		}
+	}
+	
+	return (match_result );
+}
+
+void issue_probersp_p2p(_adapter *padapter, unsigned char *da)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;	
+	unsigned char					*mac;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	//WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	u16					beacon_interval = 100;
+	u16					capInfo = 0;
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	u8					wpsie[255] = { 0x00 };
+	u32					wpsielen = 0, p2pielen = 0;
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+#ifdef CONFIG_INTEL_WIDI
+	u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
+#endif //CONFIG_INTEL_WIDI
+
+	//DBG_871X("%s\n", __FUNCTION__);
+	
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+	
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);	
+	
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+		
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;	
+	
+	mac = adapter_mac_addr(padapter);
+	
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+	
+	//	Use the device address for BSSID field.	
+	_rtw_memcpy(pwlanhdr->addr3, mac, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(fctrl, WIFI_PROBERSP);
+	
+	pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = pattrib->hdrlen;
+	pframe += pattrib->hdrlen;
+
+	//timestamp will be inserted by hardware
+	pframe += 8;
+	pattrib->pktlen += 8;
+
+	// beacon interval: 2 bytes
+	_rtw_memcpy(pframe, (unsigned char *) &beacon_interval, 2); 
+	pframe += 2;
+	pattrib->pktlen += 2;
+
+	//	capability info: 2 bytes
+	//	ESS and IBSS bits must be 0 (defined in the 3.1.2.1.1 of WiFi Direct Spec)
+	capInfo |= cap_ShortPremble;
+	capInfo |= cap_ShortSlot;
+	
+	_rtw_memcpy(pframe, (unsigned char *) &capInfo, 2);
+	pframe += 2;
+	pattrib->pktlen += 2;
+
+
+	// SSID
+	pframe = rtw_set_ie(pframe, _SSID_IE_, 7, pwdinfo->p2p_wildcard_ssid, &pattrib->pktlen);
+
+	// supported rates...
+	//	Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )
+	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
+
+	// DS parameter set
+	pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&pwdinfo->listen_channel, &pattrib->pktlen);
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
+	{
+		if( pmlmepriv->wps_probe_resp_ie != NULL && pmlmepriv->p2p_probe_resp_ie != NULL )
+		{
+			//WPS IE
+			_rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, pmlmepriv->wps_probe_resp_ie_len);
+			pattrib->pktlen += pmlmepriv->wps_probe_resp_ie_len;
+			pframe += pmlmepriv->wps_probe_resp_ie_len;
+
+			//P2P IE
+			_rtw_memcpy(pframe, pmlmepriv->p2p_probe_resp_ie, pmlmepriv->p2p_probe_resp_ie_len);
+			pattrib->pktlen += pmlmepriv->p2p_probe_resp_ie_len;
+			pframe += pmlmepriv->p2p_probe_resp_ie_len;
+		}
+	}
+	else
+#endif //CONFIG_IOCTL_CFG80211		
+	{
+
+		//	Todo: WPS IE
+		//	Noted by Albert 20100907
+		//	According to the WPS specification, all the WPS attribute is presented by Big Endian.
+
+		wpsielen = 0;
+		//	WPS OUI
+		*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+		wpsielen += 4;
+
+		//	WPS version
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+		wpsielen += 2;
+
+		//	Value:
+		wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
+
+#ifdef CONFIG_INTEL_WIDI
+		//	Commented by Kurt
+		//	Appended WiDi info. only if we did issued_probereq_widi(), and then we saved ven. ext. in pmlmepriv->sa_ext.
+		if(  _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE 
+			|| pmlmepriv->num_p2p_sdt != 0 )
+		{
+			//Sec dev type
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SEC_DEV_TYPE_LIST );
+			wpsielen += 2;
+
+			//	Length:
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
+			wpsielen += 2;
+
+			//	Value:
+			//	Category ID
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_DISPLAYS );
+			wpsielen += 2;
+
+			//	OUI
+			*(u32*) ( wpsie + wpsielen ) = cpu_to_be32( INTEL_DEV_TYPE_OUI );
+			wpsielen += 4;
+
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_WIDI_CONSUMER_SINK );
+			wpsielen += 2;
+
+			if(  _rtw_memcmp(pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN) == _FALSE )
+			{
+				//	Vendor Extension
+				_rtw_memcpy( wpsie + wpsielen, pmlmepriv->sa_ext, L2SDTA_SERVICE_VE_LEN );
+				wpsielen += L2SDTA_SERVICE_VE_LEN;
+			}
+		}
+#endif //CONFIG_INTEL_WIDI
+
+		//	WiFi Simple Config State
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SIMPLE_CONF_STATE );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+		wpsielen += 2;
+
+		//	Value:
+		wpsie[wpsielen++] = WPS_WSC_STATE_NOT_CONFIG;	//	Not Configured.
+
+		//	Response Type
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_RESP_TYPE );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+		wpsielen += 2;
+
+		//	Value:
+		wpsie[wpsielen++] = WPS_RESPONSE_TYPE_8021X;
+
+		//	UUID-E
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
+		wpsielen += 2;
+
+		//	Value:
+		if (pwdinfo->external_uuid == 0) {
+			_rtw_memset( wpsie + wpsielen, 0x0, 16 );
+			_rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);
+		} else {
+			_rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 );
+		}
+		wpsielen += 0x10;
+
+		//	Manufacturer
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MANUFACTURER );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0007 );
+		wpsielen += 2;
+
+		//	Value:
+		_rtw_memcpy( wpsie + wpsielen, "Realtek", 7 );
+		wpsielen += 7;
+
+		//	Model Name
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NAME );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0006 );
+		wpsielen += 2;	
+
+		//	Value:
+		_rtw_memcpy( wpsie + wpsielen, "8192CU", 6 );
+		wpsielen += 6;
+
+		//	Model Number
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_MODEL_NUMBER );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+		wpsielen += 2;
+
+		//	Value:
+		wpsie[ wpsielen++ ] = 0x31;		//	character 1
+
+		//	Serial Number
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_SERIAL_NUMBER );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( ETH_ALEN );
+		wpsielen += 2;
+
+		//	Value:
+		_rtw_memcpy( wpsie + wpsielen, "123456" , ETH_ALEN );
+		wpsielen += ETH_ALEN;
+
+		//	Primary Device Type
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
+		wpsielen += 2;
+
+		//	Value:
+		//	Category ID
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+		wpsielen += 2;
+
+		//	OUI
+		*(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
+		wpsielen += 4;
+
+		//	Sub Category ID
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+		wpsielen += 2;
+
+		//	Device Name
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
+		wpsielen += 2;
+
+		//	Value:
+		_rtw_memcpy( wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
+		wpsielen += pwdinfo->device_name_len;
+
+		//	Config Method
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+		wpsielen += 2;
+
+		//	Value:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
+		wpsielen += 2;
+		
+
+		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
+		
+
+		p2pielen = build_probe_resp_p2p_ie(pwdinfo, pframe);
+		pframe += p2pielen;
+		pattrib->pktlen += p2pielen;
+	}
+
+#ifdef CONFIG_WFD
+	wfdielen = rtw_append_probe_resp_wfd_ie(padapter, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+	
+
+	dump_mgntframe(padapter, pmgntframe);
+	
+	return;
+
+}
+
+int _issue_probereq_p2p(_adapter *padapter, u8 *da, int wait_ack)
+{
+	int ret = _FAIL;
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	unsigned char			*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short		*fctrl;
+	unsigned char			*mac;
+	unsigned char			bssrate[NumRates];
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	int	bssrate_len = 0;
+	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);	
+	u8					wpsie[255] = { 0x00 }, p2pie[ 255 ] = { 0x00 };
+	u16					wpsielen = 0, p2pielen = 0;
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		goto exit;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	mac = adapter_mac_addr(padapter);
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	if (da) {
+		_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+		_rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
+	} else {
+		if ( ( pwdinfo->p2p_info.scan_op_ch_only ) || ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
+		{
+			//	This two flags will be set when this is only the P2P client mode.
+			_rtw_memcpy(pwlanhdr->addr1, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr3, pwdinfo->p2p_peer_interface_addr, ETH_ALEN);
+		}
+		else
+		{
+			//	broadcast probe request frame
+			_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
+		}
+	}
+	_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_PROBEREQ);
+
+	pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
+	{
+		pframe = rtw_set_ie(pframe, _SSID_IE_, pwdinfo->tx_prov_disc_info.ssid.SsidLength, pwdinfo->tx_prov_disc_info.ssid.Ssid, &(pattrib->pktlen));
+	}
+	else
+	{
+		pframe = rtw_set_ie(pframe, _SSID_IE_, P2P_WILDCARD_SSID_LEN, pwdinfo->p2p_wildcard_ssid, &(pattrib->pktlen));
+	}
+	//	Use the OFDM rate in the P2P probe request frame. ( 6(B), 9(B), 12(B), 24(B), 36, 48, 54 )
+	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pwdinfo->support_rate, &pattrib->pktlen);
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
+	{
+		if( pmlmepriv->wps_probe_req_ie != NULL && pmlmepriv->p2p_probe_req_ie != NULL )
+		{
+			//WPS IE
+			_rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
+			pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
+			pframe += pmlmepriv->wps_probe_req_ie_len;
+
+			//P2P IE
+			_rtw_memcpy(pframe, pmlmepriv->p2p_probe_req_ie, pmlmepriv->p2p_probe_req_ie_len);
+			pattrib->pktlen += pmlmepriv->p2p_probe_req_ie_len;
+			pframe += pmlmepriv->p2p_probe_req_ie_len;
+		}
+	}
+	else
+#endif //CONFIG_IOCTL_CFG80211
+	{
+
+		//	WPS IE
+		//	Noted by Albert 20110221
+		//	According to the WPS specification, all the WPS attribute is presented by Big Endian.
+
+		wpsielen = 0;
+		//	WPS OUI
+		*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+		wpsielen += 4;
+
+		//	WPS version
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+		wpsielen += 2;
+
+		//	Value:
+		wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
+
+		if( pmlmepriv->wps_probe_req_ie == NULL )
+		{
+			//	UUID-E
+			//	Type:
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_UUID_E );
+			wpsielen += 2;
+
+			//	Length:
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0010 );
+			wpsielen += 2;
+
+			//	Value:
+			if (pwdinfo->external_uuid == 0) {
+				_rtw_memset( wpsie + wpsielen, 0x0, 16 );
+				_rtw_memcpy(wpsie + wpsielen, mac, ETH_ALEN);
+			} else {
+				_rtw_memcpy( wpsie + wpsielen, pwdinfo->uuid, 0x10 );
+			}
+			wpsielen += 0x10;
+
+			//	Config Method
+			//	Type:
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
+			wpsielen += 2;
+
+			//	Length:
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+			wpsielen += 2;
+
+			//	Value:
+			*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
+			wpsielen += 2;
+		}
+
+		//	Device Name
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( pwdinfo->device_name_len );
+		wpsielen += 2;
+
+		//	Value:
+		_rtw_memcpy( wpsie + wpsielen, pwdinfo->device_name, pwdinfo->device_name_len );
+		wpsielen += pwdinfo->device_name_len;
+
+		//	Primary Device Type
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0008 );
+		wpsielen += 2;
+
+		//	Value:
+		//	Category ID
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_CID_RTK_WIDI );
+		wpsielen += 2;
+
+		//	OUI
+		*(u32*) ( wpsie + wpsielen ) = cpu_to_be32( WPSOUI );
+		wpsielen += 4;
+
+		//	Sub Category ID
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_PDT_SCID_RTK_DMP );
+		wpsielen += 2;
+
+		//	Device Password ID
+		//	Type:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_DEVICE_PWID );
+		wpsielen += 2;
+
+		//	Length:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+		wpsielen += 2;
+
+		//	Value:
+		*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_DPID_REGISTRAR_SPEC );	//	Registrar-specified
+		wpsielen += 2;	
+
+		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );
+		
+		//	P2P OUI
+		p2pielen = 0;
+		p2pie[ p2pielen++ ] = 0x50;
+		p2pie[ p2pielen++ ] = 0x6F;
+		p2pie[ p2pielen++ ] = 0x9A;
+		p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+		//	Commented by Albert 20110221
+		//	According to the P2P Specification, the probe request frame should contain 5 P2P attributes
+		//	1. P2P Capability
+		//	2. P2P Device ID if this probe request wants to find the specific P2P device
+		//	3. Listen Channel
+		//	4. Extended Listen Timing
+		//	5. Operating Channel if this WiFi is working as the group owner now
+
+		//	P2P Capability
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+		//	Length:
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+		p2pielen += 2;
+
+		//	Value:
+		//	Device Capability Bitmap, 1 byte
+		p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+		
+		//	Group Capability Bitmap, 1 byte
+		if ( pwdinfo->persistent_supported )
+			p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+		else
+			p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
+
+		//	Listen Channel
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_LISTEN_CH;
+
+		//	Length:
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+		p2pielen += 2;
+
+		//	Value:
+		//	Country String
+		p2pie[ p2pielen++ ] = 'X';
+		p2pie[ p2pielen++ ] = 'X';
+		
+		//	The third byte should be set to 0x04.
+		//	Described in the "Operating Channel Attribute" section.
+		p2pie[ p2pielen++ ] = 0x04;
+
+		//	Operating Class
+		p2pie[ p2pielen++ ] = 0x51;	//	Copy from SD7
+		
+		//	Channel Number
+		p2pie[ p2pielen++ ] = pwdinfo->listen_channel;	//	listen channel
+		
+
+		//	Extended Listen Timing
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
+
+		//	Length:
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
+		p2pielen += 2;
+
+		//	Value:
+		//	Availability Period
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+		p2pielen += 2;
+
+		//	Availability Interval
+		*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+		p2pielen += 2;
+
+		if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) )
+		{
+			//	Operating Channel (if this WiFi is working as the group owner now)
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_OPERATING_CH;
+
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0005 );
+			p2pielen += 2;
+
+			//	Value:
+			//	Country String
+			p2pie[ p2pielen++ ] = 'X';
+			p2pie[ p2pielen++ ] = 'X';
+		
+			//	The third byte should be set to 0x04.
+			//	Described in the "Operating Channel Attribute" section.
+			p2pie[ p2pielen++ ] = 0x04;
+
+			//	Operating Class
+			p2pie[ p2pielen++ ] = 0x51;	//	Copy from SD7
+		
+			//	Channel Number
+			p2pie[ p2pielen++ ] = pwdinfo->operating_channel;	//	operating channel number
+			
+		}
+		
+		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );	
+
+	}
+
+#ifdef CONFIG_WFD
+	wfdielen = rtw_append_probe_req_wfd_ie(padapter, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
+
+	if (wait_ack) {
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+	return ret;
+}
+
+inline void issue_probereq_p2p(_adapter *adapter, u8 *da)
+{
+	_issue_probereq_p2p(adapter, da, _FALSE);
+}
+
+/*
+ * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ * try_cnt means the maximal TX count to try
+ */
+int issue_probereq_p2p_ex(_adapter *adapter, u8 *da, int try_cnt, int wait_ms)
+{
+	int ret;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+
+	do
+	{
+		ret = _issue_probereq_p2p(adapter, da, wait_ms>0?_TRUE:_FALSE);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(adapter))
+			break;
+
+		if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
+			rtw_msleep_os(wait_ms);
+
+	}while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (da)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(adapter), MAC_ARG(da), rtw_get_oper_ch(adapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(adapter), rtw_get_oper_ch(adapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+#endif //CONFIG_P2P
+
+s32 rtw_action_public_decache(union recv_frame *rframe, u8 token_offset)
+{
+	_adapter *adapter = rframe->u.hdr.adapter;
+	struct mlme_ext_priv *mlmeext = &(adapter->mlmeextpriv);
+	u8 *frame = rframe->u.hdr.rx_data;
+	u16 seq_ctrl = ((rframe->u.hdr.attrib.seq_num&0xffff) << 4) | (rframe->u.hdr.attrib.frag_num & 0xf);
+	u8 token = *(rframe->u.hdr.rx_data + sizeof(struct rtw_ieee80211_hdr_3addr) + token_offset);
+
+	if (GetRetry(frame)) {
+		if ((seq_ctrl == mlmeext->action_public_rxseq)
+			&& (token == mlmeext->action_public_dialog_token)
+		) {
+			DBG_871X(FUNC_ADPT_FMT" seq_ctrl=0x%x, rxseq=0x%x, token:%d\n",
+				FUNC_ADPT_ARG(adapter), seq_ctrl, mlmeext->action_public_rxseq, token);
+			return _FAIL;
+		}
+	}
+
+	/* TODO: per sta seq & token */
+	mlmeext->action_public_rxseq = seq_ctrl;
+	mlmeext->action_public_dialog_token = token;
+
+	return _SUCCESS;
+}
+
+unsigned int on_action_public_p2p(union recv_frame *precv_frame)
+{
+	_adapter *padapter = precv_frame->u.hdr.adapter;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint len = precv_frame->u.hdr.len;
+	u8 *frame_body;
+#ifdef CONFIG_P2P
+	u8 *p2p_ie;
+	u32	p2p_ielen, wps_ielen;
+	struct	wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+	u8	result = P2P_STATUS_SUCCESS;
+	u8	empty_addr[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+	u8 *merged_p2pie = NULL;
+	u32 merged_p2p_ielen= 0;
+#endif //CONFIG_P2P
+
+	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+#ifdef CONFIG_P2P
+	_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
+#ifdef CONFIG_IOCTL_CFG80211
+	if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211)
+	{
+		rtw_cfg80211_rx_p2p_action_public(padapter, pframe, len);
+	}
+	else
+#endif //CONFIG_IOCTL_CFG80211
+	{
+		//	Do nothing if the driver doesn't enable the P2P function.
+		if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+			return _SUCCESS;
+
+		len -= sizeof(struct rtw_ieee80211_hdr_3addr);
+
+		switch( frame_body[ 6 ] )//OUI Subtype
+		{
+			case P2P_GO_NEGO_REQ:
+			{
+				DBG_871X( "[%s] Got GO Nego Req Frame\n", __FUNCTION__);
+				_rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
+
+				if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
+				{
+					rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+				}
+
+				if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
+				{
+					//	Commented by Albert 20110526
+					//	In this case, this means the previous nego fail doesn't be reset yet.
+					_cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+					//	Restore the previous p2p state
+					rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+					DBG_871X( "[%s] Restore the previous p2p state to %d\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );						
+				}					
+#ifdef CONFIG_CONCURRENT_MODE
+				if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+				{
+					_cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer );
+				}
+#endif // CONFIG_CONCURRENT_MODE
+
+				//	Commented by Kurt 20110902
+				//Add if statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered.
+				if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
+					rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+
+				//	Commented by Kurt 20120113
+				//	Get peer_dev_addr here if peer doesn't issue prov_disc frame.
+				if( _rtw_memcmp(pwdinfo->rx_prov_disc_info.peerDevAddr, empty_addr, ETH_ALEN) )
+					_rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
+
+				result = process_p2p_group_negotation_req( pwdinfo, frame_body, len );
+				issue_p2p_GO_response( padapter, GetAddr2Ptr(pframe), frame_body, len, result );
+#ifdef CONFIG_INTEL_WIDI
+				if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) {
+					padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
+					_cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
+					intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
+				}
+#endif //CONFIG_INTEL_WIDI
+
+				//	Commented by Albert 20110718
+				//	No matter negotiating or negotiation failure, the driver should set up the restore P2P state timer.
+#ifdef CONFIG_CONCURRENT_MODE
+				//	Commented by Albert 20120107
+				_set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
+#else // CONFIG_CONCURRENT_MODE
+				_set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
+#endif // CONFIG_CONCURRENT_MODE
+				break;					
+			}
+			case P2P_GO_NEGO_RESP:
+			{
+				DBG_871X( "[%s] Got GO Nego Resp Frame\n", __FUNCTION__);
+
+				if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
+				{
+					//	Commented by Albert 20110425
+					//	The restore timer is enabled when issuing the nego request frame of rtw_p2p_connect function.
+					_cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+					pwdinfo->nego_req_info.benable = _FALSE;
+					result = process_p2p_group_negotation_resp( pwdinfo, frame_body, len);
+					issue_p2p_GO_confirm( pwdinfo->padapter, GetAddr2Ptr(pframe), result);
+					if ( P2P_STATUS_SUCCESS == result )
+					{
+						if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
+						{
+							pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
+							#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+							pwdinfo->p2p_info.operation_ch[ 1 ] = 1;	//Check whether GO is operating in channel 1;
+							pwdinfo->p2p_info.operation_ch[ 2 ] = 6;	//Check whether GO is operating in channel 6;
+							pwdinfo->p2p_info.operation_ch[ 3 ] = 11;	//Check whether GO is operating in channel 11;
+							#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
+							pwdinfo->p2p_info.scan_op_ch_only = 1;
+							_set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
+						}
+					}
+
+					//	Reset the dialog token for group negotiation frames.
+					pwdinfo->negotiation_dialog_token = 1;
+
+					if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
+					{
+						_set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
+					}
+				}
+				else
+				{
+					DBG_871X( "[%s] Skipped GO Nego Resp Frame (p2p_state != P2P_STATE_GONEGO_ING)\n", __FUNCTION__);
+				}
+				
+				break;
+			}
+			case P2P_GO_NEGO_CONF:
+			{
+				DBG_871X( "[%s] Got GO Nego Confirm Frame\n", __FUNCTION__);
+				result = process_p2p_group_negotation_confirm( pwdinfo, frame_body, len);
+				if ( P2P_STATUS_SUCCESS == result )
+				{
+					if ( rtw_p2p_role(pwdinfo) == P2P_ROLE_CLIENT )
+					{
+						pwdinfo->p2p_info.operation_ch[ 0 ] = pwdinfo->peer_operating_ch;
+						#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+						pwdinfo->p2p_info.operation_ch[ 1 ] = 1;	//Check whether GO is operating in channel 1;
+						pwdinfo->p2p_info.operation_ch[ 2 ] = 6;	//Check whether GO is operating in channel 6;
+						pwdinfo->p2p_info.operation_ch[ 3 ] = 11;	//Check whether GO is operating in channel 11;
+						#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
+						pwdinfo->p2p_info.scan_op_ch_only = 1;
+						_set_timer( &pwdinfo->reset_ch_sitesurvey2, P2P_RESET_SCAN_CH );
+					}
+				}
+				break;
+			}
+			case P2P_INVIT_REQ:
+			{
+				//	Added by Albert 2010/10/05
+				//	Received the P2P Invite Request frame.
+				
+				DBG_871X( "[%s] Got invite request frame!\n", __FUNCTION__ );
+				if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
+				{
+					//	Parse the necessary information from the P2P Invitation Request frame.
+					//	For example: The MAC address of sending this P2P Invitation Request frame.
+					u32	attr_contentlen = 0;
+					u8	status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+					struct group_id_info group_id;
+					u8	invitation_flag = 0;
+					int j=0;
+
+					merged_p2p_ielen = rtw_get_p2p_merged_ies_len(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_);
+
+					merged_p2pie = rtw_zmalloc(merged_p2p_ielen + 2);	// 2 is for EID and Length
+					if (merged_p2pie == NULL)
+					{
+						DBG_871X( "[%s] Malloc p2p ie fail\n", __FUNCTION__);
+						goto exit;
+					}
+					_rtw_memset(merged_p2pie, 0x00, merged_p2p_ielen);					
+
+					merged_p2p_ielen = rtw_p2p_merge_ies(frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, merged_p2pie);
+
+					rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_INVITATION_FLAGS, &invitation_flag, &attr_contentlen);
+					if ( attr_contentlen )
+					{
+
+						rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_BSSID, pwdinfo->p2p_peer_interface_addr, &attr_contentlen);
+						//	Commented by Albert 20120510
+						//	Copy to the pwdinfo->p2p_peer_interface_addr.
+						//	So that the WFD UI ( or Sigma ) can get the peer interface address by using the following command.
+						//	#> iwpriv wlan0 p2p_get peer_ifa
+						//	After having the peer interface address, the sigma can find the correct conf file for wpa_supplicant.
+
+						if ( attr_contentlen )
+						{
+							DBG_871X( "[%s] GO's BSSID = %.2X %.2X %.2X %.2X %.2X %.2X\n", __FUNCTION__,
+									pwdinfo->p2p_peer_interface_addr[0], pwdinfo->p2p_peer_interface_addr[1],
+									pwdinfo->p2p_peer_interface_addr[2], pwdinfo->p2p_peer_interface_addr[3],
+									pwdinfo->p2p_peer_interface_addr[4], pwdinfo->p2p_peer_interface_addr[5] );
+						}								
+
+						if ( invitation_flag & P2P_INVITATION_FLAGS_PERSISTENT )
+						{
+							//	Re-invoke the persistent group.
+							
+							_rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) );
+							rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
+							if ( attr_contentlen )
+							{
+								if (_rtw_memcmp(group_id.go_device_addr, adapter_mac_addr(padapter), ETH_ALEN))
+								{
+									//	The p2p device sending this p2p invitation request wants this Wi-Fi device to be the persistent GO.
+									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_GO );
+									rtw_p2p_set_role( pwdinfo, P2P_ROLE_GO );
+									status_code = P2P_STATUS_SUCCESS;
+								}
+								else
+								{
+									//	The p2p device sending this p2p invitation request wants to be the persistent GO.
+									if ( is_matched_in_profilelist( pwdinfo->p2p_peer_interface_addr, &pwdinfo->profileinfo[ 0 ] ) )
+									{
+										u8 operatingch_info[5] = { 0x00 };
+										if ( rtw_get_p2p_attr_content(merged_p2pie, merged_p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
+										{
+											if( rtw_ch_set_search_ch(padapter->mlmeextpriv.channel_set, (u32)operatingch_info[4] ) >= 0 )
+											{
+												//	The operating channel is acceptable for this device.
+												pwdinfo->rx_invitereq_info.operation_ch[0]= operatingch_info[4];
+												#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+												pwdinfo->rx_invitereq_info.operation_ch[1]= 1;		//Check whether GO is operating in channel 1;
+												pwdinfo->rx_invitereq_info.operation_ch[2]= 6;		//Check whether GO is operating in channel 6;
+												pwdinfo->rx_invitereq_info.operation_ch[3]= 11;		//Check whether GO is operating in channel 11;
+												#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
+												pwdinfo->rx_invitereq_info.scan_op_ch_only = 1;
+												_set_timer( &pwdinfo->reset_ch_sitesurvey, P2P_RESET_SCAN_CH );
+												rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
+												rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
+												status_code = P2P_STATUS_SUCCESS;
+											}
+											else
+											{
+												//	The operating channel isn't supported by this device.
+												rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
+												rtw_p2p_set_role( pwdinfo, P2P_ROLE_DEVICE );
+												status_code = P2P_STATUS_FAIL_NO_COMMON_CH;
+												_set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
+											}
+										}
+										else
+										{
+											//	Commented by Albert 20121130
+											//	Intel will use the different P2P IE to store the operating channel information
+											//	Workaround for Intel WiDi 3.5
+											rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_MATCH );
+											rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
+											status_code = P2P_STATUS_SUCCESS;
+										}								
+									}
+									else
+									{
+										rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
+										#ifdef CONFIG_INTEL_WIDI
+										_rtw_memcpy( pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );
+										rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
+										#endif //CONFIG_INTEL_WIDI
+
+										status_code = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
+									}
+								}
+							}
+							else
+							{
+								DBG_871X( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
+								status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+							}									
+						}
+						else
+						{
+							//	Received the invitation to join a P2P group.
+
+							_rtw_memset( &group_id, 0x00, sizeof( struct group_id_info ) );
+							rtw_get_p2p_attr_content( merged_p2pie, merged_p2p_ielen, P2P_ATTR_GROUP_ID, ( u8* ) &group_id, &attr_contentlen);
+							if ( attr_contentlen )
+							{
+								if (_rtw_memcmp(group_id.go_device_addr, adapter_mac_addr(padapter), ETH_ALEN))
+								{
+									//	In this case, the GO can't be myself.
+									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_DISMATCH );
+									status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+								}
+								else
+								{
+									//	The p2p device sending this p2p invitation request wants to join an existing P2P group
+									//	Commented by Albert 2012/06/28
+									//	In this case, this Wi-Fi device should use the iwpriv command to get the peer device address.
+									//	The peer device address should be the destination address for the provisioning discovery request.
+									//	Then, this Wi-Fi device should use the iwpriv command to get the peer interface address.
+									//	The peer interface address should be the address for WPS mac address
+									_rtw_memcpy( pwdinfo->p2p_peer_device_addr, group_id.go_device_addr , ETH_ALEN );											
+									rtw_p2p_set_role( pwdinfo, P2P_ROLE_CLIENT );
+									rtw_p2p_set_state(pwdinfo, P2P_STATE_RECV_INVITE_REQ_JOIN );
+									status_code = P2P_STATUS_SUCCESS;
+								}
+							}
+							else
+							{
+								DBG_871X( "[%s] P2P Group ID Attribute NOT FOUND!\n", __FUNCTION__ );
+								status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+							}
+						}
+					}
+					else
+					{
+						DBG_871X( "[%s] P2P Invitation Flags Attribute NOT FOUND!\n", __FUNCTION__ );
+						status_code = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+					}							
+
+					DBG_871X( "[%s] status_code = %d\n", __FUNCTION__, status_code );
+
+					pwdinfo->inviteresp_info.token = frame_body[ 7 ];
+					issue_p2p_invitation_response( padapter, GetAddr2Ptr(pframe), pwdinfo->inviteresp_info.token, status_code );
+					_set_timer( &pwdinfo->restore_p2p_state_timer, 3000 );
+				}
+#ifdef CONFIG_INTEL_WIDI
+				if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) {
+					padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
+					_cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
+					intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
+				}
+#endif //CONFIG_INTEL_WIDI
+				break;
+			}
+			case P2P_INVIT_RESP:
+			{
+				u8	attr_content = 0x00;
+				u32	attr_contentlen = 0;
+				
+				DBG_871X( "[%s] Got invite response frame!\n", __FUNCTION__ );
+				_cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+				if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
+				{
+					rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
+									
+					if ( attr_contentlen == 1 )
+					{
+						DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
+						pwdinfo->invitereq_info.benable = _FALSE;
+
+						if ( attr_content == P2P_STATUS_SUCCESS )
+						{
+							if (_rtw_memcmp(pwdinfo->invitereq_info.go_bssid, adapter_mac_addr(padapter), ETH_ALEN))
+								rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO );
+							else
+								rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+
+							rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_OK );
+						}
+						else
+						{
+							rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+							rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
+						}
+					}
+					else
+					{
+						rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+						rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
+					}
+				}
+				else
+				{
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+					rtw_p2p_set_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL );
+				}
+
+				if ( rtw_p2p_chk_state( pwdinfo, P2P_STATE_RX_INVITE_RESP_FAIL ) )
+				{
+					_set_timer( &pwdinfo->restore_p2p_state_timer, 5000 );
+				}
+				break;
+			}
+			case P2P_DEVDISC_REQ:
+
+				process_p2p_devdisc_req(pwdinfo, pframe, len);
+
+				break;
+
+			case P2P_DEVDISC_RESP:
+
+				process_p2p_devdisc_resp(pwdinfo, pframe, len);
+
+				break;
+
+			case P2P_PROVISION_DISC_REQ:
+				DBG_871X( "[%s] Got Provisioning Discovery Request Frame\n", __FUNCTION__ );
+				process_p2p_provdisc_req(pwdinfo, pframe, len);
+				_rtw_memcpy(pwdinfo->rx_prov_disc_info.peerDevAddr, GetAddr2Ptr(pframe), ETH_ALEN);
+
+				//20110902 Kurt
+				//Add the following statement to avoid receiving duplicate prov disc req. such that pre_p2p_state would be covered.
+				if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ))
+					rtw_p2p_set_pre_state(pwdinfo, rtw_p2p_state(pwdinfo));
+				
+				rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ);
+				_set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
+#ifdef CONFIG_INTEL_WIDI
+				if (padapter->mlmepriv.widi_state == INTEL_WIDI_STATE_LISTEN) {
+					padapter->mlmepriv.widi_state = INTEL_WIDI_STATE_WFD_CONNECTION;
+					_cancel_timer_ex(&(padapter->mlmepriv.listen_timer));
+					intel_widi_wk_cmd(padapter, INTEL_WIDI_LISTEN_STOP_WK, NULL, 0);
+				}
+#endif //CONFIG_INTEL_WIDI
+				break;
+
+			case P2P_PROVISION_DISC_RESP:
+				//	Commented by Albert 20110707
+				//	Should we check the pwdinfo->tx_prov_disc_info.bsent flag here??
+				DBG_871X( "[%s] Got Provisioning Discovery Response Frame\n", __FUNCTION__ );
+				//	Commented by Albert 20110426
+				//	The restore timer is enabled when issuing the provisioing request frame in rtw_p2p_prov_disc function.
+				_cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+				rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP);
+				process_p2p_provdisc_resp(pwdinfo, pframe);
+				_set_timer( &pwdinfo->restore_p2p_state_timer, P2P_PROVISION_TIMEOUT );
+				break;
+
+		}
+	}
+
+
+exit:
+
+	if(merged_p2pie)
+	{
+		rtw_mfree(merged_p2pie, merged_p2p_ielen + 2);
+	}
+#endif //CONFIG_P2P
+	return _SUCCESS;
+}
+
+unsigned int on_action_public_vendor(union recv_frame *precv_frame)
+{
+	unsigned int ret = _FAIL;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint frame_len = precv_frame->u.hdr.len;
+	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	if (_rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE) {
+		if (rtw_action_public_decache(precv_frame, 7) == _FAIL)
+			goto exit;
+
+		if (!hal_chk_wl_func(precv_frame->u.hdr.adapter, WL_FUNC_MIRACAST))
+			rtw_rframe_del_wfd_ie(precv_frame, 8);
+
+		ret = on_action_public_p2p(precv_frame);
+	}
+
+exit:
+	return ret;
+}
+
+unsigned int on_action_public_default(union recv_frame *precv_frame, u8 action)
+{
+	unsigned int ret = _FAIL;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint frame_len = precv_frame->u.hdr.len;
+	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 token;
+	_adapter *adapter = precv_frame->u.hdr.adapter;
+	int cnt = 0;
+	char msg[64];
+
+	token = frame_body[2];
+
+	if (rtw_action_public_decache(precv_frame, 2) == _FAIL)
+		goto exit;
+
+	#ifdef CONFIG_IOCTL_CFG80211
+	cnt += sprintf((msg+cnt), "%s(token:%u)", action_public_str(action), token);
+	rtw_cfg80211_rx_action(adapter, pframe, frame_len, msg);
+	#endif
+
+	ret = _SUCCESS;
+	
+exit:
+	return ret;
+}
+
+unsigned int on_action_public(_adapter *padapter, union recv_frame *precv_frame)
+{
+	unsigned int ret = _FAIL;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint frame_len = precv_frame->u.hdr.len;
+	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 category, action;
+
+	/* check RA matches or not */
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
+		goto exit;
+
+	category = frame_body[0];
+	if (category != RTW_WLAN_CATEGORY_PUBLIC)
+		goto exit;
+
+	action = frame_body[1];
+	switch (action) {
+	case ACT_PUBLIC_BSSCOEXIST:
+#ifdef CONFIG_80211N_HT
+#ifdef CONFIG_AP_MODE
+		/*20/40 BSS Coexistence Management frame is a Public Action frame*/
+		if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
+			rtw_process_public_act_bsscoex(padapter, pframe, frame_len);
+#endif /*CONFIG_AP_MODE*/
+#endif /*CONFIG_80211N_HT*/
+		break;
+	case ACT_PUBLIC_VENDOR:
+		ret = on_action_public_vendor(precv_frame);
+		break;
+	default:
+		ret = on_action_public_default(precv_frame, action);
+		break;
+	}
+
+exit:
+	return ret;
+}
+
+unsigned int OnAction_ht(_adapter *padapter, union recv_frame *precv_frame)
+{
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint frame_len = precv_frame->u.hdr.len;
+	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 category, action;
+
+	/* check RA matches or not */
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
+		goto exit;
+
+	category = frame_body[0];
+	if (category != RTW_WLAN_CATEGORY_HT)
+		goto exit;
+
+	action = frame_body[1];
+	switch (action) {
+	case RTW_WLAN_ACTION_HT_SM_PS:
+#ifdef CONFIG_80211N_HT
+#ifdef CONFIG_AP_MODE
+		if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
+			rtw_process_ht_action_smps(padapter, GetAddr2Ptr(pframe), frame_body[2]);
+#endif /*CONFIG_AP_MODE*/
+#endif /*CONFIG_80211N_HT*/		
+			break;
+	case RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING:
+#ifdef CONFIG_BEAMFORMING
+		/*DBG_871X("RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING\n");*/
+		beamforming_get_report_frame(padapter, precv_frame);
+#endif /*CONFIG_BEAMFORMING*/
+		break;
+	default:
+		break;
+	}
+
+exit:
+
+	return _SUCCESS;
+}
+
+#ifdef CONFIG_IEEE80211W
+unsigned int OnAction_sa_query(_adapter *padapter, union recv_frame *precv_frame)
+{
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct sta_info		*psta;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	u16 tid;
+	//Baron
+	
+	DBG_871X("OnAction_sa_query\n");
+	
+	switch (pframe[WLAN_HDR_A3_LEN+1])
+	{
+		case 0: //SA Query req
+			_rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(u16));
+			DBG_871X("OnAction_sa_query request,action=%d, tid=%04x, pframe=%02x-%02x\n"
+			, pframe[WLAN_HDR_A3_LEN+1], tid, pframe[WLAN_HDR_A3_LEN+2], pframe[WLAN_HDR_A3_LEN+3]);
+			issue_action_SA_Query(padapter, GetAddr2Ptr(pframe), 1, tid, IEEE80211W_RIGHT_KEY);
+			break;
+
+		case 1: //SA Query rsp
+			psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+			if (psta != NULL)
+				_cancel_timer_ex(&psta->dot11w_expire_timer);
+			
+			_rtw_memcpy(&tid, &pframe[WLAN_HDR_A3_LEN+2], sizeof(u16));
+			DBG_871X("OnAction_sa_query response,action=%d, tid=%04x, cancel timer\n", pframe[WLAN_HDR_A3_LEN+1], tid);
+			break;
+		default:
+			break;
+	}
+	if(0)
+	{
+		int pp;
+		printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
+		for(pp=0;pp< pattrib->pkt_len; pp++)
+			printk(" %02x ", pframe[pp]);
+		printk("\n");
+	}	
+	
+	return _SUCCESS;
+}
+#endif //CONFIG_IEEE80211W
+
+unsigned int OnAction_wmm(_adapter *padapter, union recv_frame *precv_frame)
+{
+	return _SUCCESS;
+}
+
+unsigned int OnAction_vht(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_80211AC_VHT
+	struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint frame_len = precv_frame->u.hdr.len;
+	struct rtw_ieee80211_hdr_3addr *whdr = (struct rtw_ieee80211_hdr_3addr *)pframe;
+	u8 *frame_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 category, action;
+	struct sta_info *psta = NULL;
+
+	/* check RA matches or not */
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
+		goto exit;
+
+	category = frame_body[0];
+	if(category != RTW_WLAN_CATEGORY_VHT)
+		goto exit;
+
+	action = frame_body[1];
+	switch (action) {
+	case RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING:
+#ifdef CONFIG_BEAMFORMING
+		/*DBG_871X("RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING\n");*/
+		beamforming_get_report_frame(padapter, precv_frame);
+#endif /*CONFIG_BEAMFORMING*/
+		break;
+	case RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION:
+		// CategoryCode(1) + ActionCode(1) + OpModeNotification(1)
+		//DBG_871X("RTW_WLAN_ACTION_VHT_OPMODE_NOTIFICATION\n");
+		psta = rtw_get_stainfo(&padapter->stapriv, whdr->addr2);
+		if (psta)
+			rtw_process_vht_op_mode_notify(padapter, &frame_body[2], psta);
+		break;
+	default:
+		break;
+	}
+
+exit:
+#endif //CONFIG_80211AC_VHT
+
+	return _SUCCESS;
+}
+
+unsigned int OnAction_p2p(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_P2P
+	u8 *frame_body;
+	u8 category, OUI_Subtype, dialogToken=0;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	uint len = precv_frame->u.hdr.len;
+	struct	wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+
+	//check RA matches or not
+	if (!_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(pframe), ETH_ALEN))
+		return _SUCCESS;
+
+	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+	category = frame_body[0];
+	if(category != RTW_WLAN_CATEGORY_P2P)
+		return _SUCCESS;
+
+	if ( cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ) != P2POUI )
+		return _SUCCESS;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (adapter_wdev_data(padapter)->p2p_enabled
+		&& pwdinfo->driver_interface == DRIVER_CFG80211
+		) {
+		rtw_cfg80211_rx_action_p2p(padapter, pframe, len);
+		return _SUCCESS;
+	}
+	else
+#endif //CONFIG_IOCTL_CFG80211
+	{
+		len -= sizeof(struct rtw_ieee80211_hdr_3addr);
+		OUI_Subtype = frame_body[5];
+		dialogToken = frame_body[6];
+
+		switch(OUI_Subtype)
+		{
+			case P2P_NOTICE_OF_ABSENCE:
+				
+				break;
+				
+			case P2P_PRESENCE_REQUEST:
+
+				process_p2p_presence_req(pwdinfo, pframe, len);			
+				
+				break;
+				
+			case P2P_PRESENCE_RESPONSE:
+				
+				break;
+				
+			case P2P_GO_DISC_REQUEST:
+				
+				break;
+				
+			default:
+				break;
+				
+		}
+	}
+#endif //CONFIG_P2P
+
+	return _SUCCESS;
+
+}
+
+unsigned int OnAction(_adapter *padapter, union recv_frame *precv_frame)
+{
+	int i;
+	unsigned char	category;
+	struct action_handler *ptable;
+	unsigned char	*frame_body;
+	u8 *pframe = precv_frame->u.hdr.rx_data; 
+
+	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+	
+	category = frame_body[0];
+	
+	for(i = 0; i < sizeof(OnAction_tbl)/sizeof(struct action_handler); i++)	
+	{
+		ptable = &OnAction_tbl[i];
+		
+		if(category == ptable->num)
+			ptable->func(padapter, precv_frame);
+	
+	}
+
+	return _SUCCESS;
+
+}
+
+unsigned int DoReserved(_adapter *padapter, union recv_frame *precv_frame)
+{
+
+	//DBG_871X("rcvd mgt frame(%x, %x)\n", (GetFrameSubType(pframe) >> 4), *(unsigned int *)GetAddr1Ptr(pframe));
+	return _SUCCESS;
+}
+
+struct xmit_frame *_alloc_mgtxmitframe(struct xmit_priv *pxmitpriv, bool once)
+{
+	struct xmit_frame *pmgntframe;
+	struct xmit_buf *pxmitbuf;
+
+	if (once)
+		pmgntframe = rtw_alloc_xmitframe_once(pxmitpriv);
+	else
+		pmgntframe = rtw_alloc_xmitframe_ext(pxmitpriv);
+
+	if (pmgntframe == NULL) {
+		DBG_871X(FUNC_ADPT_FMT" alloc xmitframe fail, once:%d\n", FUNC_ADPT_ARG(pxmitpriv->adapter), once);
+		goto exit;
+	}
+
+	if ((pxmitbuf = rtw_alloc_xmitbuf_ext(pxmitpriv)) == NULL) {
+		DBG_871X(FUNC_ADPT_FMT" alloc xmitbuf fail\n", FUNC_ADPT_ARG(pxmitpriv->adapter));
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		pmgntframe = NULL;
+		goto exit;
+	}
+
+	pmgntframe->frame_tag = MGNT_FRAMETAG;
+	pmgntframe->pxmitbuf = pxmitbuf;
+	pmgntframe->buf_addr = pxmitbuf->pbuf;
+	pxmitbuf->priv_data = pmgntframe;
+
+exit:
+	return pmgntframe;
+
+}
+
+inline struct xmit_frame *alloc_mgtxmitframe(struct xmit_priv *pxmitpriv)
+{
+	return _alloc_mgtxmitframe(pxmitpriv, _FALSE);
+}
+
+inline struct xmit_frame *alloc_mgtxmitframe_once(struct xmit_priv *pxmitpriv)
+{
+	return _alloc_mgtxmitframe(pxmitpriv, _TRUE);
+}
+
+
+/****************************************************************************
+
+Following are some TX fuctions for WiFi MLME
+
+*****************************************************************************/
+
+void update_mgnt_tx_rate(_adapter *padapter, u8 rate)
+{
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+
+	pmlmeext->tx_rate = rate;
+	//DBG_871X("%s(): rate = %x\n",__FUNCTION__, rate);
+}
+
+
+void update_monitor_frame_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	u8	wireless_mode;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
+	struct sta_info		*psta = NULL;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct sta_info *pbcmc_sta = NULL;
+
+	psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+	pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+
+	pattrib->hdrlen = 24;
+	pattrib->nr_frags = 1;
+	pattrib->priority = 7;
+
+	if (pbcmc_sta)
+		pattrib->mac_id = pbcmc_sta->mac_id;
+	else {
+		pattrib->mac_id = 0;
+		DBG_871X("mgmt use mac_id 0 will affect RA\n");
+	}
+	pattrib->qsel = QSLT_MGNT;
+
+	pattrib->pktlen = 0;
+
+	if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
+		wireless_mode = WIRELESS_11B;
+	else
+		wireless_mode = WIRELESS_11G;
+
+	pattrib->raid = rtw_get_mgntframe_raid(padapter, wireless_mode);
+	#ifdef CONFIG_80211AC_VHT
+		if (pHalData->rf_type == RF_1T1R)
+			pattrib->raid = RATEID_IDX_VHT_1SS;
+		else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R)
+			pattrib->raid = RATEID_IDX_VHT_2SS;
+		else if (pHalData->rf_type == RF_3T3R)
+			pattrib->raid = RATEID_IDX_VHT_3SS;
+		else
+			pattrib->raid = RATEID_IDX_BGN_40M_1SS;
+	#endif
+
+	#ifdef CONFIG_80211AC_VHT
+		pattrib->rate = MGN_VHT1SS_MCS9;
+	#else
+		pattrib->rate = MGN_MCS7;
+	#endif
+
+	pattrib->encrypt = _NO_PRIVACY_;
+	pattrib->bswenc = _FALSE;
+
+	pattrib->qos_en = _FALSE;
+	pattrib->ht_en = 1;
+	pattrib->bwmode = CHANNEL_WIDTH_20;
+	pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	pattrib->sgi = _FALSE;
+
+	pattrib->seqnum = pmlmeext->mgnt_seq;
+
+	pattrib->retry_ctrl = _TRUE;
+
+	pattrib->mbssid = 0;
+	pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;
+
+}
+
+
+void update_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
+{
+	u8	wireless_mode;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct xmit_priv 		*pxmitpriv = &padapter->xmitpriv;
+	struct sta_info		*psta = NULL;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct sta_info *pbcmc_sta = NULL;
+	//_rtw_memset((u8 *)(pattrib), 0, sizeof(struct pkt_attrib));
+
+	pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
+
+	pattrib->hdrlen = 24;
+	pattrib->nr_frags = 1;
+	pattrib->priority = 7;
+
+	if (pbcmc_sta)
+		pattrib->mac_id = pbcmc_sta->mac_id;
+	else {
+		pattrib->mac_id = 0;
+		DBG_871X("mgmt use mac_id 0 will affect RA\n");
+	}
+	pattrib->qsel = QSLT_MGNT;
+
+	pattrib->pktlen = 0;
+
+	if (pmlmeext->tx_rate == IEEE80211_CCK_RATE_1MB)
+		wireless_mode = WIRELESS_11B;
+	else
+		wireless_mode = WIRELESS_11G;
+	pattrib->raid =  rtw_get_mgntframe_raid(padapter, wireless_mode);
+	pattrib->rate = pmlmeext->tx_rate;
+
+	pattrib->encrypt = _NO_PRIVACY_;
+	pattrib->bswenc = _FALSE;	
+
+	pattrib->qos_en = _FALSE;
+	pattrib->ht_en = _FALSE;
+	pattrib->bwmode = CHANNEL_WIDTH_20;
+	pattrib->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	pattrib->sgi = _FALSE;
+
+	pattrib->seqnum = pmlmeext->mgnt_seq;
+
+	pattrib->retry_ctrl = _TRUE;
+
+	pattrib->mbssid = 0;
+	pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;
+
+	#ifdef CONFIG_BEAMFORMING
+	psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+	if (psta)
+		update_attrib_txbf_info(padapter, pattrib, psta);
+	#endif
+
+}
+
+void update_mgntframe_attrib_addr(_adapter *padapter, struct xmit_frame *pmgntframe)
+{
+	u8	*pframe;
+	struct pkt_attrib	*pattrib = &pmgntframe->attrib;
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+	_rtw_memcpy(pattrib->ra, GetAddr1Ptr(pframe), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, GetAddr2Ptr(pframe), ETH_ALEN);
+}
+
+void dump_mgntframe(_adapter *padapter, struct xmit_frame *pmgntframe)
+{
+	if (RTW_CANNOT_RUN(padapter)) {
+		rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
+		return;
+	}
+
+	rtw_hal_mgnt_xmit(padapter, pmgntframe);
+}
+
+s32 dump_mgntframe_and_wait(_adapter *padapter, struct xmit_frame *pmgntframe, int timeout_ms)
+{
+	s32 ret = _FAIL;
+	_irqL irqL;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;	
+	struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
+	struct submit_ctx sctx;
+
+	if (RTW_CANNOT_RUN(padapter)) {
+		rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
+		return ret;
+	}
+
+	rtw_sctx_init(&sctx, timeout_ms);
+	pxmitbuf->sctx = &sctx;
+
+	ret = rtw_hal_mgnt_xmit(padapter, pmgntframe);
+
+	if (ret == _SUCCESS)
+		ret = rtw_sctx_wait(&sctx, __func__);
+
+	_enter_critical(&pxmitpriv->lock_sctx, &irqL);
+	pxmitbuf->sctx = NULL;
+	_exit_critical(&pxmitpriv->lock_sctx, &irqL);
+
+	 return ret;
+}
+
+s32 dump_mgntframe_and_wait_ack(_adapter *padapter, struct xmit_frame *pmgntframe)
+{
+#ifdef CONFIG_XMIT_ACK
+	static u8 seq_no = 0;
+	s32 ret = _FAIL;
+	u32 timeout_ms = 500;//  500ms
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	#ifdef CONFIG_CONCURRENT_MODE
+	if (padapter->pbuddy_adapter && !padapter->isprimary)
+		pxmitpriv = &(padapter->pbuddy_adapter->xmitpriv);
+	#endif
+
+	if (RTW_CANNOT_RUN(padapter)) {
+		rtw_free_xmitbuf(&padapter->xmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(&padapter->xmitpriv, pmgntframe);
+		return -1;
+	}
+
+	_enter_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+	pxmitpriv->ack_tx = _TRUE;
+	pxmitpriv->seq_no = seq_no++;
+	pmgntframe->ack_report = 1;
+	rtw_sctx_init(&(pxmitpriv->ack_tx_ops), timeout_ms);
+	if (rtw_hal_mgnt_xmit(padapter, pmgntframe) == _SUCCESS) {
+#ifdef CONFIG_XMIT_ACK_POLLING
+		ret = rtw_ack_tx_polling(pxmitpriv, timeout_ms);
+#else
+		ret = rtw_sctx_wait(&(pxmitpriv->ack_tx_ops), __func__);
+#endif
+	}
+
+	pxmitpriv->ack_tx = _FALSE;
+	_exit_critical_mutex(&pxmitpriv->ack_tx_mutex, NULL);
+
+	 return ret;
+#else //!CONFIG_XMIT_ACK
+	dump_mgntframe(padapter, pmgntframe);
+	rtw_msleep_os(50);
+	return _SUCCESS;
+#endif //!CONFIG_XMIT_ACK	 
+}
+
+int update_hidden_ssid(u8 *ies, u32 ies_len, u8 hidden_ssid_mode)
+{
+	u8 *ssid_ie;
+	sint ssid_len_ori;
+	int len_diff = 0;
+	
+	ssid_ie = rtw_get_ie(ies,  WLAN_EID_SSID, &ssid_len_ori, ies_len);
+
+	//DBG_871X("%s hidden_ssid_mode:%u, ssid_ie:%p, ssid_len_ori:%d\n", __FUNCTION__, hidden_ssid_mode, ssid_ie, ssid_len_ori);
+	
+	if(ssid_ie && ssid_len_ori>0)
+	{
+		switch(hidden_ssid_mode)
+		{
+			case 1:
+			{
+				u8 *next_ie = ssid_ie + 2 + ssid_len_ori;
+				u32 remain_len = 0;
+				
+				remain_len = ies_len -(next_ie-ies);
+				
+				ssid_ie[1] = 0;				
+				_rtw_memcpy(ssid_ie+2, next_ie, remain_len);
+				len_diff -= ssid_len_ori;
+				
+				break;
+			}		
+			case 2:
+				_rtw_memset(&ssid_ie[2], 0, ssid_len_ori);
+				break;
+			default:
+				break;
+		}
+	}
+
+	return len_diff;
+}
+
+void issue_beacon(_adapter *padapter, int timeout_ms)
+{
+	struct xmit_frame	*pmgntframe;
+	struct pkt_attrib	*pattrib;
+	unsigned char	*pframe;
+	struct rtw_ieee80211_hdr *pwlanhdr;
+	unsigned short *fctrl;
+	unsigned int	rate_len;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	_irqL irqL;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+#endif //CONFIG_P2P
+
+
+	//DBG_871X("%s\n", __FUNCTION__);
+
+#ifdef CONFIG_BCN_ICF
+	if ((pmgntframe = rtw_alloc_bcnxmitframe(pxmitpriv)) == NULL)
+#else
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+#endif
+	{
+		DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
+		return;
+	}
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	_enter_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);
+#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+	pattrib->qsel = QSLT_BEACON;
+	#ifdef CONFIG_CONCURRENT_MODE
+	if(padapter->iface_type == IFACE_PORT1)	
+		pattrib->mbssid = 1;
+	#endif	
+	
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+		
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;	
+	
+	
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+	
+	_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, 0/*pmlmeext->mgnt_seq*/);
+	//pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_BEACON);
+	
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);	
+	pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
+	
+	if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	{
+		//DBG_871X("ie len=%d\n", cur_network->IELength);
+#ifdef CONFIG_P2P
+		// for P2P : Primary Device Type & Device Name
+		u32 wpsielen=0, insert_len=0;
+		u8 *wpsie=NULL;		
+		wpsie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wpsielen);
+		
+		if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && wpsie && wpsielen>0)
+		{
+			uint wps_offset, remainder_ielen;
+			u8 *premainder_ie, *pframe_wscie;
+	
+			wps_offset = (uint)(wpsie - cur_network->IEs);
+
+			premainder_ie = wpsie + wpsielen;
+
+			remainder_ielen = cur_network->IELength - wps_offset - wpsielen;
+
+#ifdef CONFIG_IOCTL_CFG80211
+			if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
+			{
+				if(pmlmepriv->wps_beacon_ie && pmlmepriv->wps_beacon_ie_len>0)
+				{
+					_rtw_memcpy(pframe, cur_network->IEs, wps_offset);
+					pframe += wps_offset;
+					pattrib->pktlen += wps_offset;
+
+					_rtw_memcpy(pframe, pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beacon_ie_len);
+					pframe += pmlmepriv->wps_beacon_ie_len;
+					pattrib->pktlen += pmlmepriv->wps_beacon_ie_len;
+
+					//copy remainder_ie to pframe
+					_rtw_memcpy(pframe, premainder_ie, remainder_ielen);
+					pframe += remainder_ielen;		
+					pattrib->pktlen += remainder_ielen;
+				}
+				else
+				{
+					_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
+					pframe += cur_network->IELength;
+					pattrib->pktlen += cur_network->IELength;
+				}
+			}
+			else
+#endif //CONFIG_IOCTL_CFG80211
+			{
+				pframe_wscie = pframe + wps_offset;
+				_rtw_memcpy(pframe, cur_network->IEs, wps_offset+wpsielen);			
+				pframe += (wps_offset + wpsielen);		
+				pattrib->pktlen += (wps_offset + wpsielen);
+
+				//now pframe is end of wsc ie, insert Primary Device Type & Device Name
+				//	Primary Device Type
+				//	Type:
+				*(u16*) ( pframe + insert_len) = cpu_to_be16( WPS_ATTR_PRIMARY_DEV_TYPE );
+				insert_len += 2;
+				
+				//	Length:
+				*(u16*) ( pframe + insert_len ) = cpu_to_be16( 0x0008 );
+				insert_len += 2;
+				
+				//	Value:
+				//	Category ID
+				*(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+				insert_len += 2;
+
+				//	OUI
+				*(u32*) ( pframe + insert_len ) = cpu_to_be32( WPSOUI );
+				insert_len += 4;
+
+				//	Sub Category ID
+				*(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+				insert_len += 2;
+
+
+				//	Device Name
+				//	Type:
+				*(u16*) ( pframe + insert_len ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+				insert_len += 2;
+
+				//	Length:
+				*(u16*) ( pframe + insert_len ) = cpu_to_be16( pwdinfo->device_name_len );
+				insert_len += 2;
+
+				//	Value:
+				_rtw_memcpy( pframe + insert_len, pwdinfo->device_name, pwdinfo->device_name_len );
+				insert_len += pwdinfo->device_name_len;
+
+
+				//update wsc ie length
+				*(pframe_wscie+1) = (wpsielen -2) + insert_len;
+
+				//pframe move to end
+				pframe+=insert_len;
+				pattrib->pktlen += insert_len;
+
+				//copy remainder_ie to pframe
+				_rtw_memcpy(pframe, premainder_ie, remainder_ielen);
+				pframe += remainder_ielen;		
+				pattrib->pktlen += remainder_ielen;
+			}
+		}
+		else
+#endif //CONFIG_P2P
+		{
+			int len_diff;
+			_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
+			len_diff = update_hidden_ssid(
+				pframe+_BEACON_IE_OFFSET_
+				, cur_network->IELength-_BEACON_IE_OFFSET_
+				, pmlmeinfo->hidden_ssid_mode
+			);
+			pframe += (cur_network->IELength+len_diff);
+			pattrib->pktlen += (cur_network->IELength+len_diff);
+		}
+
+		{
+			u8 *wps_ie;
+			uint wps_ielen;
+			u8 sr = 0;
+			wps_ie = rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof (struct rtw_ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_,
+				pattrib->pktlen-sizeof (struct rtw_ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_, NULL, &wps_ielen);
+			if (wps_ie && wps_ielen>0) {
+				rtw_get_wps_attr_content(wps_ie,  wps_ielen, WPS_ATTR_SELECTED_REGISTRAR, (u8*)(&sr), NULL);
+			}
+			if (sr != 0)
+				set_fwstate(pmlmepriv, WIFI_UNDER_WPS);
+			else
+				_clr_fwstate_(pmlmepriv, WIFI_UNDER_WPS);
+		}
+
+#ifdef CONFIG_P2P
+		if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+		{
+			u32 len;
+#ifdef CONFIG_IOCTL_CFG80211
+			if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
+			{
+				len = pmlmepriv->p2p_beacon_ie_len;
+				if(pmlmepriv->p2p_beacon_ie && len>0)				
+					_rtw_memcpy(pframe, pmlmepriv->p2p_beacon_ie, len);
+			}
+			else
+#endif //CONFIG_IOCTL_CFG80211
+			{
+				len = build_beacon_p2p_ie(pwdinfo, pframe);
+			}
+
+			pframe += len;
+			pattrib->pktlen += len;
+
+			#ifdef CONFIG_WFD
+			len = rtw_append_beacon_wfd_ie(padapter, pframe);
+			pframe += len;
+			pattrib->pktlen += len;
+			#endif
+		}
+#endif //CONFIG_P2P
+
+		goto _issue_bcn;
+
+	}
+
+	//below for ad-hoc mode
+
+	//timestamp will be inserted by hardware
+	pframe += 8;
+	pattrib->pktlen += 8;
+
+	// beacon interval: 2 bytes
+
+	_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
+
+	pframe += 2;
+	pattrib->pktlen += 2;
+
+	// capability info: 2 bytes
+
+	_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+
+	pframe += 2;
+	pattrib->pktlen += 2;
+
+	// SSID
+	pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+
+	// supported rates...
+	rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+
+	// DS parameter set
+	pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
+
+	//if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
+	{
+		u8 erpinfo=0;
+		u32 ATIMWindow;
+		// IBSS Parameter Set...
+		//ATIMWindow = cur->Configuration.ATIMWindow;
+		ATIMWindow = 0;
+		pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
+
+		//ERP IE
+		pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
+	}	
+
+
+	// EXTERNDED SUPPORTED RATE
+	if (rate_len > 8)
+	{
+		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+	}
+
+
+	//todo:HT for adhoc
+
+_issue_bcn:
+
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	pmlmepriv->update_bcn = _FALSE;
+	
+	_exit_critical_bh(&pmlmepriv->bcn_update_lock, &irqL);	
+#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+
+	if ((pattrib->pktlen + TXDESC_SIZE) > 512)
+	{
+		DBG_871X("beacon frame too large\n");
+		return;
+	}
+	
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	//DBG_871X("issue bcn_sz=%d\n", pattrib->last_txcmdsz);
+	if(timeout_ms > 0)
+		dump_mgntframe_and_wait(padapter, pmgntframe, timeout_ms);
+	else
+		dump_mgntframe(padapter, pmgntframe);
+
+}
+
+void issue_probersp(_adapter *padapter, unsigned char *da, u8 is_valid_p2p_probereq)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;	
+	unsigned char					*mac, *bssid;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	u8 *pwps_ie;
+	uint wps_ielen;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#endif //#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	unsigned int	rate_len;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+#endif //CONFIG_P2P
+
+	//DBG_871X("%s\n", __FUNCTION__);
+
+	if(da == NULL)
+		return;
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		DBG_871X("%s, alloc mgnt frame fail\n", __FUNCTION__);
+		return;
+	}
+
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);	
+	
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+		
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;	
+	
+	mac = adapter_mac_addr(padapter);
+	bssid = cur_network->MacAddress;
+	
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, bssid, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(fctrl, WIFI_PROBERSP);
+	
+	pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = pattrib->hdrlen;
+	pframe += pattrib->hdrlen;
+
+
+	if(cur_network->IELength>MAX_IE_SZ)
+		return;
+	
+#if defined (CONFIG_AP_MODE) && defined (CONFIG_NATIVEAP_MLME)
+	if( (pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	{
+		pwps_ie = rtw_get_wps_ie(cur_network->IEs+_FIXED_IE_LENGTH_, cur_network->IELength-_FIXED_IE_LENGTH_, NULL, &wps_ielen);
+	
+		//inerset & update wps_probe_resp_ie
+		if((pmlmepriv->wps_probe_resp_ie!=NULL) && pwps_ie && (wps_ielen>0))
+		{
+			uint wps_offset, remainder_ielen;
+			u8 *premainder_ie;		
+	
+			wps_offset = (uint)(pwps_ie - cur_network->IEs);
+
+			premainder_ie = pwps_ie + wps_ielen;
+
+			remainder_ielen = cur_network->IELength - wps_offset - wps_ielen;
+
+			_rtw_memcpy(pframe, cur_network->IEs, wps_offset);		
+			pframe += wps_offset;		
+			pattrib->pktlen += wps_offset;		
+
+			wps_ielen = (uint)pmlmepriv->wps_probe_resp_ie[1];//to get ie data len
+			if((wps_offset+wps_ielen+2)<=MAX_IE_SZ)
+			{
+				_rtw_memcpy(pframe, pmlmepriv->wps_probe_resp_ie, wps_ielen+2);
+				pframe += wps_ielen+2;		
+				pattrib->pktlen += wps_ielen+2;	
+			}
+
+			if((wps_offset+wps_ielen+2+remainder_ielen)<=MAX_IE_SZ)
+			{
+				_rtw_memcpy(pframe, premainder_ie, remainder_ielen);
+				pframe += remainder_ielen;		
+				pattrib->pktlen += remainder_ielen;	
+			}
+		}
+		else
+		{
+			_rtw_memcpy(pframe, cur_network->IEs, cur_network->IELength);
+			pframe += cur_network->IELength;
+			pattrib->pktlen += cur_network->IELength;
+		}
+
+		/* retrieve SSID IE from cur_network->Ssid */
+		{
+			u8 *ssid_ie;
+			sint ssid_ielen;
+			sint ssid_ielen_diff;
+			u8 buf[MAX_IE_SZ];
+			u8 *ies = pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(struct rtw_ieee80211_hdr_3addr);
+
+			ssid_ie = rtw_get_ie(ies+_FIXED_IE_LENGTH_, _SSID_IE_, &ssid_ielen,
+				(pframe-ies)-_FIXED_IE_LENGTH_);
+
+			ssid_ielen_diff = cur_network->Ssid.SsidLength - ssid_ielen;
+
+			if (ssid_ie &&  cur_network->Ssid.SsidLength) {
+				uint remainder_ielen;
+				u8 *remainder_ie;
+				remainder_ie = ssid_ie+2;
+				remainder_ielen = (pframe-remainder_ie);
+
+				if (remainder_ielen > MAX_IE_SZ) {
+					DBG_871X_LEVEL(_drv_warning_, FUNC_ADPT_FMT" remainder_ielen > MAX_IE_SZ\n", FUNC_ADPT_ARG(padapter));
+					remainder_ielen = MAX_IE_SZ;
+				}
+
+				_rtw_memcpy(buf, remainder_ie, remainder_ielen);
+				_rtw_memcpy(remainder_ie+ssid_ielen_diff, buf, remainder_ielen);
+				*(ssid_ie+1) = cur_network->Ssid.SsidLength;
+				_rtw_memcpy(ssid_ie+2, cur_network->Ssid.Ssid, cur_network->Ssid.SsidLength);
+
+				pframe += ssid_ielen_diff;
+				pattrib->pktlen += ssid_ielen_diff;
+			}
+		}
+	}	
+	else		
+#endif		
+	{
+	
+		//timestamp will be inserted by hardware
+		pframe += 8;
+		pattrib->pktlen += 8;
+
+		// beacon interval: 2 bytes
+
+		_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
+
+		pframe += 2;
+		pattrib->pktlen += 2;
+
+		// capability info: 2 bytes
+
+		_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+
+		pframe += 2;
+		pattrib->pktlen += 2;
+
+		//below for ad-hoc mode
+
+		// SSID
+		pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &pattrib->pktlen);
+
+		// supported rates...
+		rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &pattrib->pktlen);
+
+		// DS parameter set
+		pframe =rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &pattrib->pktlen);
+
+		if( (pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
+		{
+			u8 erpinfo=0;
+			u32 ATIMWindow;
+			// IBSS Parameter Set...
+			//ATIMWindow = cur->Configuration.ATIMWindow;
+			ATIMWindow = 0;
+			pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &pattrib->pktlen);
+
+			//ERP IE
+			pframe = rtw_set_ie(pframe, _ERPINFO_IE_, 1, &erpinfo, &pattrib->pktlen);
+		}
+
+		
+		// EXTERNDED SUPPORTED RATE
+		if (rate_len > 8)
+		{
+			pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &pattrib->pktlen);
+		}
+
+
+		//todo:HT for adhoc
+
+	}	
+
+#ifdef CONFIG_P2P
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)
+		/* IOT issue, When wifi_spec is not set, send probe_resp with P2P IE even if probe_req has no P2P IE */
+		&& (is_valid_p2p_probereq || !padapter->registrypriv.wifi_spec))
+	{
+		u32 len;
+#ifdef CONFIG_IOCTL_CFG80211
+		if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
+		{
+			//if pwdinfo->role == P2P_ROLE_DEVICE will call issue_probersp_p2p()
+			len = pmlmepriv->p2p_go_probe_resp_ie_len;
+			if(pmlmepriv->p2p_go_probe_resp_ie && len>0)
+				_rtw_memcpy(pframe, pmlmepriv->p2p_go_probe_resp_ie, len);
+		}
+		else
+#endif //CONFIG_IOCTL_CFG80211
+		{
+			len = build_probe_resp_p2p_ie(pwdinfo, pframe);
+		}
+
+		pframe += len;
+		pattrib->pktlen += len;
+		
+		#ifdef CONFIG_WFD
+		len = rtw_append_probe_resp_wfd_ie(padapter, pframe);
+		pframe += len;
+		pattrib->pktlen += len;
+		#endif
+	}
+#endif //CONFIG_P2P
+
+
+#ifdef CONFIG_AUTO_AP_MODE
+{
+	struct sta_info	*psta;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	DBG_871X("(%s)\n", __FUNCTION__);
+
+	//check rc station
+	psta = rtw_get_stainfo(pstapriv, da);
+	if (psta && psta->isrc && psta->pid>0)
+	{
+		u8 RC_OUI[4]={0x00,0xE0,0x4C,0x0A};
+		u8 RC_INFO[14] = {0};
+		//EID[1] + EID_LEN[1] + RC_OUI[4] + MAC[6] + PairingID[2] + ChannelNum[2]
+		u16 cu_ch = (u16)cur_network->Configuration.DSConfig;
+
+		DBG_871X("%s, reply rc(pid=0x%x) device "MAC_FMT" in ch=%d\n", __FUNCTION__,
+			psta->pid, MAC_ARG(psta->hwaddr), cu_ch);
+
+		//append vendor specific ie
+		_rtw_memcpy(RC_INFO, RC_OUI, sizeof(RC_OUI));
+		_rtw_memcpy(&RC_INFO[4], mac, ETH_ALEN);
+		_rtw_memcpy(&RC_INFO[10], (u8*)&psta->pid, 2);
+		_rtw_memcpy(&RC_INFO[12], (u8*)&cu_ch, 2);
+
+		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(RC_INFO), RC_INFO, &pattrib->pktlen);
+	}
+}
+#endif //CONFIG_AUTO_AP_MODE
+
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+	
+
+	dump_mgntframe(padapter, pmgntframe);
+	
+	return;
+
+}
+
+int _issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, u8 ch, bool append_wps, int wait_ack)
+{
+	int ret = _FAIL;
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	unsigned char			*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short		*fctrl;
+	unsigned char			*mac;
+	unsigned char			bssrate[NumRates];
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	int	bssrate_len = 0;
+	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		goto exit;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	mac = adapter_mac_addr(padapter);
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	if (da)
+	{
+		//	unicast probe request frame
+		_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+		_rtw_memcpy(pwlanhdr->addr3, da, ETH_ALEN);
+	}
+	else
+	{
+		//	broadcast probe request frame
+		_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+		_rtw_memcpy(pwlanhdr->addr3, bc_addr, ETH_ALEN);
+	}
+
+	_rtw_memcpy(pwlanhdr->addr2, mac, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_PROBEREQ);
+
+	pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
+
+	if(pssid)
+		pframe = rtw_set_ie(pframe, _SSID_IE_, pssid->SsidLength, pssid->Ssid, &(pattrib->pktlen));
+	else
+		pframe = rtw_set_ie(pframe, _SSID_IE_, 0, NULL, &(pattrib->pktlen));
+
+	get_rate_set(padapter, bssrate, &bssrate_len);
+
+	if (bssrate_len > 8)
+	{
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
+		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
+	}
+	else
+	{
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
+	}
+
+	if (ch)
+		pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, &ch, &pattrib->pktlen);
+
+	if (append_wps) {
+		//add wps_ie for wps2.0
+		if(pmlmepriv->wps_probe_req_ie_len>0 && pmlmepriv->wps_probe_req_ie)
+		{
+			_rtw_memcpy(pframe, pmlmepriv->wps_probe_req_ie, pmlmepriv->wps_probe_req_ie_len);
+			pframe += pmlmepriv->wps_probe_req_ie_len;
+			pattrib->pktlen += pmlmepriv->wps_probe_req_ie_len;
+			//pmlmepriv->wps_probe_req_ie_len = 0 ;//reset to zero
+		}
+	}
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_notice_,("issuing probe_req, tx_len=%d\n", pattrib->last_txcmdsz));
+
+	if (wait_ack) {
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+	return ret;
+}
+
+inline void issue_probereq(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da)
+{
+	_issue_probereq(padapter, pssid, da, 0, 1, _FALSE);
+}
+
+/*
+ * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ * try_cnt means the maximal TX count to try
+ */
+int issue_probereq_ex(_adapter *padapter, NDIS_802_11_SSID *pssid, u8 *da, u8 ch, bool append_wps,
+	int try_cnt, int wait_ms)
+{
+	int ret = _FAIL;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	do
+	{
+		ret = _issue_probereq(padapter, pssid, da, ch, append_wps, wait_ms>0?_TRUE:_FALSE);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(padapter))
+			break;
+
+		if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
+			rtw_msleep_os(wait_ms);
+
+	}while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (da)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+// if psta == NULL, indiate we are station(client) now...
+void issue_auth(_adapter *padapter, struct sta_info *psta, unsigned short status)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	unsigned int					val32;
+	unsigned short				val16;
+	int use_shared_key = 0;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_AUTH);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+
+	if(psta)// for AP mode
+	{
+#ifdef CONFIG_NATIVEAP_MLME
+
+		_rtw_memcpy(pwlanhdr->addr1, psta->hwaddr, ETH_ALEN);		
+		_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+		_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
+
+	
+		// setting auth algo number
+		val16 = (u16)psta->authalg;
+
+		if(status != _STATS_SUCCESSFUL_)
+			val16 = 0;
+
+		if (val16)	{
+			val16 = cpu_to_le16(val16);	
+			use_shared_key = 1;
+		}
+
+		pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
+
+		// setting auth seq number
+		val16 =(u16)psta->auth_seq;
+		val16 = cpu_to_le16(val16);	
+		pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
+
+		// setting status code...
+		val16 = status;
+		val16 = cpu_to_le16(val16);	
+		pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
+
+		// added challenging text...
+		if ((psta->auth_seq == 2) && (psta->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
+		{
+			pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, psta->chg_txt, &(pattrib->pktlen));
+		}
+#endif
+	}
+	else
+	{		
+		_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+		_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+		_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&pmlmeinfo->network), ETH_ALEN);
+	
+		// setting auth algo number		
+		val16 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_Shared)? 1: 0;// 0:OPEN System, 1:Shared key
+		if (val16)	{
+			val16 = cpu_to_le16(val16);	
+			use_shared_key = 1;
+		}	
+		//DBG_871X("%s auth_algo= %s auth_seq=%d\n",__FUNCTION__,(pmlmeinfo->auth_algo==0)?"OPEN":"SHARED",pmlmeinfo->auth_seq);
+		
+		//setting IV for auth seq #3
+		if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
+		{
+			//DBG_871X("==> iv(%d),key_index(%d)\n",pmlmeinfo->iv,pmlmeinfo->key_index);
+			val32 = ((pmlmeinfo->iv++) | (pmlmeinfo->key_index << 30));
+			val32 = cpu_to_le32(val32);
+			pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *)&val32, &(pattrib->pktlen));
+
+			pattrib->iv_len = 4;
+		}
+
+		pframe = rtw_set_fixed_ie(pframe, _AUTH_ALGM_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
+		
+		// setting auth seq number
+		val16 = pmlmeinfo->auth_seq;
+		val16 = cpu_to_le16(val16);	
+		pframe = rtw_set_fixed_ie(pframe, _AUTH_SEQ_NUM_, (unsigned char *)&val16, &(pattrib->pktlen));
+
+		
+		// setting status code...
+		val16 = status;
+		val16 = cpu_to_le16(val16);	
+		pframe = rtw_set_fixed_ie(pframe, _STATUS_CODE_, (unsigned char *)&val16, &(pattrib->pktlen));
+
+		// then checking to see if sending challenging text...
+		if ((pmlmeinfo->auth_seq == 3) && (pmlmeinfo->state & WIFI_FW_AUTH_STATE) && (use_shared_key==1))
+		{
+			pframe = rtw_set_ie(pframe, _CHLGETXT_IE_, 128, pmlmeinfo->chg_txt, &(pattrib->pktlen));
+
+			SetPrivacy(fctrl);
+			
+			pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);			
+			
+			pattrib->encrypt = _WEP40_;
+
+			pattrib->icv_len = 4;
+			
+			pattrib->pktlen += pattrib->icv_len;			
+			
+		}
+		
+	}
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	rtw_wep_encrypt(padapter, (u8 *)pmgntframe);
+	DBG_871X("%s\n", __FUNCTION__);
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+}
+
+
+void issue_asocrsp(_adapter *padapter, unsigned short status, struct sta_info *pstat, int pkt_type)
+{
+#ifdef CONFIG_AP_MODE
+	struct xmit_frame	*pmgntframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	struct pkt_attrib *pattrib;
+	unsigned char	*pbuf, *pframe;
+	unsigned short val, ie_status;		
+	unsigned short *fctrl;
+	struct xmit_priv *pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);	
+	WLAN_BSSID_EX *pnetwork = &(pmlmeinfo->network);
+	u8 *ie = pnetwork->IEs; 
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+
+#endif //CONFIG_P2P
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy((void *)GetAddr1Ptr(pwlanhdr), pstat->hwaddr, ETH_ALEN);
+	_rtw_memcpy((void *)GetAddr2Ptr(pwlanhdr), adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy((void *)GetAddr3Ptr(pwlanhdr), get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	if ((pkt_type == WIFI_ASSOCRSP) || (pkt_type == WIFI_REASSOCRSP))
+		SetFrameSubType(pwlanhdr, pkt_type);		
+	else
+		return;
+
+	pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen += pattrib->hdrlen;
+	pframe += pattrib->hdrlen;
+
+	//capability
+	val = *(unsigned short *)rtw_get_capability_from_ie(ie);
+
+	pframe = rtw_set_fixed_ie(pframe, _CAPABILITY_ , (unsigned char *)&val, &(pattrib->pktlen));
+
+	ie_status = cpu_to_le16(status);
+	pframe = rtw_set_fixed_ie(pframe , _STATUS_CODE_ , (unsigned char *)&ie_status, &(pattrib->pktlen));
+	
+	val = cpu_to_le16(pstat->aid | BIT(14) | BIT(15));
+	pframe = rtw_set_fixed_ie(pframe, _ASOC_ID_ , (unsigned char *)&val, &(pattrib->pktlen));
+
+	if (pstat->bssratelen <= 8)
+	{
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, pstat->bssratelen, pstat->bssrateset, &(pattrib->pktlen));
+	}	
+	else 
+	{
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, 8, pstat->bssrateset, &(pattrib->pktlen));
+		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (pstat->bssratelen-8), pstat->bssrateset+8, &(pattrib->pktlen));
+	}
+
+#ifdef CONFIG_IEEE80211W	
+	if (status == _STATS_REFUSED_TEMPORARILY_) {
+		u8 timeout_itvl[5];
+		u32 timeout_interval = 3000;
+		/* Association Comeback time */
+		timeout_itvl[0] = 0x03;
+		timeout_interval = cpu_to_le32(timeout_interval);
+		_rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);
+		pframe = rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
+	}
+#endif /* CONFIG_IEEE80211W */
+
+#ifdef CONFIG_80211N_HT
+	if ((pstat->flags & WLAN_STA_HT) && (pmlmepriv->htpriv.ht_option))
+	{
+		uint ie_len=0;
+		
+		//FILL HT CAP INFO IE
+		//p = hostapd_eid_ht_capabilities_info(hapd, p);
+		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_CAPABILITY_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+		if(pbuf && ie_len>0)
+		{
+			_rtw_memcpy(pframe, pbuf, ie_len+2);
+			pframe += (ie_len+2);
+			pattrib->pktlen +=(ie_len+2);
+		}
+
+		//FILL HT ADD INFO IE
+		//p = hostapd_eid_ht_operation(hapd, p);
+		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _HT_ADD_INFO_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+		if(pbuf && ie_len>0)
+		{
+			_rtw_memcpy(pframe, pbuf, ie_len+2);
+			pframe += (ie_len+2);
+			pattrib->pktlen +=(ie_len+2);
+		}
+		
+	}	
+#endif
+
+	/*adding EXT_CAPAB_IE */
+	if (pmlmepriv->ext_capab_ie_len > 0) {
+		uint ie_len = 0;
+		
+		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, _EXT_CAP_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+		if (pbuf && ie_len > 0) {
+			_rtw_memcpy(pframe, pbuf, ie_len+2);
+			pframe += (ie_len+2);
+			pattrib->pktlen += (ie_len+2);
+		}
+	}	
+	
+#ifdef CONFIG_80211AC_VHT
+	if ((pstat->flags & WLAN_STA_VHT) && (pmlmepriv->vhtpriv.vht_option)
+		&& (pstat->wpa_pairwise_cipher != WPA_CIPHER_TKIP)
+		&& (pstat->wpa2_pairwise_cipher != WPA_CIPHER_TKIP))
+	{
+		u32 ie_len=0;
+
+		//FILL VHT CAP IE
+		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTCapability, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+		if(pbuf && ie_len>0)
+		{
+			_rtw_memcpy(pframe, pbuf, ie_len+2);
+			pframe += (ie_len+2);
+			pattrib->pktlen +=(ie_len+2);
+		}
+
+		//FILL VHT OPERATION IE
+		pbuf = rtw_get_ie(ie + _BEACON_IE_OFFSET_, EID_VHTOperation, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_));
+		if(pbuf && ie_len>0)
+		{
+			_rtw_memcpy(pframe, pbuf, ie_len+2);
+			pframe += (ie_len+2);
+			pattrib->pktlen +=(ie_len+2);
+		}
+	}
+#endif //CONFIG_80211AC_VHT
+
+	//FILL WMM IE
+	if ((pstat->flags & WLAN_STA_WME) && (pmlmepriv->qospriv.qos_option))
+	{
+		uint ie_len=0;
+		unsigned char WMM_PARA_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x01, 0x01};	
+		
+		for (pbuf = ie + _BEACON_IE_OFFSET_; ;pbuf+= (ie_len + 2))
+		{			
+			pbuf = rtw_get_ie(pbuf, _VENDOR_SPECIFIC_IE_, &ie_len, (pnetwork->IELength - _BEACON_IE_OFFSET_ - (ie_len + 2)));	
+			if(pbuf && _rtw_memcmp(pbuf+2, WMM_PARA_IE, 6)) 
+			{				
+				_rtw_memcpy(pframe, pbuf, ie_len+2);
+				pframe += (ie_len+2);
+				pattrib->pktlen +=(ie_len+2);
+				
+				break;				
+			}
+			
+			if ((pbuf == NULL) || (ie_len == 0))
+			{
+				break;
+			}			
+		}
+		
+	}
+
+
+	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
+	{
+		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
+	}
+
+	//add WPS IE ie for wps 2.0
+	if(pmlmepriv->wps_assoc_resp_ie && pmlmepriv->wps_assoc_resp_ie_len>0)
+	{
+		_rtw_memcpy(pframe, pmlmepriv->wps_assoc_resp_ie, pmlmepriv->wps_assoc_resp_ie_len);
+		
+		pframe += pmlmepriv->wps_assoc_resp_ie_len;
+		pattrib->pktlen += pmlmepriv->wps_assoc_resp_ie_len;
+	}
+
+#ifdef CONFIG_P2P
+	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO) && (pstat->is_p2p_device == _TRUE)) {
+		u32 len;
+
+		if (padapter->wdinfo.driver_interface == DRIVER_CFG80211) {
+			len = 0;
+			if (pmlmepriv->p2p_assoc_resp_ie && pmlmepriv->p2p_assoc_resp_ie_len > 0) {
+				len = pmlmepriv->p2p_assoc_resp_ie_len;
+				_rtw_memcpy(pframe, pmlmepriv->p2p_assoc_resp_ie, len);
+			}
+		} else {
+			len = build_assoc_resp_p2p_ie(pwdinfo, pframe, pstat->p2p_status_code);
+		}
+		pframe += len;
+		pattrib->pktlen += len;
+	}
+
+	#ifdef CONFIG_WFD
+	if (rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO)) {
+		wfdielen = rtw_append_assoc_resp_wfd_ie(padapter, pframe);
+		pframe += wfdielen;
+		pattrib->pktlen += wfdielen;
+	}
+	#endif
+
+#endif /* CONFIG_P2P */
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+	
+	dump_mgntframe(padapter, pmgntframe);
+	
+#endif
+}
+
+void issue_assocreq(_adapter *padapter)
+{
+	int ret = _FAIL;
+	struct xmit_frame				*pmgntframe;
+	struct pkt_attrib				*pattrib;
+	unsigned char					*pframe, *p;
+	struct rtw_ieee80211_hdr			*pwlanhdr;
+	unsigned short				*fctrl;
+	unsigned short				val16;
+	unsigned int					i, j, ie_len, index=0;
+	unsigned char					rf_type, bssrate[NumRates], sta_bssrate[NumRates];
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	int	bssrate_len = 0, sta_bssrate_len = 0;
+	u8	vs_ie_length = 0;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(padapter->wdinfo);
+	u8					p2pie[ 255 ] = { 0x00 };
+	u16					p2pielen = 0;	
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+#endif //CONFIG_P2P
+
+#ifdef CONFIG_DFS
+	u16	cap;
+
+	/* Dot H */
+	u8 pow_cap_ele[2] = { 0x00 };
+	u8 sup_ch[ 30 * 2 ] = {0x00 }, sup_ch_idx = 0, idx_5g = 2;	//For supported channel
+#endif //CONFIG_DFS
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+	_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ASSOCREQ);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	//caps
+
+#ifdef CONFIG_DFS
+	_rtw_memcpy(&cap, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+	cap |= cap_SpecMgmt;
+	_rtw_memcpy(pframe, &cap, 2);
+#else
+	_rtw_memcpy(pframe, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+#endif //CONFIG_DFS
+
+	pframe += 2;
+	pattrib->pktlen += 2;
+
+	//listen interval
+	//todo: listen interval for power saving
+	val16 = cpu_to_le16(3);
+	_rtw_memcpy(pframe ,(unsigned char *)&val16, 2);
+	pframe += 2;
+	pattrib->pktlen += 2;
+
+	//SSID
+	pframe = rtw_set_ie(pframe, _SSID_IE_,  pmlmeinfo->network.Ssid.SsidLength, pmlmeinfo->network.Ssid.Ssid, &(pattrib->pktlen));
+
+#ifdef CONFIG_DFS
+	/* Dot H */
+	if(pmlmeext->cur_channel > 14)
+	{
+		pow_cap_ele[0] = 13;	// Minimum transmit power capability
+		pow_cap_ele[1] = 21;	// Maximum transmit power capability
+		pframe = rtw_set_ie(pframe, EID_PowerCap, 2, pow_cap_ele, &(pattrib->pktlen));
+
+		//supported channels
+		do{
+			if( pmlmeext->channel_set[sup_ch_idx].ChannelNum <= 14 )
+			{
+				sup_ch[0] = 1;	//First channel number
+				sup_ch[1] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;	//Number of channel
+			}
+			else
+			{
+				sup_ch[idx_5g++] = pmlmeext->channel_set[sup_ch_idx].ChannelNum;
+				sup_ch[idx_5g++] = 1;
+			}
+			sup_ch_idx++;
+		}
+		while( pmlmeext->channel_set[sup_ch_idx].ChannelNum != 0 );
+		pframe = rtw_set_ie(pframe, EID_SupportedChannels, idx_5g, sup_ch, &(pattrib->pktlen));
+	}
+#endif //CONFIG_DFS
+
+	//supported rate & extended supported rate
+
+#if 1	// Check if the AP's supported rates are also supported by STA.
+	get_rate_set(padapter, sta_bssrate, &sta_bssrate_len);
+	//DBG_871X("sta_bssrate_len=%d\n", sta_bssrate_len);
+	
+	if(pmlmeext->cur_channel == 14)// for JAPAN, channel 14 can only uses B Mode(CCK) 
+	{
+		sta_bssrate_len = 4;
+	}
+
+	
+	//for (i = 0; i < sta_bssrate_len; i++) {
+	//	DBG_871X("sta_bssrate[%d]=%02X\n", i, sta_bssrate[i]);
+	//}
+
+	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+		if (pmlmeinfo->network.SupportedRates[i] == 0) break;
+		DBG_871X("network.SupportedRates[%d]=%02X\n", i, pmlmeinfo->network.SupportedRates[i]);
+	}
+	
+
+	for (i = 0; i < NDIS_802_11_LENGTH_RATES_EX; i++) {
+		if (pmlmeinfo->network.SupportedRates[i] == 0) break;
+
+		
+		// Check if the AP's supported rates are also supported by STA.
+		for (j=0; j < sta_bssrate_len; j++) {
+			 // Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP
+			if ( (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK) 
+					== (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK)) {
+				//DBG_871X("match i = %d, j=%d\n", i, j);
+				break;
+			} else {
+				//DBG_871X("not match: %02X != %02X\n", (pmlmeinfo->network.SupportedRates[i]|IEEE80211_BASIC_RATE_MASK), (sta_bssrate[j]|IEEE80211_BASIC_RATE_MASK));
+			}
+		}
+		
+		if (j == sta_bssrate_len) {
+			// the rate is not supported by STA
+			DBG_871X("%s(): the rate[%d]=%02X is not supported by STA!\n",__FUNCTION__, i, pmlmeinfo->network.SupportedRates[i]);
+		} else {
+			// the rate is supported by STA
+			bssrate[index++] = pmlmeinfo->network.SupportedRates[i];
+		}
+	}
+	
+	bssrate_len = index;
+	DBG_871X("bssrate_len = %d\n", bssrate_len);
+
+#else	// Check if the AP's supported rates are also supported by STA.
+#if 0
+	get_rate_set(padapter, bssrate, &bssrate_len);
+#else
+	for (bssrate_len = 0; bssrate_len < NumRates; bssrate_len++) {
+		if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0) break;
+
+		if (pmlmeinfo->network.SupportedRates[bssrate_len] == 0x2C) // Avoid the proprietary data rate (22Mbps) of Handlink WSG-4000 AP
+			break;
+
+		bssrate[bssrate_len] = pmlmeinfo->network.SupportedRates[bssrate_len];
+	}
+#endif
+#endif	// Check if the AP's supported rates are also supported by STA.
+
+	if ((bssrate_len == 0) && (pmlmeinfo->network.SupportedRates[0] != 0)) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit; //don't connect to AP if no joint supported rate
+	}
+
+
+	if (bssrate_len > 8)
+	{
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
+		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
+	}
+	else if (bssrate_len > 0)
+	{
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
+	} else {
+		DBG_871X("%s: Connect to AP without 11b and 11g data rate!\n",__FUNCTION__);
+	}
+
+	//vendor specific IE, such as WPA, WMM, WPS
+	for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
+
+		switch (pIE->ElementID)
+		{
+			case _VENDOR_SPECIFIC_IE_:
+				if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) ||
+						(_rtw_memcmp(pIE->data, WMM_OUI, 4)) ||
+						(_rtw_memcmp(pIE->data, WPS_OUI, 4)))
+				{	
+					vs_ie_length = pIE->Length;
+					if((!padapter->registrypriv.wifi_spec) && (_rtw_memcmp(pIE->data, WPS_OUI, 4)))
+					{
+						//Commented by Kurt 20110629
+						//In some older APs, WPS handshake
+						//would be fail if we append vender extensions informations to AP
+
+						vs_ie_length = 14;
+					}
+					
+					pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, vs_ie_length, pIE->data, &(pattrib->pktlen));
+				}
+				break;
+
+			case EID_WPA2:
+				pframe = rtw_set_ie(pframe, EID_WPA2, pIE->Length, pIE->data, &(pattrib->pktlen));
+				break;
+#ifdef CONFIG_80211N_HT
+			case EID_HTCapability:
+				if(padapter->mlmepriv.htpriv.ht_option==_TRUE) {
+					if (!(is_ap_in_tkip(padapter)))
+					{
+						_rtw_memcpy(&(pmlmeinfo->HT_caps), pIE->data, sizeof(struct HT_caps_element));
+
+						pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = cpu_to_le16(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info);
+
+						pframe = rtw_set_ie(pframe, EID_HTCapability, pIE->Length , (u8 *)(&(pmlmeinfo->HT_caps)), &(pattrib->pktlen));
+					}
+				}
+				break;
+
+			case EID_EXTCapability:
+				if(padapter->mlmepriv.htpriv.ht_option==_TRUE) {
+					pframe = rtw_set_ie(pframe, EID_EXTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
+				}
+				break;
+#endif //CONFIG_80211N_HT
+#ifdef CONFIG_80211AC_VHT
+			case EID_VHTCapability:
+				if (padapter->mlmepriv.vhtpriv.vht_option ==_TRUE) {
+					pframe = rtw_set_ie(pframe, EID_VHTCapability, pIE->Length, pIE->data, &(pattrib->pktlen));
+				}
+				break;
+
+			case EID_OpModeNotification:
+				if (padapter->mlmepriv.vhtpriv.vht_option ==_TRUE) {
+					pframe = rtw_set_ie(pframe, EID_OpModeNotification, pIE->Length, pIE->data, &(pattrib->pktlen));
+				}
+				break;
+#endif // CONFIG_80211AC_VHT
+			default:
+				break;
+		}
+
+		i += (pIE->Length + 2);
+	}
+
+	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_REALTEK)
+	{
+		pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, 6 , REALTEK_96B_IE, &(pattrib->pktlen));
+	}
+
+
+#ifdef CONFIG_WAPI_SUPPORT
+	rtw_build_assoc_req_wapi_ie(padapter, pframe, pattrib);
+#endif
+
+
+#ifdef CONFIG_P2P
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if(adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->driver_interface == DRIVER_CFG80211 )
+	{
+		if(pmlmepriv->p2p_assoc_req_ie && pmlmepriv->p2p_assoc_req_ie_len>0)
+		{
+			_rtw_memcpy(pframe, pmlmepriv->p2p_assoc_req_ie, pmlmepriv->p2p_assoc_req_ie_len);
+			pframe += pmlmepriv->p2p_assoc_req_ie_len;
+			pattrib->pktlen += pmlmepriv->p2p_assoc_req_ie_len;
+		}
+	}
+	else
+#endif //CONFIG_IOCTL_CFG80211
+	{
+		if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) && !rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+		{
+			//	Should add the P2P IE in the association request frame.	
+			//	P2P OUI
+			
+			p2pielen = 0;
+			p2pie[ p2pielen++ ] = 0x50;
+			p2pie[ p2pielen++ ] = 0x6F;
+			p2pie[ p2pielen++ ] = 0x9A;
+			p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+			//	Commented by Albert 20101109
+			//	According to the P2P Specification, the association request frame should contain 3 P2P attributes
+			//	1. P2P Capability
+			//	2. Extended Listen Timing
+			//	3. Device Info
+			//	Commented by Albert 20110516
+			//	4. P2P Interface
+
+			//	P2P Capability
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+			p2pielen += 2;
+
+			//	Value:
+			//	Device Capability Bitmap, 1 byte
+			p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+
+			//	Group Capability Bitmap, 1 byte
+			if ( pwdinfo->persistent_supported )
+				p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+			else
+				p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
+
+			//	Extended Listen Timing
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
+
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
+			p2pielen += 2;
+
+			//	Value:
+			//	Availability Period
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+			p2pielen += 2;
+
+			//	Availability Interval
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+			p2pielen += 2;
+
+			//	Device Info
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+			//	Length:
+			//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
+			//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+			p2pielen += 2;
+
+			//	Value:
+			//	P2P Device Address
+			_rtw_memcpy(p2pie + p2pielen, adapter_mac_addr(padapter), ETH_ALEN);
+			p2pielen += ETH_ALEN;
+
+			//	Config Method
+			//	This field should be big endian. Noted by P2P specification.
+			if ( ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PEER_DISPLAY_PIN ) ||
+				( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_SELF_DISPLAY_PIN ) )
+			{
+				*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
+			}
+			else
+			{
+				*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC );
+			}
+
+			p2pielen += 2;
+
+			//	Primary Device Type
+			//	Category ID
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+			p2pielen += 2;
+
+			//	OUI
+			*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+			p2pielen += 4;
+
+			//	Sub Category ID
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+			p2pielen += 2;
+
+			//	Number of Secondary Device Types
+			p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
+
+			//	Device Name
+			//	Type:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+			p2pielen += 2;
+
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
+			p2pielen += 2;
+
+			//	Value:
+			_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
+			p2pielen += pwdinfo->device_name_len;
+		
+			//	P2P Interface
+			//	Type:
+			p2pie[ p2pielen++ ] = P2P_ATTR_INTERFACE;
+			
+			//	Length:
+			*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x000D );
+			p2pielen += 2;
+			
+			//	Value:
+			_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );	//	P2P Device Address
+			p2pielen += ETH_ALEN;
+
+			p2pie[ p2pielen++ ] = 1;	//	P2P Interface Address Count
+			
+			_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );	//	P2P Interface Address List
+			p2pielen += ETH_ALEN;
+		
+			pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &pattrib->pktlen );
+		}
+	}
+
+#endif //CONFIG_P2P
+
+#ifdef CONFIG_WFD
+	wfdielen = rtw_append_assoc_req_wfd_ie(padapter, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+	dump_mgntframe(padapter, pmgntframe);
+
+	ret = _SUCCESS;
+
+exit:
+	if (ret == _SUCCESS)
+		rtw_buf_update(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len, (u8 *)pwlanhdr, pattrib->pktlen);
+	else
+		rtw_buf_free(&pmlmepriv->assoc_req, &pmlmepriv->assoc_req_len);
+
+	return;
+}
+
+//when wait_ack is ture, this function shoule be called at process context
+static int _issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
+{
+	int ret = _FAIL;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv	*pxmitpriv;
+	struct mlme_ext_priv	*pmlmeext;
+	struct mlme_ext_info	*pmlmeinfo;
+
+	//DBG_871X("%s:%d\n", __FUNCTION__, power_mode);
+
+	if(!padapter)
+		goto exit;
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	pxmitpriv = &(padapter->xmitpriv);
+	pmlmeext = &(padapter->mlmeextpriv);
+	pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		goto exit;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+	pattrib->retry_ctrl = _FALSE;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	{
+		SetFrDs(fctrl);
+	}
+	else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	{
+		SetToDs(fctrl);
+	}
+	
+	if (power_mode)
+	{
+		SetPwrMgt(fctrl);
+	}
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_DATA_NULL);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	if(wait_ack)
+	{
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	}
+	else
+	{
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+	return ret;
+}
+
+/*
+ * [IMPORTANT] Don't call this function in interrupt context
+ *
+ * When wait_ms > 0, this function should be called at process context
+ * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ * try_cnt means the maximal TX count to try
+ * da == NULL for station mode
+ */
+int issue_nulldata(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
+{
+	int ret = _FAIL;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_info *psta;
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	/* da == NULL, assum it's null data for sta to ap*/
+	if (da == NULL)
+		da = get_my_bssid(&(pmlmeinfo->network));
+
+	psta = rtw_get_stainfo(&padapter->stapriv, da);
+	if (psta) {
+		if (power_mode)
+			rtw_hal_macid_sleep(padapter, psta->mac_id);
+		else
+			rtw_hal_macid_wakeup(padapter, psta->mac_id);
+	} else {
+		DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
+			FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
+		rtw_warn_on(1);
+	}
+
+	do {
+		ret = _issue_nulldata(padapter, da, power_mode, wait_ms>0?_TRUE:_FALSE);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(padapter))
+			break;
+
+		if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
+			rtw_msleep_os(wait_ms);
+
+	}while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (da)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+/*
+ * [IMPORTANT] This function run in interrupt context
+ *
+ * The null data packet would be sent without power bit,
+ * and not guarantee success.
+ */
+s32 issue_nulldata_in_interrupt(PADAPTER padapter, u8 *da, unsigned int power_mode)
+{
+	int ret;
+	struct mlme_ext_priv *pmlmeext;
+	struct mlme_ext_info *pmlmeinfo;
+
+
+	pmlmeext = &padapter->mlmeextpriv;
+	pmlmeinfo = &pmlmeext->mlmext_info;
+
+	/* da == NULL, assum it's null data for sta to ap*/
+	if (da == NULL)
+		da = get_my_bssid(&(pmlmeinfo->network));
+
+	ret = _issue_nulldata(padapter, da, power_mode, _FALSE);
+
+	return ret;
+}
+
+//when wait_ack is ture, this function shoule be called at process context
+static int _issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int wait_ack)
+{
+	int ret = _FAIL;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl, *qc;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		goto exit;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	pattrib->hdrlen +=2;
+	pattrib->qos_en = _TRUE;
+	pattrib->eosp = 1;
+	pattrib->ack_policy = 0;
+	pattrib->mdata = 0;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	if((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+	{
+		SetFrDs(fctrl);
+	}
+	else if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	{
+		SetToDs(fctrl);
+	}
+
+	if(pattrib->mdata)
+		SetMData(fctrl);
+
+	qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
+	
+	SetPriority(qc, tid);
+
+	SetEOSP(qc, pattrib->eosp);
+
+	SetAckpolicy(qc, pattrib->ack_policy);
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+	
+	if(wait_ack)
+	{
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	}
+	else
+	{
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+	return ret;
+}
+
+/*
+ * when wait_ms >0 , this function should be called at process context
+ * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ * try_cnt means the maximal TX count to try
+ * da == NULL for station mode
+ */
+int issue_qos_nulldata(_adapter *padapter, unsigned char *da, u16 tid, int try_cnt, int wait_ms)
+{
+	int ret = _FAIL;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	/* da == NULL, assum it's null data for sta to ap*/
+	if (da == NULL)
+		da = get_my_bssid(&(pmlmeinfo->network));
+	
+	do
+	{
+		ret = _issue_qos_nulldata(padapter, da, tid, wait_ms>0?_TRUE:_FALSE);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(padapter))
+			break;
+
+		if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
+			rtw_msleep_os(wait_ms);
+
+	}while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (da)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+static int _issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason, u8 wait_ack, u8 key_type)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	int ret = _FAIL;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif //CONFIG_P2P	
+
+	//DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
+
+#ifdef CONFIG_P2P
+	if ( !( rtw_p2p_chk_state( pwdinfo, P2P_STATE_NONE ) ) && ( pwdinfo->rx_invitereq_info.scan_op_ch_only ) )
+	{
+		_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey );
+		_set_timer( &pwdinfo->reset_ch_sitesurvey, 10 );
+	}
+#endif //CONFIG_P2P
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		goto exit;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+	pattrib->retry_ctrl = _FALSE;
+	pattrib->key_type = key_type;
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_DEAUTH);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	reason = cpu_to_le16(reason);
+	pframe = rtw_set_fixed_ie(pframe, _RSON_CODE_ , (unsigned char *)&reason, &(pattrib->pktlen));
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+
+	if(wait_ack)
+	{
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	}
+	else
+	{
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+	return ret;
+}
+
+int issue_deauth(_adapter *padapter, unsigned char *da, unsigned short reason)
+{
+	DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
+	return _issue_deauth(padapter, da, reason, _FALSE, IEEE80211W_RIGHT_KEY);
+}
+
+#ifdef CONFIG_IEEE80211W
+int issue_deauth_11w(_adapter *padapter, unsigned char *da, unsigned short reason, u8 key_type)
+{
+	DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(da));
+	return _issue_deauth(padapter, da, reason, _FALSE, key_type);
+}
+#endif /* CONFIG_IEEE80211W */
+
+/*
+ * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ * try_cnt means the maximal TX count to try
+ */
+int issue_deauth_ex(_adapter *padapter, u8 *da, unsigned short reason, int try_cnt,
+	int wait_ms)
+{
+	int ret = _FAIL;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	do
+	{
+		ret = _issue_deauth(padapter, da, reason, wait_ms > 0 ? _TRUE:_FALSE, IEEE80211W_RIGHT_KEY);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(padapter))
+			break;
+
+		if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
+			rtw_msleep_os(wait_ms);
+
+	}while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (da)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+void issue_action_spct_ch_switch(_adapter *padapter, u8 *ra, u8 new_ch, u8 ch_offset)
+{	
+	_irqL	irqL;
+	_list		*plist, *phead;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char				*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short			*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return;
+
+	DBG_871X(FUNC_NDEV_FMT" ra="MAC_FMT", ch:%u, offset:%u\n",
+		FUNC_NDEV_ARG(padapter->pnetdev), MAC_ARG(ra), new_ch, ch_offset);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		return;
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, ra, ETH_ALEN); /* RA */
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */
+	_rtw_memcpy(pwlanhdr->addr3, ra, ETH_ALEN); /* DA = RA */
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	/* category, action */
+	{
+		u8 category, action;
+		category = RTW_WLAN_CATEGORY_SPECTRUM_MGMT;
+		action = RTW_WLAN_ACTION_SPCT_CHL_SWITCH;
+
+		pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+		pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	}
+
+	pframe = rtw_set_ie_ch_switch(pframe, &(pattrib->pktlen), 0, new_ch, 0);
+	pframe = rtw_set_ie_secondary_ch_offset(pframe, &(pattrib->pktlen),
+		hal_ch_offset_to_secondary_ch_offset(ch_offset));
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+}
+
+#ifdef CONFIG_IEEE80211W
+void issue_action_SA_Query(_adapter *padapter, unsigned char *raddr, unsigned char action, unsigned short tid, u8 key_type)
+{
+	u8	category = RTW_WLAN_CATEGORY_SA_QUERY;
+	u16	reason_code;
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	u8					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	u16					*fctrl;
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_info		*psta;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct registry_priv	 	*pregpriv = &padapter->registrypriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return;
+
+	DBG_871X("%s, %04x\n", __FUNCTION__, tid);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		DBG_871X("%s: alloc_mgtxmitframe fail\n", __FUNCTION__);
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+	pattrib->key_type = key_type;
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	if(raddr)
+		_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	else
+		_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &category, &pattrib->pktlen);
+	pframe = rtw_set_fixed_ie(pframe, 1, &action, &pattrib->pktlen);
+
+	switch (action)
+	{
+		case 0: //SA Query req
+			pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&pmlmeext->sa_query_seq, &pattrib->pktlen);
+			pmlmeext->sa_query_seq++;
+			/* send sa query request to AP, AP should reply sa query response in 1 second */
+			if (pattrib->key_type == IEEE80211W_RIGHT_KEY) {
+				psta = rtw_get_stainfo(pstapriv, raddr);
+				if (psta != NULL) {
+					/* DBG_871X("%s, %d, set dot11w_expire_timer\n", __func__, __LINE__); */
+					_set_timer(&psta->dot11w_expire_timer, 1000);
+				}
+			}
+			break;
+
+		case 1: //SA Query rsp
+			tid = cpu_to_le16(tid);
+			/* DBG_871X("rtw_set_fixed_ie, %04x\n", tid); */
+			pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)&tid, &pattrib->pktlen);
+			break;
+		default:
+			break;
+	}
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+}
+#endif //CONFIG_IEEE80211W
+
+/**
+ * issue_action_ba - internal function to TX Block Ack action frame
+ * @padapter: the adapter to TX
+ * @raddr: receiver address
+ * @action: Block Ack Action
+ * @tid: tid
+ * @size: the announced AMPDU buffer size. used by ADDBA_RESP
+ * @status: status/reason code. used by ADDBA_RESP, DELBA
+ * @initiator: if we are the initiator of AMPDU association. used by DELBA
+ * @wait_ack: used xmit ack
+ *
+ * Returns:
+ * _SUCCESS: No xmit ack is used or acked
+ * _FAIL: not acked when using xmit ack
+ */
+static int issue_action_ba(_adapter *padapter, unsigned char *raddr, unsigned char action
+	, u8 tid, u8 size, u16 status, u8 initiator, int wait_ack)
+{
+	int ret = _FAIL;
+	u8	category = RTW_WLAN_CATEGORY_BACK;
+	u16	start_seq;
+	u16	BA_para_set;
+	u16	BA_timeout_value;
+	u16	BA_starting_seqctrl;
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	u8					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	u16					*fctrl;
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_info		*psta;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct registry_priv	 	*pregpriv = &padapter->registrypriv;
+
+#ifdef CONFIG_80211N_HT
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	//_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+
+	if (category == 3)
+	{
+		switch (action)
+		{
+			case RTW_WLAN_ACTION_ADDBA_REQ:
+				do {
+					pmlmeinfo->dialogToken++;
+				} while (pmlmeinfo->dialogToken == 0);
+				pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->dialogToken), &(pattrib->pktlen));
+
+				#if defined(CONFIG_RTL8188E) && defined(CONFIG_SDIO_HCI)
+				BA_para_set = (0x0802 | ((tid & 0xf) << 2)); /* immediate ack & 16 buffer size */
+				#else
+				BA_para_set = (0x1002 | ((tid & 0xf) << 2)); /* immediate ack & 64 buffer size */
+				#endif
+
+				BA_para_set = cpu_to_le16(BA_para_set);
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
+
+				//BA_timeout_value = 0xffff;//max: 65535 TUs(~ 65 ms)
+				BA_timeout_value = 5000;//~ 5ms
+				BA_timeout_value = cpu_to_le16(BA_timeout_value);
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_timeout_value)), &(pattrib->pktlen));
+
+				//if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
+				if ((psta = rtw_get_stainfo(pstapriv, raddr)) != NULL)
+				{
+					start_seq = (psta->sta_xmitpriv.txseq_tid[tid & 0x07]&0xfff) + 1;
+
+					DBG_871X("BA_starting_seqctrl = %d for TID=%d\n", start_seq, tid & 0x07);
+					
+					psta->BA_starting_seqctrl[tid & 0x07] = start_seq;
+					
+					BA_starting_seqctrl = start_seq << 4;
+				}
+				
+				BA_starting_seqctrl = cpu_to_le16(BA_starting_seqctrl);
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_starting_seqctrl)), &(pattrib->pktlen));
+				break;
+
+			case RTW_WLAN_ACTION_ADDBA_RESP:
+				pframe = rtw_set_fixed_ie(pframe, 1, &(pmlmeinfo->ADDBA_req.dialog_token), &(pattrib->pktlen));
+				status = cpu_to_le16(status);
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&status), &(pattrib->pktlen));
+
+				BA_para_set = le16_to_cpu(pmlmeinfo->ADDBA_req.BA_para_set);
+
+				BA_para_set &= ~IEEE80211_ADDBA_PARAM_TID_MASK;
+				BA_para_set |= (tid << 2) & IEEE80211_ADDBA_PARAM_TID_MASK;
+
+				BA_para_set &= ~RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
+				BA_para_set |= (size << 6) & RTW_IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK;
+
+				if (!padapter->registrypriv.wifi_spec) {
+					if(pregpriv->ampdu_amsdu==0)//disabled
+						BA_para_set &= ~BIT(0);
+					else if(pregpriv->ampdu_amsdu==1)//enabled
+						BA_para_set |= BIT(0);
+				}
+
+				BA_para_set = cpu_to_le16(BA_para_set);
+
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(pmlmeinfo->ADDBA_req.BA_timeout_value)), &(pattrib->pktlen));
+				break;
+
+			case RTW_WLAN_ACTION_DELBA:
+				BA_para_set = 0;
+				BA_para_set |= (tid << 12) & IEEE80211_DELBA_PARAM_TID_MASK;
+				BA_para_set |= (initiator << 11) & IEEE80211_DELBA_PARAM_INITIATOR_MASK;
+
+				BA_para_set = cpu_to_le16(BA_para_set);				
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(BA_para_set)), &(pattrib->pktlen));
+				status = cpu_to_le16(status);
+				pframe = rtw_set_fixed_ie(pframe, 2, (unsigned char *)(&(status)), &(pattrib->pktlen));
+				break;
+			default:
+				break;
+		}
+	}
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	if (wait_ack) {
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+#endif //CONFIG_80211N_HT
+	return ret;
+}
+
+/**
+ * issue_addba_req - TX ADDBA_REQ
+ * @adapter: the adapter to TX
+ * @ra: receiver address
+ * @tid: tid
+ */
+inline void issue_addba_req(_adapter *adapter, unsigned char *ra, u8 tid)
+{
+	issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_REQ
+		, tid
+		, 0 /* unused */
+		, 0 /* unused */
+		, 0 /* unused */
+		, _FALSE
+	);
+	DBG_871X(FUNC_ADPT_FMT" ra="MAC_FMT" tid=%u\n"
+		, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), tid);
+
+}
+
+/**
+ * issue_addba_rsp - TX ADDBA_RESP
+ * @adapter: the adapter to TX
+ * @ra: receiver address
+ * @tid: tid
+ * @status: status code
+ * @size: the announced AMPDU buffer size
+ */
+inline void issue_addba_rsp(_adapter *adapter, unsigned char *ra, u8 tid, u16 status, u8 size)
+{
+	issue_action_ba(adapter, ra, RTW_WLAN_ACTION_ADDBA_RESP
+		, tid
+		, size
+		, status
+		, 0 /* unused */
+		, _FALSE
+	);
+	DBG_871X(FUNC_ADPT_FMT" ra="MAC_FMT" status=%u, tid=%u, size=%u\n"
+		, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), status, tid, size);
+}
+
+/**
+ * issue_del_ba - TX DELBA
+ * @adapter: the adapter to TX
+ * @ra: receiver address
+ * @tid: tid
+ * @reason: reason code
+ * @initiator: if we are the initiator of AMPDU association. used by DELBA
+ */
+inline void issue_del_ba(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator)
+{
+	issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA
+		, tid
+		, 0 /* unused */
+		, reason
+		, initiator
+		, _FALSE
+	);
+	DBG_871X(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u\n"
+		, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator);
+}
+
+/**
+ * issue_del_ba_ex - TX DELBA with xmit ack options
+ * @adapter: the adapter to TX
+ * @ra: receiver address
+ * @tid: tid
+ * @reason: reason code
+ * @initiator: if we are the initiator of AMPDU association. used by DELBA
+ * @try_cnt: the maximal TX count to try
+ * @wait_ms: == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ *           > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ */
+int issue_del_ba_ex(_adapter *adapter, unsigned char *ra, u8 tid, u16 reason, u8 initiator
+	, int try_cnt, int wait_ms)
+{
+	int ret = _FAIL;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(adapter)))
+		goto exit;
+
+	do {
+		ret = issue_action_ba(adapter, ra, RTW_WLAN_ACTION_DELBA
+			, tid
+			, 0 /* unused */
+			, reason
+			, initiator
+			, wait_ms > 0?_TRUE:_FALSE
+		);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(adapter))
+			break;
+
+		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+			rtw_msleep_os(wait_ms);
+
+	} while ((i < try_cnt) && ((ret == _FAIL) || (wait_ms == 0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+	#ifndef DBG_XMIT_ACK
+		/* goto exit; */
+	#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		DBG_871X(FUNC_ADPT_FMT" ra="MAC_FMT" reason=%u, tid=%u, initiator=%u%s, %d/%d in %u ms\n"
+			, FUNC_ADPT_ARG(adapter), MAC_ARG(ra), reason, tid, initiator
+			, ret == _SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+static void issue_action_BSSCoexistPacket(_adapter *padapter)
+{	
+	_irqL	irqL;
+	_list		*plist, *phead;
+	unsigned char category, action;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char				*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short			*fctrl;
+	struct	wlan_network	*pnetwork = NULL;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	_queue		*queue	= &(pmlmepriv->scanned_queue);
+	u8 InfoContent[16] = {0};
+	u8 ICS[8][15];
+#ifdef CONFIG_80211N_HT	
+	if((pmlmepriv->num_FortyMHzIntolerant==0) || (pmlmepriv->num_sta_no_ht==0))
+		return;
+
+	if(_TRUE == pmlmeinfo->bwmode_updated)
+		return;
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return;	
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+
+	category = RTW_WLAN_CATEGORY_PUBLIC;
+	action = ACT_PUBLIC_BSSCOEXIST;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+
+
+	//
+	if(pmlmepriv->num_FortyMHzIntolerant>0)
+	{
+		u8 iedata=0;
+		
+		iedata |= BIT(2);//20 MHz BSS Width Request
+
+		pframe = rtw_set_ie(pframe, EID_BSSCoexistence,  1, &iedata, &(pattrib->pktlen));
+		
+	}
+	
+
+	//
+	_rtw_memset(ICS, 0, sizeof(ICS));
+	if(pmlmepriv->num_sta_no_ht>0)
+	{	
+		int i;
+	
+		_enter_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+		phead = get_list_head(queue);
+		plist = get_next(phead);
+       
+		while(1)
+		{
+			int len;
+			u8 *p;
+			WLAN_BSSID_EX *pbss_network;
+	
+			if (rtw_end_of_queue_search(phead,plist)== _TRUE)
+				break;		
+
+			pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);      
+		
+			plist = get_next(plist);
+
+			pbss_network = (WLAN_BSSID_EX *)&pnetwork->network;
+
+			p = rtw_get_ie(pbss_network->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, pbss_network->IELength - _FIXED_IE_LENGTH_);
+			if((p==NULL) || (len==0))//non-HT
+			{
+				if((pbss_network->Configuration.DSConfig<=0) || (pbss_network->Configuration.DSConfig>14))
+					continue;
+				
+				ICS[0][pbss_network->Configuration.DSConfig]=1;
+				
+				if(ICS[0][0] == 0)
+					ICS[0][0] = 1;		
+			}		
+	
+		}        
+
+		_exit_critical_bh(&(pmlmepriv->scanned_queue.lock), &irqL);
+
+
+		for(i= 0;i<8;i++)
+		{
+			if(ICS[i][0] == 1)
+			{
+				int j, k = 0;
+				
+				InfoContent[k] = i;				
+				//SET_BSS_INTOLERANT_ELE_REG_CLASS(InfoContent,i);
+				k++;
+				
+				for(j=1;j<=14;j++)
+				{
+					if(ICS[i][j]==1)
+					{
+						if(k<16)
+						{
+							InfoContent[k] = j; //channel number
+							//SET_BSS_INTOLERANT_ELE_CHANNEL(InfoContent+k, j);
+							k++;
+						}	
+					}	
+				}	
+
+				pframe = rtw_set_ie(pframe, EID_BSSIntolerantChlReport, k, InfoContent, &(pattrib->pktlen));
+				
+			}
+			
+		}
+		
+
+	}
+		
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+#endif //CONFIG_80211N_HT
+}
+
+// Spatial Multiplexing Powersave (SMPS) action frame
+int _issue_action_SM_PS(_adapter *padapter ,  unsigned char *raddr , u8 NewMimoPsMode ,  u8 wait_ack)
+{
+
+	int ret = _FAIL;
+	unsigned char category = RTW_WLAN_CATEGORY_HT;
+	u8 action = RTW_WLAN_ACTION_HT_SM_PS; 	
+	u8 sm_power_control=0;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+
+	if(NewMimoPsMode==WLAN_HT_CAP_SM_PS_DISABLED)
+	{
+		sm_power_control = sm_power_control  & ~(BIT(0)); // SM Power Save Enable = 0 SM Power Save Disable 
+	}
+        else if(NewMimoPsMode==WLAN_HT_CAP_SM_PS_STATIC)
+        {
+                sm_power_control = sm_power_control | BIT(0);    // SM Power Save Enable = 1 SM Power Save Enable  
+                sm_power_control = sm_power_control & ~(BIT(1)); // SM Mode = 0 Static Mode
+        }
+        else if(NewMimoPsMode==WLAN_HT_CAP_SM_PS_DYNAMIC)
+        {
+                sm_power_control = sm_power_control | BIT(0); // SM Power Save Enable = 1 SM Power Save Enable  
+                sm_power_control = sm_power_control | BIT(1); // SM Mode = 1 Dynamic Mode
+        }
+        else 
+		return ret;
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		return ret;
+
+        DBG_871X("%s, sm_power_control=%u, NewMimoPsMode=%u\n", __FUNCTION__ , sm_power_control , NewMimoPsMode );
+    
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		return ret;
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN); /* RA */
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN); /* TA */
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN); /* DA = RA */
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	/* category, action */
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(sm_power_control), &(pattrib->pktlen));
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	if(wait_ack)
+	{
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	}
+	else
+	{
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+        if (ret != _SUCCESS)
+            DBG_8192C("%s, ack to\n", __func__);
+
+	return ret;
+}
+
+/*
+ * wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ * wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ * try_cnt means the maximal TX count to try
+ */
+int issue_action_SM_PS_wait_ack(_adapter *padapter, unsigned char *raddr, u8 NewMimoPsMode, int try_cnt, int wait_ms)
+{
+	int ret = _FAIL;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+
+	if (rtw_rfctl_is_tx_blocked_by_cac(adapter_to_rfctl(padapter)))
+		goto exit;
+
+	do {
+		ret = _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , wait_ms>0?_TRUE:_FALSE );
+
+		i++;
+
+		if (RTW_CANNOT_RUN(padapter))
+			break;
+
+		if(i < try_cnt && wait_ms > 0 && ret==_FAIL)
+			rtw_msleep_os(wait_ms);
+
+	}while((i<try_cnt) && ((ret==_FAIL)||(wait_ms==0)));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (raddr)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", %s , %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), MAC_ARG(raddr),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", %s , %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+
+	return ret;
+}
+
+int issue_action_SM_PS(_adapter *padapter ,  unsigned char *raddr , u8 NewMimoPsMode )
+{
+	DBG_871X("%s to "MAC_FMT"\n", __func__, MAC_ARG(raddr));
+	return _issue_action_SM_PS(padapter, raddr, NewMimoPsMode , _FALSE );
+}
+
+/**
+ * _send_delba_sta_tid - Cancel the AMPDU association for the specific @sta, @tid
+ * @adapter: the adapter to which @sta belongs
+ * @initiator: if we are the initiator of AMPDU association
+ * @sta: the sta to be checked
+ * @tid: the tid to be checked
+ * @force: cancel and send DELBA even when no AMPDU association is setup
+ * @wait_ack: send delba with xmit ack (valid when initiator == 0)
+ *
+ * Returns:
+ * _FAIL if sta is NULL
+ * when initiator is 1, always _SUCCESS
+ * when initiator is 0, _SUCCESS if DELBA is acked
+ */
+static unsigned int _send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid
+	, u8 force, int wait_ack)
+{
+	int ret = _SUCCESS;
+
+	if (sta == NULL) {
+		ret = _FAIL;
+		goto exit;
+	}
+
+	if (initiator == 0) {
+		/* recipient */
+		if (force || sta->recvreorder_ctrl[tid].enable == _TRUE) {
+			u8 ampdu_size_bak = sta->recvreorder_ctrl[tid].ampdu_size;
+
+			sta->recvreorder_ctrl[tid].enable = _FALSE;
+			sta->recvreorder_ctrl[tid].ampdu_size = RX_AMPDU_SIZE_INVALID;
+
+			if (rtw_del_rx_ampdu_test_trigger_no_tx_fail())
+				ret = _FAIL;
+			else if (wait_ack)
+				ret = issue_del_ba_ex(adapter, sta->hwaddr, tid, 37, initiator, 3, 1);
+			else
+				issue_del_ba(adapter, sta->hwaddr, tid, 37, initiator);
+
+			if (ret == _FAIL && sta->recvreorder_ctrl[tid].enable == _FALSE)
+				sta->recvreorder_ctrl[tid].ampdu_size = ampdu_size_bak;
+		}
+	} else if (initiator == 1) {
+		/* originator */
+#ifdef CONFIG_80211N_HT
+		if (force || sta->htpriv.agg_enable_bitmap & BIT(tid)) {
+			sta->htpriv.agg_enable_bitmap &= ~BIT(tid);
+			sta->htpriv.candidate_tid_bitmap &= ~BIT(tid);
+			issue_del_ba(adapter, sta->hwaddr, tid, 37, initiator);
+		}
+#endif
+	}
+
+exit:
+	return ret;
+}
+
+inline unsigned int send_delba_sta_tid(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid
+	, u8 force)
+{
+	return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 0);
+}
+
+inline unsigned int send_delba_sta_tid_wait_ack(_adapter *adapter, u8 initiator, struct sta_info *sta, u8 tid
+	, u8 force)
+{
+	return _send_delba_sta_tid(adapter, initiator, sta, tid, force, 1);
+}
+
+unsigned int send_delba(_adapter *padapter, u8 initiator, u8 *addr)
+{
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *psta = NULL;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u16 tid;
+
+	if ((pmlmeinfo->state&0x03) != WIFI_FW_AP_STATE)
+		if (!(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS))
+			return _SUCCESS;
+
+	psta = rtw_get_stainfo(pstapriv, addr);
+	if(psta==NULL)
+		return _SUCCESS;
+
+	#if 0
+	DBG_871X("%s:%s\n", __func__, (initiator == 0)?"RX_DIR":"TX_DIR");
+	if (initiator == 1) /* originator */
+		DBG_871X("tx agg_enable_bitmap(0x%08x)\n", psta->htpriv.agg_enable_bitmap);
+	#endif
+
+	for (tid = 0; tid < TID_NUM; tid++)
+		send_delba_sta_tid(padapter, initiator, psta, tid, 0);
+
+	return _SUCCESS;
+}
+
+unsigned int send_beacon(_adapter *padapter)
+{
+	u8	bxmitok = _FALSE;
+	int	issue=0;
+	int poll = 0;
+#if defined(CONFIG_PCI_HCI) && defined(RTL8814AE_SW_BCN)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+#endif
+//#ifdef CONFIG_CONCURRENT_MODE
+	//struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	//struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	//_adapter *pbuddy_adapter = padapter->pbuddy_adapter;
+	//struct mlme_priv *pbuddy_mlmepriv = &(pbuddy_adapter->mlmepriv);
+//#endif		
+
+#ifdef CONFIG_PCI_HCI
+	//DBG_871X("%s\n", __FUNCTION__);
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
+
+	/* 8192EE Port select for Beacon DL */
+	rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
+
+	issue_beacon(padapter, 0);
+
+#ifdef RTL8814AE_SW_BCN
+	if (pHalData->bCorrectBCN != 0)
+		DBG_871X("%s, line%d, Warnning, pHalData->bCorrectBCN != 0\n", __func__, __LINE__);
+	pHalData->bCorrectBCN = 1;
+#endif
+
+	return _SUCCESS;
+#endif
+
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+	u32 start = rtw_get_current_time();
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_BCN_VALID, NULL);
+	rtw_hal_set_hwreg(padapter, HW_VAR_DL_BCN_SEL, NULL);
+	do{
+		issue_beacon(padapter, 100);
+		issue++;
+		do {
+			rtw_yield_os();
+			rtw_hal_get_hwreg(padapter, HW_VAR_BCN_VALID, (u8 *)(&bxmitok));
+			poll++;
+		} while ((poll%10) != 0 && _FALSE == bxmitok && !RTW_CANNOT_RUN(padapter));
+
+	} while (_FALSE == bxmitok && issue < 100 && !RTW_CANNOT_RUN(padapter));
+
+	if (RTW_CANNOT_RUN(padapter))
+		return _FAIL;
+
+	
+	if(_FALSE == bxmitok)
+	{
+		DBG_871X("%s fail! %u ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
+		return _FAIL;
+	}
+	else
+	{
+		u32 passing_time = rtw_get_passing_time_ms(start);
+
+		if(passing_time > 100 || issue > 3)
+			DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
+		//else
+		//	DBG_871X("%s success, issue:%d, poll:%d, %u ms\n", __FUNCTION__, issue, poll, rtw_get_passing_time_ms(start));
+		
+		rtw_hal_fw_correct_bcn(padapter);
+
+		return _SUCCESS;
+	}
+
+#endif
+
+}
+
+/****************************************************************************
+
+Following are some utitity fuctions for WiFi MLME
+
+*****************************************************************************/
+
+BOOLEAN IsLegal5GChannel(
+	IN PADAPTER			Adapter,
+	IN u8			channel)
+{
+	
+	int i=0;
+	u8 Channel_5G[45] = {36,38,40,42,44,46,48,50,52,54,56,58,
+		60,62,64,100,102,104,106,108,110,112,114,116,118,120,122,
+		124,126,128,130,132,134,136,138,140,149,151,153,155,157,159,
+		161,163,165};
+	for(i=0;i<sizeof(Channel_5G);i++)
+		if(channel == Channel_5G[i])
+			return _TRUE;
+	return _FALSE;
+}
+
+//collect bss info from Beacon and Probe request/response frames.
+u8 collect_bss_info(_adapter *padapter, union recv_frame *precv_frame, WLAN_BSSID_EX *bssid)
+{
+	int	i;
+	u32	len;
+	u8	*p;
+	u16	val16, subtype;
+	u8	*pframe = precv_frame->u.hdr.rx_data;
+	u32	packet_len = precv_frame->u.hdr.len;
+	u8 ie_offset;
+	struct registry_priv 	*pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	if (len > MAX_IE_SZ)
+	{
+		//DBG_871X("IE too long for survey event\n");
+		return _FAIL;
+	}
+
+	_rtw_memset(bssid, 0, sizeof(WLAN_BSSID_EX));
+
+	subtype = GetFrameSubType(pframe);
+
+	if(subtype==WIFI_BEACON) {
+		bssid->Reserved[0] = 1;
+		ie_offset = _BEACON_IE_OFFSET_;
+	} else {
+		// FIXME : more type
+		if (subtype == WIFI_PROBERSP) {
+			ie_offset = _PROBERSP_IE_OFFSET_;
+			bssid->Reserved[0] = 3;
+		}
+		else if (subtype == WIFI_PROBEREQ) {
+			ie_offset = _PROBEREQ_IE_OFFSET_;
+			bssid->Reserved[0] = 2;
+		}
+		else {
+			bssid->Reserved[0] = 0;
+			ie_offset = _FIXED_IE_LENGTH_;
+		}
+	}
+		
+	bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;
+
+	//below is to copy the information element
+	bssid->IELength = len;
+	_rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
+
+	//get the signal strength
+	//bssid->Rssi = precv_frame->u.hdr.attrib.SignalStrength; // 0-100 index.
+	bssid->Rssi = precv_frame->u.hdr.attrib.phy_info.RecvSignalPower; // in dBM.raw data	
+	bssid->PhyInfo.SignalQuality = precv_frame->u.hdr.attrib.phy_info.SignalQuality;//in percentage 
+	bssid->PhyInfo.SignalStrength = precv_frame->u.hdr.attrib.phy_info.SignalStrength;//in percentage
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	//rtw_hal_get_hwreg(padapter, HW_VAR_CURRENT_ANTENNA, (u8 *)(&bssid->PhyInfo.Optimum_antenna));
+	rtw_hal_get_def_var(padapter, HAL_DEF_CURRENT_ANTENNA,  &bssid->PhyInfo.Optimum_antenna);
+#endif
+
+	// checking SSID
+	if ((p = rtw_get_ie(bssid->IEs + ie_offset, _SSID_IE_, &len, bssid->IELength - ie_offset)) == NULL)
+	{
+		DBG_871X("marc: cannot find SSID for survey event\n");
+		return _FAIL;
+	}
+
+	if (*(p + 1))
+	{
+		if (len > NDIS_802_11_LENGTH_SSID)
+		{
+			DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
+			return _FAIL;
+		}
+		_rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
+		bssid->Ssid.SsidLength = *(p + 1);
+	}
+	else
+	{
+		bssid->Ssid.SsidLength = 0;
+	}
+
+	_rtw_memset(bssid->SupportedRates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+	//checking rate info...
+	i = 0;
+	p = rtw_get_ie(bssid->IEs + ie_offset, _SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
+	if (p != NULL)
+	{
+		if (len > NDIS_802_11_LENGTH_RATES_EX)
+		{
+			DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
+			return _FAIL;
+		}
+		_rtw_memcpy(bssid->SupportedRates, (p + 2), len);
+		i = len;
+	}
+
+	p = rtw_get_ie(bssid->IEs + ie_offset, _EXT_SUPPORTEDRATES_IE_, &len, bssid->IELength - ie_offset);
+	if (p != NULL)
+	{
+		if (len > (NDIS_802_11_LENGTH_RATES_EX-i))
+		{
+			DBG_871X("%s()-%d: IE too long (%d) for survey event\n", __FUNCTION__, __LINE__, len);
+			return _FAIL;
+		}
+		_rtw_memcpy(bssid->SupportedRates + i, (p + 2), len);
+	}
+
+	//todo:
+#if 0
+	if (judge_network_type(bssid->SupportedRates, (len + i)) == WIRELESS_11B)
+	{
+		bssid->NetworkTypeInUse = Ndis802_11DS;
+	}
+	else
+#endif
+	{
+		bssid->NetworkTypeInUse = Ndis802_11OFDM24;
+	}
+
+#ifdef CONFIG_P2P
+	if (subtype == WIFI_PROBEREQ)
+	{
+		u8 *p2p_ie;
+		u32	p2p_ielen;
+		// Set Listion Channel
+		if ((p2p_ie = rtw_get_p2p_ie(bssid->IEs, bssid->IELength, NULL, &p2p_ielen)))
+		{
+			u32	attr_contentlen = 0;
+			u8 listen_ch[5] = { 0x00 };
+
+			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, listen_ch, &attr_contentlen);
+			bssid->Configuration.DSConfig = listen_ch[4];
+		} else
+		{ // use current channel
+			bssid->Configuration.DSConfig = padapter->mlmeextpriv.cur_channel;
+			DBG_871X("%s()-%d: Cannot get p2p_ie. set DSconfig to op_ch(%d)\n", __FUNCTION__, __LINE__, bssid->Configuration.DSConfig);
+		}
+
+		// FIXME
+		bssid->InfrastructureMode = Ndis802_11Infrastructure;
+		_rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
+		bssid->Privacy = 1;
+		return _SUCCESS;
+	}
+#endif //CONFIG_P2P
+
+	if (bssid->IELength < 12)
+		return _FAIL;
+
+	// Checking for DSConfig
+	p = rtw_get_ie(bssid->IEs + ie_offset, _DSSET_IE_, &len, bssid->IELength - ie_offset);
+
+	bssid->Configuration.DSConfig = 0;
+	bssid->Configuration.Length = 0;
+
+	if (p)
+	{
+		bssid->Configuration.DSConfig = *(p + 2);
+	}
+	else
+	{// In 5G, some ap do not have DSSET IE
+		// checking HT info for channel
+		p = rtw_get_ie(bssid->IEs + ie_offset, _HT_ADD_INFO_IE_, &len, bssid->IELength - ie_offset);
+		if(p)
+		{
+			struct HT_info_element *HT_info = (struct HT_info_element *)(p + 2);
+			bssid->Configuration.DSConfig = HT_info->primary_channel;
+		}
+		else
+		{ // use current channel
+			bssid->Configuration.DSConfig = rtw_get_oper_ch(padapter);
+		}
+	}
+
+	_rtw_memcpy(&bssid->Configuration.BeaconPeriod, rtw_get_beacon_interval_from_ie(bssid->IEs), 2);
+	bssid->Configuration.BeaconPeriod = le32_to_cpu(bssid->Configuration.BeaconPeriod);
+
+	val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);
+
+	if (val16 & BIT(0))
+	{
+		bssid->InfrastructureMode = Ndis802_11Infrastructure;
+		_rtw_memcpy(bssid->MacAddress, GetAddr2Ptr(pframe), ETH_ALEN);
+	}
+	else
+	{
+		bssid->InfrastructureMode = Ndis802_11IBSS;
+		_rtw_memcpy(bssid->MacAddress, GetAddr3Ptr(pframe), ETH_ALEN);
+	}
+
+	if (val16 & BIT(4))
+		bssid->Privacy = 1;
+	else
+		bssid->Privacy = 0;
+
+	bssid->Configuration.ATIMWindow = 0;
+
+	//20/40 BSS Coexistence check
+	if((pregistrypriv->wifi_spec==1) && (_FALSE == pmlmeinfo->bwmode_updated))
+	{	
+		struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_80211N_HT
+		p = rtw_get_ie(bssid->IEs + ie_offset, _HT_CAPABILITY_IE_, &len, bssid->IELength - ie_offset);
+		if(p && len>0)
+		{
+			struct HT_caps_element	*pHT_caps;
+			pHT_caps = (struct HT_caps_element	*)(p + 2);
+			
+			if(pHT_caps->u.HT_cap_element.HT_caps_info&BIT(14))
+			{				
+				pmlmepriv->num_FortyMHzIntolerant++;
+			}
+		}
+		else
+		{
+			pmlmepriv->num_sta_no_ht++;
+		}
+#endif //CONFIG_80211N_HT
+		
+	}
+
+#ifdef CONFIG_INTEL_WIDI
+	//process_intel_widi_query_or_tigger(padapter, bssid);
+	if(process_intel_widi_query_or_tigger(padapter, bssid))
+	{
+		return _FAIL;
+	}
+#endif // CONFIG_INTEL_WIDI
+
+	#if defined(DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) & 1
+	if(strcmp(bssid->Ssid.Ssid, DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED) == 0) {
+		DBG_871X("Receiving %s("MAC_FMT", DSConfig:%u) from ch%u with ss:%3u, sq:%3u, RawRSSI:%3ld\n"
+			, bssid->Ssid.Ssid, MAC_ARG(bssid->MacAddress), bssid->Configuration.DSConfig
+			, rtw_get_oper_ch(padapter)
+			, bssid->PhyInfo.SignalStrength, bssid->PhyInfo.SignalQuality, bssid->Rssi
+		);
+	}
+	#endif
+
+	// mark bss info receving from nearby channel as SignalQuality 101
+	if(bssid->Configuration.DSConfig != rtw_get_oper_ch(padapter))
+	{
+		bssid->PhyInfo.SignalQuality= 101;
+	}
+
+	return _SUCCESS;
+}
+
+void start_create_ibss(_adapter* padapter)
+{
+	unsigned short	caps;
+	u8	val8;
+	u8	join_type;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+	u8 doiqk = _FALSE;
+	pmlmeext->cur_channel = (u8)pnetwork->Configuration.DSConfig;
+	pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
+
+	//update wireless mode
+	update_wireless_mode(padapter);
+
+	//udpate capability
+	caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
+	update_capinfo(padapter, caps);
+	if(caps&cap_IBSS)//adhoc master
+	{
+		//set_opmode_cmd(padapter, adhoc);//removed
+
+		val8 = 0xcf;
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+		doiqk = _TRUE;
+		rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+
+		//switch channel
+		//SelectChannel(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE);
+		set_channel_bwmode(padapter, pmlmeext->cur_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+
+		doiqk = _FALSE;
+		rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+
+		beacon_timing_control(padapter);
+
+		//set msr to WIFI_FW_ADHOC_STATE
+		pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+		Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+		//issue beacon
+		if(send_beacon(padapter)==_FAIL)
+		{
+			RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,("issuing beacon frame fail....\n"));
+
+			report_join_res(padapter, -1);
+			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		}
+		else
+		{
+			rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, padapter->registrypriv.dev_network.MacAddress);
+			join_type = 0;
+			rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+			report_join_res(padapter, 1);
+			pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+			rtw_indicate_connect(padapter);
+		}
+	}
+	else
+	{
+		DBG_871X("start_create_ibss, invalid cap:%x\n", caps);
+		return;
+	}
+	//update bc/mc sta_info
+	update_bmc_sta(padapter);
+
+}
+
+void start_clnt_join(_adapter* padapter)
+{
+	unsigned short	caps;
+	u8	val8;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+	int beacon_timeout;
+	u8 ASIX_ID[]= {0x00, 0x0E, 0xC6};
+
+	//update wireless mode
+	update_wireless_mode(padapter);
+
+	//udpate capability
+	caps = rtw_get_capability((WLAN_BSSID_EX *)pnetwork);
+	update_capinfo(padapter, caps);
+	
+	//check if sta is ASIX peer and fix IOT issue if it is.
+	if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) ,ASIX_ID ,3)) {
+		u8 iot_flag = _TRUE;
+		rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag));
+	}
+	
+	if (caps&cap_ESS)
+	{
+		Set_MSR(padapter, WIFI_FW_STATION_STATE);
+
+		val8 = (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X)? 0xcc: 0xcf;
+
+#ifdef CONFIG_WAPI_SUPPORT
+		if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI)
+		{
+			//Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey.
+			val8 = 0x4c;
+		}
+#endif
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+		#ifdef CONFIG_DEAUTH_BEFORE_CONNECT
+		// Because of AP's not receiving deauth before
+		// AP may: 1)not response auth or 2)deauth us after link is complete
+		// issue deauth before issuing auth to deal with the situation
+
+		//	Commented by Albert 2012/07/21
+		//	For the Win8 P2P connection, it will be hard to have a successful connection if this Wi-Fi doesn't connect to it.
+		{
+			#ifdef CONFIG_P2P
+			_queue *queue = &(padapter->mlmepriv.scanned_queue);
+			_list	*head = get_list_head(queue);
+			_list *pos = get_next(head);
+			struct wlan_network *scanned = NULL;
+			u8 ie_offset = 0;
+			_irqL irqL;
+			bool has_p2p_ie = _FALSE;
+
+			_enter_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
+
+			for (pos = get_next(head);!rtw_end_of_queue_search(head, pos); pos = get_next(pos)) {
+				
+				scanned = LIST_CONTAINOR(pos, struct wlan_network, list);
+
+				if (_rtw_memcmp(&(scanned->network.Ssid), &(pnetwork->Ssid), sizeof(NDIS_802_11_SSID)) == _TRUE
+					&& _rtw_memcmp(scanned->network.MacAddress, pnetwork->MacAddress, sizeof(NDIS_802_11_MAC_ADDRESS)) == _TRUE
+				) {
+					ie_offset = (scanned->network.Reserved[0] == 2? 0:12);
+					if (rtw_get_p2p_ie(scanned->network.IEs+ie_offset, scanned->network.IELength-ie_offset, NULL, NULL))
+						has_p2p_ie = _TRUE;
+					break;
+				}
+			}
+	
+			_exit_critical_bh(&(padapter->mlmepriv.scanned_queue.lock), &irqL);
+
+			if (scanned == NULL || rtw_end_of_queue_search(head, pos) || has_p2p_ie == _FALSE)
+			#endif /* CONFIG_P2P */
+				//To avoid connecting to AP fail during resume process, change retry count from 5 to 1
+				issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
+		}
+		#endif /* CONFIG_DEAUTH_BEFORE_CONNECT */
+
+		//here wait for receiving the beacon to start auth
+		//and enable a timer
+		beacon_timeout = decide_wait_for_beacon_timeout(pmlmeinfo->bcn_interval);
+		set_link_timer(pmlmeext, beacon_timeout);	
+		_set_timer( &padapter->mlmepriv.assoc_timer, 
+			(REAUTH_TO * REAUTH_LIMIT) + (REASSOC_TO*REASSOC_LIMIT) +beacon_timeout);
+		
+		pmlmeinfo->state = WIFI_FW_AUTH_NULL | WIFI_FW_STATION_STATE;
+	}
+	else if (caps&cap_IBSS) //adhoc client
+	{
+		Set_MSR(padapter, WIFI_FW_ADHOC_STATE);
+
+		val8 = 0xcf;
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+
+		beacon_timing_control(padapter);
+
+		pmlmeinfo->state = WIFI_FW_ADHOC_STATE;
+
+		report_join_res(padapter, 1);
+	}
+	else
+	{
+		//DBG_871X("marc: invalid cap:%x\n", caps);
+		return;
+	}
+
+}
+
+void start_clnt_auth(_adapter* padapter)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	_cancel_timer_ex(&pmlmeext->link_timer);
+
+	pmlmeinfo->state &= (~WIFI_FW_AUTH_NULL);
+	pmlmeinfo->state |= WIFI_FW_AUTH_STATE;
+
+	pmlmeinfo->auth_seq = 1;
+	pmlmeinfo->reauth_count = 0;
+	pmlmeinfo->reassoc_count = 0;
+	pmlmeinfo->link_count = 0;
+	pmlmeext->retry = 0;
+
+
+	DBG_871X_LEVEL(_drv_always_, "start auth\n");
+	issue_auth(padapter, NULL, 0);
+
+	set_link_timer(pmlmeext, REAUTH_TO);
+
+}
+
+
+void start_clnt_assoc(_adapter* padapter)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	_cancel_timer_ex(&pmlmeext->link_timer);
+
+	pmlmeinfo->state &= (~(WIFI_FW_AUTH_NULL | WIFI_FW_AUTH_STATE));
+	pmlmeinfo->state |= (WIFI_FW_AUTH_SUCCESS | WIFI_FW_ASSOC_STATE);
+
+	issue_assocreq(padapter);
+
+	set_link_timer(pmlmeext, REASSOC_TO);
+}
+
+unsigned int receive_disconnect(_adapter *padapter, unsigned char *MacAddr, unsigned short reason)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (!(_rtw_memcmp(MacAddr, get_my_bssid(&pmlmeinfo->network), ETH_ALEN)))
+		return _SUCCESS;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	{
+		if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+		{
+			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+			report_del_sta_event(padapter, MacAddr, reason, _TRUE);
+
+		}
+		else if (pmlmeinfo->state & WIFI_FW_LINKING_STATE)
+		{
+			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+			report_join_res(padapter, -2);
+		} else
+			DBG_871X(FUNC_ADPT_FMT" - End to Disconnect\n", FUNC_ADPT_ARG(padapter));
+	}
+
+	return _SUCCESS;
+}
+
+#ifdef CONFIG_80211D
+static void process_80211d(PADAPTER padapter, WLAN_BSSID_EX *bssid)
+{
+	struct registry_priv *pregistrypriv;
+	struct mlme_ext_priv *pmlmeext;
+	RT_CHANNEL_INFO *chplan_new;
+	u8 channel;
+	u8 i;
+
+
+	pregistrypriv = &padapter->registrypriv;
+	pmlmeext = &padapter->mlmeextpriv;
+
+	// Adjust channel plan by AP Country IE
+	if (pregistrypriv->enable80211d &&
+		(!pmlmeext->update_channel_plan_by_ap_done))
+	{
+		u8 *ie, *p;
+		u32 len;
+		RT_CHANNEL_PLAN chplan_ap;
+		RT_CHANNEL_INFO chplan_sta[MAX_CHANNEL_NUM];
+		u8 country[4];
+		u8 fcn; // first channel number
+		u8 noc; // number of channel
+		u8 j, k;
+
+		ie = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _COUNTRY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+		if (!ie) return;
+		if (len < 6) return;
+
+		ie += 2;
+		p = ie;
+		ie += len;
+
+		_rtw_memset(country, 0, 4);
+		_rtw_memcpy(country, p, 3);
+		p += 3;
+		RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+				("%s: 802.11d country=%s\n", __FUNCTION__, country));
+
+		i = 0;
+		while ((ie - p) >= 3)
+		{
+			fcn = *(p++);
+			noc = *(p++);
+			p++;
+
+			for (j = 0; j < noc; j++)
+			{
+				if (fcn <= 14) channel = fcn + j; // 2.4 GHz
+				else channel = fcn + j*4; // 5 GHz
+
+				chplan_ap.Channel[i++] = channel;
+			}
+		}
+		chplan_ap.Len = i;
+
+#ifdef CONFIG_DEBUG_RTL871X
+		i = 0;
+		DBG_871X("%s: AP[%s] channel plan {", __FUNCTION__, bssid->Ssid.Ssid);
+		while ((i < chplan_ap.Len) && (chplan_ap.Channel[i] != 0))
+		{
+			DBG_8192C("%02d,", chplan_ap.Channel[i]);
+			i++;
+		}
+		DBG_871X("}\n");
+#endif
+
+		_rtw_memcpy(chplan_sta, pmlmeext->channel_set, sizeof(chplan_sta));
+#ifdef CONFIG_DEBUG_RTL871X
+		i = 0;
+		DBG_871X("%s: STA channel plan {", __FUNCTION__);
+		while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
+		{
+			DBG_871X("%02d(%c),", chplan_sta[i].ChannelNum, chplan_sta[i].ScanType==SCAN_PASSIVE?'p':'a');
+			i++;
+		}
+		DBG_871X("}\n");
+#endif
+
+		_rtw_memset(pmlmeext->channel_set, 0, sizeof(pmlmeext->channel_set));
+		chplan_new = pmlmeext->channel_set;
+
+		i = j = k = 0;
+		if (pregistrypriv->wireless_mode & WIRELESS_11G)
+		{
+			do {
+				if ((i == MAX_CHANNEL_NUM) ||
+					(chplan_sta[i].ChannelNum == 0) ||
+					(chplan_sta[i].ChannelNum > 14))
+					break;
+
+				if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] > 14))
+					break;
+
+				if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
+				{
+					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+					chplan_new[k].ScanType = SCAN_ACTIVE;
+					i++;
+					j++;
+					k++;
+				}
+				else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
+				{
+					chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+//					chplan_new[k].ScanType = chplan_sta[i].ScanType;
+					chplan_new[k].ScanType = SCAN_PASSIVE;
+					i++;
+					k++;
+				}
+				else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
+				{
+					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+					chplan_new[k].ScanType = SCAN_ACTIVE;
+					j++;
+					k++;
+				}
+			} while (1);
+
+			// change AP not support channel to Passive scan
+			while ((i < MAX_CHANNEL_NUM) &&
+				(chplan_sta[i].ChannelNum != 0) &&
+				(chplan_sta[i].ChannelNum <= 14))
+			{
+				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+//				chplan_new[k].ScanType = chplan_sta[i].ScanType;
+				chplan_new[k].ScanType = SCAN_PASSIVE;
+				i++;
+				k++;
+			}
+
+			// add channel AP supported
+			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
+			{
+				chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+				chplan_new[k].ScanType = SCAN_ACTIVE;
+				j++;
+				k++;
+			}
+		}
+		else
+		{
+			// keep original STA 2.4G channel plan
+			while ((i < MAX_CHANNEL_NUM) &&
+				(chplan_sta[i].ChannelNum != 0) &&
+				(chplan_sta[i].ChannelNum <= 14))
+			{
+				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+				chplan_new[k].ScanType = chplan_sta[i].ScanType;
+				i++;
+				k++;
+			}
+
+			// skip AP 2.4G channel plan
+			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] <= 14))
+			{
+				j++;
+			}
+		}
+
+		if (pregistrypriv->wireless_mode & WIRELESS_11A)
+		{
+			do {
+				if ((i >= MAX_CHANNEL_NUM) ||
+					(chplan_sta[i].ChannelNum == 0))
+					break;
+
+				if ((j == chplan_ap.Len) || (chplan_ap.Channel[j] == 0))
+					break;
+
+				if (chplan_sta[i].ChannelNum == chplan_ap.Channel[j])
+				{
+					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+					chplan_new[k].ScanType = SCAN_ACTIVE;
+					i++;
+					j++;
+					k++;
+				}
+				else if (chplan_sta[i].ChannelNum < chplan_ap.Channel[j])
+				{
+					chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+//					chplan_new[k].ScanType = chplan_sta[i].ScanType;
+					chplan_new[k].ScanType = SCAN_PASSIVE;
+					i++;
+					k++;
+				}
+				else if (chplan_sta[i].ChannelNum > chplan_ap.Channel[j])
+				{
+					chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+					chplan_new[k].ScanType = SCAN_ACTIVE;
+					j++;
+					k++;
+				}
+			} while (1);
+
+			// change AP not support channel to Passive scan
+			while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
+			{
+				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+//				chplan_new[k].ScanType = chplan_sta[i].ScanType;
+				chplan_new[k].ScanType = SCAN_PASSIVE;
+				i++;
+				k++;
+			}
+
+			// add channel AP supported
+			while ((j < chplan_ap.Len) && (chplan_ap.Channel[j] != 0))
+			{
+				chplan_new[k].ChannelNum = chplan_ap.Channel[j];
+				chplan_new[k].ScanType = SCAN_ACTIVE;
+				j++;
+				k++;
+			}
+		}
+		else
+		{
+			// keep original STA 5G channel plan
+			while ((i < MAX_CHANNEL_NUM) && (chplan_sta[i].ChannelNum != 0))
+			{
+				chplan_new[k].ChannelNum = chplan_sta[i].ChannelNum;
+				chplan_new[k].ScanType = chplan_sta[i].ScanType;
+				i++;
+				k++;
+			}
+		}
+
+		pmlmeext->update_channel_plan_by_ap_done = 1;
+
+#ifdef CONFIG_DEBUG_RTL871X
+		k = 0;
+		DBG_871X("%s: new STA channel plan {", __FUNCTION__);
+		while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0))
+		{
+			DBG_871X("%02d(%c),", chplan_new[k].ChannelNum, chplan_new[k].ScanType==SCAN_PASSIVE?'p':'c');
+			k++;
+		}
+		DBG_871X("}\n");
+#endif
+
+#if 0
+		// recover the right channel index
+		channel = chplan_sta[pmlmeext->sitesurvey_res.channel_idx].ChannelNum;
+		k = 0;
+		while ((k < MAX_CHANNEL_NUM) && (chplan_new[k].ChannelNum != 0))
+		{
+			if (chplan_new[k].ChannelNum == channel) {
+				RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+						 ("%s: change mlme_ext sitesurvey channel index from %d to %d\n",
+						  __FUNCTION__, pmlmeext->sitesurvey_res.channel_idx, k));
+				pmlmeext->sitesurvey_res.channel_idx = k;
+				break;
+			}
+			k++;
+		}
+#endif
+	}
+
+	// If channel is used by AP, set channel scan type to active
+	channel = bssid->Configuration.DSConfig;
+	chplan_new = pmlmeext->channel_set;
+	i = 0;
+	while ((i < MAX_CHANNEL_NUM) && (chplan_new[i].ChannelNum != 0))
+	{
+		if (chplan_new[i].ChannelNum == channel)
+		{
+			if (chplan_new[i].ScanType == SCAN_PASSIVE)
+			{
+				//5G Bnad 2, 3 (DFS) doesn't change to active scan
+				if(channel >= 52 && channel <= 144)
+					break;
+				
+				chplan_new[i].ScanType = SCAN_ACTIVE;
+				RT_TRACE(_module_rtl871x_mlme_c_, _drv_notice_,
+						 ("%s: change channel %d scan type from passive to active\n",
+						  __FUNCTION__, channel));
+			}
+			break;
+		}
+		i++;
+	}
+}
+#endif
+
+/****************************************************************************
+
+Following are the functions to report events
+
+*****************************************************************************/
+
+void report_survey_event(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct survey_event	*psurvey_evt;
+	struct C2HEvent_Header *pc2h_evt_hdr;
+	struct mlme_ext_priv *pmlmeext;
+	struct cmd_priv *pcmdpriv;
+	//u8 *pframe = precv_frame->u.hdr.rx_data;
+	//uint len = precv_frame->u.hdr.len;
+
+	if(!padapter)
+		return;
+
+	pmlmeext = &padapter->mlmeextpriv;
+	pcmdpriv = &padapter->cmdpriv;
+	
+
+	if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		return;
+	}
+
+	cmdsz = (sizeof(struct survey_event) + sizeof(struct C2HEvent_Header));
+	if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+	{
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		return;
+	}
+
+	_rtw_init_listhead(&pcmd_obj->list);
+
+	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+	pcmd_obj->cmdsz = cmdsz;
+	pcmd_obj->parmbuf = pevtcmd;
+
+	pcmd_obj->rsp = NULL;
+	pcmd_obj->rspsz  = 0;
+
+	pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct survey_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_Survey);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	psurvey_evt = (struct survey_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
+
+	if (collect_bss_info(padapter, precv_frame, (WLAN_BSSID_EX *)&psurvey_evt->bss) == _FAIL)
+	{
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		rtw_mfree((u8 *)pevtcmd, cmdsz);
+		return;
+	}
+
+#ifdef CONFIG_80211D
+	process_80211d(padapter, &psurvey_evt->bss);
+#endif
+
+	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+	pmlmeext->sitesurvey_res.bss_cnt++;
+
+	return;
+
+}
+
+void report_surveydone_event(_adapter *padapter)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct surveydone_event *psurveydone_evt;
+	struct C2HEvent_Header	*pc2h_evt_hdr;
+	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+	if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		return;
+	}
+
+	cmdsz = (sizeof(struct surveydone_event) + sizeof(struct C2HEvent_Header));
+	if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+	{
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		return;
+	}
+
+	_rtw_init_listhead(&pcmd_obj->list);
+
+	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+	pcmd_obj->cmdsz = cmdsz;
+	pcmd_obj->parmbuf = pevtcmd;
+
+	pcmd_obj->rsp = NULL;
+	pcmd_obj->rspsz  = 0;
+
+	pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct surveydone_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_SurveyDone);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	psurveydone_evt = (struct surveydone_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
+	psurveydone_evt->bss_cnt = pmlmeext->sitesurvey_res.bss_cnt;
+
+	DBG_871X("survey done event(%x) band:%d for "ADPT_FMT"\n", psurveydone_evt->bss_cnt, padapter->setband, ADPT_ARG(padapter));
+
+	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+	return;
+
+}
+
+void report_join_res(_adapter *padapter, int res)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct joinbss_event		*pjoinbss_evt;
+	struct C2HEvent_Header	*pc2h_evt_hdr;
+	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+	if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		return;
+	}
+
+	cmdsz = (sizeof(struct joinbss_event) + sizeof(struct C2HEvent_Header));
+	if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+	{
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		return;
+	}
+
+	_rtw_init_listhead(&pcmd_obj->list);
+
+	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+	pcmd_obj->cmdsz = cmdsz;
+	pcmd_obj->parmbuf = pevtcmd;
+
+	pcmd_obj->rsp = NULL;
+	pcmd_obj->rspsz  = 0;
+
+	pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct joinbss_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_JoinBss);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	pjoinbss_evt = (struct joinbss_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
+	_rtw_memcpy((unsigned char *)(&(pjoinbss_evt->network.network)), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
+	pjoinbss_evt->network.join_res 	= pjoinbss_evt->network.aid = res;
+
+	DBG_871X("report_join_res(%d)\n", res);
+	
+	
+	rtw_joinbss_event_prehandle(padapter, (u8 *)&pjoinbss_evt->network);
+	
+	
+	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+	return;
+
+}
+
+void report_wmm_edca_update(_adapter *padapter)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct wmm_event		*pwmm_event;
+	struct C2HEvent_Header	*pc2h_evt_hdr;
+	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+	if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		return;
+	}
+
+	cmdsz = (sizeof(struct wmm_event) + sizeof(struct C2HEvent_Header));
+	if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+	{
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		return;
+	}
+
+	_rtw_init_listhead(&pcmd_obj->list);
+
+	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+	pcmd_obj->cmdsz = cmdsz;
+	pcmd_obj->parmbuf = pevtcmd;
+
+	pcmd_obj->rsp = NULL;
+	pcmd_obj->rspsz  = 0;
+
+	pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct wmm_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_WMM);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	pwmm_event = (struct wmm_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
+	pwmm_event->wmm =0;
+	
+	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+	return;
+
+}
+
+void report_del_sta_event(_adapter *padapter, unsigned char *MacAddr, unsigned short reason, bool enqueue)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct sta_info *psta;
+	int	mac_id = -1;
+	struct stadel_event			*pdel_sta_evt;
+	struct C2HEvent_Header	*pc2h_evt_hdr;
+	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+	u8 res = _SUCCESS;
+
+	/* prepare cmd parameter */
+	cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	if (pevtcmd == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct stadel_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_DelSTA);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	pdel_sta_evt = (struct stadel_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
+	_rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
+	_rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd),(unsigned char *)(&reason),2);
+	psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
+	if(psta)
+		mac_id = (int)psta->mac_id;	
+	else
+		mac_id = (-1);
+	pdel_sta_evt->mac_id = mac_id;
+
+	if (!enqueue) {
+		/* do directly */
+		rtw_stadel_event_callback(padapter, (u8 *)pdel_sta_evt);
+		rtw_mfree(pevtcmd, cmdsz);
+	} else {
+		pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+		if (pcmd_obj == NULL) {
+			rtw_mfree(pevtcmd, cmdsz);
+			res = _FAIL;
+			goto exit;
+		}
+
+		_rtw_init_listhead(&pcmd_obj->list);
+		pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+		pcmd_obj->cmdsz = cmdsz;
+		pcmd_obj->parmbuf = pevtcmd;
+
+		pcmd_obj->rsp = NULL;
+		pcmd_obj->rspsz  = 0;
+
+		res = rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+	}
+
+exit:
+
+	DBG_871X(FUNC_ADPT_FMT" "MAC_FMT" mac_id=%d, enqueue:%d, res:%u\n"
+		, FUNC_ADPT_ARG(padapter), MAC_ARG(MacAddr), mac_id, enqueue, res);
+
+	return;
+}
+
+void report_add_sta_event(_adapter *padapter, unsigned char* MacAddr, int cam_idx)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct stassoc_event		*padd_sta_evt;
+	struct C2HEvent_Header	*pc2h_evt_hdr;
+	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+
+	if ((pcmd_obj = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		return;
+	}
+
+	cmdsz = (sizeof(struct stassoc_event) + sizeof(struct C2HEvent_Header));
+	if ((pevtcmd = (u8*)rtw_zmalloc(cmdsz)) == NULL)
+	{
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		return;
+	}
+
+	_rtw_init_listhead(&pcmd_obj->list);
+
+	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+	pcmd_obj->cmdsz = cmdsz;
+	pcmd_obj->parmbuf = pevtcmd;
+
+	pcmd_obj->rsp = NULL;
+	pcmd_obj->rspsz  = 0;
+
+	pc2h_evt_hdr = (struct C2HEvent_Header*)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct stassoc_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_AddSTA);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	padd_sta_evt = (struct stassoc_event*)(pevtcmd + sizeof(struct C2HEvent_Header));
+	_rtw_memcpy((unsigned char *)(&(padd_sta_evt->macaddr)), MacAddr, ETH_ALEN);
+	padd_sta_evt->cam_id = cam_idx;
+
+	DBG_871X("report_add_sta_event: add STA\n");
+
+	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+	return;
+}
+
+
+bool rtw_port_switch_chk(_adapter *adapter)
+{
+	bool switch_needed = _FALSE;
+#ifdef CONFIG_CONCURRENT_MODE
+#ifdef CONFIG_RUNTIME_PORT_SWITCH
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct pwrctrl_priv *pwrctl = dvobj_to_pwrctl(dvobj);
+	_adapter *if_port0 = NULL;
+	_adapter *if_port1 = NULL;
+	struct mlme_ext_info *if_port0_mlmeinfo = NULL;
+	struct mlme_ext_info *if_port1_mlmeinfo = NULL;
+	int i;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT0) {
+			if_port0 = dvobj->padapters[i];
+			if_port0_mlmeinfo = &(if_port0->mlmeextpriv.mlmext_info);
+		}
+		else if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT1) {
+			if_port1 = dvobj->padapters[i];
+			if_port1_mlmeinfo = &(if_port1->mlmeextpriv.mlmext_info);
+		}
+	}
+
+	if (if_port0 == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (if_port1 == NULL) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+#ifdef DBG_RUNTIME_PORT_SWITCH
+	DBG_871X(FUNC_ADPT_FMT" wowlan_mode:%u\n"
+		ADPT_FMT", port0, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n"
+		ADPT_FMT", port1, mlmeinfo->state:0x%08x, p2p_state:%d, %d\n",
+		FUNC_ADPT_ARG(adapter), pwrctl->wowlan_mode,
+		ADPT_ARG(if_port0), if_port0_mlmeinfo->state, rtw_p2p_state(&if_port0->wdinfo), rtw_p2p_chk_state(&if_port0->wdinfo, P2P_STATE_NONE),
+		ADPT_ARG(if_port1), if_port1_mlmeinfo->state, rtw_p2p_state(&if_port1->wdinfo), rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE));
+#endif /* DBG_RUNTIME_PORT_SWITCH */
+
+#ifdef CONFIG_WOWLAN
+	/* WOWLAN interface(primary, for now) should be port0 */
+	if (pwrctl->wowlan_mode == _TRUE) {
+		if(!is_primary_adapter(if_port0)) {
+			DBG_871X("%s "ADPT_FMT" enable WOWLAN\n", __func__, ADPT_ARG(if_port1));
+			switch_needed = _TRUE;
+		}
+		goto exit;
+	}
+#endif /* CONFIG_WOWLAN */
+
+	/* AP should use port0 for ctl frame's ack */
+	if ((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_AP_STATE) {
+		DBG_871X("%s "ADPT_FMT" is AP/GO\n", __func__, ADPT_ARG(if_port1));
+		switch_needed = _TRUE;
+		goto exit;
+	}
+
+	/* GC should use port0 for p2p ps */	
+	if (((if_port1_mlmeinfo->state & 0x03) == WIFI_FW_STATION_STATE)
+		&& (if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+		&& !rtw_p2p_chk_state(&if_port1->wdinfo, P2P_STATE_NONE)
+		&& !check_fwstate(&if_port1->mlmepriv, WIFI_UNDER_WPS)
+	) {
+		DBG_871X("%s "ADPT_FMT" is GC\n", __func__, ADPT_ARG(if_port1));
+		switch_needed = _TRUE;
+		goto exit;
+	}
+
+	/* port1 linked, but port0 not linked */
+	if ((if_port1_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+		&& !(if_port0_mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+		&& ((if_port0_mlmeinfo->state & 0x03) != WIFI_FW_AP_STATE)
+	) {
+		DBG_871X("%s "ADPT_FMT" is SINGLE_LINK\n", __func__, ADPT_ARG(if_port1));
+		switch_needed = _TRUE;
+		goto exit;
+	}
+
+exit:
+#ifdef DBG_RUNTIME_PORT_SWITCH
+	DBG_871X(FUNC_ADPT_FMT" ret:%d\n", FUNC_ADPT_ARG(adapter), switch_needed);
+#endif /* DBG_RUNTIME_PORT_SWITCH */
+#endif /* CONFIG_RUNTIME_PORT_SWITCH */
+#endif /* CONFIG_CONCURRENT_MODE */
+	return switch_needed;
+}
+
+/****************************************************************************
+
+Following are the event callback functions
+
+*****************************************************************************/
+
+//for sta/adhoc mode
+void update_sta_info(_adapter *padapter, struct sta_info *psta)
+{
+	_irqL	irqL;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	//ERP
+	VCS_update(padapter, psta);
+
+#ifdef CONFIG_80211N_HT
+	//HT
+	if(pmlmepriv->htpriv.ht_option)
+	{
+		psta->htpriv.ht_option = _TRUE;
+
+		psta->htpriv.ampdu_enable = pmlmepriv->htpriv.ampdu_enable;
+
+		psta->htpriv.rx_ampdu_min_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para&IEEE80211_HT_CAP_AMPDU_DENSITY)>>2;
+
+		if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_20))
+			psta->htpriv.sgi_20m = _TRUE;
+
+		if (support_short_GI(padapter, &(pmlmeinfo->HT_caps), CHANNEL_WIDTH_40))
+			psta->htpriv.sgi_40m = _TRUE;
+
+		psta->qos_option = _TRUE;
+
+		psta->htpriv.ldpc_cap = pmlmepriv->htpriv.ldpc_cap;
+		psta->htpriv.stbc_cap = pmlmepriv->htpriv.stbc_cap;
+		psta->htpriv.beamform_cap = pmlmepriv->htpriv.beamform_cap;
+
+		_rtw_memcpy(&psta->htpriv.ht_cap, &pmlmeinfo->HT_caps, sizeof(struct rtw_ieee80211_ht_cap));
+	}
+	else
+#endif //CONFIG_80211N_HT
+	{
+#ifdef CONFIG_80211N_HT
+		psta->htpriv.ht_option = _FALSE;
+
+		psta->htpriv.ampdu_enable = _FALSE;
+		
+		psta->htpriv.sgi_20m = _FALSE;
+		psta->htpriv.sgi_40m = _FALSE;
+#endif //CONFIG_80211N_HT
+		psta->qos_option = _FALSE;
+
+	}
+
+#ifdef CONFIG_80211N_HT
+	psta->htpriv.ch_offset = pmlmeext->cur_ch_offset;
+	
+	psta->htpriv.agg_enable_bitmap = 0x0;//reset
+	psta->htpriv.candidate_tid_bitmap = 0x0;//reset
+#endif //CONFIG_80211N_HT
+
+	psta->bw_mode = pmlmeext->cur_bwmode;
+
+	//QoS
+	if(pmlmepriv->qospriv.qos_option)
+		psta->qos_option = _TRUE;
+
+#ifdef CONFIG_80211AC_VHT
+	_rtw_memcpy(&psta->vhtpriv, &pmlmepriv->vhtpriv, sizeof(struct vht_priv));
+#endif //CONFIG_80211AC_VHT
+
+	update_ldpc_stbc_cap(psta);
+
+	_enter_critical_bh(&psta->lock, &irqL);
+	psta->state = _FW_LINKED;
+	_exit_critical_bh(&psta->lock, &irqL);
+
+}
+
+static void rtw_mlmeext_disconnect(_adapter *padapter)
+{
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+	u8 state_backup = (pmlmeinfo->state&0x03);
+	u8 ASIX_ID[]= {0x00, 0x0E, 0xC6};
+
+	//set_opmode_cmd(padapter, infra_client_with_mlme);
+
+#if 1
+	/*
+	 * For safety, prevent from keeping macid sleep.
+	 * If we can sure all power mode enter/leave are paired,
+	 * this check can be removed.
+	 * Lucas@20131113
+	 */
+	/* wakeup macid after disconnect. */
+	{
+		struct sta_info *psta;
+		psta = rtw_get_stainfo(&padapter->stapriv, get_my_bssid(pnetwork));
+		if (psta)
+			rtw_hal_macid_wakeup(padapter, psta->mac_id);
+	}
+#endif	
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
+	rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+	//set MSR to no link state -> infra. mode
+	Set_MSR(padapter, _HW_STATE_STATION_);
+
+	//check if sta is ASIX peer and fix IOT issue if it is.
+	if (_rtw_memcmp(get_my_bssid(&pmlmeinfo->network) ,ASIX_ID ,3)) {
+		u8 iot_flag = _FALSE;
+		rtw_hal_set_hwreg(padapter, HW_VAR_ASIX_IOT, (u8 *)(&iot_flag));
+	}
+	pmlmeinfo->state = WIFI_FW_NULL_STATE;
+
+	if(state_backup == WIFI_FW_STATION_STATE)
+	{
+		if (rtw_port_switch_chk(padapter) == _TRUE) {
+			rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
+			#ifdef CONFIG_LPS
+			{
+				_adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
+				if (port0_iface)
+					rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
+			}
+			#endif
+		}
+	}
+
+	/* switch to the 20M Hz mode after disconnect */
+	pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
+	pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+#ifdef CONFIG_FCS_MODE
+	if (EN_FCS(padapter))
+		rtw_hal_set_hwreg(padapter, HW_VAR_STOP_FCS_MODE, NULL);
+#endif
+
+#ifdef CONFIG_DFS_MASTER
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
+		rtw_dfs_master_status_apply(padapter, MLME_AP_STOPPED);
+	else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+		rtw_dfs_master_status_apply(padapter, MLME_STA_DISCONNECTED);
+#endif
+
+	{
+		u8 ch, bw, offset;
+
+		if (rtw_get_ch_setting_union_no_self(padapter, &ch, &bw, &offset) != 0)
+			set_channel_bwmode(padapter, ch, offset, bw);
+	}
+
+	flush_all_cam_entry(padapter);
+
+	_cancel_timer_ex(&pmlmeext->link_timer);
+
+	//pmlmepriv->LinkDetectInfo.TrafficBusyState = _FALSE;
+	pmlmepriv->LinkDetectInfo.TrafficTransitionCount = 0;
+	pmlmepriv->LinkDetectInfo.LowPowerTransitionCount = 0;
+
+#ifdef CONFIG_TDLS
+	padapter->tdlsinfo.ap_prohibited = _FALSE;
+
+	/* For TDLS channel switch, currently we only allow it to work in wifi logo test mode */
+	if (padapter->registrypriv.wifi_spec == 1)
+	{
+		padapter->tdlsinfo.ch_switch_prohibited = _FALSE;
+	}
+#endif /* CONFIG_TDLS */
+
+}
+
+void mlmeext_joinbss_event_callback(_adapter *padapter, int join_res)
+{
+	struct sta_info		*psta, *psta_bmc;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	u8	join_type;
+#ifdef CONFIG_ARP_KEEP_ALIVE
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+#endif
+
+	if(join_res < 0)
+	{
+		join_type = 1;
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+		rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, null_addr);
+
+		goto exit_mlmeext_joinbss_event_callback;
+	}
+#ifdef CONFIG_ARP_KEEP_ALIVE
+	pmlmepriv->bGetGateway = 1;
+#endif
+
+	if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
+	{
+		//update bc/mc sta_info
+		update_bmc_sta(padapter);
+	}
+
+
+	//turn on dynamic functions
+	/* Switch_DM_Func(padapter, DYNAMIC_ALL_FUNC_ENABLE, _TRUE); */
+
+	// update IOT-releated issue
+	update_IOT_info(padapter);
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, cur_network->SupportedRates);
+
+	//BCN interval
+	rtw_hal_set_hwreg(padapter, HW_VAR_BEACON_INTERVAL, (u8 *)(&pmlmeinfo->bcn_interval));
+
+	//udpate capability
+	update_capinfo(padapter, pmlmeinfo->capability);
+
+	//WMM, Update EDCA param
+	WMMOnAssocRsp(padapter);
+
+	//HT
+	HTOnAssocRsp(padapter);
+
+#ifdef CONFIG_80211AC_VHT
+	//VHT
+	VHTOnAssocRsp(padapter);
+#endif
+
+	psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+	if (psta) //only for infra. mode
+	{
+		pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+		//DBG_871X("set_sta_rate\n");
+
+		psta->wireless_mode = pmlmeext->cur_wireless_mode;
+	
+		//set per sta rate after updating HT cap.
+		set_sta_rate(padapter, psta);
+		
+		rtw_sta_media_status_rpt(padapter, psta, 1);
+
+		/* wakeup macid after join bss successfully to ensure 
+			the subsequent data frames can be sent out normally */
+		rtw_hal_macid_wakeup(padapter, psta->mac_id);
+	}
+
+	if (rtw_port_switch_chk(padapter) == _TRUE)
+		rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
+
+	join_type = 2;
+	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+
+	if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+	{
+		// correcting TSF
+		correct_TSF(padapter, pmlmeext);
+	
+		//set_link_timer(pmlmeext, DISCONNECT_TO);
+	}
+
+#ifdef CONFIG_LPS
+	if(get_iface_type(padapter) == IFACE_PORT0)
+		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
+#endif
+
+#ifdef CONFIG_BEAMFORMING
+	if (psta)
+		beamforming_wk_cmd(padapter, BEAMFORMING_CTRL_ENTER, (u8 *)psta, sizeof(struct sta_info), 0);
+#endif/*CONFIG_BEAMFORMING*/
+
+exit_mlmeext_joinbss_event_callback:
+
+	rtw_join_done_chk_ch(padapter, join_res);
+
+	DBG_871X("=>%s - End to Connection without 4-way\n", __FUNCTION__);
+}
+
+//currently only adhoc mode will go here
+void mlmeext_sta_add_event_callback(_adapter *padapter, struct sta_info *psta)
+{
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	join_type;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE)
+	{
+		if(pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)//adhoc master or sta_count>1
+		{
+			//nothing to do
+		}
+		else//adhoc client
+		{
+			//update TSF Value
+			//update_TSF(pmlmeext, pframe, len);			
+
+			// correcting TSF
+			correct_TSF(padapter, pmlmeext);
+
+			//start beacon
+			if(send_beacon(padapter)==_FAIL)
+			{
+				pmlmeinfo->FW_sta_info[psta->mac_id].status = 0;
+
+				pmlmeinfo->state ^= WIFI_FW_ADHOC_STATE;
+
+				return;
+			}
+
+			pmlmeinfo->state |= WIFI_FW_ASSOC_SUCCESS;
+				
+		}
+
+		join_type = 2;
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+	}
+
+	pmlmeinfo->FW_sta_info[psta->mac_id].psta = psta;
+
+	psta->bssratelen = rtw_get_rateset_len(pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates);
+	_rtw_memcpy(psta->bssrateset, pmlmeinfo->FW_sta_info[psta->mac_id].SupportedRates, psta->bssratelen);
+
+	//update adhoc sta_info
+	update_sta_info(padapter, psta);
+
+	rtw_hal_update_sta_rate_mask(padapter, psta);
+
+	// ToDo: HT for Ad-hoc 
+	psta->wireless_mode = rtw_check_network_type(psta->bssrateset, psta->bssratelen, pmlmeext->cur_channel);
+	psta->raid = rtw_hal_networktype_to_raid(padapter, psta);
+
+	//rate radaptive
+	Update_RA_Entry(padapter, psta);
+}
+
+void mlmeext_sta_del_event_callback(_adapter *padapter)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (is_client_associated_to_ap(padapter) || is_IBSS_empty(padapter))
+	{
+		rtw_mlmeext_disconnect(padapter);
+	}
+
+}
+
+/****************************************************************************
+
+Following are the functions for the timer handlers
+
+*****************************************************************************/
+void _linked_info_dump(_adapter *padapter)
+{
+	int i;
+	struct mlme_ext_priv    *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
+	int UndecoratedSmoothedPWDB = 0;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	
+	if(padapter->bLinkInfoDump){
+
+		DBG_871X("\n============["ADPT_FMT"] linked status check ===================\n",ADPT_ARG(padapter));	
+
+		if((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE)
+		{
+			rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);	
+		
+			DBG_871X("AP[" MAC_FMT "] - UndecoratedSmoothedPWDB:%d\n",
+				MAC_ARG(padapter->mlmepriv.cur_network.network.MacAddress),UndecoratedSmoothedPWDB);
+		}
+		else if((pmlmeinfo->state&0x03) == _HW_STATE_AP_)
+		{
+			_irqL irqL;
+			_list	*phead, *plist;
+	
+			struct sta_info *psta=NULL;	
+			struct sta_priv *pstapriv = &padapter->stapriv;
+			
+			_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);	
+			phead = &pstapriv->asoc_list;
+			plist = get_next(phead);
+			while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+			{
+				psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+				plist = get_next(plist);			
+				
+				DBG_871X("STA[" MAC_FMT "]:UndecoratedSmoothedPWDB:%d\n", 
+					MAC_ARG(psta->hwaddr),psta->rssi_stat.UndecoratedSmoothedPWDB);
+			}
+			_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);		
+			
+		}
+		for(i=0; i<macid_ctl->num; i++)
+		{
+			if(rtw_macid_is_used(macid_ctl, i) 
+				&& !rtw_macid_is_bmc(macid_ctl, i) /* skip bc/mc sta */
+			) {
+				//============  tx info ============	
+				rtw_hal_get_def_var(padapter, HW_DEF_RA_INFO_DUMP, &i);			
+			}
+		}
+		rtw_hal_set_odm_var(padapter, HAL_ODM_RX_INFO_DUMP, NULL, _FALSE);
+		
+	}
+	      
+
+}
+void rtw_delba_check(_adapter *padapter, struct sta_info *psta, u8 from_timer)
+{
+	int	i = 0;
+	int ret = _SUCCESS;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	/*
+		IOT issue,occur Broadcom ap(Buffalo WZR-D1800H,Netgear R6300).
+		AP is originator.AP does not transmit unicast packets when STA response its BAR.
+		This case probably occur ap issue BAR after AP builds BA. 
+				
+		Follow 802.11 spec, STA shall maintain an inactivity timer for every negotiated Block Ack setup.
+		The inactivity timer is not reset when MPDUs corresponding to other TIDs are received.
+	*/
+	if (pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_BROADCOM) {
+		for (i = 0; i < TID_NUM ; i++) {				
+			if (sta_rx_data_qos_pkts(psta, i) == sta_last_rx_data_qos_pkts(psta, i)) {			
+				if (_TRUE == rtw_inc_and_chk_continual_no_rx_packet(psta, i)) {
+					if (psta->recvreorder_ctrl[i].enable) {						
+						/* send a DELBA frame to the peer STA with the Reason Code field set to TIMEOUT */		
+						if (!from_timer)
+							ret = issue_del_ba_ex(padapter, psta->hwaddr, i, 39, 0, 3, 1);
+						else
+							issue_del_ba(padapter,  psta->hwaddr, i, 39, 0);							
+							psta->recvreorder_ctrl[i].enable = _FALSE;
+						if (ret != _FAIL)
+							psta->recvreorder_ctrl[i].ampdu_size = RX_AMPDU_SIZE_INVALID;
+							rtw_reset_continual_no_rx_packet(psta, i);
+						}				
+					}
+				}
+			else{   
+				/* The inactivity timer is reset when MPDUs to the TID is received. */
+				rtw_reset_continual_no_rx_packet(psta, i);	
+			}
+		}
+	}
+}
+
+u8 chk_ap_is_alive(_adapter *padapter, struct sta_info *psta)
+{
+	u8 ret = _FALSE;
+	int i = 0;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	#ifdef DBG_EXPIRATION_CHK
+	DBG_871X(FUNC_ADPT_FMT" rx:"STA_PKTS_FMT", beacon:%llu, probersp_to_self:%llu"
+				/*", probersp_bm:%llu, probersp_uo:%llu, probereq:%llu, BI:%u"*/
+				", retry:%u\n"
+		, FUNC_ADPT_ARG(padapter)
+		, STA_RX_PKTS_DIFF_ARG(psta)
+		, psta->sta_stats.rx_beacon_pkts - psta->sta_stats.last_rx_beacon_pkts
+		, psta->sta_stats.rx_probersp_pkts - psta->sta_stats.last_rx_probersp_pkts
+		/*, psta->sta_stats.rx_probersp_bm_pkts - psta->sta_stats.last_rx_probersp_bm_pkts
+		, psta->sta_stats.rx_probersp_uo_pkts - psta->sta_stats.last_rx_probersp_uo_pkts
+		, psta->sta_stats.rx_probereq_pkts - psta->sta_stats.last_rx_probereq_pkts
+		, pmlmeinfo->bcn_interval*/
+		, pmlmeext->retry
+	);
+
+	DBG_871X(FUNC_ADPT_FMT" tx_pkts:%llu, link_count:%u\n", FUNC_ADPT_ARG(padapter)
+		, padapter->xmitpriv.tx_pkts
+		, pmlmeinfo->link_count
+	);
+	#endif
+
+	if((sta_rx_data_pkts(psta) == sta_last_rx_data_pkts(psta))
+		&& sta_rx_beacon_pkts(psta) == sta_last_rx_beacon_pkts(psta)
+		&& sta_rx_probersp_pkts(psta) == sta_last_rx_probersp_pkts(psta)
+	)
+	{
+		ret = _FALSE;
+	}
+	else
+	{
+		ret = _TRUE;
+	}
+
+	sta_update_last_rx_pkts(psta);
+
+	/*
+		record last rx data packets for every tid.
+	*/
+	for (i = 0; i < TID_NUM; i++)	
+		psta->sta_stats.last_rx_data_qos_pkts[i] = psta->sta_stats.rx_data_qos_pkts[i];
+
+	return ret;
+}
+
+#ifdef CONFIG_TDLS
+u8 chk_tdls_peer_sta_is_alive(_adapter *padapter, struct sta_info *psta)
+{
+	if ((psta->sta_stats.rx_data_pkts == psta->sta_stats.last_rx_data_pkts)
+		&& (psta->sta_stats.rx_tdls_disc_rsp_pkts == psta->sta_stats.last_rx_tdls_disc_rsp_pkts))
+		return _FALSE;
+
+	return _TRUE;
+}
+
+void linked_status_chk_tdls(_adapter *padapter)
+{
+struct candidate_pool{
+	struct sta_info *psta;
+	u8 addr[ETH_ALEN];
+};
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	_irqL irqL;
+	u8 ack_chk;
+	struct sta_info *psta;
+	int i, num_teardown=0, num_checkalive=0;
+	_list	*plist, *phead;
+	struct tdls_txmgmt txmgmt;
+	struct candidate_pool checkalive[NUM_STA];
+	struct candidate_pool teardown[NUM_STA];
+#define ALIVE_MIN 2
+#define ALIVE_MAX 5
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	_rtw_memset(checkalive, 0x00, sizeof(checkalive));
+	_rtw_memset(teardown, 0x00, sizeof(teardown));
+
+	if((padapter->tdlsinfo.link_established == _TRUE)){
+		_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		for(i=0; i< NUM_STA; i++)
+		{
+			phead = &(pstapriv->sta_hash[i]);
+			plist = get_next(phead);
+			
+			while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+			{
+				psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+				plist = get_next(plist);
+
+				if(psta->tdls_sta_state & TDLS_LINKED_STATE)
+				{
+					psta->alive_count++;
+					if(psta->alive_count >= ALIVE_MIN)
+					{
+						if (chk_tdls_peer_sta_is_alive(padapter, psta) == _FALSE) {
+							if (psta->alive_count < ALIVE_MAX) {
+								_rtw_memcpy(checkalive[num_checkalive].addr, psta->hwaddr, ETH_ALEN);
+								checkalive[num_checkalive].psta = psta;
+								num_checkalive++;
+							}
+							else
+							{
+								_rtw_memcpy(teardown[num_teardown].addr, psta->hwaddr, ETH_ALEN);
+								teardown[num_teardown].psta = psta;
+								num_teardown++;
+							}
+						}
+						else
+						{
+							psta->alive_count = 0;
+						}
+					}
+					psta->sta_stats.last_rx_data_pkts = psta->sta_stats.rx_data_pkts;
+					psta->sta_stats.last_rx_tdls_disc_rsp_pkts = psta->sta_stats.rx_tdls_disc_rsp_pkts;
+				}
+			}
+		}
+		_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+		if (num_checkalive > 0) {
+			for (i = 0; i < num_checkalive; i++) {
+				_rtw_memcpy(txmgmt.peer, checkalive[i].addr, ETH_ALEN);
+				issue_tdls_dis_req(padapter, &txmgmt);
+				issue_tdls_dis_req(padapter, &txmgmt);
+				issue_tdls_dis_req(padapter, &txmgmt);
+			}
+		}
+
+		if(num_teardown > 0)
+		{
+			for(i=0; i< num_teardown; i++)
+			{
+				DBG_871X("[%s %d] Send teardown to "MAC_FMT" \n", __FUNCTION__, __LINE__, MAC_ARG(teardown[i].addr));
+				txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
+				_rtw_memcpy(txmgmt.peer, teardown[i].addr, ETH_ALEN);
+				issue_tdls_teardown(padapter, &txmgmt, _FALSE);
+			}
+		}
+	}
+
+}
+#endif //CONFIG_TDLS
+
+//from_timer == 1 means driver is in LPS
+void linked_status_chk(_adapter *padapter, u8 from_timer)
+{
+	u32	i;
+	struct sta_info		*psta;
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+#ifdef CONFIG_ARP_KEEP_ALIVE
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+#endif
+	
+
+	if (is_client_associated_to_ap(padapter))
+	{
+		//linked infrastructure client mode
+
+		int tx_chk = _SUCCESS, rx_chk = _SUCCESS;
+		int rx_chk_limit;
+		int link_count_limit;
+
+		#if defined(DBG_ROAMING_TEST)
+		rx_chk_limit = 1;
+		#elif defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
+		rx_chk_limit = 4;
+		#else
+		rx_chk_limit = 8;
+		#endif
+#ifdef CONFIG_ARP_KEEP_ALIVE
+		if (!from_timer && pmlmepriv->bGetGateway == 1) {
+			DBG_871X("do rtw_gw_addr_query()");
+			if (rtw_gw_addr_query(padapter) == 0) {
+				pmlmepriv->bGetGateway = 0;
+			} else {
+				_rtw_memset(pmlmepriv->gw_ip, 0, 4);
+				_rtw_memset(pmlmepriv->gw_mac_addr, 0, 6);
+			}
+		}
+#endif
+#ifdef CONFIG_P2P
+		if (!rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE))
+		{
+			if(!from_timer)
+				link_count_limit = 3; // 8 sec
+			else
+				link_count_limit = 15; // 32 sec
+		}
+		else
+#endif // CONFIG_P2P
+		{
+			if(!from_timer)
+				link_count_limit = 7; // 16 sec
+			else
+				link_count_limit = 29; // 60 sec
+		}		
+
+#ifdef CONFIG_TDLS
+#ifdef CONFIG_TDLS_CH_SW
+		if (ATOMIC_READ(&padapter->tdlsinfo.chsw_info.chsw_on) == _TRUE)
+			return;
+#endif /* CONFIG_TDLS_CH_SW */
+
+#ifdef CONFIG_TDLS_AUTOCHECKALIVE
+		linked_status_chk_tdls(padapter);
+#endif /* CONFIG_TDLS_AUTOCHECKALIVE */
+#endif /* CONFIG_TDLS */
+
+		if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
+		{
+			bool is_p2p_enable = _FALSE;
+			#ifdef CONFIG_P2P
+			is_p2p_enable = !rtw_p2p_chk_state(&padapter->wdinfo, P2P_STATE_NONE);
+			#endif
+
+			/*issue delba when ap does not tx data packet that is Broadcom ap */
+			rtw_delba_check(padapter, psta, from_timer);
+
+			if (chk_ap_is_alive(padapter, psta) == _FALSE)
+				rx_chk = _FAIL;
+
+			if (pxmitpriv->last_tx_pkts == pxmitpriv->tx_pkts)
+				tx_chk = _FAIL;
+
+			#if defined(CONFIG_ACTIVE_KEEP_ALIVE_CHECK) && !defined(CONFIG_LPS_LCLK_WD_TIMER)
+			if (pmlmeext->active_keep_alive_check && (rx_chk == _FAIL || tx_chk == _FAIL)) {
+				u8 backup_oper_channel=0;
+
+				/* switch to correct channel of current network  before issue keep-alive frames */
+				if (rtw_get_oper_ch(padapter) != pmlmeext->cur_channel) {
+					backup_oper_channel = rtw_get_oper_ch(padapter);
+					SelectChannel(padapter, pmlmeext->cur_channel);
+				}
+
+				if (rx_chk != _SUCCESS)
+					issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, psta->hwaddr, 0, 0, 3, 1);
+
+				if ((tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) || rx_chk != _SUCCESS) {
+					tx_chk = issue_nulldata(padapter, psta->hwaddr, 0, 3, 1);
+					/* if tx acked and p2p disabled, set rx_chk _SUCCESS to reset retry count */
+					if (tx_chk == _SUCCESS && !is_p2p_enable)
+						rx_chk = _SUCCESS;
+				}
+
+				/* back to the original operation channel */
+				if(backup_oper_channel>0)
+					SelectChannel(padapter, backup_oper_channel);
+
+			}
+			else
+			#endif /* CONFIG_ACTIVE_KEEP_ALIVE_CHECK */
+			{
+				if (rx_chk != _SUCCESS) {
+					if (pmlmeext->retry == 0) {
+						#ifdef DBG_EXPIRATION_CHK
+						DBG_871X("issue_probereq to trigger probersp, retry=%d\n", pmlmeext->retry);
+						#endif
+						issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
+						issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
+						issue_probereq_ex(padapter, &pmlmeinfo->network.Ssid, pmlmeinfo->network.MacAddress, 0, 0, 0, 0);
+					}
+				}
+
+				if (tx_chk != _SUCCESS && pmlmeinfo->link_count++ == link_count_limit) {
+					#ifdef DBG_EXPIRATION_CHK
+					DBG_871X("%s issue_nulldata(%d)\n", __FUNCTION__, from_timer?1:0);
+					#endif
+					tx_chk = issue_nulldata_in_interrupt(padapter, NULL, from_timer?1:0);
+				}
+			}
+
+			if (rx_chk == _FAIL) {
+				pmlmeext->retry++;
+				if (pmlmeext->retry > rx_chk_limit) {
+					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" disconnect or roaming\n",
+						FUNC_ADPT_ARG(padapter));
+					receive_disconnect(padapter, pmlmeinfo->network.MacAddress
+						, WLAN_REASON_EXPIRATION_CHK);
+					return;
+				}
+			} else {
+				pmlmeext->retry = 0;
+			}
+
+			if (tx_chk == _FAIL) {
+				pmlmeinfo->link_count %= (link_count_limit+1);
+			} else {
+				pxmitpriv->last_tx_pkts = pxmitpriv->tx_pkts;
+				pmlmeinfo->link_count = 0;
+			}
+
+		} //end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL)
+
+	}
+	else if (is_client_associated_to_ibss(padapter))
+	{
+		//linked IBSS mode
+		//for each assoc list entry to check the rx pkt counter
+		for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
+		{
+			if (pmlmeinfo->FW_sta_info[i].status == 1)
+			{
+				psta = pmlmeinfo->FW_sta_info[i].psta;
+
+				if(NULL==psta) continue;
+
+				if (pmlmeinfo->FW_sta_info[i].rx_pkt == sta_rx_pkts(psta))
+				{
+
+					if(pmlmeinfo->FW_sta_info[i].retry<3)
+					{
+						pmlmeinfo->FW_sta_info[i].retry++;
+					}
+					else
+					{
+						pmlmeinfo->FW_sta_info[i].retry = 0;
+						pmlmeinfo->FW_sta_info[i].status = 0;
+						report_del_sta_event(padapter, psta->hwaddr, WLAN_REASON_EXPIRATION_CHK, _TRUE);
+					}	
+				}
+				else
+				{
+					pmlmeinfo->FW_sta_info[i].retry = 0;
+					pmlmeinfo->FW_sta_info[i].rx_pkt = (u32)sta_rx_pkts(psta);
+				}
+			}
+		}
+
+		//set_link_timer(pmlmeext, DISCONNECT_TO);
+
+	}
+
+}
+
+void survey_timer_hdl(struct timer_list *t)
+{
+	_adapter *padapter =
+		from_timer(padapter, t, mlmeextpriv.survey_timer);
+	struct cmd_obj *cmd;
+	struct sitesurvey_parm *psurveyPara;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+#endif
+
+	if (mlmeext_scan_state(pmlmeext) > SCAN_DISABLE) {
+		cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+		if (cmd == NULL) {
+			rtw_warn_on(1);
+			goto exit;
+		}
+
+		psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
+		if (psurveyPara == NULL) {
+			rtw_warn_on(1);
+			rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
+			goto exit;
+		}
+
+		init_h2fwcmd_w_parm_no_rsp(cmd, psurveyPara, GEN_CMD_CODE(_SiteSurvey));
+		rtw_enqueue_cmd(pcmdpriv, cmd);
+	}
+
+exit:
+	return;
+}
+
+void link_timer_hdl(struct timer_list *t)
+{
+	_adapter *padapter =
+		from_timer(padapter, t, mlmeextpriv.link_timer);
+	//static unsigned int		rx_pkt = 0;
+	//static u64				tx_cnt = 0;
+	//struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	//struct sta_priv		*pstapriv = &padapter->stapriv;
+
+
+	if (pmlmeinfo->state & WIFI_FW_AUTH_NULL)
+	{
+		DBG_871X("link_timer_hdl:no beacon while connecting\n");
+		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		report_join_res(padapter, -3);
+	}
+	else if (pmlmeinfo->state & WIFI_FW_AUTH_STATE)
+	{
+		//re-auth timer
+		if (++pmlmeinfo->reauth_count > REAUTH_LIMIT)
+		{
+			//if (pmlmeinfo->auth_algo != dot11AuthAlgrthm_Auto)
+			//{
+				pmlmeinfo->state = 0;
+				report_join_res(padapter, -1);
+				return;
+			//}
+			//else
+			//{
+			//	pmlmeinfo->auth_algo = dot11AuthAlgrthm_Shared;
+			//	pmlmeinfo->reauth_count = 0;
+			//}
+		}
+		
+		DBG_871X("link_timer_hdl: auth timeout and try again\n");
+		pmlmeinfo->auth_seq = 1;
+		issue_auth(padapter, NULL, 0);
+		set_link_timer(pmlmeext, REAUTH_TO);
+	}
+	else if (pmlmeinfo->state & WIFI_FW_ASSOC_STATE)
+	{
+		//re-assoc timer
+		if (++pmlmeinfo->reassoc_count > REASSOC_LIMIT)
+		{
+			pmlmeinfo->state = WIFI_FW_NULL_STATE;
+			report_join_res(padapter, -2);
+			return;
+		}
+
+		DBG_871X("link_timer_hdl: assoc timeout and try again\n");
+		issue_assocreq(padapter);
+		set_link_timer(pmlmeext, REASSOC_TO);
+	}
+#if 0
+	else if (is_client_associated_to_ap(padapter))
+	{
+		//linked infrastructure client mode
+		if ((psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress)) != NULL)
+		{
+			/*to monitor whether the AP is alive or not*/
+			if (rx_pkt == psta->sta_stats.rx_pkts)
+			{
+				receive_disconnect(padapter, pmlmeinfo->network.MacAddress);
+				return;
+			}
+			else
+			{
+				rx_pkt = psta->sta_stats.rx_pkts;
+				set_link_timer(pmlmeext, DISCONNECT_TO);
+			}
+
+			//update the EDCA paramter according to the Tx/RX mode
+			update_EDCA_param(padapter);
+
+			/*to send the AP a nulldata if no frame is xmitted in order to keep alive*/
+			if (pmlmeinfo->link_count++ == 0)
+			{
+				tx_cnt = pxmitpriv->tx_pkts;
+			}
+			else if ((pmlmeinfo->link_count & 0xf) == 0)
+			{
+				if (tx_cnt == pxmitpriv->tx_pkts)
+				{
+					issue_nulldata_in_interrupt(padapter, NULL, 0);
+				}
+
+				tx_cnt = pxmitpriv->tx_pkts;
+			}
+		} //end of if ((psta = rtw_get_stainfo(pstapriv, passoc_res->network.MacAddress)) != NULL)
+	}
+	else if (is_client_associated_to_ibss(padapter))
+	{
+		//linked IBSS mode
+		//for each assoc list entry to check the rx pkt counter
+		for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
+		{
+			if (pmlmeinfo->FW_sta_info[i].status == 1)
+			{
+				psta = pmlmeinfo->FW_sta_info[i].psta;
+
+				if (pmlmeinfo->FW_sta_info[i].rx_pkt == psta->sta_stats.rx_pkts)
+				{
+					pmlmeinfo->FW_sta_info[i].status = 0;
+					report_del_sta_event(padapter, psta->hwaddr);
+				}
+				else
+				{
+					pmlmeinfo->FW_sta_info[i].rx_pkt = psta->sta_stats.rx_pkts;
+				}
+			}
+		}
+
+		set_link_timer(pmlmeext, DISCONNECT_TO);
+	}
+#endif
+
+	return;
+}
+
+void addba_timer_hdl(struct timer_list *t)
+{
+	struct sta_info *psta = from_timer(psta, t, addba_retry_timer);
+#ifdef CONFIG_80211N_HT
+	struct ht_priv	*phtpriv;
+
+	if(!psta)
+		return;
+	
+	phtpriv = &psta->htpriv;
+
+	if((phtpriv->ht_option==_TRUE) && (phtpriv->ampdu_enable==_TRUE)) 
+	{
+		if(phtpriv->candidate_tid_bitmap)
+			phtpriv->candidate_tid_bitmap=0x0;
+		
+	}
+#endif //CONFIG_80211N_HT
+}
+
+#ifdef CONFIG_IEEE80211W
+void report_sta_timeout_event(_adapter *padapter, u8 *MacAddr, unsigned short reason)
+{
+	struct cmd_obj *pcmd_obj;
+	u8	*pevtcmd;
+	u32 cmdsz;
+	struct sta_info *psta;
+	int	mac_id;
+	struct stadel_event			*pdel_sta_evt;
+	struct C2HEvent_Header	*pc2h_evt_hdr;
+	struct mlme_ext_priv		*pmlmeext = &padapter->mlmeextpriv;
+	struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
+	
+	pcmd_obj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
+	if (pcmd_obj == NULL)
+		return;
+
+	cmdsz = (sizeof(struct stadel_event) + sizeof(struct C2HEvent_Header));
+	pevtcmd = (u8 *)rtw_zmalloc(cmdsz);
+	if (pevtcmd == NULL) {
+		rtw_mfree((u8 *)pcmd_obj, sizeof(struct cmd_obj));
+		return;
+	}
+
+	_rtw_init_listhead(&pcmd_obj->list);
+
+	pcmd_obj->cmdcode = GEN_CMD_CODE(_Set_MLME_EVT);
+	pcmd_obj->cmdsz = cmdsz;
+	pcmd_obj->parmbuf = pevtcmd;
+
+	pcmd_obj->rsp = NULL;
+	pcmd_obj->rspsz  = 0;
+
+	pc2h_evt_hdr = (struct C2HEvent_Header *)(pevtcmd);
+	pc2h_evt_hdr->len = sizeof(struct stadel_event);
+	pc2h_evt_hdr->ID = GEN_EVT_CODE(_TimeoutSTA);
+	pc2h_evt_hdr->seq = ATOMIC_INC_RETURN(&pmlmeext->event_seq);
+
+	pdel_sta_evt = (struct stadel_event *)(pevtcmd + sizeof(struct C2HEvent_Header));
+	_rtw_memcpy((unsigned char *)(&(pdel_sta_evt->macaddr)), MacAddr, ETH_ALEN);
+	_rtw_memcpy((unsigned char *)(pdel_sta_evt->rsvd), (unsigned char *)(&reason), 2);
+
+
+	psta = rtw_get_stainfo(&padapter->stapriv, MacAddr);
+	if (psta)
+		mac_id = (int)psta->mac_id;	
+	else
+		mac_id = (-1);
+
+	pdel_sta_evt->mac_id = mac_id;
+
+	DBG_871X("report_del_sta_event: delete STA, mac_id=%d\n", mac_id);
+
+	rtw_enqueue_cmd(pcmdpriv, pcmd_obj);
+
+	return;
+}
+
+void clnt_sa_query_timeout(_adapter *padapter)
+{
+
+	rtw_disassoc_cmd(padapter, 0, _TRUE);
+	rtw_indicate_disconnect(padapter);
+	rtw_free_assoc_resources(padapter, 1);	
+
+	DBG_871X("SA query timeout client disconnect\n");
+}
+
+void sa_query_timer_hdl(struct timer_list *t)
+{
+	struct sta_info *psta = from_timer(psta, t, dot11w_expire_timer);
+	_adapter *padapter = psta->padapter;
+	_irqL irqL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+
+	if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE &&
+					check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+		clnt_sa_query_timeout(padapter);
+	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+		report_sta_timeout_event(padapter, psta->hwaddr, WLAN_REASON_PREV_AUTH_NOT_VALID);
+}
+
+#endif //CONFIG_IEEE80211W
+
+u8 NULL_hdl(_adapter *padapter, u8 *pbuf)
+{
+	return H2C_SUCCESS;
+}
+
+#ifdef CONFIG_AUTO_AP_MODE
+void rtw_start_auto_ap(_adapter *adapter)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	rtw_set_802_11_infrastructure_mode(adapter, Ndis802_11APMode);
+
+	rtw_setopmode_cmd(adapter, Ndis802_11APMode,_TRUE);
+}
+
+static int rtw_auto_ap_start_beacon(_adapter *adapter)
+{
+	int ret=0;
+	u8 *pbuf = NULL;
+	uint len;
+	u8	supportRate[16];
+	int 	sz = 0, rateLen;
+	u8 *	ie;
+	u8	wireless_mode, oper_channel;
+	u8 ssid[3] = {0}; //hidden ssid
+	u32 ssid_len = sizeof(ssid);
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+
+
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) != _TRUE)
+		return -EINVAL;
+
+
+	len = 128;
+	pbuf = rtw_zmalloc(len);
+	if(!pbuf)
+		return -ENOMEM;
+
+
+	//generate beacon
+	ie = pbuf;
+
+	//timestamp will be inserted by hardware
+	sz += 8;
+	ie += sz;
+
+	//beacon interval : 2bytes
+	*(u16*)ie = cpu_to_le16((u16)100);//BCN_INTERVAL=100;
+	sz += 2;
+	ie += 2;
+
+	//capability info
+	*(u16*)ie = 0;
+	*(u16*)ie |= cpu_to_le16(cap_ESS);
+	*(u16*)ie |= cpu_to_le16(cap_ShortPremble);
+	//*(u16*)ie |= cpu_to_le16(cap_Privacy);
+	sz += 2;
+	ie += 2;
+
+	//SSID
+	ie = rtw_set_ie(ie, _SSID_IE_, ssid_len, ssid, &sz);
+
+	//supported rates
+	wireless_mode = WIRELESS_11BG_24N;
+	rtw_set_supported_rate(supportRate, wireless_mode) ;
+	rateLen = rtw_get_rateset_len(supportRate);
+	if (rateLen > 8)
+	{
+		ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, 8, supportRate, &sz);
+	}
+	else
+	{
+		ie = rtw_set_ie(ie, _SUPPORTEDRATES_IE_, rateLen, supportRate, &sz);
+	}
+
+
+	//DS parameter set
+	if(check_buddy_fwstate(adapter, _FW_LINKED) &&
+		check_buddy_fwstate(adapter, WIFI_STATION_STATE))
+	{
+		PADAPTER pbuddy_adapter = adapter->pbuddy_adapter;
+		struct mlme_ext_priv *pbuddy_mlmeext  = &pbuddy_adapter->mlmeextpriv;
+
+		oper_channel = pbuddy_mlmeext->cur_channel;
+	}
+	else
+	{
+		oper_channel = adapter_to_dvobj(adapter)->oper_channel;
+	}
+	ie = rtw_set_ie(ie, _DSSET_IE_, 1, &oper_channel, &sz);
+
+	//ext supported rates
+	if (rateLen > 8)
+	{
+		ie = rtw_set_ie(ie, _EXT_SUPPORTEDRATES_IE_, (rateLen - 8), (supportRate + 8), &sz);
+	}
+
+	DBG_871X("%s, start auto ap beacon sz=%d\n", __FUNCTION__, sz);
+
+	//lunch ap mode & start to issue beacon
+	if(rtw_check_beacon_data(adapter, pbuf,  sz) == _SUCCESS)
+	{
+
+	}
+	else
+	{
+		ret = -EINVAL;
+	}
+
+
+	rtw_mfree(pbuf, len);
+
+	return ret;
+
+}
+#endif//CONFIG_AUTO_AP_MODE
+
+u8 setopmode_hdl(_adapter *padapter, u8 *pbuf)
+{
+	u8	type;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct setopmode_parm *psetop = (struct setopmode_parm *)pbuf;
+
+	if(psetop->mode == Ndis802_11APMode)
+	{
+		pmlmeinfo->state = WIFI_FW_AP_STATE;
+		type = _HW_STATE_AP_;
+#ifdef CONFIG_NATIVEAP_MLME
+		//start_ap_mode(padapter);
+#endif
+	}
+	else if(psetop->mode == Ndis802_11Infrastructure)
+	{
+		pmlmeinfo->state &= ~(BIT(0)|BIT(1));// clear state
+		pmlmeinfo->state |= WIFI_FW_STATION_STATE;//set to 	STATION_STATE
+		type = _HW_STATE_STATION_;
+	}
+	else if(psetop->mode == Ndis802_11IBSS)
+	{
+		type = _HW_STATE_ADHOC_;
+	} else if (psetop->mode == Ndis802_11Monitor) {
+		type = _HW_STATE_MONITOR_;
+	}
+	else
+	{
+		type = _HW_STATE_NOLINK_;
+	}
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
+	//Set_NETYPE0_MSR(padapter, type);
+
+
+#ifdef CONFIG_AUTO_AP_MODE
+	if(psetop->mode == Ndis802_11APMode)
+		rtw_auto_ap_start_beacon(padapter);
+#endif
+
+	if (rtw_port_switch_chk(padapter) == _TRUE)
+	{
+		rtw_hal_set_hwreg(padapter, HW_VAR_PORT_SWITCH, NULL);
+
+		if(psetop->mode == Ndis802_11APMode)
+			adapter_to_pwrctl(padapter)->fw_psmode_iface_id = 0xff; //ap mode won't dowload rsvd pages
+		else if (psetop->mode == Ndis802_11Infrastructure) {
+			#ifdef CONFIG_LPS
+			_adapter *port0_iface = dvobj_get_port0_adapter(adapter_to_dvobj(padapter));
+			if (port0_iface)
+				rtw_lps_ctrl_wk_cmd(port0_iface, LPS_CTRL_CONNECT, 0);
+			#endif	
+		}
+	}	
+
+#ifdef CONFIG_BT_COEXIST
+	if (psetop->mode == Ndis802_11APMode)
+	{
+		// Do this after port switch to
+		// prevent from downloading rsvd page to wrong port
+		rtw_btcoex_MediaStatusNotify(padapter, 1); //connect 
+	}
+#endif // CONFIG_BT_COEXIST
+
+	return H2C_SUCCESS;
+	
+}
+
+u8 createbss_hdl(_adapter *padapter, u8 *pbuf)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX	*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+	WLAN_BSSID_EX	*pdev_network = &padapter->registrypriv.dev_network;
+	struct createbss_parm *parm = (struct createbss_parm *)pbuf;
+	u8 ret = H2C_SUCCESS;
+	//u8	initialgain;
+	
+#ifdef CONFIG_AP_MODE
+	if (pmlmeinfo->state == WIFI_FW_AP_STATE) {
+		start_bss_network(padapter, parm);
+		goto exit;
+	}
+#endif
+
+	/* below is for ad-hoc master */
+	if (parm->adhoc) {
+		rtw_warn_on(pdev_network->InfrastructureMode != Ndis802_11IBSS);
+		rtw_joinbss_reset(padapter);
+	
+		pmlmeext->cur_bwmode = CHANNEL_WIDTH_20;
+		pmlmeext->cur_ch_offset= HAL_PRIME_CHNL_OFFSET_DONT_CARE;	
+		pmlmeinfo->ERP_enable = 0;
+		pmlmeinfo->WMM_enable = 0;
+		pmlmeinfo->HT_enable = 0;
+		pmlmeinfo->HT_caps_enable = 0;
+		pmlmeinfo->HT_info_enable = 0;
+		pmlmeinfo->agg_enable_bitmap = 0;
+		pmlmeinfo->candidate_tid_bitmap = 0;
+
+		//config the initial gain under linking, need to write the BB registers
+		//initialgain = 0x1E;
+		/*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/
+
+		//disable dynamic functions, such as high power, DIG
+		rtw_phydm_ability_backup(padapter);
+		rtw_phydm_func_disable_all(padapter);
+		
+		//cancel link timer 
+		_cancel_timer_ex(&pmlmeext->link_timer);
+
+		//clear CAM
+		flush_all_cam_entry(padapter);	
+
+		pdev_network->Length = get_WLAN_BSSID_EX_sz(pdev_network);
+		_rtw_memcpy(pnetwork, pdev_network, FIELD_OFFSET(WLAN_BSSID_EX, IELength));
+		pnetwork->IELength = pdev_network->IELength;
+
+		if (pnetwork->IELength > MAX_IE_SZ) {
+			ret = H2C_PARAMETERS_ERROR;
+			goto ibss_post_hdl;
+		}
+
+		_rtw_memcpy(pnetwork->IEs, pdev_network->IEs, pnetwork->IELength);
+		start_create_ibss(padapter);
+	} else {
+		rtw_warn_on(1);
+		ret = H2C_PARAMETERS_ERROR;
+	}
+
+ibss_post_hdl:
+	rtw_create_ibss_post_hdl(padapter, ret);
+
+exit:
+	return ret;
+}
+
+u8 join_cmd_hdl(_adapter *padapter, u8 *pbuf)
+{
+	u8	join_type;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	struct joinbss_parm	*pparm = (struct joinbss_parm *)pbuf;
+#endif //CONFIG_ANTENNA_DIVERSITY
+	u32 i;
+	//u8	initialgain;
+	//u32	acparm;
+	u8 u_ch, u_bw, u_offset;
+	u8 doiqk = _FALSE;
+
+	//check already connecting to AP or not
+	if (pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)
+	{
+		if (pmlmeinfo->state & WIFI_FW_STATION_STATE)
+		{
+			issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
+		}
+		pmlmeinfo->state = WIFI_FW_NULL_STATE;
+		
+		//clear CAM
+		flush_all_cam_entry(padapter);		
+		
+		_cancel_timer_ex(&pmlmeext->link_timer);
+		
+		//set MSR to nolink -> infra. mode		
+		//Set_MSR(padapter, _HW_STATE_NOLINK_);
+		Set_MSR(padapter, _HW_STATE_STATION_);	
+		
+
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_DISCONNECT, 0);
+	}
+
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	rtw_antenna_select_cmd(padapter, pparm->network.PhyInfo.Optimum_antenna, _FALSE);
+#endif
+
+#ifdef CONFIG_WAPI_SUPPORT
+	rtw_wapi_clear_all_cam_entry(padapter);
+#endif
+
+	rtw_joinbss_reset(padapter);
+
+	pmlmeinfo->ERP_enable = 0;
+	pmlmeinfo->WMM_enable = 0;
+	pmlmeinfo->HT_enable = 0;
+	pmlmeinfo->HT_caps_enable = 0;
+	pmlmeinfo->HT_info_enable = 0;
+	pmlmeinfo->agg_enable_bitmap = 0;
+	pmlmeinfo->candidate_tid_bitmap = 0;
+	pmlmeinfo->bwmode_updated = _FALSE;
+	//pmlmeinfo->assoc_AP_vendor = HT_IOT_PEER_MAX;
+	pmlmeinfo->VHT_enable = 0;
+
+	_rtw_memcpy(pnetwork, pbuf, FIELD_OFFSET(WLAN_BSSID_EX, IELength)); 
+	pnetwork->IELength = ((WLAN_BSSID_EX *)pbuf)->IELength;
+	
+	if(pnetwork->IELength>MAX_IE_SZ)//Check pbuf->IELength
+		return H2C_PARAMETERS_ERROR;	
+	
+	if (pnetwork->IELength < 2) {
+		report_join_res(padapter, (-4));
+		return H2C_SUCCESS;
+	}
+	_rtw_memcpy(pnetwork->IEs, ((WLAN_BSSID_EX *)pbuf)->IEs, pnetwork->IELength); 
+
+	pmlmeinfo->bcn_interval = get_beacon_interval(pnetwork);
+
+	//Check AP vendor to move rtw_joinbss_cmd()
+	//pmlmeinfo->assoc_AP_vendor = check_assoc_AP(pnetwork->IEs, pnetwork->IELength);
+
+	//sizeof(NDIS_802_11_FIXED_IEs)	
+	for (i = _FIXED_IE_LENGTH_ ; i < pnetwork->IELength - 2 ;) {
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pnetwork->IEs + i);
+
+		switch (pIE->ElementID)
+		{
+			case _VENDOR_SPECIFIC_IE_://Get WMM IE.
+				if ( _rtw_memcmp(pIE->data, WMM_OUI, 4) )
+				{
+					WMM_param_handler(padapter, pIE);
+				}
+				break;
+
+#ifdef CONFIG_80211N_HT
+			case _HT_CAPABILITY_IE_:	//Get HT Cap IE.
+				pmlmeinfo->HT_caps_enable = 1;
+				break;
+
+			case _HT_EXTRA_INFO_IE_:	//Get HT Info IE.
+				pmlmeinfo->HT_info_enable = 1;
+				break;
+#endif /* CONFIG_80211N_HT */
+
+#ifdef CONFIG_80211AC_VHT
+			case EID_VHTCapability://Get VHT Cap IE.
+				pmlmeinfo->VHT_enable = 1;
+				break;
+
+			case EID_VHTOperation://Get VHT Operation IE.
+				break;
+#endif /* CONFIG_80211AC_VHT */
+			default:
+				break;
+		}
+
+		i += (pIE->Length + 2);
+	}
+
+	rtw_bss_get_chbw(pnetwork
+		, &pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset);
+
+	rtw_adjust_chbw(padapter, pmlmeext->cur_channel, &pmlmeext->cur_bwmode, &pmlmeext->cur_ch_offset);
+
+#if 0
+	if (padapter->registrypriv.wifi_spec) {
+		// for WiFi test, follow WMM test plan spec
+		acparm = 0x002F431C; // VO
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
+		acparm = 0x005E541C; // VI
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
+		acparm = 0x0000A525; // BE
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+		acparm = 0x0000A549; // BK
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
+	
+		// for WiFi test, mixed mode with intel STA under bg mode throughput issue
+		if (padapter->mlmepriv.htpriv.ht_option == _FALSE){
+			acparm = 0x00004320;
+			rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+		}
+	}
+	else {
+		acparm = 0x002F3217; // VO
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acparm));
+		acparm = 0x005E4317; // VI
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acparm));
+		acparm = 0x00105320; // BE
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acparm));
+		acparm = 0x0000A444; // BK
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acparm));
+	}
+#endif
+
+	/* check channel, bandwidth, offset and switch */
+	if (rtw_chk_start_clnt_join(padapter, &u_ch, &u_bw, &u_offset) == _FAIL) {
+		report_join_res(padapter, (-4));
+		return H2C_SUCCESS;
+	}
+
+	//disable dynamic functions, such as high power, DIG
+	/*rtw_phydm_func_disable_all(padapter);*/
+
+	//config the initial gain under linking, need to write the BB registers
+	//initialgain = 0x1E;
+	/*rtw_hal_set_odm_var(padapter, HAL_ODM_INITIAL_GAIN, &initialgain, _FALSE);*/
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
+	join_type = 0;
+	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+	doiqk = _TRUE;
+	rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+
+	set_channel_bwmode(padapter, u_ch, u_offset, u_bw);
+
+	doiqk = _FALSE;
+	rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+
+	//cancel link timer 
+	_cancel_timer_ex(&pmlmeext->link_timer);
+	
+	start_clnt_join(padapter);
+	
+	return H2C_SUCCESS;
+	
+}
+
+u8 disconnect_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	struct disconnect_parm *param = (struct disconnect_parm *)pbuf;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+	u8 val8;
+
+	if (is_client_associated_to_ap(padapter))
+	{
+#ifdef CONFIG_DFS
+		if(padapter->mlmepriv.handle_dfs == _FALSE)
+#endif //CONFIG_DFS
+#ifdef CONFIG_PLATFORM_ROCKCHIPS
+			//To avoid connecting to AP fail during resume process, change retry count from 5 to 1
+			issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, 1, 100);
+#else
+			issue_deauth_ex(padapter, pnetwork->MacAddress, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
+#endif //CONFIG_PLATFORM_ROCKCHIPS
+	}
+
+#ifdef CONFIG_DFS
+	if( padapter->mlmepriv.handle_dfs == _TRUE )
+		padapter->mlmepriv.handle_dfs = _FALSE;
+#endif //CONFIG_DFS
+
+	if(((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
+	{
+		//Stop BCN
+		val8 = 0;
+		rtw_hal_set_hwreg(padapter, HW_VAR_BCN_FUNC, (u8 *)(&val8));
+	}
+
+	rtw_mlmeext_disconnect(padapter);
+
+	rtw_free_uc_swdec_pending_queue(padapter);
+
+	return 	H2C_SUCCESS;
+}
+
+static const char * const _scan_state_str[] = {
+	"SCAN_DISABLE",
+	"SCAN_START",
+	"SCAN_PS_ANNC_WAIT",
+	"SCAN_ENTER",
+	"SCAN_PROCESS",
+	"SCAN_BACKING_OP",
+	"SCAN_BACK_OP",
+	"SCAN_LEAVING_OP",
+	"SCAN_LEAVE_OP",
+	"SCAN_SW_ANTDIV_BL",
+	"SCAN_TO_P2P_LISTEN",
+	"SCAN_P2P_LISTEN",
+	"SCAN_COMPLETE",
+	"SCAN_STATE_MAX",
+};
+
+const char *scan_state_str(u8 state)
+{
+	state = (state >= SCAN_STATE_MAX) ? SCAN_STATE_MAX : state;
+	return _scan_state_str[state];
+}
+
+static bool scan_abort_hdl(_adapter *adapter)
+{
+	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct ss_res *ss = &pmlmeext->sitesurvey_res;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+#endif
+	bool ret = _FALSE;
+
+	if (pmlmeext->scan_abort == _TRUE) {
+		#ifdef CONFIG_P2P
+		if (!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) {
+			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
+			ss->channel_idx = 3;
+			DBG_871X("%s idx:%d, cnt:%u\n", __FUNCTION__
+				, ss->channel_idx
+				, pwdinfo->find_phase_state_exchange_cnt
+			);
+		} else
+		#endif
+		{
+			ss->channel_idx = ss->ch_num;
+			DBG_871X("%s idx:%d\n", __FUNCTION__
+				, ss->channel_idx
+			);
+		}
+		pmlmeext->scan_abort = _FALSE;
+		ret = _TRUE;
+	}
+
+	return ret;
+}
+
+u8 rtw_scan_sparse(_adapter *adapter, struct rtw_ieee80211_channel *ch, u8 ch_num)
+{
+/* interval larger than this is treated as backgroud scan */
+#ifndef RTW_SCAN_SPARSE_BG_INTERVAL_MS
+#define RTW_SCAN_SPARSE_BG_INTERVAL_MS 12000
+#endif
+
+#ifndef RTW_SCAN_SPARSE_CH_NUM_MIRACAST
+#define RTW_SCAN_SPARSE_CH_NUM_MIRACAST 1
+#endif
+#ifndef RTW_SCAN_SPARSE_CH_NUM_BG
+#define RTW_SCAN_SPARSE_CH_NUM_BG 4
+#endif
+
+#define SCAN_SPARSE_CH_NUM_INVALID 255
+
+	static u8 token = 255;
+	u32 interval;
+	bool busy_traffic = _FALSE;
+	bool miracast_enabled = _FALSE;
+	bool bg_scan = _FALSE;
+	u8 max_allow_ch = SCAN_SPARSE_CH_NUM_INVALID;
+	u8 scan_division_num;
+	u8 ret_num = ch_num;
+	struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(adapter));
+	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
+
+	if (regsty->wifi_spec)
+		goto exit;
+
+	/* assume ch_num > 6 is normal scan */
+	if (ch_num <= 6)
+		goto exit;
+
+	if (mlmeext->last_scan_time == 0)
+		mlmeext->last_scan_time = rtw_get_current_time();
+
+	interval = rtw_get_passing_time_ms(mlmeext->last_scan_time);
+
+	if (adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE
+		#ifdef CONFIG_CONCURRENT_MODE
+		|| (adapter->pbuddy_adapter && adapter->pbuddy_adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
+		#endif
+	)
+			busy_traffic = _TRUE;
+
+	if (is_miracast_enabled(adapter)
+		#ifdef CONFIG_CONCURRENT_MODE
+		|| (adapter->pbuddy_adapter && is_miracast_enabled(adapter->pbuddy_adapter))
+		#endif
+	)
+		miracast_enabled = _TRUE;
+
+	if (interval > RTW_SCAN_SPARSE_BG_INTERVAL_MS)
+		bg_scan = _TRUE;
+
+	/* max_allow_ch by conditions*/
+
+	#if RTW_SCAN_SPARSE_MIRACAST
+	if (miracast_enabled == _TRUE && busy_traffic == _TRUE)
+		max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_MIRACAST);
+	#endif
+
+	#if RTW_SCAN_SPARSE_BG
+	if (bg_scan == _TRUE)
+		max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_BG);
+	#endif
+
+
+	if (max_allow_ch != SCAN_SPARSE_CH_NUM_INVALID) {
+		int i;
+		int k = 0;
+
+		scan_division_num = (ch_num / max_allow_ch) + ((ch_num % max_allow_ch)?1:0);
+		token = (token + 1) % scan_division_num;
+		
+		if (0)
+			DBG_871X("scan_division_num:%u, token:%u\n", scan_division_num, token);
+		
+		for (i = 0; i < ch_num; i++) {
+			if (ch[i].hw_value && (i % scan_division_num) == token
+			) {
+				if (i != k)
+					_rtw_memcpy(&ch[k], &ch[i], sizeof(struct rtw_ieee80211_channel));
+				k++;
+			}
+		}
+
+		_rtw_memset(&ch[k], 0, sizeof(struct rtw_ieee80211_channel));
+
+		ret_num = k;
+		mlmeext->last_scan_time = rtw_get_current_time();
+	}
+
+exit:
+	return ret_num;
+}
+
+static int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,
+	u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num)
+{
+	int i, j;
+	int scan_ch_num = 0;
+	int set_idx;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	/* clear first */
+	_rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel)*out_num);
+
+	/* acquire channels from in */
+	j = 0;
+	for (i=0;i<in_num;i++) {
+
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
+
+		if(in[i].hw_value && !(in[i].flags & RTW_IEEE80211_CHAN_DISABLED)
+			&& (set_idx=rtw_ch_set_search_ch(pmlmeext->channel_set, in[i].hw_value)) >=0
+			&& rtw_mlme_band_check(padapter, in[i].hw_value) == _TRUE
+		)
+		{
+			if (j >= out_num) {
+				DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
+					FUNC_ADPT_ARG(padapter), out_num);
+				break;
+			}
+
+			_rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
+			
+			if(pmlmeext->channel_set[set_idx].ScanType == SCAN_PASSIVE)
+				out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
+				
+			j++;
+		}
+		if(j>=out_num)
+			break;
+	}
+	
+	/* if out is empty, use channel_set as default */
+	if(j == 0) {
+		for (i=0;i<pmlmeext->max_chan_nums;i++) {
+
+			if (0)
+				DBG_871X(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), pmlmeext->channel_set[i].ChannelNum);
+
+			if (rtw_mlme_band_check(padapter, pmlmeext->channel_set[i].ChannelNum) == _TRUE) {
+
+				if (j >= out_num) {
+					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" out_num:%u not enough\n",
+						FUNC_ADPT_ARG(padapter), out_num);
+					break;
+				}
+
+				out[j].hw_value = pmlmeext->channel_set[i].ChannelNum;
+			
+				if(pmlmeext->channel_set[i].ScanType == SCAN_PASSIVE)
+					out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
+
+				j++;
+			}
+		}
+	}
+
+	/* scan_sparse */
+	j = rtw_scan_sparse(padapter, out, j);
+
+	return j;
+}
+
+static void sitesurvey_res_reset(_adapter *adapter, struct sitesurvey_parm *parm)
+{
+	struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;
+	int i;
+
+	ss->bss_cnt = 0;
+	ss->channel_idx = 0;
+#ifdef CONFIG_SCAN_BACKOP
+	ss->scan_cnt = 0;
+#endif
+#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
+	ss->is_sw_antdiv_bl_scan = 0;
+#endif
+	
+	for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+		if (parm->ssid[i].SsidLength) {
+			_rtw_memcpy(ss->ssid[i].Ssid, parm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
+			ss->ssid[i].SsidLength = parm->ssid[i].SsidLength;
+		} else {
+			ss->ssid[i].SsidLength = 0;
+		}
+	}
+
+	ss->ch_num = rtw_scan_ch_decision(adapter
+		, ss->ch, RTW_CHANNEL_SCAN_AMOUNT
+		, parm->ch, parm->ch_num
+	);
+
+	ss->scan_mode = parm->scan_mode;
+}
+
+static u8 sitesurvey_pick_ch_behavior(_adapter *padapter, u8 *ch, RT_SCAN_TYPE *type)
+{
+	u8 next_state;
+	u8 scan_ch = 0;
+	RT_SCAN_TYPE scan_type = SCAN_PASSIVE;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+	struct ss_res *ss = &pmlmeext->sitesurvey_res;
+
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif
+
+	/* handle scan abort request */
+	scan_abort_hdl(padapter);
+
+#ifdef CONFIG_P2P
+	if (pwdinfo->rx_invitereq_info.scan_op_ch_only || pwdinfo->p2p_info.scan_op_ch_only) {
+		if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
+			scan_ch = pwdinfo->rx_invitereq_info.operation_ch[ss->channel_idx];
+		else
+			scan_ch = pwdinfo->p2p_info.operation_ch[ss->channel_idx];
+		scan_type = SCAN_ACTIVE;
+	} else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
+		/*
+		* Commented by Albert 2011/06/03
+		* The driver is in the find phase, it should go through the social channel.
+		*/
+		int ch_set_idx;
+
+		scan_ch = pwdinfo->social_chan[ss->channel_idx];
+		ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, scan_ch);
+		if (ch_set_idx >= 0)
+			scan_type = pmlmeext->channel_set[ch_set_idx].ScanType;
+		else
+			scan_type = SCAN_ACTIVE;
+	} else
+#endif /* CONFIG_P2P */
+	{
+		struct rtw_ieee80211_channel *ch;
+
+		if (ss->channel_idx < ss->ch_num) {
+			ch = &ss->ch[ss->channel_idx];
+			scan_ch = ch->hw_value;
+			scan_type = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? SCAN_PASSIVE : SCAN_ACTIVE;
+		}
+	}
+
+	if (scan_ch != 0) {
+		next_state = SCAN_PROCESS;
+		#ifdef CONFIG_SCAN_BACKOP
+		{
+			u8 sta_num;
+			u8 ld_sta_num;
+			u8 ap_num;
+			u8 ld_ap_num;
+			u8 backop_flags = 0;
+
+			rtw_dev_iface_status(padapter, &sta_num, &ld_sta_num, NULL, &ap_num, &ld_ap_num);
+
+			if ((ld_sta_num > 0 && mlmeext_chk_scan_backop_flags_sta(pmlmeext, SS_BACKOP_EN))
+					|| (sta_num > 0 && mlmeext_chk_scan_backop_flags_sta(pmlmeext, SS_BACKOP_EN_NL))
+			) {
+				backop_flags |= mlmeext_scan_backop_flags_sta(pmlmeext);
+			}
+
+			if ((ld_ap_num > 0 && mlmeext_chk_scan_backop_flags_ap(pmlmeext, SS_BACKOP_EN))
+					|| (ap_num > 0 && mlmeext_chk_scan_backop_flags_ap(pmlmeext, SS_BACKOP_EN_NL))
+			) {
+				backop_flags |= mlmeext_scan_backop_flags_ap(pmlmeext);
+			}
+
+			if (backop_flags) {
+				if (ss->scan_cnt < ss->scan_cnt_max) {
+					ss->scan_cnt++;
+				} else {
+					mlmeext_assign_scan_backop_flags(pmlmeext, backop_flags);
+					next_state = SCAN_BACKING_OP;
+				}
+			}
+		}
+		#endif /* CONFIG_SCAN_BACKOP */
+	} else if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
+		/* go p2p listen */
+		next_state = SCAN_TO_P2P_LISTEN;
+
+	#ifdef CONFIG_ANTENNA_DIVERSITY
+	} else if (rtw_hal_antdiv_before_linked(padapter)) {
+		/* go sw antdiv before link */
+		next_state = SCAN_SW_ANTDIV_BL;
+	#endif
+	} else {
+		next_state = SCAN_COMPLETE;
+
+		#if defined(DBG_SCAN_SW_ANTDIV_BL)
+		{
+			/* for SCAN_SW_ANTDIV_BL state testing */
+			struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+			int i;
+			bool is_linked = _FALSE;
+
+			for (i = 0; i < dvobj->iface_nums; i++) {
+				if (rtw_linked_check(dvobj->padapters[i]))
+					is_linked = _TRUE;
+			}
+
+			if (!is_linked) {
+				static bool fake_sw_antdiv_bl_state = 0;
+
+				if (fake_sw_antdiv_bl_state == 0) {
+					next_state = SCAN_SW_ANTDIV_BL;
+					fake_sw_antdiv_bl_state = 1;
+				} else {
+					fake_sw_antdiv_bl_state = 0;
+				}
+			}
+		}
+		#endif /* defined(DBG_SCAN_SW_ANTDIV_BL) */
+	}
+
+	#ifdef CONFIG_SCAN_BACKOP
+	if (next_state != SCAN_PROCESS)
+		ss->scan_cnt = 0;
+	#endif
+
+
+#ifdef DBG_FIXED_CHAN
+	if (pmlmeext->fixed_chan != 0xff && next_state == SCAN_PROCESS)
+		scan_ch = pmlmeext->fixed_chan;
+#endif
+
+	if (ch)
+		*ch = scan_ch;
+	if (type)
+		*type = scan_type;
+
+	return next_state;
+}
+
+void site_survey(_adapter *padapter, u8 survey_channel, RT_SCAN_TYPE ScanType)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#endif
+
+	if (survey_channel != 0) {
+		set_channel_bwmode(padapter, survey_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+
+		#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+		if (ACS_ENABLE == GET_ACS_STATE(padapter)) {
+			ACS_OP acs_op = ACS_RESET;
+
+			rtw_hal_set_odm_var(padapter, HAL_ODM_AUTO_CHNL_SEL, &acs_op, _TRUE);
+			rtw_set_acs_channel(padapter, survey_channel);
+			#ifdef DBG_AUTO_CHNL_SEL_NHM
+			DBG_871X("[ACS-"ADPT_FMT"]-set ch:%u\n",
+				ADPT_ARG(padapter), rtw_get_acs_channel(padapter));
+			#endif
+		}
+		#endif
+
+		if (ScanType == SCAN_ACTIVE) {
+			#ifdef CONFIG_P2P
+			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN) || 
+				rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
+			) {
+				issue_probereq_p2p(padapter, NULL);
+				issue_probereq_p2p(padapter, NULL);
+				issue_probereq_p2p(padapter, NULL);
+			} else
+			#endif /* CONFIG_P2P */
+			{
+				int i;
+
+				for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
+					if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
+						/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
+						if (padapter->registrypriv.wifi_spec)
+							issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
+						else
+							issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
+						issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
+					}
+				}
+
+				if (pmlmeext->sitesurvey_res.scan_mode == SCAN_ACTIVE) {
+					/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
+					if (padapter->registrypriv.wifi_spec)
+						issue_probereq(padapter, NULL, NULL);
+					else
+						issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
+					issue_probereq(padapter, NULL, NULL);
+				}
+			}
+		}
+	} else {
+		/* channel number is 0 or this channel is not valid. */
+		rtw_warn_on(1);
+	}
+
+	return;
+}
+
+void survey_done_set_ch_bw(_adapter *padapter)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	u8 cur_channel = 0;
+	u8 cur_bwmode;
+	u8 cur_ch_offset;
+	
+	if (rtw_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0) {
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
+				FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
+	} else {
+		#ifdef CONFIG_P2P
+		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+		_adapter *iface;
+		int i;
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			if (!iface)
+				continue;
+
+			#ifdef CONFIG_IOCTL_CFG80211
+			if (iface->wdinfo.driver_interface == DRIVER_CFG80211 && !adapter_wdev_data(iface)->p2p_enabled)
+				continue;
+			#endif
+
+			if (rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_LISTEN)) {
+				cur_channel = iface->wdinfo.listen_channel;
+				cur_bwmode = CHANNEL_WIDTH_20;
+				cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+				if (0)
+					DBG_871X(FUNC_ADPT_FMT" back to "ADPT_FMT"'s listen ch - ch:%u, bw:%u, offset:%u\n",
+						FUNC_ADPT_ARG(padapter), ADPT_ARG(iface), cur_channel, cur_bwmode, cur_ch_offset);
+				break;
+			}
+		}
+		#endif /* CONFIG_P2P */
+
+		if (cur_channel == 0) {
+			cur_channel = pmlmeext->cur_channel;
+			cur_bwmode = pmlmeext->cur_bwmode;
+			cur_ch_offset = pmlmeext->cur_ch_offset;
+			if (0)
+				DBG_871X(FUNC_ADPT_FMT" back to ch:%u, bw:%u, offset:%u\n",
+					FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
+		}
+	}
+
+	set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode);
+}
+
+/**
+ * sitesurvey_ps_annc - check and doing ps announcement for all the adapters of given @dvobj
+ * @dvobj: the dvobj to check
+ * @ps: power saving or not
+ *
+ * Returns: 0: no ps announcement is doing. 1: ps announcement is doing
+ */
+u8 sitesurvey_ps_annc(struct dvobj_priv *dvobj, bool ps)
+{
+	_adapter *adapter;
+	int i;
+	u8 ps_anc = 0;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		adapter = dvobj->padapters[i];
+		if (!adapter)
+			continue;
+
+		if (ps) {
+			if (is_client_associated_to_ap(adapter) == _TRUE) {
+				/* TODO: TDLS peers */
+				issue_nulldata(adapter, NULL, 1, 3, 500);
+				ps_anc = 1;
+			}
+		} else {
+			if (is_client_associated_to_ap(adapter) == _TRUE) {
+				/* TODO: TDLS peers */
+				issue_nulldata(adapter, NULL, 0, 3, 500);
+				ps_anc = 1;
+			}
+		}
+	}
+
+	return ps_anc;
+}
+
+void sitesurvey_set_igi(_adapter *adapter, bool enter)
+{
+	u8 igi;
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
+#endif
+
+	if (enter) {
+#ifdef CONFIG_P2P
+#ifdef CONFIG_IOCTL_CFG80211
+		if (adapter_wdev_data(adapter)->p2p_enabled == _TRUE && pwdinfo->driver_interface == DRIVER_CFG80211)
+			igi = 0x30;
+		else
+#endif /* CONFIG_IOCTL_CFG80211 */
+		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+			igi = 0x28;
+		else
+#endif /* CONFIG_P2P */
+			igi = 0x1e;
+	} else {
+			igi = 0xff; /* restore RX GAIN */
+	}
+
+	rtw_hal_set_odm_var(adapter, HAL_ODM_INITIAL_GAIN, &igi, _FALSE);
+}
+
+u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
+{
+	struct sitesurvey_parm	*pparm = (struct sitesurvey_parm *)pbuf;
+	struct dvobj_priv *dvobj = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct ss_res *ss = &pmlmeext->sitesurvey_res;
+	u8 val8;
+
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+#endif
+
+#ifdef DBG_CHECK_FW_PS_STATE
+	if (rtw_fw_ps_state(padapter) == _FAIL) {
+		DBG_871X("scan without leave 32k\n");
+		pdbgpriv->dbg_scan_pwr_state_cnt++;
+	}
+#endif /* DBG_CHECK_FW_PS_STATE */
+
+	/* increase channel idx */
+	if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS))
+		ss->channel_idx++;
+
+	/* update scan state to next state (assigned by previous cmd hdl) */
+	if (mlmeext_scan_state(pmlmeext) != mlmeext_scan_next_state(pmlmeext))
+		mlmeext_set_scan_state(pmlmeext, mlmeext_scan_next_state(pmlmeext));
+
+operation_by_state:
+	switch (mlmeext_scan_state(pmlmeext)) {
+
+	case SCAN_DISABLE:
+		/* 
+		* SW parameter initialization
+		*/
+
+		sitesurvey_res_reset(padapter, pparm);
+		mlmeext_set_scan_state(pmlmeext, SCAN_START);
+		goto operation_by_state;
+
+	case SCAN_START:
+		/*
+		* prepare to leave operating channel
+		*/
+
+		/* apply rx ampdu setting */
+		if (ss->rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID
+			|| ss->rx_ampdu_size != RX_AMPDU_SIZE_INVALID
+		) {
+			rtw_rx_ampdu_apply(padapter);
+		}
+
+		/* clear HW TX queue before scan */
+		rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
+
+		/* power save state announcement */
+		if (sitesurvey_ps_annc(adapter_to_dvobj(padapter), 1)) {
+			mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);
+			mlmeext_set_scan_next_state(pmlmeext, SCAN_ENTER);
+			set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */
+		} else {
+			mlmeext_set_scan_state(pmlmeext, SCAN_ENTER);
+			goto operation_by_state;
+		}
+
+		break;
+
+	case SCAN_ENTER:
+		/*
+		* HW register and DM setting for enter scan
+		*/
+
+		/* config the initial gain under scanning */
+		sitesurvey_set_igi(padapter, 1);
+		
+		/* disable dynamic functions, such as high power, DIG */
+		rtw_phydm_ability_backup(padapter);
+		rtw_phydm_func_for_offchannel(padapter);
+		
+		/* set MSR to no link state */
+		Set_MSR(padapter, _HW_STATE_NOLINK_);
+		val8 = 1; /* under site survey */
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+		mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
+		goto operation_by_state;
+
+	case SCAN_PROCESS:
+	{
+		u8 scan_ch;
+		RT_SCAN_TYPE scan_type;
+		u8 next_state;
+		u32 scan_ms;
+
+		#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+		if ((ACS_ENABLE == GET_ACS_STATE(padapter)) && (0 != rtw_get_acs_channel(padapter))) {
+			ACS_OP acs_op = ACS_SELECT;
+
+			rtw_hal_set_odm_var(padapter, HAL_ODM_AUTO_CHNL_SEL, &acs_op, _TRUE);
+		}
+		#endif
+
+		next_state = sitesurvey_pick_ch_behavior(padapter, &scan_ch, &scan_type);
+		if (next_state != SCAN_PROCESS) {
+			#ifdef CONFIG_AUTO_CHNL_SEL_NHM
+			if (ACS_ENABLE == GET_ACS_STATE(padapter)) {
+				rtw_set_acs_channel(padapter, 0);
+				#ifdef DBG_AUTO_CHNL_SEL_NHM
+				DBG_871X("[ACS-"ADPT_FMT"]-set ch:%u\n", ADPT_ARG(padapter), rtw_get_acs_channel(padapter));
+				#endif
+			}
+			#endif
+
+			mlmeext_set_scan_state(pmlmeext, next_state);
+			goto operation_by_state;
+		}
+
+		/* still SCAN_PROCESS state */
+		if (0)
+			#ifdef CONFIG_P2P
+			DBG_871X(FUNC_ADPT_FMT" %s ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c\n"
+				, FUNC_ADPT_ARG(padapter)
+				, mlmeext_scan_state_str(pmlmeext)
+				, scan_ch
+				, pwdinfo->find_phase_state_exchange_cnt, ss->channel_idx
+				, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
+				, scan_type?'A':'P', ss->scan_mode?'A':'P'
+				, ss->ssid[0].SsidLength?'S':' ' 
+			);
+			#else
+			DBG_871X(FUNC_ADPT_FMT" %s ch:%u (idx:%d) at %dms, %c%c%c\n"
+				, FUNC_ADPT_ARG(padapter)
+				, mlmeext_scan_state_str(pmlmeext)
+				, scan_ch
+				, ss->channel_idx
+				, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
+				, scan_type?'A':'P', ss->scan_mode?'A':'P'
+				, ss->ssid[0].SsidLength?'S':' '
+			);
+			#endif /* CONFIG_P2P */
+
+		#ifdef DBG_FIXED_CHAN
+		if (pmlmeext->fixed_chan != 0xff)
+			DBG_871X(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
+		#endif
+
+		site_survey(padapter, scan_ch, scan_type);
+
+		#if defined(CONFIG_ATMEL_RC_PATCH)
+		if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+			scan_ms = 20;
+		else
+			scan_ms = 40;
+		#else
+		scan_ms = ss->scan_ch_ms;
+		#endif
+
+		#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
+		if (ss->is_sw_antdiv_bl_scan)
+			scan_ms = scan_ms/2;
+		#endif
+
+		#if defined(CONFIG_SIGNAL_DISPLAY_DBM) && defined(CONFIG_BACKGROUND_NOISE_MONITOR)
+		{
+			struct noise_info info;
+
+			info.bPauseDIG = _FALSE;
+			info.IGIValue = 0;
+			info.max_time = scan_ms/2;
+			info.chan = scan_ch;
+			rtw_hal_set_odm_var(padapter, HAL_ODM_NOISE_MONITOR, &info, _FALSE); 
+		}
+		#endif
+
+		set_survey_timer(pmlmeext, scan_ms);
+		break;
+	}
+
+	#ifdef CONFIG_SCAN_BACKOP
+	case SCAN_BACKING_OP:
+	{
+		u8 back_ch, back_bw, back_ch_offset;
+
+		if (rtw_get_ch_setting_union(padapter, &back_ch, &back_bw, &back_ch_offset) == 0)
+			rtw_warn_on(1);
+
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" %s ch:%u, bw:%u, offset:%u at %dms\n"
+				, FUNC_ADPT_ARG(padapter)
+				, mlmeext_scan_state_str(pmlmeext)
+				, back_ch, back_bw, back_ch_offset
+				, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
+			);
+
+		set_channel_bwmode(padapter, back_ch, back_ch_offset, back_bw);
+
+		Set_MSR(padapter, (pmlmeinfo->state & 0x3));		
+		val8 = 0; /* survey done */
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) {
+			sitesurvey_set_igi(padapter, 0);
+			sitesurvey_ps_annc(adapter_to_dvobj(padapter), 0);
+		}
+
+		mlmeext_set_scan_state(pmlmeext, SCAN_BACK_OP);
+		ss->backop_time = rtw_get_current_time();
+
+		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_TX_RESUME)) {
+			int	i;
+
+			/* resume TX */
+			for (i = 0; i < dvobj->iface_nums; i++) {
+				if (!dvobj->padapters[i])
+					continue;
+
+				rtw_os_xmit_schedule(dvobj->padapters[i]);
+			}
+		}
+
+		goto operation_by_state;
+	}
+	
+	case SCAN_BACK_OP:
+		if (rtw_get_passing_time_ms(ss->backop_time) >= ss->backop_ms
+			|| pmlmeext->scan_abort
+		) {
+			mlmeext_set_scan_state(pmlmeext, SCAN_LEAVING_OP);
+			goto operation_by_state;
+		}
+		set_survey_timer(pmlmeext, 50);
+		break;
+
+	case SCAN_LEAVING_OP:
+		/*
+		* prepare to leave operating channel
+		*/
+
+		/* clear HW TX queue before scan */
+		rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
+
+		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)
+			&& sitesurvey_ps_annc(adapter_to_dvobj(padapter), 1)
+		) {
+			mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);
+			mlmeext_set_scan_next_state(pmlmeext, SCAN_LEAVE_OP);
+			set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */
+		} else {
+			mlmeext_set_scan_state(pmlmeext, SCAN_LEAVE_OP);
+			goto operation_by_state;
+		}
+
+		break;
+
+	case SCAN_LEAVE_OP:
+		/*
+		* HW register and DM setting for enter scan
+		*/
+
+		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) {
+			/* config the initial gain under scanning */
+			sitesurvey_set_igi(padapter, 1);
+		}
+
+		/* set MSR to no link state */
+		Set_MSR(padapter, _HW_STATE_NOLINK_);
+		val8 = 1; //under site survey
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+		mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
+		goto operation_by_state;
+
+	#endif /* CONFIG_SCAN_BACKOP */
+
+	#if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
+	case SCAN_SW_ANTDIV_BL:
+		/*
+		* 20100721
+		* For SW antenna diversity before link, it needs to switch to another antenna and scan again.
+		* It compares the scan result and select better one to do connection.
+		*/
+		ss->bss_cnt = 0;
+		ss->channel_idx = 0;
+		ss->is_sw_antdiv_bl_scan = 1;
+
+		mlmeext_set_scan_next_state(pmlmeext, SCAN_PROCESS);
+		set_survey_timer(pmlmeext, ss->scan_ch_ms);
+		break;
+	#endif
+
+	#ifdef CONFIG_P2P
+	case SCAN_TO_P2P_LISTEN:
+		/*
+		* Set the P2P State to the listen state of find phase
+		* and set the current channel to the listen channel
+		*/
+		set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
+	
+		/* turn on phy-dynamic functions */
+		rtw_phydm_ability_restore(padapter);
+
+		sitesurvey_set_igi(padapter, 0);
+
+		mlmeext_set_scan_state(pmlmeext, SCAN_P2P_LISTEN);
+		_set_timer(&pwdinfo->find_phase_timer, (u32)((u32)pwdinfo->listen_dwell * 100));
+		break;
+
+	case SCAN_P2P_LISTEN:
+		mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
+		ss->channel_idx = 0;
+		goto operation_by_state;
+	#endif /* CONFIG_P2P */
+
+	case SCAN_COMPLETE:		
+		#ifdef CONFIG_P2P
+		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
+			|| rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
+		) {
+			#ifdef CONFIG_CONCURRENT_MODE
+			if (pwdinfo->driver_interface == DRIVER_WEXT) {
+				if (check_buddy_fwstate(padapter, _FW_LINKED))
+					_set_timer(&pwdinfo->ap_p2p_switch_timer, 500);
+			}
+			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+			#else
+			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+			#endif
+		}
+		rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+		#endif /* CONFIG_P2P */
+
+		/* switch channel */
+		survey_done_set_ch_bw(padapter);
+
+		/* config MSR */
+		Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+		val8 = 0; /* survey done */
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+
+		/* turn on phy-dynamic functions */
+		rtw_phydm_ability_restore(padapter);
+
+		sitesurvey_set_igi(padapter, 0);
+
+		sitesurvey_ps_annc(adapter_to_dvobj(padapter), 0);
+
+		/* apply rx ampdu setting */
+		rtw_rx_ampdu_apply(padapter);
+
+		mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
+
+		report_surveydone_event(padapter);
+
+		issue_action_BSSCoexistPacket(padapter);
+		issue_action_BSSCoexistPacket(padapter);
+		issue_action_BSSCoexistPacket(padapter);
+	}
+
+	return H2C_SUCCESS;
+}
+
+u8 setauth_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	struct setauth_parm		*pparm = (struct setauth_parm *)pbuf;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	if (pparm->mode < 4)
+	{
+		pmlmeinfo->auth_algo = pparm->mode;
+	}
+
+	return 	H2C_SUCCESS;
+}
+
+u8 setkey_hdl(_adapter *padapter, u8 *pbuf)
+{
+	u16	ctrl = 0;
+	s16 cam_id = 0;
+	struct setkey_parm		*pparm = (struct setkey_parm *)pbuf;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	unsigned char null_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	u8 *addr;
+	bool used;
+
+	//main tx key for wep.
+	if(pparm->set_tx)
+		pmlmeinfo->key_index = pparm->keyid;
+
+	cam_id = rtw_camid_alloc(padapter, NULL, pparm->keyid, &used);
+
+	if (cam_id < 0)
+		goto enable_mc;
+
+	if (cam_id > 3) /* not default key, searched by A2 */
+		addr = get_bssid(&padapter->mlmepriv);
+	else
+		addr = null_addr;
+
+	#ifdef DYNAMIC_CAMID_ALLOC
+	/* cam entry searched is pairwise key */
+	if (used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _FALSE) {
+		s16 camid_clr;
+
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key with "MAC_FMT" id:%u the same key id as pairwise key\n"
+			, FUNC_ADPT_ARG(padapter), MAC_ARG(addr), pparm->keyid);
+
+		/* HW has problem to distinguish this group key with existing pairwise key, stop HW enc and dec for BMC */
+		rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH);
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL);
+
+		/* clear group key */
+		while ((camid_clr = rtw_camid_search(padapter, addr, -1, 1)) >= 0) {
+			DBG_871X_LEVEL(_drv_always_, "clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(addr), camid_clr);
+			clear_cam_entry(padapter, camid_clr);
+			rtw_camid_free(padapter, camid_clr);
+		}
+
+		goto enable_mc;
+	}
+	#endif
+
+	ctrl = BIT(15) | BIT6 | ((pparm->algorithm) << 2) | pparm->keyid;
+	DBG_871X_LEVEL(_drv_always_, "set group key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n"
+		, cam_id, MAC_ARG(addr), pparm->keyid, security_type_str(pparm->algorithm));
+	write_cam(padapter, cam_id, ctrl, addr, pparm->key);
+
+	#ifdef DYNAMIC_CAMID_ALLOC
+	if (cam_id >=0 && cam_id <=3)
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)_TRUE);
+	#endif
+
+enable_mc:
+	//allow multicast packets to driver
+	rtw_hal_set_hwreg(padapter, HW_VAR_ON_RCR_AM, null_addr);
+
+	return H2C_SUCCESS;
+}
+
+u8 set_stakey_hdl(_adapter *padapter, u8 *pbuf)
+{
+	u16 ctrl = 0;
+	s16 cam_id = 0;
+	bool used;
+	u8 ret = H2C_SUCCESS;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct set_stakey_parm	*pparm = (struct set_stakey_parm *)pbuf;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *psta;
+
+	if(pparm->algorithm == _NO_PRIVACY_)
+		goto write_to_cam;
+
+	psta = rtw_get_stainfo(pstapriv, pparm->addr);
+	if (!psta) {
+		DBG_871X_LEVEL(_drv_always_, "%s sta:"MAC_FMT" not found\n", __func__, MAC_ARG(pparm->addr));
+		ret = H2C_REJECTED;
+		goto exit;
+	}
+
+	pmlmeinfo->enc_algo = pparm->algorithm;
+	cam_id = rtw_camid_alloc(padapter, psta, 0, &used);
+	if (cam_id < 0)
+		goto exit;
+
+	#ifdef DYNAMIC_CAMID_ALLOC
+	/* cam entry searched is group key */
+	if (used == _TRUE && rtw_camid_is_gk(padapter, cam_id) == _TRUE) {
+		s16 camid_clr;
+
+		DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pairwise key with "MAC_FMT" id:%u the same key id as group key\n"
+			, FUNC_ADPT_ARG(padapter), MAC_ARG(pparm->addr), pparm->keyid);
+
+		/* HW has problem to distinguish this pairwise key with existing group key, stop HW enc and dec for BMC */
+		rtw_camctl_set_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH);
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, NULL);
+
+		/* clear group key */
+		while ((camid_clr = rtw_camid_search(padapter, pparm->addr, -1, 1)) >= 0) {
+			DBG_871X_LEVEL(_drv_always_, "clear group key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), camid_clr);
+			clear_cam_entry(padapter, camid_clr);
+			rtw_camid_free(padapter, camid_clr);
+		}
+	}
+	#endif
+
+write_to_cam:
+	if(pparm->algorithm == _NO_PRIVACY_) {
+		while ((cam_id = rtw_camid_search(padapter, pparm->addr, -1, -1)) >= 0) {
+			DBG_871X_LEVEL(_drv_always_, "clear key for addr:"MAC_FMT", camid:%d\n", MAC_ARG(pparm->addr), cam_id);
+			clear_cam_entry(padapter, cam_id);
+			rtw_camid_free(padapter,cam_id);
+		}
+	} else {
+		DBG_871X_LEVEL(_drv_always_, "set pairwise key camid:%d, addr:"MAC_FMT", kid:%d, type:%s\n",
+			cam_id, MAC_ARG(pparm->addr), pparm->keyid, security_type_str(pparm->algorithm));
+		ctrl = BIT(15) | ((pparm->algorithm) << 2) | pparm->keyid;
+		write_cam(padapter, cam_id, ctrl, pparm->addr, pparm->key);
+	}
+	ret = H2C_SUCCESS_RSP;
+
+exit:
+	return ret;
+}
+
+u8 add_ba_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	struct addBaReq_parm 	*pparm = (struct addBaReq_parm *)pbuf;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, pparm->addr);
+	
+	if(!psta)
+		return 	H2C_SUCCESS;
+		
+#ifdef CONFIG_80211N_HT
+	if (((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && (pmlmeinfo->HT_enable)) ||
+		((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE))
+	{
+		//pmlmeinfo->ADDBA_retry_count = 0;
+		//pmlmeinfo->candidate_tid_bitmap |= (0x1 << pparm->tid);		
+		//psta->htpriv.candidate_tid_bitmap |= BIT(pparm->tid);
+		issue_addba_req(padapter, pparm->addr, (u8)pparm->tid);
+		//_set_timer(&pmlmeext->ADDBA_timer, ADDBA_TO);
+		_set_timer(&psta->addba_retry_timer, ADDBA_TO);
+	}
+#ifdef CONFIG_TDLS
+	else if((psta->tdls_sta_state & TDLS_LINKED_STATE)&& 
+		(psta->htpriv.ht_option==_TRUE) && 
+		(psta->htpriv.ampdu_enable==_TRUE) )
+	{
+		issue_addba_req(padapter, pparm->addr, (u8)pparm->tid);
+		_set_timer(&psta->addba_retry_timer, ADDBA_TO);
+	}
+#endif //CONFIG
+	else
+	{		
+		psta->htpriv.candidate_tid_bitmap &= ~BIT(pparm->tid);		
+	}
+#endif //CONFIG_80211N_HT
+	return 	H2C_SUCCESS;
+}
+
+
+u8 chk_bmc_sleepq_cmd(_adapter* padapter)
+{
+	struct cmd_obj *ph2c;
+	struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
+	u8 res = _SUCCESS;
+
+_func_enter_;
+
+	if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		res= _FAIL;
+		goto exit;
+	}
+
+	init_h2fwcmd_w_parm_no_parm_rsp(ph2c, GEN_CMD_CODE(_ChkBMCSleepq));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+u8 set_tx_beacon_cmd(_adapter* padapter)
+{
+	struct cmd_obj	*ph2c;
+	struct Tx_Beacon_param 	*ptxBeacon_parm;	
+	struct cmd_priv	*pcmdpriv = &(padapter->cmdpriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	res = _SUCCESS;
+	int len_diff = 0;
+	
+_func_enter_;	
+
+	if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		res= _FAIL;
+		goto exit;
+	}
+
+	if ((ptxBeacon_parm = (struct Tx_Beacon_param *)rtw_zmalloc(sizeof(struct Tx_Beacon_param))) == NULL)
+	{
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct	cmd_obj));
+		res= _FAIL;
+		goto exit;
+	}
+
+	_rtw_memcpy(&(ptxBeacon_parm->network), &(pmlmeinfo->network), sizeof(WLAN_BSSID_EX));
+
+	len_diff = update_hidden_ssid(
+		ptxBeacon_parm->network.IEs+_BEACON_IE_OFFSET_
+		, ptxBeacon_parm->network.IELength-_BEACON_IE_OFFSET_
+		, pmlmeinfo->hidden_ssid_mode
+	);
+	ptxBeacon_parm->network.IELength += len_diff;
+
+	init_h2fwcmd_w_parm_no_rsp(ph2c, ptxBeacon_parm, GEN_CMD_CODE(_TX_Beacon));
+
+	res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+}
+
+
+u8 mlme_evt_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	u8 evt_code, evt_seq;
+	u16 evt_sz;
+	uint 	*peventbuf;
+	void (*event_callback)(_adapter *dev, u8 *pbuf);
+	struct evt_priv *pevt_priv = &(padapter->evtpriv);
+
+	if (pbuf == NULL)
+		goto _abort_event_;
+
+	peventbuf = (uint*)pbuf;
+	evt_sz = (u16)(*peventbuf&0xffff);
+	evt_seq = (u8)((*peventbuf>>24)&0x7f);
+	evt_code = (u8)((*peventbuf>>16)&0xff);
+	
+		
+	#ifdef CHECK_EVENT_SEQ
+	// checking event sequence...		
+	if (evt_seq != (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f) )
+	{
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_info_,("Evetn Seq Error! %d vs %d\n", (evt_seq & 0x7f), (ATOMIC_READ(&pevt_priv->event_seq) & 0x7f)));
+	
+		pevt_priv->event_seq = (evt_seq+1)&0x7f;
+
+		goto _abort_event_;
+	}
+	#endif
+
+	// checking if event code is valid
+	if (evt_code >= MAX_C2HEVT)
+	{
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent Code(%d) mismatch!\n", evt_code));
+		goto _abort_event_;
+	}
+
+	// checking if event size match the event parm size	
+	if ((wlanevents[evt_code].parmsize != 0) && 
+			(wlanevents[evt_code].parmsize != evt_sz))
+	{
+			
+		RT_TRACE(_module_rtl871x_cmd_c_,_drv_err_,("\nEvent(%d) Parm Size mismatch (%d vs %d)!\n", 
+			evt_code, wlanevents[evt_code].parmsize, evt_sz));
+		goto _abort_event_;	
+			
+	}
+
+	ATOMIC_INC(&pevt_priv->event_seq);
+
+	peventbuf += 2;
+				
+	if(peventbuf)
+	{
+		event_callback = wlanevents[evt_code].event_callback;
+		event_callback(padapter, (u8*)peventbuf);
+
+		pevt_priv->evt_done_cnt++;
+	}
+
+
+_abort_event_:
+
+
+	return H2C_SUCCESS;
+		
+}
+
+u8 h2c_msg_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	if(!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	return H2C_SUCCESS;
+}
+
+u8 chk_bmc_sleepq_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+#ifdef CONFIG_AP_MODE
+	_irqL irqL;
+	struct sta_info *psta_bmc;
+	_list	*xmitframe_plist, *xmitframe_phead;
+	struct xmit_frame *pxmitframe=NULL;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct sta_priv  *pstapriv = &padapter->stapriv;
+
+	//for BC/MC Frames
+	psta_bmc = rtw_get_bcmc_stainfo(padapter);
+	if(!psta_bmc)
+		return H2C_SUCCESS;
+
+	if((pstapriv->tim_bitmap&BIT(0)) && (psta_bmc->sleepq_len>0))
+	{
+#ifndef CONFIG_PCI_HCI
+		rtw_msleep_os(10);// 10ms, ATIM(HIQ) Windows
+#endif
+		//_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+		_enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+		xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+		xmitframe_plist = get_next(xmitframe_phead);
+
+		while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+		{
+			pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+			xmitframe_plist = get_next(xmitframe_plist);
+
+			rtw_list_delete(&pxmitframe->list);
+
+			psta_bmc->sleepq_len--;
+			if(psta_bmc->sleepq_len>0)
+				pxmitframe->attrib.mdata = 1;
+			else
+				pxmitframe->attrib.mdata = 0;
+
+			pxmitframe->attrib.triggered=1;
+
+			if (xmitframe_hiq_filter(pxmitframe) == _TRUE)
+				pxmitframe->attrib.qsel = QSLT_HIGH;//HIQ
+
+			#if 0
+			_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+			if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
+			{
+				rtw_os_xmit_complete(padapter, pxmitframe);
+			}
+			_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+			#endif
+			rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+		}
+
+		//_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+		_exit_critical_bh(&pxmitpriv->lock, &irqL);
+
+		if (rtw_get_intf_type(padapter) != RTW_PCIE) {
+			/* check hi queue and bmc_sleepq */
+			rtw_chk_hi_queue_cmd(padapter);
+		}
+	}
+#endif
+
+	return H2C_SUCCESS;
+}
+
+u8 tx_beacon_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	if(send_beacon(padapter)==_FAIL)
+	{
+		DBG_871X("issue_beacon, fail!\n");
+		return H2C_PARAMETERS_ERROR;
+	}
+
+
+	if (padapter->registrypriv.wifi_spec == 1)
+		return H2C_SUCCESS;
+	
+	/* tx bc/mc frames after update TIM */
+	chk_bmc_sleepq_hdl(padapter, NULL);
+
+	return H2C_SUCCESS;
+}
+
+/*
+* according to channel
+* add/remove WLAN_BSSID_EX.IEs's ERP ie
+* set WLAN_BSSID_EX.SupportedRates
+* update WLAN_BSSID_EX.IEs's Supported Rate and Extended Supported Rate ie
+*/
+void change_band_update_ie(_adapter *padapter, WLAN_BSSID_EX *pnetwork, u8 ch)
+{
+	u8	network_type,rate_len, total_rate_len,remainder_rate_len;
+	struct mlme_ext_priv *pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	erpinfo=0x4;
+
+	if (ch >= 36) {
+		network_type = WIRELESS_11A;
+		total_rate_len = IEEE80211_NUM_OFDM_RATESLEN;
+		rtw_remove_bcn_ie(padapter, pnetwork, _ERPINFO_IE_);
+	} else {
+		network_type = WIRELESS_11BG;
+		total_rate_len = IEEE80211_CCK_RATE_LEN+IEEE80211_NUM_OFDM_RATESLEN;
+		rtw_add_bcn_ie(padapter, pnetwork, _ERPINFO_IE_, &erpinfo, 1);
+	}
+
+	rtw_set_supported_rate(pnetwork->SupportedRates, network_type);
+
+	UpdateBrateTbl(padapter, pnetwork->SupportedRates);
+
+	if(total_rate_len > 8)
+	{
+		rate_len = 8;
+		remainder_rate_len = total_rate_len - 8;
+	}
+	else
+	{
+		rate_len = total_rate_len;
+		remainder_rate_len = 0;
+	}
+
+	rtw_add_bcn_ie(padapter, pnetwork, _SUPPORTEDRATES_IE_, pnetwork->SupportedRates, rate_len);
+
+	if(remainder_rate_len)
+	{
+		rtw_add_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_, (pnetwork->SupportedRates+8), remainder_rate_len);
+	}
+	else
+	{
+		rtw_remove_bcn_ie(padapter, pnetwork, _EXT_SUPPORTEDRATES_IE_);
+	}
+
+	pnetwork->Length = get_WLAN_BSSID_EX_sz(pnetwork);
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+sint check_buddy_mlmeinfo_state(_adapter *padapter, u32 state)
+{
+	PADAPTER pbuddy_adapter;
+	struct mlme_ext_priv *pbuddy_mlmeext;
+	struct mlme_ext_info *pbuddy_mlmeinfo;
+
+	if(padapter == NULL)
+		return _FALSE;	
+	
+	pbuddy_adapter = padapter->pbuddy_adapter;
+
+	if(pbuddy_adapter == NULL)
+		return _FALSE;	
+
+
+	pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+	pbuddy_mlmeinfo = &(pbuddy_mlmeext->mlmext_info);
+		
+	if((pbuddy_mlmeinfo->state&0x03) == state)
+		return _TRUE;		
+
+	return _FALSE;
+	
+}
+#endif /* CONFIG_CONCURRENT_MODE */
+
+void rtw_join_done_chk_ch(_adapter *adapter, int join_res)
+{
+#define DUMP_ADAPTERS_STATUS 0
+
+	struct dvobj_priv *dvobj;
+	_adapter *iface;
+	struct mlme_priv *mlme;
+	struct mlme_ext_priv *mlmeext;
+	u8 u_ch, u_offset, u_bw;
+	int i;
+
+	dvobj = adapter_to_dvobj(adapter);
+
+	if (DUMP_ADAPTERS_STATUS) {
+		DBG_871X(FUNC_ADPT_FMT" enter\n", FUNC_ADPT_ARG(adapter));
+		dump_adapters_status(RTW_DBGDUMP , dvobj);
+	}
+
+	if (join_res >= 0) {
+		if (rtw_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset) <= 0) {
+			dump_adapters_status(RTW_DBGDUMP , dvobj);
+			rtw_warn_on(1);
+		}
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			mlme = &iface->mlmepriv;
+			mlmeext = &iface->mlmeextpriv;
+
+			if (!iface || iface == adapter)
+				continue;
+
+			if (check_fwstate(mlme, WIFI_AP_STATE)
+				&& check_fwstate(mlme, WIFI_ASOC_STATE)
+			) {
+				bool is_grouped = rtw_is_chbw_grouped(u_ch, u_bw, u_offset
+					, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);
+
+				if (is_grouped == _FALSE) {
+					/* handle AP which need to switch ch setting */
+
+					/* restore original bw, adjust bw by registry setting on target ch */
+					mlmeext->cur_bwmode = mlme->ori_bw;
+					mlmeext->cur_channel = u_ch;
+					rtw_adjust_chbw(iface
+						, mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset);
+					
+					rtw_sync_chbw(&mlmeext->cur_channel, &mlmeext->cur_bwmode, &mlmeext->cur_ch_offset
+						, &u_ch, &u_bw, &u_offset);
+
+					rtw_ap_update_bss_chbw(iface, &(mlmeext->mlmext_info.network)
+						, mlmeext->cur_channel, mlmeext->cur_bwmode, mlmeext->cur_ch_offset);
+
+					_rtw_memcpy(&(mlme->cur_network.network), &(mlmeext->mlmext_info.network), sizeof(WLAN_BSSID_EX));
+
+					rtw_start_bss_hdl_after_chbw_decided(iface);
+				}
+
+				update_beacon(iface, 0, NULL, _TRUE);
+			}
+
+			clr_fwstate(mlme, WIFI_OP_CH_SWITCHING);
+		}
+
+		#ifdef CONFIG_DFS_MASTER
+		rtw_dfs_master_status_apply(adapter, MLME_STA_CONNECTED);
+		#endif
+	} else {
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			mlme = &iface->mlmepriv;
+			mlmeext = &iface->mlmeextpriv;
+
+			if (!iface || iface == adapter)
+				continue;
+
+			if (check_fwstate(mlme, WIFI_AP_STATE)
+				&& check_fwstate(mlme, WIFI_ASOC_STATE))
+				update_beacon(iface, 0, NULL, _TRUE);
+
+			clr_fwstate(mlme, WIFI_OP_CH_SWITCHING);
+		}
+		#ifdef CONFIG_DFS_MASTER
+		rtw_dfs_master_status_apply(adapter, MLME_STA_DISCONNECTED);
+		#endif
+	}
+
+	if (rtw_get_ch_setting_union(adapter, &u_ch, &u_bw, &u_offset))
+		set_channel_bwmode(adapter, u_ch, u_offset, u_bw);
+
+	if (DUMP_ADAPTERS_STATUS) {
+		DBG_871X(FUNC_ADPT_FMT" exit\n", FUNC_ADPT_ARG(adapter));
+		dump_adapters_status(RTW_DBGDUMP , dvobj);
+	}
+}
+
+int rtw_chk_start_clnt_join(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
+{
+	bool chbw_allow = _TRUE;
+	bool connect_allow = _TRUE;
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+	u8 cur_ch, cur_bw, cur_ch_offset;
+	u8 u_ch, u_offset, u_bw;
+
+	u_ch = cur_ch = pmlmeext->cur_channel;
+	u_bw = cur_bw = pmlmeext->cur_bwmode;
+	u_offset = cur_ch_offset = pmlmeext->cur_ch_offset;
+
+	if (!ch || !bw || !offset) {
+		connect_allow = _FALSE;
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (cur_ch == 0) {
+		connect_allow = _FALSE;
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" cur_ch:%u\n"
+			, FUNC_ADPT_ARG(adapter), cur_ch);
+		rtw_warn_on(1);
+		goto exit;
+	}
+	DBG_871X(FUNC_ADPT_FMT" req: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
+
+#ifdef CONFIG_CONCURRENT_MODE
+{
+	struct dvobj_priv *dvobj;
+	_adapter *iface;
+	struct mlme_priv *mlme;
+	struct mlme_ext_priv *mlmeext;
+	u8 sta_num;
+	u8 ld_sta_num;
+	u8 lg_sta_num;
+	u8 ap_num;
+	u8 ld_ap_num;
+	int i;
+
+	dvobj = adapter_to_dvobj(adapter);
+
+	rtw_dev_iface_status_no_self(adapter, &sta_num, &ld_sta_num, &lg_sta_num, &ap_num, &ld_ap_num);
+	DBG_871X(FUNC_ADPT_FMT" ld_sta_num:%u, ap_num:%u\n"
+		, FUNC_ADPT_ARG(adapter), ld_sta_num, ap_num);
+
+	if (!ld_sta_num && !ap_num) {
+		/* consider linking STA? */
+		goto connect_allow_hdl;
+	}
+
+	if (rtw_get_ch_setting_union_no_self(adapter, &u_ch, &u_bw, &u_offset) <= 0) {
+		dump_adapters_status(RTW_DBGDUMP , dvobj);
+		rtw_warn_on(1);
+	}
+	DBG_871X(FUNC_ADPT_FMT" union no self: %u,%u,%u\n"
+		, FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
+
+	/* chbw_allow? */
+	chbw_allow = rtw_is_chbw_grouped(pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset
+		, u_ch, u_bw, u_offset);
+
+	DBG_871X(FUNC_ADPT_FMT" chbw_allow:%d\n"
+		, FUNC_ADPT_ARG(adapter), chbw_allow);
+
+	if (chbw_allow == _TRUE) {
+		rtw_sync_chbw(&cur_ch, &cur_bw, &cur_ch_offset, &u_ch, &u_bw, &u_offset);
+		rtw_warn_on(cur_ch != pmlmeext->cur_channel);
+		rtw_warn_on(cur_bw != pmlmeext->cur_bwmode);
+		rtw_warn_on(cur_ch_offset != pmlmeext->cur_ch_offset);
+		goto connect_allow_hdl;
+	}
+
+	/* chbw_allow is _FALSE, connect allow? */
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		mlme = &iface->mlmepriv;
+		mlmeext = &iface->mlmeextpriv;
+
+		#ifdef CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT
+		if (check_fwstate(mlme, WIFI_STATION_STATE)
+			&& check_fwstate(mlme, WIFI_ASOC_STATE)
+			#if defined(CONFIG_P2P)
+			&& rtw_p2p_chk_state(&(iface->wdinfo), P2P_STATE_NONE)
+			#endif
+		) {
+			connect_allow = _FALSE;
+			break;
+		}
+		#endif /* CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT */
+	}
+	DBG_871X(FUNC_ADPT_FMT" connect_allow:%d\n"
+		, FUNC_ADPT_ARG(adapter), connect_allow);
+
+	if (connect_allow == _FALSE)
+		goto exit;
+
+connect_allow_hdl:
+	/* connect_allow == _TRUE */
+
+	#ifdef CONFIG_DFS_MASTER
+	rtw_dfs_master_status_apply(adapter, MLME_STA_CONNECTING);
+	#endif
+
+	if (chbw_allow == _FALSE) {
+		u_ch = cur_ch;
+		u_bw = cur_bw;
+		u_offset = cur_ch_offset;
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			iface = dvobj->padapters[i];
+			mlme = &iface->mlmepriv;
+			mlmeext = &iface->mlmeextpriv;
+
+			if (!iface || iface == adapter)
+				continue;
+
+			if (check_fwstate(mlme, WIFI_AP_STATE)
+				&& check_fwstate(mlme, WIFI_ASOC_STATE)
+			) {
+				#ifdef CONFIG_SPCT_CH_SWITCH
+				if (1)
+					rtw_ap_inform_ch_switch(iface, pmlmeext->cur_channel , pmlmeext->cur_ch_offset);
+				else
+				#endif
+					rtw_sta_flush(iface, _FALSE);
+
+				rtw_hal_set_hwreg(iface, HW_VAR_CHECK_TXBUF, 0);
+				set_fwstate(mlme, WIFI_OP_CH_SWITCHING);
+			} else if (check_fwstate(mlme, WIFI_STATION_STATE)
+				&& check_fwstate(mlme, WIFI_ASOC_STATE)
+			) {
+				rtw_disassoc_cmd(iface, 500, _FALSE);
+				rtw_indicate_disconnect(iface);
+				rtw_free_assoc_resources(iface, 1);
+			}
+		}
+	}
+}
+#endif /* CONFIG_CONCURRENT_MODE */
+
+exit:
+
+	if (connect_allow == _TRUE) {
+		DBG_871X(FUNC_ADPT_FMT" union: %u,%u,%u\n", FUNC_ADPT_ARG(adapter), u_ch, u_bw, u_offset);
+		*ch = u_ch;
+		*bw = u_bw;
+		*offset = u_offset;
+	}
+
+	return connect_allow == _TRUE ? _SUCCESS : _FAIL;
+}
+
+/* Find union about ch, bw, ch_offset of all linked/linking interfaces */
+int _rtw_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset, bool include_self)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	_adapter *iface;
+	struct mlme_ext_priv *mlmeext;
+	int i;
+	u8 ch_ret = 0;
+	u8 bw_ret = CHANNEL_WIDTH_20;
+	u8 offset_ret = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	int num = 0;
+
+	if (ch) *ch = 0;
+	if (bw) *bw = CHANNEL_WIDTH_20;
+	if (offset) *offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+	for (i = 0; i<dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		mlmeext = &iface->mlmeextpriv;
+
+		if (!check_fwstate(&iface->mlmepriv, _FW_LINKED|_FW_UNDER_LINKING))
+			continue;
+
+		if (check_fwstate(&iface->mlmepriv, WIFI_OP_CH_SWITCHING))
+			continue;
+
+		if (include_self == _FALSE && adapter == iface)
+			continue;
+
+		if (num == 0) {
+			ch_ret = mlmeext->cur_channel;
+			bw_ret = mlmeext->cur_bwmode;
+			offset_ret = mlmeext->cur_ch_offset;
+			num++;
+			continue;
+		}
+
+		if (ch_ret != mlmeext->cur_channel) {
+			num = 0;
+			break;
+		}
+
+		if (bw_ret < mlmeext->cur_bwmode) {
+			bw_ret = mlmeext->cur_bwmode;
+			offset_ret = mlmeext->cur_ch_offset;
+		} else if (bw_ret == mlmeext->cur_bwmode && offset_ret != mlmeext->cur_ch_offset) {
+			num = 0;
+			break;
+		}
+
+		num++;
+	}
+
+	if (num) {
+		if (ch) *ch = ch_ret;
+		if (bw) *bw = bw_ret;
+		if (offset) *offset = offset_ret;
+	}
+
+	return num;
+}
+
+inline int rtw_get_ch_setting_union(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
+{
+	return _rtw_get_ch_setting_union(adapter, ch, bw, offset, 1);
+}
+
+inline int rtw_get_ch_setting_union_no_self(_adapter *adapter, u8 *ch, u8 *bw, u8 *offset)
+{
+	return _rtw_get_ch_setting_union(adapter, ch, bw, offset, 0);
+}
+
+void _rtw_dev_iface_status(_adapter *adapter, u8 *sta_num, u8 *ld_sta_num, u8 *lg_sta_num
+	, u8 *ap_num, u8 *ld_ap_num, bool include_self)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	_adapter *iface;
+	struct mlme_ext_priv *mlmeext;
+	struct mlme_ext_info *mlmeextinfo;
+	int i;
+	u8 sta_num_ret = 0;
+	u8 ld_sta_num_ret = 0;
+	u8 lg_sta_num_ret = 0;
+	u8 ap_num_ret = 0;
+	u8 ld_ap_num_ret = 0;
+
+	if (sta_num)
+		*sta_num = 0;
+	if (ld_sta_num)
+		*ld_sta_num = 0;
+	if (lg_sta_num)
+		*lg_sta_num = 0;
+	if (ap_num)
+		*ap_num = 0;
+	if (ld_ap_num)
+		*ld_ap_num = 0;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+
+		if (include_self == _FALSE && iface == adapter)
+			continue;
+
+		mlmeext = &iface->mlmeextpriv;
+
+		if (mlmeext_msr(mlmeext) == WIFI_FW_STATION_STATE) {
+			sta_num_ret++;
+			if (check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE)
+				ld_sta_num_ret++;
+			if (check_fwstate(&iface->mlmepriv, _FW_UNDER_LINKING) == _TRUE)
+				lg_sta_num_ret++;
+		}
+
+		if (mlmeext_msr(mlmeext) == WIFI_FW_AP_STATE
+			&& check_fwstate(&iface->mlmepriv, _FW_LINKED) == _TRUE
+		) {
+			ap_num_ret++;
+			if (iface->stapriv.asoc_sta_count > 2)
+				ld_ap_num_ret++;
+		}
+	}
+
+	if (sta_num)
+		*sta_num = sta_num_ret;
+	if (ld_sta_num)
+		*ld_sta_num = ld_sta_num_ret;
+	if (lg_sta_num)
+		*lg_sta_num = lg_sta_num_ret;
+	if (ap_num)
+		*ap_num = ap_num_ret;
+	if (ld_ap_num)
+		*ld_ap_num = ld_ap_num_ret;
+}
+
+inline void rtw_dev_iface_status(_adapter *adapter, u8 *sta_num, u8 *ld_sta_num, u8 *lg_sta_num
+	, u8 *ap_num, u8 *ld_ap_num)
+{
+	return _rtw_dev_iface_status(adapter, sta_num, ld_sta_num, lg_sta_num, ap_num, ld_ap_num, 1);
+}
+
+inline void rtw_dev_iface_status_no_self(_adapter *adapter, u8 *sta_num, u8 *ld_sta_num, u8 *lg_sta_num
+	, u8 *ap_num, u8 *ld_ap_num)
+{
+	return _rtw_dev_iface_status(adapter, sta_num, ld_sta_num, lg_sta_num, ap_num, ld_ap_num, 0);
+}
+
+u8 set_ch_hdl(_adapter *padapter, u8 *pbuf)
+{
+	struct set_ch_parm *set_ch_parm;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	if(!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	set_ch_parm = (struct set_ch_parm *)pbuf;
+
+	DBG_871X(FUNC_NDEV_FMT" ch:%u, bw:%u, ch_offset:%u\n",
+		FUNC_NDEV_ARG(padapter->pnetdev),
+		set_ch_parm->ch, set_ch_parm->bw, set_ch_parm->ch_offset);
+
+	pmlmeext->cur_channel = set_ch_parm->ch;
+	pmlmeext->cur_ch_offset = set_ch_parm->ch_offset;
+	pmlmeext->cur_bwmode = set_ch_parm->bw;
+
+	set_channel_bwmode(padapter, set_ch_parm->ch, set_ch_parm->ch_offset, set_ch_parm->bw);
+
+	return 	H2C_SUCCESS;
+}
+
+u8 set_chplan_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	struct SetChannelPlan_param *setChannelPlan_param;
+	struct mlme_priv *mlme = &padapter->mlmepriv;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	if(!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	setChannelPlan_param = (struct SetChannelPlan_param *)pbuf;
+
+	if(!rtw_is_channel_plan_valid(setChannelPlan_param->channel_plan)) {
+		return H2C_PARAMETERS_ERROR;
+	}
+
+	mlme->ChannelPlan = setChannelPlan_param->channel_plan;
+
+	pmlmeext->max_chan_nums = init_channel_set(padapter, setChannelPlan_param->channel_plan, pmlmeext->channel_set);
+	init_channel_list(padapter, pmlmeext->channel_set, pmlmeext->max_chan_nums, &pmlmeext->channel_list);	
+
+	rtw_hal_set_odm_var(padapter,HAL_ODM_REGULATION,NULL,_TRUE);
+	
+#ifdef CONFIG_IOCTL_CFG80211
+	if (padapter->rtw_wdev != NULL) {
+		rtw_reg_notify_by_driver(padapter->rtw_wdev->wiphy);
+	}
+#endif //CONFIG_IOCTL_CFG80211
+
+	return 	H2C_SUCCESS;
+}
+
+u8 led_blink_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+	struct LedBlink_param *ledBlink_param;
+
+	if(!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	ledBlink_param = (struct LedBlink_param *)pbuf;
+
+	#ifdef CONFIG_LED_HANDLED_BY_CMD_THREAD
+	BlinkHandler((PLED_DATA)ledBlink_param->pLed);
+	#endif
+
+	return 	H2C_SUCCESS;
+}
+
+u8 set_csa_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+#ifdef CONFIG_DFS
+	struct SetChannelSwitch_param *setChannelSwitch_param;
+	u8 new_ch_no;
+	u8 gval8 = 0x00, sval8 = 0xff;
+
+	if(!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	setChannelSwitch_param = (struct SetChannelSwitch_param *)pbuf;
+	new_ch_no = setChannelSwitch_param->new_ch_no;
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &sval8);
+
+	DBG_871X("DFS detected! Swiching channel to %d!\n", new_ch_no);
+	SelectChannel(padapter, new_ch_no);
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &gval8);
+
+	rtw_disassoc_cmd(padapter, 0, _FALSE);
+	rtw_indicate_disconnect(padapter);
+	rtw_free_assoc_resources(padapter, 1);
+	rtw_free_network_queue(padapter, _TRUE);
+
+	if ( ((new_ch_no >= 52) && (new_ch_no <= 64)) ||((new_ch_no >= 100) && (new_ch_no <= 140)) ) {
+		DBG_871X("Switched to DFS band (ch %02x) again!!\n", new_ch_no);
+	}
+
+	return 	H2C_SUCCESS;
+#else
+	return	H2C_REJECTED;
+#endif //CONFIG_DFS
+
+}
+
+u8 tdls_hdl(_adapter *padapter, unsigned char *pbuf)
+{
+#ifdef CONFIG_TDLS
+	_irqL irqL;
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+#ifdef CONFIG_TDLS_CH_SW	
+	struct tdls_ch_switch *pchsw_info = &ptdlsinfo->chsw_info;
+#endif
+	struct TDLSoption_param *TDLSoption;
+	struct sta_info *ptdls_sta = NULL;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &pmlmeext->mlmext_info;
+	u8 survey_channel, i, min, option;
+	struct tdls_txmgmt txmgmt;
+	u32 setchtime, resp_sleep = 0, wait_time;
+	u8 zaddr[ETH_ALEN] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	if (!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	TDLSoption = (struct TDLSoption_param *)pbuf;
+	option = TDLSoption->option;
+
+	if (!_rtw_memcmp(TDLSoption->addr, zaddr, ETH_ALEN)) {
+		ptdls_sta = rtw_get_stainfo( &(padapter->stapriv), TDLSoption->addr );
+		if (ptdls_sta == NULL) {
+			return H2C_REJECTED;
+		}
+	} else {
+		if (!(option == TDLS_RS_RCR || option == TDLS_CH_SW_BACK))
+			return H2C_REJECTED;
+	}
+
+	//_enter_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
+	//DBG_871X("[%s] option:%d\n", __FUNCTION__, option);
+		
+	switch (option) {
+	case TDLS_ESTABLISHED:
+	{
+		/* As long as TDLS handshake success, we should set RCR_CBSSID_DATA bit to 0 */
+		/* So we can receive all kinds of data frames. */
+		u8 sta_band = 0;
+
+		//leave ALL PS when TDLS is established
+			rtw_pwr_wakeup(padapter);
+
+		rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_WRCR, 0);
+		DBG_871X("Created Direct Link with "MAC_FMT"\n", MAC_ARG(ptdls_sta->hwaddr));
+
+		pmlmeinfo->FW_sta_info[ptdls_sta->mac_id].psta = ptdls_sta;
+		/* Set TDLS sta rate. */
+		/* Update station supportRate */
+		rtw_hal_update_sta_rate_mask(padapter, ptdls_sta);
+		if (pmlmeext->cur_channel > 14) {
+			if (ptdls_sta->ra_mask & 0xffff000)
+				sta_band |= WIRELESS_11_5N ;
+
+			if (ptdls_sta->ra_mask & 0xff0)
+				sta_band |= WIRELESS_11A;
+
+			/* 5G band */
+			#ifdef CONFIG_80211AC_VHT
+			if (ptdls_sta->vhtpriv.vht_option)
+				sta_band = WIRELESS_11_5AC;
+			#endif
+			
+		} else {
+			if (ptdls_sta->ra_mask & 0xffff000)
+				sta_band |= WIRELESS_11_24N;
+
+			if (ptdls_sta->ra_mask & 0xff0)
+				sta_band |= WIRELESS_11G;
+
+			if (ptdls_sta->ra_mask & 0x0f)
+				sta_band |= WIRELESS_11B;
+		}
+		ptdls_sta->wireless_mode = sta_band;
+		ptdls_sta->raid = rtw_hal_networktype_to_raid(padapter,ptdls_sta);
+		set_sta_rate(padapter, ptdls_sta);
+		rtw_sta_media_status_rpt(padapter, ptdls_sta, 1);
+		/* Sta mode */
+		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, ptdls_sta,_TRUE);
+		break;
+	}
+	case TDLS_ISSUE_PTI:
+		ptdls_sta->tdls_sta_state |= TDLS_WAIT_PTR_STATE;
+		issue_tdls_peer_traffic_indication(padapter, ptdls_sta);
+		_set_timer(&ptdls_sta->pti_timer, TDLS_PTI_TIME);
+		break;
+#ifdef CONFIG_TDLS_CH_SW		
+	case TDLS_CH_SW_RESP:
+		_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+		txmgmt.status_code = 0;
+		_rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
+
+		issue_nulldata(padapter, NULL, 1, 0, 0);
+
+		DBG_871X("issue tdls channel switch response\n");
+		issue_tdls_ch_switch_rsp(padapter, &txmgmt, _FALSE);
+		resp_sleep = 5;
+		rtw_msleep_os(resp_sleep);
+
+		/* If we receive TDLS_CH_SW_REQ at off channel which it's target is AP's channel */
+		/* then we just SelectChannel to AP's channel*/
+		if (padapter->mlmeextpriv.cur_channel == pchsw_info->off_ch_num) {
+			SelectChannel(padapter, padapter->mlmeextpriv.cur_channel);
+			issue_nulldata(padapter, NULL, 0, 0, 0);
+			pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE);
+			ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
+			break;
+		}
+
+		_set_timer(&ptdls_sta->delay_timer, pmlmeinfo->bcn_interval - 40);
+
+		/* Continue following actions */
+
+	case TDLS_CH_SW:
+		issue_nulldata(padapter, NULL, 1, 0, 0);
+		_set_timer(&ptdls_sta->ch_sw_timer, (u32)(ptdls_sta->ch_switch_timeout)/1000);
+
+		setchtime = rtw_systime_to_ms(rtw_get_current_time());
+		SelectChannel(padapter, pchsw_info->off_ch_num);
+		setchtime = rtw_systime_to_ms(rtw_get_current_time()) - setchtime;
+		setchtime += resp_sleep;
+
+		if (pmlmeext->cur_channel != rtw_get_oper_ch(padapter))
+			issue_nulldata(padapter, NULL, 0, 0, 0);
+		pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE);
+
+		if ((u32)ptdls_sta->ch_switch_time/1000 > setchtime)
+			wait_time = (u32)ptdls_sta->ch_switch_time/1000 - setchtime;
+		else
+			wait_time = 0;
+
+		if (wait_time > 0)
+			rtw_msleep_os(wait_time);
+
+		issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->hwaddr, 0, 0, 0);
+		issue_nulldata_to_TDLS_peer_STA(ptdls_sta->padapter, ptdls_sta->hwaddr, 0, 0, 0);
+
+		break;
+	case TDLS_CH_SW_BACK:
+		pchsw_info->ch_sw_state &= ~(TDLS_PEER_AT_OFF_STATE | TDLS_WAIT_CH_RSP_STATE);
+		ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
+		SelectChannel(padapter, padapter->mlmeextpriv.cur_channel);
+		issue_nulldata(padapter, NULL, 0, 0, 0);
+		break;
+#endif		
+	case TDLS_RS_RCR:
+		rtw_hal_set_hwreg(padapter, HW_VAR_TDLS_RS_RCR, 0);
+		DBG_871X("wirte REG_RCR, set bit6 on\n");
+		break;
+	case TDLS_TEAR_STA:
+#ifdef CONFIG_TDLS_CH_SW	
+		if (_rtw_memcmp(TDLSoption->addr, pchsw_info->addr, ETH_ALEN) == _TRUE) {
+			pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE |
+										TDLS_CH_SWITCH_ON_STATE |
+										TDLS_PEER_AT_OFF_STATE);
+			ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
+			_rtw_memset(pchsw_info->addr, 0x00, ETH_ALEN);
+		}
+#endif		
+		rtw_sta_media_status_rpt(padapter, ptdls_sta, 0);
+		free_tdls_sta(padapter, ptdls_sta);
+		break;			
+	}
+
+	//_exit_critical_bh(&(ptdlsinfo->hdl_lock), &irqL);
+
+	return H2C_SUCCESS;
+#else
+	return H2C_REJECTED;
+#endif /* CONFIG_TDLS */
+
+}
+
+u8 run_in_thread_hdl(_adapter *padapter, u8 *pbuf)
+{
+	struct RunInThread_param *p;
+
+
+	if (NULL == pbuf)
+		return H2C_PARAMETERS_ERROR;
+	p = (struct RunInThread_param*)pbuf;
+
+	if (p->func)
+		p->func(p->context);
+
+	return H2C_SUCCESS;
+}
+
+u8 rtw_getmacreg_hdl(_adapter *padapter, u8 *pbuf)
+{
+
+	struct readMAC_parm *preadmacparm = NULL;
+	u8 sz = 0;
+	u32	addr = 0;
+	u32	value = 0;
+
+	if (!pbuf)
+		return H2C_PARAMETERS_ERROR;
+
+	preadmacparm = (struct readMAC_parm *) pbuf;
+	sz = preadmacparm->len;
+	addr = preadmacparm->addr;
+	value = 0;
+
+	switch (sz) {
+	case 1:
+		value = rtw_read8(padapter, addr);
+		break;
+	case 2:
+		value = rtw_read16(padapter, addr);
+		break;
+	case 4:
+		value = rtw_read32(padapter, addr);
+		break;
+	default:
+		DBG_871X("%s: Unknown size\n", __func__);
+		break;
+	}
+	DBG_871X("%s: addr:0x%02x valeu:0x%02x\n", __func__, addr, value);
+
+	return H2C_SUCCESS;
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp.c
new file mode 100644
index 000000000..126662182
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp.c
@@ -0,0 +1,2577 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_MP_C_
+
+#include <drv_types.h>
+
+#ifdef PLATFORM_FREEBSD
+#include <sys/unistd.h>		/* for RFHIGHPID */
+#endif
+
+#include "../hal/phydm/phydm_precomp.h"		
+#if defined(CONFIG_RTL8723B) || defined(CONFIG_RTL8821A)
+#include <rtw_bt_mp.h>
+#endif
+
+
+#ifdef CONFIG_MP_INCLUDED
+
+u32 read_macreg(_adapter *padapter, u32 addr, u32 sz)
+{
+	u32 val = 0;
+
+	switch(sz)
+	{
+		case 1:
+			val = rtw_read8(padapter, addr);
+			break;
+		case 2:
+			val = rtw_read16(padapter, addr);
+			break;
+		case 4:
+			val = rtw_read32(padapter, addr);
+			break;
+		default:
+			val = 0xffffffff;
+			break;
+	}
+
+	return val;
+	
+}
+
+void write_macreg(_adapter *padapter, u32 addr, u32 val, u32 sz)
+{
+	switch(sz)
+	{
+		case 1:
+			rtw_write8(padapter, addr, (u8)val);
+			break;
+		case 2:
+			rtw_write16(padapter, addr, (u16)val);
+			break;
+		case 4:
+			rtw_write32(padapter, addr, val);
+			break;
+		default:
+			break;
+	}
+
+}
+
+u32 read_bbreg(_adapter *padapter, u32 addr, u32 bitmask)
+{
+	return rtw_hal_read_bbreg(padapter, addr, bitmask);
+}
+
+void write_bbreg(_adapter *padapter, u32 addr, u32 bitmask, u32 val)
+{
+	rtw_hal_write_bbreg(padapter, addr, bitmask, val);
+}
+
+u32 _read_rfreg(PADAPTER padapter, u8 rfpath, u32 addr, u32 bitmask)
+{
+	return rtw_hal_read_rfreg(padapter, rfpath, addr, bitmask);
+}
+
+void _write_rfreg(PADAPTER padapter, u8 rfpath, u32 addr, u32 bitmask, u32 val)
+{
+	rtw_hal_write_rfreg(padapter, rfpath, addr, bitmask, val);
+}
+
+u32 read_rfreg(PADAPTER padapter, u8 rfpath, u32 addr)
+{
+	return _read_rfreg(padapter, rfpath, addr, bRFRegOffsetMask);
+}
+
+void write_rfreg(PADAPTER padapter, u8 rfpath, u32 addr, u32 val)
+{
+	_write_rfreg(padapter, rfpath, addr, bRFRegOffsetMask, val);
+}
+
+static void _init_mp_priv_(struct mp_priv *pmp_priv)
+{
+	WLAN_BSSID_EX *pnetwork;
+
+	_rtw_memset(pmp_priv, 0, sizeof(struct mp_priv));
+
+	pmp_priv->mode = MP_OFF;
+
+	pmp_priv->channel = 1;
+	pmp_priv->bandwidth = CHANNEL_WIDTH_20;
+	pmp_priv->prime_channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	pmp_priv->rateidx = MPT_RATE_1M;
+	pmp_priv->txpoweridx = 0x2A;
+
+	pmp_priv->antenna_tx = ANTENNA_A;
+	pmp_priv->antenna_rx = ANTENNA_AB;
+
+	pmp_priv->check_mp_pkt = 0;
+
+	pmp_priv->tx_pktcount = 0;
+
+	pmp_priv->rx_bssidpktcount=0;
+	pmp_priv->rx_pktcount = 0;
+	pmp_priv->rx_crcerrpktcount = 0;
+
+	pmp_priv->network_macaddr[0] = 0x00;
+	pmp_priv->network_macaddr[1] = 0xE0;
+	pmp_priv->network_macaddr[2] = 0x4C;
+	pmp_priv->network_macaddr[3] = 0x87;
+	pmp_priv->network_macaddr[4] = 0x66;
+	pmp_priv->network_macaddr[5] = 0x55;
+
+	pmp_priv->bSetRxBssid = _FALSE;
+	pmp_priv->bRTWSmbCfg = _FALSE;
+
+	pnetwork = &pmp_priv->mp_network.network;
+	_rtw_memcpy(pnetwork->MacAddress, pmp_priv->network_macaddr, ETH_ALEN);
+
+	pnetwork->Ssid.SsidLength = 8;
+	_rtw_memcpy(pnetwork->Ssid.Ssid, "mp_871x", pnetwork->Ssid.SsidLength);
+
+	pmp_priv->tx.payload = 2;
+#ifdef CONFIG_80211N_HT
+	pmp_priv->tx.attrib.ht_en = 1;
+#endif
+
+}
+
+#ifdef PLATFORM_WINDOWS
+/*
+void mp_wi_callback(
+	IN NDIS_WORK_ITEM*	pwk_item,
+	IN PVOID			cntx
+	)
+{
+	_adapter* padapter =(_adapter *)cntx;
+	struct mp_priv *pmppriv=&padapter->mppriv;
+	struct mp_wi_cntx	*pmp_wi_cntx=&pmppriv->wi_cntx;
+
+	// Execute specified action.
+	if(pmp_wi_cntx->curractfunc != NULL)
+	{
+		LARGE_INTEGER	cur_time;
+		ULONGLONG start_time, end_time;
+		NdisGetCurrentSystemTime(&cur_time);	// driver version
+		start_time = cur_time.QuadPart/10; // The return value is in microsecond
+
+		pmp_wi_cntx->curractfunc(padapter);
+
+		NdisGetCurrentSystemTime(&cur_time);	// driver version
+		end_time = cur_time.QuadPart/10; // The return value is in microsecond
+
+		RT_TRACE(_module_mp_, _drv_info_,
+			 ("WorkItemActType: %d, time spent: %I64d us\n",
+			  pmp_wi_cntx->param.act_type, (end_time-start_time)));
+	}
+
+	NdisAcquireSpinLock(&(pmp_wi_cntx->mp_wi_lock));
+	pmp_wi_cntx->bmp_wi_progress= _FALSE;
+	NdisReleaseSpinLock(&(pmp_wi_cntx->mp_wi_lock));
+
+	if (pmp_wi_cntx->bmpdrv_unload)
+	{
+		NdisSetEvent(&(pmp_wi_cntx->mp_wi_evt));
+	}
+
+}
+*/
+
+static int init_mp_priv_by_os(struct mp_priv *pmp_priv)
+{
+	struct mp_wi_cntx *pmp_wi_cntx;
+
+	if (pmp_priv == NULL) return _FAIL;
+
+	pmp_priv->rx_testcnt = 0;
+	pmp_priv->rx_testcnt1 = 0;
+	pmp_priv->rx_testcnt2 = 0;
+
+	pmp_priv->tx_testcnt = 0;
+	pmp_priv->tx_testcnt1 = 0;
+
+	pmp_wi_cntx = &pmp_priv->wi_cntx
+	pmp_wi_cntx->bmpdrv_unload = _FALSE;
+	pmp_wi_cntx->bmp_wi_progress = _FALSE;
+	pmp_wi_cntx->curractfunc = NULL;
+
+	return _SUCCESS;
+}
+#endif
+
+#ifdef PLATFORM_LINUX
+static int init_mp_priv_by_os(struct mp_priv *pmp_priv)
+{
+	int i, res;
+	struct mp_xmit_frame *pmp_xmitframe;
+
+	if (pmp_priv == NULL) return _FAIL;
+
+	_rtw_init_queue(&pmp_priv->free_mp_xmitqueue);
+
+	pmp_priv->pallocated_mp_xmitframe_buf = NULL;
+	pmp_priv->pallocated_mp_xmitframe_buf = rtw_zmalloc(NR_MP_XMITFRAME * sizeof(struct mp_xmit_frame) + 4);
+	if (pmp_priv->pallocated_mp_xmitframe_buf == NULL) {
+		res = _FAIL;
+		goto _exit_init_mp_priv;
+	}
+
+	pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf + 4 - ((SIZE_PTR) (pmp_priv->pallocated_mp_xmitframe_buf) & 3);
+
+	pmp_xmitframe = (struct mp_xmit_frame*)pmp_priv->pmp_xmtframe_buf;
+
+	for (i = 0; i < NR_MP_XMITFRAME; i++)
+	{
+		_rtw_init_listhead(&pmp_xmitframe->list);
+		rtw_list_insert_tail(&pmp_xmitframe->list, &pmp_priv->free_mp_xmitqueue.queue);
+
+		pmp_xmitframe->pkt = NULL;
+		pmp_xmitframe->frame_tag = MP_FRAMETAG;
+		pmp_xmitframe->padapter = pmp_priv->papdater;
+
+		pmp_xmitframe++;
+	}
+
+	pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME;
+
+	res = _SUCCESS;
+
+_exit_init_mp_priv:
+
+	return res;
+}
+#endif
+
+static void mp_init_xmit_attrib(struct mp_tx *pmptx, PADAPTER padapter)
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+
+	struct pkt_attrib *pattrib;
+
+	// init xmitframe attribute
+	pattrib = &pmptx->attrib;
+	_rtw_memset(pattrib, 0, sizeof(struct pkt_attrib));
+	_rtw_memset(pmptx->desc, 0, TXDESC_SIZE);
+
+	pattrib->ether_type = 0x8712;
+	#if 0
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+	#endif
+	_rtw_memset(pattrib->dst, 0xFF, ETH_ALEN);
+
+//	pattrib->dhcp_pkt = 0;
+//	pattrib->pktlen = 0;
+	pattrib->ack_policy = 0;
+//	pattrib->pkt_hdrlen = ETH_HLEN;
+	pattrib->hdrlen = WLAN_HDR_A3_LEN;
+	pattrib->subtype = WIFI_DATA;
+	pattrib->priority = 0;
+	pattrib->qsel = pattrib->priority;
+//	do_queue_select(padapter, pattrib);
+	pattrib->nr_frags = 1;
+	pattrib->encrypt = 0;
+	pattrib->bswenc = _FALSE;
+	pattrib->qos_en = _FALSE;
+
+	pattrib->pktlen = 1500;
+	
+#ifdef CONFIG_80211AC_VHT
+		if (pHalData->rf_type == RF_1T1R)
+			pattrib->raid = RATEID_IDX_VHT_1SS;
+		else if (pHalData->rf_type == RF_2T2R || pHalData->rf_type == RF_2T4R)
+			pattrib->raid = RATEID_IDX_VHT_2SS;
+		else if (pHalData->rf_type == RF_3T3R)
+			pattrib->raid = RATEID_IDX_VHT_3SS;
+		else
+			pattrib->raid = RATEID_IDX_BGN_40M_1SS;
+#endif		
+}
+
+s32 init_mp_priv(PADAPTER padapter)
+{
+	struct mp_priv *pmppriv = &padapter->mppriv;
+	PHAL_DATA_TYPE pHalData;
+
+	pHalData = GET_HAL_DATA(padapter);
+	
+	_init_mp_priv_(pmppriv);
+	pmppriv->papdater = padapter;
+	pmppriv->mp_dm =0;
+	pmppriv->tx.stop = 1;
+	pmppriv->bSetTxPower=0;		//for  manually set tx power
+	pmppriv->bTxBufCkFail=_FALSE;
+	pmppriv->pktInterval=0;
+	
+	mp_init_xmit_attrib(&pmppriv->tx, padapter);
+
+	switch (padapter->registrypriv.rf_config) {
+		case RF_1T1R:
+			pmppriv->antenna_tx = ANTENNA_A;
+			pmppriv->antenna_rx = ANTENNA_A;
+			break;
+		case RF_1T2R:
+		default:
+			pmppriv->antenna_tx = ANTENNA_A;
+			pmppriv->antenna_rx = ANTENNA_AB;
+			break;
+		case RF_2T2R:
+		case RF_2T2R_GREEN:
+			pmppriv->antenna_tx = ANTENNA_AB;
+			pmppriv->antenna_rx = ANTENNA_AB;
+			break;
+		case RF_2T4R:
+			pmppriv->antenna_tx = ANTENNA_BC;
+			pmppriv->antenna_rx = ANTENNA_ABCD;
+			break;
+	}
+	
+	pHalData->AntennaRxPath = pmppriv->antenna_rx;
+	pHalData->AntennaTxPath = pmppriv->antenna_tx;
+	
+	return _SUCCESS;
+}
+
+void free_mp_priv(struct mp_priv *pmp_priv)
+{
+	if (pmp_priv->pallocated_mp_xmitframe_buf) {
+		rtw_mfree(pmp_priv->pallocated_mp_xmitframe_buf, 0);
+		pmp_priv->pallocated_mp_xmitframe_buf = NULL;
+	}
+	pmp_priv->pmp_xmtframe_buf = NULL;
+}
+
+
+static VOID PHY_IQCalibrate_default(
+	IN	PADAPTER	pAdapter,
+	IN	BOOLEAN 	bReCovery
+	)
+{	
+	DBG_871X("%s\n", __func__);
+}
+
+static VOID PHY_LCCalibrate_default(
+	IN	PADAPTER	pAdapter
+	)
+{
+	DBG_871X("%s\n", __func__);
+}
+
+static VOID PHY_SetRFPathSwitch_default(
+	IN	PADAPTER	pAdapter,
+	IN	BOOLEAN		bMain
+	)
+{
+	DBG_871X("%s\n", __func__);
+}
+
+
+void mpt_InitHWConfig(PADAPTER Adapter)
+{
+	if (IS_HARDWARE_TYPE_8723B(Adapter)) {
+		// TODO: <20130114, Kordan> The following setting is only for DPDT and Fixed board type.
+		// TODO:  A better solution is configure it according EFUSE during the run-time. 
+
+		PHY_SetMacReg(Adapter, 0x64, BIT20, 0x0);		   //0x66[4]=0		
+		PHY_SetMacReg(Adapter, 0x64, BIT24, 0x0);		   //0x66[8]=0
+		PHY_SetMacReg(Adapter, 0x40, BIT4, 0x0);		   //0x40[4]=0		
+		PHY_SetMacReg(Adapter, 0x40, BIT3, 0x1);		   //0x40[3]=1		
+		PHY_SetMacReg(Adapter, 0x4C, BIT24, 0x1);		   //0x4C[24:23]=10
+		PHY_SetMacReg(Adapter, 0x4C, BIT23, 0x0);		   //0x4C[24:23]=10
+		PHY_SetBBReg(Adapter, 0x944, BIT1|BIT0, 0x3);	  //0x944[1:0]=11	
+		PHY_SetBBReg(Adapter, 0x930, bMaskByte0, 0x77);   //0x930[7:0]=77	  
+		PHY_SetMacReg(Adapter, 0x38, BIT11, 0x1);		   //0x38[11]=1
+
+		// TODO: <20130206, Kordan> The default setting is wrong, hard-coded here. 
+		PHY_SetMacReg(Adapter, 0x778, 0x3, 0x3);					// Turn off hardware PTA control (Asked by Scott)
+		PHY_SetMacReg(Adapter, 0x64, bMaskDWord, 0x36000000);	 //Fix BT S0/S1
+		PHY_SetMacReg(Adapter, 0x948, bMaskDWord, 0x0); 		   //Fix BT can't Tx
+
+		/* <20130522, Kordan> Turn off equalizer to improve Rx sensitivity. (Asked by EEChou) */
+		PHY_SetBBReg(Adapter, 0xA00, BIT8, 0x0);			/*0xA01[0] = 0*/
+	 } else if (IS_HARDWARE_TYPE_8821(Adapter)) {
+		/* <20131121, VincentL> Add for 8821AU DPDT setting and fix switching antenna issue (Asked by Rock)
+		<20131122, VincentL> Enable for all 8821A/8811AU  (Asked by Alex)*/
+		PHY_SetMacReg(Adapter, 0x4C, BIT23, 0x0);		   /*0x4C[23:22]=01*/
+		PHY_SetMacReg(Adapter, 0x4C, BIT22, 0x1);		   /*0x4C[23:22]=01*/
+	} else if (IS_HARDWARE_TYPE_8188ES(Adapter))
+		PHY_SetMacReg(Adapter, 0x4C , BIT23, 0);		/*select DPDT_P and DPDT_N as output pin*/
+#ifdef CONFIG_RTL8814A	
+	  else if (IS_HARDWARE_TYPE_8814A(Adapter))
+		PlatformEFIOWrite2Byte(Adapter, REG_RXFLTMAP1_8814A, 0x2000);
+#endif		
+	/*
+	else if(IS_HARDWARE_TYPE_8822B(Adapter))
+	{
+		PlatformEFIOWrite2Byte(Adapter, REG_RXFLTMAP1_8822B, 0x2000);
+	}*/
+}
+
+#ifdef CONFIG_RTL8188E
+#define PHY_IQCalibrate(a,b)	PHY_IQCalibrate_8188E(a,b)
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8188E(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a,b) PHY_SetRFPathSwitch_8188E(a,b)
+#endif
+
+#ifdef CONFIG_RTL8814A
+#define PHY_IQCalibrate(a,b)	PHY_IQCalibrate_8814A(&(GET_HAL_DATA(a)->odmpriv), b)
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8814A(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a,b) PHY_SetRFPathSwitch_8814A(a,b)
+#endif /* CONFIG_RTL8814A */
+
+#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
+/*
+#define PHY_IQCalibrate(a,b)	PHY_IQCalibrate_8812A(a,b)
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8812A(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a,b) PHY_SetRFPathSwitch_8812A(a,b)
+*/
+
+#ifndef CONFIG_RTL8812A
+#define	PHY_IQCalibrate_8812A 
+#define	PHY_LCCalibrate_8812A 
+#define	PHY_SetRFPathSwitch_8812A 
+#endif
+
+#ifndef CONFIG_RTL8821A
+#define	PHY_IQCalibrate_8821A 
+#define	PHY_LCCalibrate_8821A 
+#define	PHY_SetRFPathSwitch_8812A 
+#endif
+
+#define PHY_IQCalibrate(_Adapter, b)	\
+		IS_HARDWARE_TYPE_8812(_Adapter) ? PHY_IQCalibrate_8812A(_Adapter, b) : \
+		IS_HARDWARE_TYPE_8821(_Adapter) ? PHY_IQCalibrate_8821A(&(GET_HAL_DATA(_Adapter)->odmpriv), b) : \
+		PHY_IQCalibrate_default(_Adapter, b)
+
+#define PHY_LCCalibrate(_Adapter)	\
+		IS_HARDWARE_TYPE_8812(_Adapter) ? PHY_LCCalibrate_8812A(&(GET_HAL_DATA(_Adapter)->odmpriv)) : \
+		IS_HARDWARE_TYPE_8821(_Adapter) ? PHY_LCCalibrate_8821A(&(GET_HAL_DATA(_Adapter)->odmpriv)) : \
+		PHY_LCCalibrate_default(_Adapter)
+
+#define PHY_SetRFPathSwitch(_Adapter, b)	\
+		(IS_HARDWARE_TYPE_JAGUAR(_Adapter)) ? PHY_SetRFPathSwitch_8812A(_Adapter, b) : \
+		PHY_SetRFPathSwitch_default(_Adapter, b)
+
+#endif //#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
+#ifdef CONFIG_RTL8192E
+#define PHY_IQCalibrate(a,b)	PHY_IQCalibrate_8192E(a,b)
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8192E(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a,b) PHY_SetRFPathSwitch_8192E(a,b)
+#endif //CONFIG_RTL8812A_8821A
+
+#ifdef CONFIG_RTL8723B
+static void PHY_IQCalibrate(PADAPTER padapter, u8 bReCovery)
+{
+	PHAL_DATA_TYPE pHalData;
+	u8 b2ant;	//false:1ant, true:2-ant
+	u8 RF_Path;	//0:S1, 1:S0
+
+	pHalData = GET_HAL_DATA(padapter);
+	b2ant = pHalData->EEPROMBluetoothAntNum==Ant_x2?_TRUE:_FALSE;
+
+	PHY_IQCalibrate_8723B(padapter, bReCovery, _FALSE, b2ant, pHalData->ant_path);
+}
+
+
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8723B(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a,b)	PHY_SetRFPathSwitch_8723B(a,b)
+#endif
+
+#ifdef CONFIG_RTL8703B
+static void PHY_IQCalibrate(PADAPTER padapter, u8 bReCovery) 
+{
+	PHY_IQCalibrate_8703B(padapter, bReCovery);
+}
+
+
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8703B(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a, b)	
+#endif
+
+#ifdef CONFIG_RTL8188F
+static void PHY_IQCalibrate(PADAPTER padapter, u8 bReCovery)
+{
+	PHY_IQCalibrate_8188F(padapter, bReCovery, _FALSE);
+}
+
+
+#define PHY_LCCalibrate(a)	PHY_LCCalibrate_8188F(&(GET_HAL_DATA(a)->odmpriv))
+#define PHY_SetRFPathSwitch(a, b)	PHY_SetRFPathSwitch_8188F(a, b)
+#endif
+
+s32
+MPT_InitializeAdapter(
+	IN	PADAPTER			pAdapter,
+	IN	u8				Channel
+	)
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(pAdapter);
+	s32		rtStatus = _SUCCESS;
+	PMPT_CONTEXT	pMptCtx = &pAdapter->mppriv.MptCtx;
+	u32		ledsetting;
+	struct mlme_priv *pmlmepriv = &pAdapter->mlmepriv;
+
+	pMptCtx->bMptDrvUnload = _FALSE;
+	pMptCtx->bMassProdTest = _FALSE;
+	pMptCtx->bMptIndexEven = _TRUE;	//default gain index is -6.0db
+	pMptCtx->h2cReqNum = 0x0;
+	//init for BT MP
+#if defined(CONFIG_RTL8723B)
+	pMptCtx->bMPh2c_timeout = _FALSE;
+	pMptCtx->MptH2cRspEvent = _FALSE;
+	pMptCtx->MptBtC2hEvent = _FALSE;
+	_rtw_init_sema(&pMptCtx->MPh2c_Sema, 0);
+	_init_timer( &pMptCtx->MPh2c_timeout_timer, pAdapter->pnetdev, MPh2c_timeout_handle, pAdapter );
+#endif
+
+	mpt_InitHWConfig(pAdapter);
+
+#ifdef CONFIG_RTL8723B
+	rtl8723b_InitAntenna_Selection(pAdapter);
+	if (IS_HARDWARE_TYPE_8723B(pAdapter))
+	{
+
+		/* <20130522, Kordan> Turn off equalizer to improve Rx sensitivity. (Asked by EEChou)*/
+		PHY_SetBBReg(pAdapter, 0xA00, BIT8, 0x0);
+		PHY_SetRFPathSwitch(pAdapter, 1/*pHalData->bDefaultAntenna*/); /*default use Main*/
+		/*<20130522, Kordan> 0x51 and 0x71 should be set immediately after path switched, or they might be overwritten. */
+		if ((pHalData->PackageType == PACKAGE_TFBGA79) || (pHalData->PackageType == PACKAGE_TFBGA90))
+					PHY_SetRFReg(pAdapter, ODM_RF_PATH_A, 0x51, bRFRegOffsetMask, 0x6B10E);
+		else
+					PHY_SetRFReg(pAdapter, ODM_RF_PATH_A, 0x51, bRFRegOffsetMask, 0x6B04E);
+	}	
+	/*set ant to wifi side in mp mode*/
+	rtw_write16(pAdapter, 0x870, 0x300);
+	rtw_write16(pAdapter, 0x860, 0x110);
+#endif
+
+	pMptCtx->bMptWorkItemInProgress = _FALSE;
+	pMptCtx->CurrMptAct = NULL;
+	pMptCtx->MptRfPath = ODM_RF_PATH_A;
+	//-------------------------------------------------------------------------
+	// Don't accept any packets
+	rtw_write32(pAdapter, REG_RCR, 0);
+
+	//ledsetting = rtw_read32(pAdapter, REG_LEDCFG0);
+	//rtw_write32(pAdapter, REG_LEDCFG0, ledsetting & ~LED0DIS);
+	
+	//rtw_write32(pAdapter, REG_LEDCFG0, 0x08080);
+	ledsetting = rtw_read32(pAdapter, REG_LEDCFG0);
+	
+	
+	PHY_LCCalibrate(pAdapter);
+	PHY_IQCalibrate(pAdapter, _FALSE);
+	//dm_CheckTXPowerTracking(&pHalData->odmpriv);	//trigger thermal meter
+	
+	PHY_SetRFPathSwitch(pAdapter, 1/*pHalData->bDefaultAntenna*/); //default use Main
+	
+	pMptCtx->backup0xc50 = (u1Byte)PHY_QueryBBReg(pAdapter, rOFDM0_XAAGCCore1, bMaskByte0);
+	pMptCtx->backup0xc58 = (u1Byte)PHY_QueryBBReg(pAdapter, rOFDM0_XBAGCCore1, bMaskByte0);
+	pMptCtx->backup0xc30 = (u1Byte)PHY_QueryBBReg(pAdapter, rOFDM0_RxDetector1, bMaskByte0);
+	pMptCtx->backup0x52_RF_A = (u1Byte)PHY_QueryRFReg(pAdapter, RF_PATH_A, RF_0x52, 0x000F0);
+	pMptCtx->backup0x52_RF_B = (u1Byte)PHY_QueryRFReg(pAdapter, RF_PATH_B, RF_0x52, 0x000F0);
+#ifdef CONFIG_RTL8188E
+	rtw_write32(pAdapter, REG_MACID_NO_LINK_0, 0x0);
+	rtw_write32(pAdapter, REG_MACID_NO_LINK_1, 0x0);
+#endif
+	return	rtStatus;
+}
+
+/*-----------------------------------------------------------------------------
+ * Function:	MPT_DeInitAdapter()
+ *
+ * Overview:	Extra DeInitialization for Mass Production Test.
+ *
+ * Input:		PADAPTER	pAdapter
+ *
+ * Output:		NONE
+ *
+ * Return:		NONE
+ *
+ * Revised History:
+ *	When		Who		Remark
+ *	05/08/2007	MHC		Create Version 0.
+ *	05/18/2007	MHC		Add normal driver MPHalt code.
+ *
+ *---------------------------------------------------------------------------*/
+VOID
+MPT_DeInitAdapter(
+	IN	PADAPTER	pAdapter
+	)
+{
+	PMPT_CONTEXT		pMptCtx = &pAdapter->mppriv.MptCtx;
+
+	pMptCtx->bMptDrvUnload = _TRUE;
+	#if defined(CONFIG_RTL8723B)
+	_rtw_free_sema(&(pMptCtx->MPh2c_Sema));
+	_cancel_timer_ex( &pMptCtx->MPh2c_timeout_timer);
+	#endif
+	#if	defined(CONFIG_RTL8723B)
+	PHY_SetBBReg(pAdapter,0xA01, BIT0, 1); ///suggestion  by jerry for MP Rx.
+	#endif
+#if 0 // for Windows
+	PlatformFreeWorkItem( &(pMptCtx->MptWorkItem) );
+
+	while(pMptCtx->bMptWorkItemInProgress)
+	{
+		if(NdisWaitEvent(&(pMptCtx->MptWorkItemEvent), 50))
+		{
+			break;
+		}
+	}
+	NdisFreeSpinLock( &(pMptCtx->MptWorkItemSpinLock) );
+#endif
+}
+
+static u8 mpt_ProStartTest(PADAPTER padapter)
+{
+	PMPT_CONTEXT pMptCtx = &padapter->mppriv.MptCtx;
+
+	pMptCtx->bMassProdTest = _TRUE;
+	pMptCtx->bStartContTx = _FALSE;
+	pMptCtx->bCckContTx = _FALSE;
+	pMptCtx->bOfdmContTx = _FALSE;
+	pMptCtx->bSingleCarrier = _FALSE;
+	pMptCtx->bCarrierSuppression = _FALSE;
+	pMptCtx->bSingleTone = _FALSE;
+
+	return _SUCCESS;
+}
+
+/*
+ * General use
+ */
+s32 SetPowerTracking(PADAPTER padapter, u8 enable)
+{
+
+	hal_mpt_SetPowerTracking(padapter, enable);
+	return 0;
+}
+
+void GetPowerTracking(PADAPTER padapter, u8 *enable)
+{
+	hal_mpt_GetPowerTracking(padapter, enable);
+}
+
+static void disable_dm(PADAPTER padapter)
+{
+	u8 v8;
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	PDM_ODM_T		pDM_Odm = &pHalData->odmpriv;
+
+	//3 1. disable firmware dynamic mechanism
+	// disable Power Training, Rate Adaptive
+	v8 = rtw_read8(padapter, REG_BCN_CTRL);
+	v8 &= ~EN_BCN_FUNCTION;
+	rtw_write8(padapter, REG_BCN_CTRL, v8);
+
+	//3 2. disable driver dynamic mechanism
+	rtw_phydm_func_disable_all(padapter);
+
+	// enable APK, LCK and IQK but disable power tracking
+	pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = _FALSE;
+	rtw_phydm_func_set(padapter, ODM_RF_CALIBRATION);
+
+//#ifdef CONFIG_BT_COEXIST
+//	rtw_btcoex_Switch(padapter, 0); //remove for BT MP Down.
+//#endif
+}
+
+
+void MPT_PwrCtlDM(PADAPTER padapter, u32 bstart)
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	PDM_ODM_T		pDM_Odm = &pHalData->odmpriv;
+
+	if (bstart==1){
+		DBG_871X("in MPT_PwrCtlDM start\n");
+		rtw_phydm_func_set(padapter, ODM_RF_TX_PWR_TRACK | ODM_RF_CALIBRATION);
+
+		pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = _TRUE;
+		padapter->mppriv.mp_dm =1;
+		
+	}else{
+		DBG_871X("in MPT_PwrCtlDM stop \n");
+		disable_dm(padapter);
+		pDM_Odm->RFCalibrateInfo.TxPowerTrackControl = _FALSE;
+		padapter->mppriv.mp_dm = 0;
+		{
+			TXPWRTRACK_CFG	c;
+			u1Byte	chnl =0 ;
+			_rtw_memset(&c, 0, sizeof(TXPWRTRACK_CFG));
+			ConfigureTxpowerTrack(pDM_Odm, &c);
+			ODM_ClearTxPowerTrackingState(pDM_Odm);
+			if (*c.ODM_TxPwrTrackSetPwr) {
+				(*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, BBSWING, ODM_RF_PATH_A, chnl);
+				(*c.ODM_TxPwrTrackSetPwr)(pDM_Odm, BBSWING, ODM_RF_PATH_B, chnl);
+			}
+		}
+	}
+		
+}
+
+
+u32 mp_join(PADAPTER padapter,u8 mode)
+{
+	WLAN_BSSID_EX bssid;
+	struct sta_info *psta;
+	u32 length;
+	u8 val8;
+	_irqL irqL;
+	s32 res = _SUCCESS;
+
+	struct mp_priv *pmppriv = &padapter->mppriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX		*pnetwork = (WLAN_BSSID_EX*)(&(pmlmeinfo->network));
+	
+#ifdef CONFIG_IOCTL_CFG80211		
+	struct wireless_dev *pwdev = padapter->rtw_wdev;
+	pwdev->iftype = NL80211_IFTYPE_ADHOC;
+#endif //#ifdef CONFIG_IOCTL_CFG80211
+	// 1. initialize a new WLAN_BSSID_EX
+	_rtw_memset(&bssid, 0, sizeof(WLAN_BSSID_EX));
+	DBG_8192C("%s ,pmppriv->network_macaddr=%x %x %x %x %x %x \n",__func__,
+				pmppriv->network_macaddr[0],pmppriv->network_macaddr[1],pmppriv->network_macaddr[2],pmppriv->network_macaddr[3],pmppriv->network_macaddr[4],pmppriv->network_macaddr[5]);
+	_rtw_memcpy(bssid.MacAddress, pmppriv->network_macaddr, ETH_ALEN);
+	
+	if( mode==WIFI_FW_ADHOC_STATE ){
+		bssid.Ssid.SsidLength = strlen("mp_pseudo_adhoc");
+		_rtw_memcpy(bssid.Ssid.Ssid, (u8*)"mp_pseudo_adhoc", bssid.Ssid.SsidLength);
+		bssid.InfrastructureMode = Ndis802_11IBSS;
+		bssid.NetworkTypeInUse = Ndis802_11DS;
+		bssid.IELength = 0;
+		bssid.Configuration.DSConfig=pmppriv->channel;
+
+	}else if(mode==WIFI_FW_STATION_STATE){
+		bssid.Ssid.SsidLength = strlen("mp_pseudo_STATION");
+		_rtw_memcpy(bssid.Ssid.Ssid, (u8*)"mp_pseudo_STATION", bssid.Ssid.SsidLength);
+		bssid.InfrastructureMode = Ndis802_11Infrastructure;
+		bssid.NetworkTypeInUse = Ndis802_11DS;
+		bssid.IELength = 0;
+	}
+	
+	length = get_WLAN_BSSID_EX_sz(&bssid);
+	if (length % 4)
+		bssid.Length = ((length >> 2) + 1) << 2; //round up to multiple of 4 bytes.
+	else
+		bssid.Length = length;
+
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+		goto end_of_mp_start_test;
+
+	//init mp_start_test status
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) {
+		rtw_disassoc_cmd(padapter, 500, _TRUE);
+		rtw_indicate_disconnect(padapter);
+		rtw_free_assoc_resources(padapter, 1);
+	}
+	pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
+	pmlmepriv->fw_state = WIFI_MP_STATE;
+
+	set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
+
+	//3 2. create a new psta for mp driver
+	//clear psta in the cur_network, if any
+	psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
+	if (psta) rtw_free_stainfo(padapter, psta);
+
+	psta = rtw_alloc_stainfo(&padapter->stapriv, bssid.MacAddress);
+	if (psta == NULL) {
+		RT_TRACE(_module_mp_, _drv_err_, ("mp_start_test: Can't alloc sta_info!\n"));
+		pmlmepriv->fw_state = pmppriv->prev_fw_state;
+		res = _FAIL;
+		goto end_of_mp_start_test;
+	}
+	set_fwstate(pmlmepriv,WIFI_ADHOC_MASTER_STATE);
+	//3 3. join psudo AdHoc
+	tgt_network->join_res = 1;
+	tgt_network->aid = psta->aid = 1;
+
+	_rtw_memcpy(&padapter->registrypriv.dev_network, &bssid, length);
+	rtw_update_registrypriv_dev_network(padapter);
+	_rtw_memcpy(&tgt_network->network,&padapter->registrypriv.dev_network, padapter->registrypriv.dev_network.Length);
+	_rtw_memcpy(pnetwork,&padapter->registrypriv.dev_network, padapter->registrypriv.dev_network.Length);
+
+	rtw_indicate_connect(padapter);
+	_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
+	set_fwstate(pmlmepriv,_FW_LINKED);
+
+end_of_mp_start_test:
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+	if(1) //(res == _SUCCESS)
+	{
+		// set MSR to WIFI_FW_ADHOC_STATE
+		if( mode==WIFI_FW_ADHOC_STATE ){
+
+			val8 = rtw_read8(padapter, MSR) & 0xFC; // 0x0102
+			val8 |= WIFI_FW_ADHOC_STATE;
+			rtw_write8(padapter, MSR, val8); // Link in ad hoc network
+		} 
+		else {
+			Set_MSR(padapter, WIFI_FW_STATION_STATE);
+
+			DBG_8192C("%s , pmppriv->network_macaddr =%x %x %x %x %x %x\n",__func__,
+						pmppriv->network_macaddr[0],pmppriv->network_macaddr[1],pmppriv->network_macaddr[2],pmppriv->network_macaddr[3],pmppriv->network_macaddr[4],pmppriv->network_macaddr[5]);
+
+			rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmppriv->network_macaddr);
+		}
+	}
+
+	return res;
+}
+//This function initializes the DUT to the MP test mode
+s32 mp_start_test(PADAPTER padapter)
+{
+	struct mp_priv *pmppriv = &padapter->mppriv;
+	s32 res = _SUCCESS;
+
+	padapter->registrypriv.mp_mode = 1;
+
+	//3 disable dynamic mechanism
+	disable_dm(padapter);
+	#ifdef CONFIG_RTL8814A
+	rtl8814_InitHalDm(padapter);
+	#endif /* CONFIG_RTL8814A */
+	#ifdef CONFIG_RTL8812A
+	rtl8812_InitHalDm(padapter);
+	#endif /* CONFIG_RTL8812A */
+	#ifdef CONFIG_RTL8723B
+	rtl8723b_InitHalDm(padapter);
+	#endif /* CONFIG_RTL8723B */
+	#ifdef CONFIG_RTL8703B
+	rtl8703b_InitHalDm(padapter);
+	#endif /* CONFIG_RTL8703B */
+	#ifdef CONFIG_RTL8192E
+	rtl8192e_InitHalDm(padapter);
+	#endif
+	#ifdef CONFIG_RTL8188F
+	rtl8188f_InitHalDm(padapter);
+	#endif
+
+	//3 0. update mp_priv
+
+	if (padapter->registrypriv.rf_config == RF_MAX_TYPE) {
+//		switch (phal->rf_type) {
+		switch (GET_RF_TYPE(padapter)) {
+			case RF_1T1R:
+				pmppriv->antenna_tx = ANTENNA_A;
+				pmppriv->antenna_rx = ANTENNA_A;
+				break;
+			case RF_1T2R:
+			default:
+				pmppriv->antenna_tx = ANTENNA_A;
+				pmppriv->antenna_rx = ANTENNA_AB;
+				break;
+			case RF_2T2R:
+			case RF_2T2R_GREEN:
+				pmppriv->antenna_tx = ANTENNA_AB;
+				pmppriv->antenna_rx = ANTENNA_AB;
+				break;
+			case RF_2T4R:
+				pmppriv->antenna_tx = ANTENNA_AB;
+				pmppriv->antenna_rx = ANTENNA_ABCD;
+				break;
+	}
+	}
+
+	mpt_ProStartTest(padapter);
+
+	mp_join(padapter,WIFI_FW_ADHOC_STATE);
+
+	return res;
+}
+//------------------------------------------------------------------------------
+//This function change the DUT from the MP test mode into normal mode
+void mp_stop_test(PADAPTER padapter)
+{
+	struct mp_priv *pmppriv = &padapter->mppriv;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct wlan_network *tgt_network = &pmlmepriv->cur_network;
+	struct sta_info *psta;
+
+	_irqL irqL;
+	
+	if(pmppriv->mode==MP_ON)
+	{
+	pmppriv->bSetTxPower=0;
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);	
+	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _FALSE)
+		goto end_of_mp_stop_test;
+
+	//3 1. disconnect psudo AdHoc
+	rtw_indicate_disconnect(padapter);
+
+	//3 2. clear psta used in mp test mode.
+//	rtw_free_assoc_resources(padapter, 1);
+	psta = rtw_get_stainfo(&padapter->stapriv, tgt_network->network.MacAddress);
+	if (psta) rtw_free_stainfo(padapter, psta);
+
+	//3 3. return to normal state (default:station mode)
+	pmlmepriv->fw_state = pmppriv->prev_fw_state; // WIFI_STATION_STATE;
+
+	//flush the cur_network
+	_rtw_memset(tgt_network, 0, sizeof(struct wlan_network));
+	
+	_clr_fwstate_(pmlmepriv, WIFI_MP_STATE);
+
+end_of_mp_stop_test:
+
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+	#ifdef CONFIG_RTL8812A
+	rtl8812_InitHalDm(padapter);
+	#endif
+	#ifdef CONFIG_RTL8723B
+	rtl8723b_InitHalDm(padapter);
+	#endif
+	#ifdef CONFIG_RTL8703B
+	rtl8703b_InitHalDm(padapter);
+	#endif
+	#ifdef CONFIG_RTL8192E
+	rtl8192e_InitHalDm(padapter);
+	#endif
+	#ifdef CONFIG_RTL8188F
+	rtl8188f_InitHalDm(padapter);
+	#endif
+	}
+}
+/*---------------------------hal\rtl8192c\MPT_Phy.c---------------------------*/
+#if 0
+//#ifdef CONFIG_USB_HCI
+static VOID mpt_AdjustRFRegByRateByChan92CU(PADAPTER pAdapter, u8 RateIdx, u8 Channel, u8 BandWidthID)
+{
+	u8		eRFPath;
+	u32		rfReg0x26;
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(pAdapter);
+
+
+	if (RateIdx < MPT_RATE_6M) {	// CCK rate,for 88cu
+		rfReg0x26 = 0xf400;
+	}
+	else if ((RateIdx >= MPT_RATE_6M) && (RateIdx <= MPT_RATE_54M)) {// OFDM rate,for 88cu
+		if ((4 == Channel) || (8 == Channel) || (12 == Channel))
+			rfReg0x26 = 0xf000;
+		else if ((5 == Channel) || (7 == Channel) || (13 == Channel) || (14 == Channel))
+			rfReg0x26 = 0xf400;
+		else
+			rfReg0x26 = 0x4f200;
+	}
+	else if ((RateIdx >= MPT_RATE_MCS0) && (RateIdx <= MPT_RATE_MCS15)) {// MCS 20M ,for 88cu // MCS40M rate,for 88cu
+
+		if (CHANNEL_WIDTH_20 == BandWidthID) {
+			if ((4 == Channel) || (8 == Channel))
+				rfReg0x26 = 0xf000;
+			else if ((5 == Channel) || (7 == Channel) || (13 == Channel) || (14 == Channel))
+				rfReg0x26 = 0xf400;
+			else
+				rfReg0x26 = 0x4f200;
+		}
+		else{
+			if ((4 == Channel) || (8 == Channel))
+				rfReg0x26 = 0xf000;
+			else if ((5 == Channel) || (7 == Channel))
+				rfReg0x26 = 0xf400;
+			else
+				rfReg0x26 = 0x4f200;
+		}
+	}
+
+//	RT_TRACE(COMP_CMD, DBG_LOUD, ("\n mpt_AdjustRFRegByRateByChan92CU():Chan:%d Rate=%d rfReg0x26:0x%08x\n",Channel, RateIdx,rfReg0x26));
+	for (eRFPath = 0; eRFPath < pHalData->NumTotalRFPath; eRFPath++) {
+		write_rfreg(pAdapter, eRFPath, RF_SYN_G2, rfReg0x26);
+	}
+}
+#endif
+/*-----------------------------------------------------------------------------
+ * Function:	mpt_SwitchRfSetting
+ *
+ * Overview:	Change RF Setting when we siwthc channel/rate/BW for MP.
+ *
+ * Input:       IN	PADAPTER				pAdapter
+ *
+ * Output:      NONE
+ *
+ * Return:      NONE
+ *
+ * Revised History:
+ * When			Who		Remark
+ * 01/08/2009	MHC		Suggestion from SD3 Willis for 92S series.
+ * 01/09/2009	MHC		Add CCK modification for 40MHZ. Suggestion from SD3.
+ *
+ *---------------------------------------------------------------------------*/
+static void mpt_SwitchRfSetting(PADAPTER pAdapter)
+{
+	hal_mpt_SwitchRfSetting(pAdapter);
+    }
+
+/*---------------------------hal\rtl8192c\MPT_Phy.c---------------------------*/
+/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
+static void MPT_CCKTxPowerAdjust(PADAPTER Adapter, BOOLEAN bInCH14)
+{
+	hal_mpt_CCKTxPowerAdjust(Adapter, bInCH14);
+}
+
+static void MPT_CCKTxPowerAdjustbyIndex(PADAPTER pAdapter, BOOLEAN beven)
+{
+	hal_mpt_CCKTxPowerAdjustbyIndex(pAdapter, beven);
+	}
+
+/*---------------------------hal\rtl8192c\MPT_HelperFunc.c---------------------------*/
+
+/*
+ * SetChannel
+ * Description
+ *	Use H2C command to change channel,
+ *	not only modify rf register, but also other setting need to be done.
+ */
+void SetChannel(PADAPTER pAdapter)
+{
+	hal_mpt_SetChannel(pAdapter);
+}
+
+/*
+ * Notice
+ *	Switch bandwitdth may change center frequency(channel)
+ */
+void SetBandwidth(PADAPTER pAdapter)
+{
+	hal_mpt_SetBandwidth(pAdapter);
+
+}
+
+void SetAntenna(PADAPTER pAdapter)
+{
+	hal_mpt_SetAntenna(pAdapter);
+}
+
+int SetTxPower(PADAPTER pAdapter)
+{
+
+	hal_mpt_SetTxPower(pAdapter);
+	return _TRUE;
+}
+
+void SetTxAGCOffset(PADAPTER pAdapter, u32 ulTxAGCOffset)
+{
+	u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D,tmpAGC;
+
+	TxAGCOffset_B = (ulTxAGCOffset&0x000000ff);
+	TxAGCOffset_C = ((ulTxAGCOffset&0x0000ff00)>>8);
+	TxAGCOffset_D = ((ulTxAGCOffset&0x00ff0000)>>16);
+
+	tmpAGC = (TxAGCOffset_D<<8 | TxAGCOffset_C<<4 | TxAGCOffset_B);
+	write_bbreg(pAdapter, rFPGA0_TxGainStage,
+			(bXBTxAGC|bXCTxAGC|bXDTxAGC), tmpAGC);
+}
+
+void SetDataRate(PADAPTER pAdapter)
+{
+	hal_mpt_SetDataRate(pAdapter);
+}
+
+void MP_PHY_SetRFPathSwitch(PADAPTER pAdapter ,BOOLEAN bMain)
+{
+
+	PHY_SetRFPathSwitch(pAdapter, bMain);
+
+}
+
+
+s32 SetThermalMeter(PADAPTER pAdapter, u8 target_ther)
+{
+	return hal_mpt_SetThermalMeter(pAdapter, target_ther);
+}
+
+static void TriggerRFThermalMeter(PADAPTER pAdapter)
+{
+	hal_mpt_TriggerRFThermalMeter(pAdapter);
+}
+
+static u8 ReadRFThermalMeter(PADAPTER pAdapter)
+{
+	return hal_mpt_ReadRFThermalMeter(pAdapter);
+}
+
+void GetThermalMeter(PADAPTER pAdapter, u8 *value)
+{
+	hal_mpt_GetThermalMeter(pAdapter, value);
+}
+
+void SetSingleCarrierTx(PADAPTER pAdapter, u8 bStart)
+{
+	PhySetTxPowerLevel(pAdapter);
+	hal_mpt_SetSingleCarrierTx(pAdapter, bStart);
+}
+
+void SetSingleToneTx(PADAPTER pAdapter, u8 bStart)
+{
+	PhySetTxPowerLevel(pAdapter);
+	hal_mpt_SetSingleToneTx(pAdapter, bStart);
+}
+
+void SetCarrierSuppressionTx(PADAPTER pAdapter, u8 bStart)
+{
+	PhySetTxPowerLevel(pAdapter);
+	hal_mpt_SetCarrierSuppressionTx(pAdapter, bStart);
+}
+
+void SetCCKContinuousTx(PADAPTER pAdapter, u8 bStart)
+{
+	PhySetTxPowerLevel(pAdapter);
+	hal_mpt_SetCCKContinuousTx(pAdapter, bStart);
+}
+
+void SetOFDMContinuousTx(PADAPTER pAdapter, u8 bStart)
+{
+	PhySetTxPowerLevel(pAdapter);
+	hal_mpt_SetOFDMContinuousTx(pAdapter, bStart);
+}/* mpt_StartOfdmContTx */
+
+void SetContinuousTx(PADAPTER pAdapter, u8 bStart)
+{
+	PhySetTxPowerLevel(pAdapter);
+	hal_mpt_SetContinuousTx(pAdapter, bStart);
+}
+
+
+void PhySetTxPowerLevel(PADAPTER pAdapter)
+{
+	struct mp_priv *pmp_priv = &pAdapter->mppriv;
+		
+	if (pmp_priv->bSetTxPower==0) // for NO manually set power index
+	{
+#ifdef CONFIG_RTL8188E	
+		PHY_SetTxPowerLevel8188E(pAdapter,pmp_priv->channel);
+#endif
+#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
+		PHY_SetTxPowerLevel8812(pAdapter,pmp_priv->channel);
+#endif
+#if defined(CONFIG_RTL8192E)
+		PHY_SetTxPowerLevel8192E(pAdapter,pmp_priv->channel);
+#endif
+#if defined(CONFIG_RTL8723B)
+		PHY_SetTxPowerLevel8723B(pAdapter,pmp_priv->channel);
+#endif
+#if defined(CONFIG_RTL8188F)
+		PHY_SetTxPowerLevel8188F(pAdapter, pmp_priv->channel);
+#endif
+	mpt_ProQueryCalTxPower(pAdapter,pmp_priv->antenna_tx);
+
+	}
+}
+
+//------------------------------------------------------------------------------
+static void dump_mpframe(PADAPTER padapter, struct xmit_frame *pmpframe)
+{
+	rtw_hal_mgnt_xmit(padapter, pmpframe);
+}
+
+static struct xmit_frame *alloc_mp_xmitframe(struct xmit_priv *pxmitpriv)
+{
+	struct xmit_frame	*pmpframe;
+	struct xmit_buf	*pxmitbuf;
+
+	if ((pmpframe = rtw_alloc_xmitframe(pxmitpriv)) == NULL)
+	{
+		return NULL;
+	}
+
+	if ((pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv)) == NULL)
+	{
+		rtw_free_xmitframe(pxmitpriv, pmpframe);
+		return NULL;
+	}
+
+	pmpframe->frame_tag = MP_FRAMETAG;
+
+	pmpframe->pxmitbuf = pxmitbuf;
+
+	pmpframe->buf_addr = pxmitbuf->pbuf;
+
+	pxmitbuf->priv_data = pmpframe;
+
+	return pmpframe;
+
+}
+
+static thread_return mp_xmit_packet_thread(thread_context context)
+{
+	struct xmit_frame	*pxmitframe;
+	struct mp_tx		*pmptx;
+	struct mp_priv	*pmp_priv;
+	struct xmit_priv	*pxmitpriv;
+	PADAPTER padapter;
+
+	pmp_priv = (struct mp_priv *)context;
+	pmptx = &pmp_priv->tx;
+	padapter = pmp_priv->papdater;
+	pxmitpriv = &(padapter->xmitpriv);
+	
+	thread_enter("RTW_MP_THREAD");
+
+	DBG_871X("%s:pkTx Start\n", __func__);
+	while (1) {
+		pxmitframe = alloc_mp_xmitframe(pxmitpriv);
+		if (pxmitframe == NULL) {
+			if (pmptx->stop ||
+				RTW_CANNOT_RUN(padapter)) {
+				goto exit;
+			}
+			else {
+				rtw_usleep_os(10);
+				continue;
+			}
+		}
+		_rtw_memcpy((u8 *)(pxmitframe->buf_addr+TXDESC_OFFSET), pmptx->buf, pmptx->write_size);
+		_rtw_memcpy(&(pxmitframe->attrib), &(pmptx->attrib), sizeof(struct pkt_attrib));
+
+		
+		rtw_usleep_os(padapter->mppriv.pktInterval);
+		dump_mpframe(padapter, pxmitframe);
+		
+		pmptx->sended++;
+		pmp_priv->tx_pktcount++;
+
+		if (pmptx->stop ||
+			RTW_CANNOT_RUN(padapter))
+			goto exit;
+		if ((pmptx->count != 0) &&
+		    (pmptx->count == pmptx->sended))
+			goto exit;
+
+		flush_signals_thread();
+	}
+
+exit:
+	//DBG_871X("%s:pkTx Exit\n", __func__);
+	rtw_mfree(pmptx->pallocated_buf, pmptx->buf_size);
+	pmptx->pallocated_buf = NULL;
+	pmptx->stop = 1;
+
+	thread_exit();
+}
+
+void fill_txdesc_for_mp(PADAPTER padapter, u8 *ptxdesc)
+{		
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	_rtw_memcpy(ptxdesc, pmp_priv->tx.desc, TXDESC_SIZE);
+}
+
+#if defined(CONFIG_RTL8188E) 
+void fill_tx_desc_8188e(PADAPTER padapter)
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	struct tx_desc *desc   = (struct tx_desc *)&(pmp_priv->tx.desc);
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+	u32	pkt_size = pattrib->last_txcmdsz;
+	s32 bmcast = IS_MCAST(pattrib->ra);
+// offset 0
+#if !defined(CONFIG_RTL8188E_SDIO) && !defined(CONFIG_PCI_HCI)
+	desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
+	desc->txdw0 |= cpu_to_le32(pkt_size & 0x0000FFFF); // packet size
+	desc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00FF0000); //32 bytes for TX Desc
+	if (bmcast) desc->txdw0 |= cpu_to_le32(BMC); // broadcast packet
+
+	desc->txdw1 |= cpu_to_le32((0x01 << 26) & 0xff000000);
+#endif
+
+	desc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x3F); //CAM_ID(MAC_ID)
+	desc->txdw1 |= cpu_to_le32((pattrib->qsel << QSEL_SHT) & 0x00001F00); // Queue Select, TID
+	desc->txdw1 |= cpu_to_le32((pattrib->raid << RATE_ID_SHT) & 0x000F0000); // Rate Adaptive ID
+	// offset 8
+	//	desc->txdw2 |= cpu_to_le32(AGG_BK);//AGG BK
+
+	desc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0x0fff0000);
+	desc->txdw4 |= cpu_to_le32(HW_SSN);
+		
+	desc->txdw4 |= cpu_to_le32(USERATE);
+	desc->txdw4 |= cpu_to_le32(DISDATAFB);
+
+	if( pmp_priv->preamble ){
+		if (pmp_priv->rateidx <=  MPT_RATE_54M)
+			desc->txdw4 |= cpu_to_le32(DATA_SHORT); // CCK Short Preamble
+	}
+
+	if (pmp_priv->bandwidth == CHANNEL_WIDTH_40)
+		desc->txdw4 |= cpu_to_le32(DATA_BW);
+
+	// offset 20
+	desc->txdw5 |= cpu_to_le32(pmp_priv->rateidx & 0x0000001F);
+
+	if( pmp_priv->preamble ){
+		if (pmp_priv->rateidx > MPT_RATE_54M)
+			desc->txdw5 |= cpu_to_le32(SGI); // MCS Short Guard Interval
+	}
+
+	desc->txdw5 |= cpu_to_le32(RTY_LMT_EN); // retry limit enable
+	desc->txdw5 |= cpu_to_le32(0x00180000); // DATA/RTS Rate Fallback Limit	
+		
+	
+}
+#endif
+
+#if defined(CONFIG_RTL8814A)
+void fill_tx_desc_8814a(PADAPTER padapter)
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	u8 *pDesc   = (u8 *)&(pmp_priv->tx.desc);
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+	
+	u32	pkt_size = pattrib->last_txcmdsz;
+	s32 bmcast = IS_MCAST(pattrib->ra);
+	u8 data_rate,pwr_status,offset;
+
+	//SET_TX_DESC_FIRST_SEG_8814A(pDesc, 1);
+	SET_TX_DESC_LAST_SEG_8814A(pDesc, 1);
+	//SET_TX_DESC_OWN_(pDesc, 1);
+	
+	SET_TX_DESC_PKT_SIZE_8814A(pDesc, pkt_size);
+	
+	offset = TXDESC_SIZE + OFFSET_SZ;		
+
+	SET_TX_DESC_OFFSET_8814A(pDesc, offset);
+#if defined(CONFIG_PCI_HCI)
+	SET_TX_DESC_PKT_OFFSET_8814A(pDesc, 0); /* 8814AE pkt_offset is 0 */
+#else
+	SET_TX_DESC_PKT_OFFSET_8814A(pDesc, 1);
+#endif
+	
+	if (bmcast) {
+		SET_TX_DESC_BMC_8814A(pDesc, 1);
+	}
+
+	SET_TX_DESC_MACID_8814A(pDesc, pattrib->mac_id);
+	SET_TX_DESC_RATE_ID_8814A(pDesc, pattrib->raid);
+	
+	//SET_TX_DESC_RATE_ID_8812(pDesc, RATEID_IDX_G);
+	SET_TX_DESC_QUEUE_SEL_8814A(pDesc,  pattrib->qsel);
+	//SET_TX_DESC_QUEUE_SEL_8812(pDesc,  QSLT_MGNT);
+
+	if ( pmp_priv->preamble ){
+		SET_TX_DESC_DATA_SHORT_8814A(pDesc, 1);
+	}
+	
+	if (!pattrib->qos_en) {
+		SET_TX_DESC_HWSEQ_EN_8814A(pDesc, 1); // Hw set sequence number
+	} else {
+		SET_TX_DESC_SEQ_8814A(pDesc, pattrib->seqnum);
+	}
+	
+	if (pmp_priv->bandwidth <= CHANNEL_WIDTH_160) {
+		SET_TX_DESC_DATA_BW_8814A(pDesc, pmp_priv->bandwidth);
+	} else {
+		DBG_871X("%s:Err: unknown bandwidth %d, use 20M\n", __func__,pmp_priv->bandwidth);
+		SET_TX_DESC_DATA_BW_8814A(pDesc, CHANNEL_WIDTH_20);
+	}
+
+	SET_TX_DESC_DISABLE_FB_8814A(pDesc, 1);
+	SET_TX_DESC_USE_RATE_8814A(pDesc, 1);
+	SET_TX_DESC_TX_RATE_8814A(pDesc, pmp_priv->rateidx);
+
+}
+#endif
+
+#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
+void fill_tx_desc_8812a(PADAPTER padapter)
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	u8 *pDesc   = (u8 *)&(pmp_priv->tx.desc);
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+	
+	u32	pkt_size = pattrib->last_txcmdsz;
+	s32 bmcast = IS_MCAST(pattrib->ra);
+	u8 data_rate,pwr_status,offset;
+
+	SET_TX_DESC_FIRST_SEG_8812(pDesc, 1);
+	SET_TX_DESC_LAST_SEG_8812(pDesc, 1);
+	SET_TX_DESC_OWN_8812(pDesc, 1);
+	
+	SET_TX_DESC_PKT_SIZE_8812(pDesc, pkt_size);
+	
+	offset = TXDESC_SIZE + OFFSET_SZ;		
+
+	SET_TX_DESC_OFFSET_8812(pDesc, offset);
+
+#if defined(CONFIG_PCI_HCI)
+	SET_TX_DESC_PKT_OFFSET_8812(pDesc, 0);
+#else
+	SET_TX_DESC_PKT_OFFSET_8812(pDesc, 1);
+#endif
+	if (bmcast) {
+		SET_TX_DESC_BMC_8812(pDesc, 1);
+	}
+
+	SET_TX_DESC_MACID_8812(pDesc, pattrib->mac_id);
+	SET_TX_DESC_RATE_ID_8812(pDesc, pattrib->raid);
+
+	//SET_TX_DESC_RATE_ID_8812(pDesc, RATEID_IDX_G);
+	SET_TX_DESC_QUEUE_SEL_8812(pDesc,  pattrib->qsel);
+	//SET_TX_DESC_QUEUE_SEL_8812(pDesc,  QSLT_MGNT);
+	
+	if (!pattrib->qos_en) {
+		SET_TX_DESC_HWSEQ_EN_8812(pDesc, 1); // Hw set sequence number
+	} else {
+		SET_TX_DESC_SEQ_8812(pDesc, pattrib->seqnum);
+	}
+	
+	if (pmp_priv->bandwidth <= CHANNEL_WIDTH_160) {
+		SET_TX_DESC_DATA_BW_8812(pDesc, pmp_priv->bandwidth);
+	} else {
+		DBG_871X("%s:Err: unknown bandwidth %d, use 20M\n", __func__,pmp_priv->bandwidth);
+		SET_TX_DESC_DATA_BW_8812(pDesc, CHANNEL_WIDTH_20);
+	}
+
+	SET_TX_DESC_DISABLE_FB_8812(pDesc, 1);
+	SET_TX_DESC_USE_RATE_8812(pDesc, 1);
+	SET_TX_DESC_TX_RATE_8812(pDesc, pmp_priv->rateidx);
+
+}
+#endif
+#if defined(CONFIG_RTL8192E)
+void fill_tx_desc_8192e(PADAPTER padapter)
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	u8 *pDesc	= (u8 *)&(pmp_priv->tx.desc);
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+		
+	u32 pkt_size = pattrib->last_txcmdsz;
+	s32 bmcast = IS_MCAST(pattrib->ra);
+	u8 data_rate,pwr_status,offset;
+	
+
+	SET_TX_DESC_PKT_SIZE_92E(pDesc, pkt_size);
+		
+	offset = TXDESC_SIZE + OFFSET_SZ;		
+	
+	SET_TX_DESC_OFFSET_92E(pDesc, offset);
+	#if defined(CONFIG_PCI_HCI) /* 8192EE */
+
+	SET_TX_DESC_PKT_OFFSET_92E(pDesc, 0); /* 8192EE pkt_offset is 0 */
+	#else /* 8192EU 8192ES */
+	SET_TX_DESC_PKT_OFFSET_92E(pDesc, 1);
+	#endif
+		
+	if (bmcast) {
+		SET_TX_DESC_BMC_92E(pDesc, 1);
+	}
+	
+	SET_TX_DESC_MACID_92E(pDesc, pattrib->mac_id);
+	SET_TX_DESC_RATE_ID_92E(pDesc, pattrib->raid);
+	
+	
+	SET_TX_DESC_QUEUE_SEL_92E(pDesc,  pattrib->qsel);
+	//SET_TX_DESC_QUEUE_SEL_8812(pDesc,  QSLT_MGNT);
+		
+	if (!pattrib->qos_en) {
+		SET_TX_DESC_EN_HWSEQ_92E(pDesc, 1);// Hw set sequence number
+		SET_TX_DESC_HWSEQ_SEL_92E(pDesc, pattrib->hw_ssn_sel);
+	} else {
+		SET_TX_DESC_SEQ_92E(pDesc, pattrib->seqnum);
+	}
+		
+	if ((pmp_priv->bandwidth == CHANNEL_WIDTH_20) || (pmp_priv->bandwidth == CHANNEL_WIDTH_40)) {
+		SET_TX_DESC_DATA_BW_92E(pDesc, pmp_priv->bandwidth);
+	} else {
+		DBG_871X("%s:Err: unknown bandwidth %d, use 20M\n", __func__,pmp_priv->bandwidth);
+		SET_TX_DESC_DATA_BW_92E(pDesc, CHANNEL_WIDTH_20);
+	}
+	
+	//SET_TX_DESC_DATA_SC_92E(pDesc, SCMapping_92E(padapter,pattrib));
+	
+	SET_TX_DESC_DISABLE_FB_92E(pDesc, 1);
+	SET_TX_DESC_USE_RATE_92E(pDesc, 1);
+	SET_TX_DESC_TX_RATE_92E(pDesc, pmp_priv->rateidx);
+
+}
+#endif
+
+#if defined(CONFIG_RTL8723B)
+void fill_tx_desc_8723b(PADAPTER padapter)
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+	u8 *ptxdesc = pmp_priv->tx.desc;
+
+	SET_TX_DESC_AGG_BREAK_8723B(ptxdesc, 1);
+	SET_TX_DESC_MACID_8723B(ptxdesc, pattrib->mac_id);
+	SET_TX_DESC_QUEUE_SEL_8723B(ptxdesc, pattrib->qsel);
+
+	SET_TX_DESC_RATE_ID_8723B(ptxdesc, pattrib->raid);
+	SET_TX_DESC_SEQ_8723B(ptxdesc, pattrib->seqnum);
+	SET_TX_DESC_HWSEQ_EN_8723B(ptxdesc, 1);
+	SET_TX_DESC_USE_RATE_8723B(ptxdesc, 1);
+	SET_TX_DESC_DISABLE_FB_8723B(ptxdesc, 1);
+
+	if (pmp_priv->preamble)
+		if (pmp_priv->rateidx <=  MPT_RATE_54M) {
+			SET_TX_DESC_DATA_SHORT_8723B(ptxdesc, 1);
+		}
+
+	if (pmp_priv->bandwidth == CHANNEL_WIDTH_40) {
+		SET_TX_DESC_DATA_BW_8723B(ptxdesc, 1);
+	}
+
+	SET_TX_DESC_TX_RATE_8723B(ptxdesc, pmp_priv->rateidx);
+
+	SET_TX_DESC_DATA_RATE_FB_LIMIT_8723B(ptxdesc, 0x1F);
+	SET_TX_DESC_RTS_RATE_FB_LIMIT_8723B(ptxdesc, 0xF);
+}
+#endif
+
+#if defined(CONFIG_RTL8703B)
+void fill_tx_desc_8703b(PADAPTER padapter) 
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+	u8 *ptxdesc = pmp_priv->tx.desc;
+
+	SET_TX_DESC_AGG_BREAK_8703B(ptxdesc, 1);
+	SET_TX_DESC_MACID_8703B(ptxdesc, pattrib->mac_id);
+	SET_TX_DESC_QUEUE_SEL_8703B(ptxdesc, pattrib->qsel);
+
+	SET_TX_DESC_RATE_ID_8703B(ptxdesc, pattrib->raid);
+	SET_TX_DESC_SEQ_8703B(ptxdesc, pattrib->seqnum);
+	SET_TX_DESC_HWSEQ_EN_8703B(ptxdesc, 1);
+	SET_TX_DESC_USE_RATE_8703B(ptxdesc, 1);
+	SET_TX_DESC_DISABLE_FB_8703B(ptxdesc, 1);
+
+	if (pmp_priv->preamble) {
+		if (pmp_priv->rateidx <=  MPT_RATE_54M)
+			SET_TX_DESC_DATA_SHORT_8703B(ptxdesc, 1);
+	}
+
+	if (pmp_priv->bandwidth == CHANNEL_WIDTH_40)
+		SET_TX_DESC_DATA_BW_8703B(ptxdesc, 1);
+
+	SET_TX_DESC_TX_RATE_8703B(ptxdesc, pmp_priv->rateidx);
+
+	SET_TX_DESC_DATA_RATE_FB_LIMIT_8703B(ptxdesc, 0x1F);
+	SET_TX_DESC_RTS_RATE_FB_LIMIT_8703B(ptxdesc, 0xF);
+}
+#endif
+
+#if defined(CONFIG_RTL8188F)
+void fill_tx_desc_8188f(PADAPTER padapter)
+{
+	struct mp_priv *pmp_priv = &padapter->mppriv;
+	struct pkt_attrib *pattrib = &(pmp_priv->tx.attrib);
+	u8 *ptxdesc = pmp_priv->tx.desc;
+
+	SET_TX_DESC_AGG_BREAK_8188F(ptxdesc, 1);
+	SET_TX_DESC_MACID_8188F(ptxdesc, pattrib->mac_id);
+	SET_TX_DESC_QUEUE_SEL_8188F(ptxdesc, pattrib->qsel);
+
+	SET_TX_DESC_RATE_ID_8188F(ptxdesc, pattrib->raid);
+	SET_TX_DESC_SEQ_8188F(ptxdesc, pattrib->seqnum);
+	SET_TX_DESC_HWSEQ_EN_8188F(ptxdesc, 1);
+	SET_TX_DESC_USE_RATE_8188F(ptxdesc, 1);
+	SET_TX_DESC_DISABLE_FB_8188F(ptxdesc, 1);
+
+	if (pmp_priv->preamble)
+		if (pmp_priv->rateidx <=  MPT_RATE_54M) 
+			SET_TX_DESC_DATA_SHORT_8188F(ptxdesc, 1);
+
+	if (pmp_priv->bandwidth == CHANNEL_WIDTH_40) 
+		SET_TX_DESC_DATA_BW_8188F(ptxdesc, 1);
+
+	SET_TX_DESC_TX_RATE_8188F(ptxdesc, pmp_priv->rateidx);
+
+	SET_TX_DESC_DATA_RATE_FB_LIMIT_8188F(ptxdesc, 0x1F);
+	SET_TX_DESC_RTS_RATE_FB_LIMIT_8188F(ptxdesc, 0xF);
+}
+#endif
+
+static void Rtw_MPSetMacTxEDCA(PADAPTER padapter)
+{
+
+	rtw_write32(padapter, 0x508 , 0x00a422); //Disable EDCA BE Txop for MP pkt tx adjust Packet interval
+	//DBG_871X("%s:write 0x508~~~~~~ 0x%x\n", __func__,rtw_read32(padapter, 0x508));
+	PHY_SetMacReg(padapter, 0x458 ,bMaskDWord , 0x0);
+	//DBG_8192C("%s()!!!!! 0x460 = 0x%x\n" ,__func__,PHY_QueryBBReg(padapter, 0x460, bMaskDWord));
+	PHY_SetMacReg(padapter, 0x460 ,bMaskLWord , 0x0);//fast EDCA queue packet interval & time out vaule
+	//PHY_SetMacReg(padapter, ODM_EDCA_VO_PARAM ,bMaskLWord , 0x431C);
+	//PHY_SetMacReg(padapter, ODM_EDCA_BE_PARAM ,bMaskLWord , 0x431C);
+	//PHY_SetMacReg(padapter, ODM_EDCA_BK_PARAM ,bMaskLWord , 0x431C);
+	DBG_8192C("%s()!!!!! 0x460 = 0x%x\n" ,__func__,PHY_QueryBBReg(padapter, 0x460, bMaskDWord));
+
+}
+
+void SetPacketTx(PADAPTER padapter)
+{
+	u8 *ptr, *pkt_start, *pkt_end,*fctrl;
+	u32 pkt_size,offset,startPlace,i;
+	struct rtw_ieee80211_hdr *hdr;
+	u8 payload;
+	s32 bmcast;
+	struct pkt_attrib *pattrib;
+	struct mp_priv *pmp_priv;
+
+	pmp_priv = &padapter->mppriv;
+	
+	if (pmp_priv->tx.stop) return;
+	pmp_priv->tx.sended = 0;
+	pmp_priv->tx.stop = 0;
+	pmp_priv->tx_pktcount = 0;
+
+	//3 1. update_attrib()
+	pattrib = &pmp_priv->tx.attrib;
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+	bmcast = IS_MCAST(pattrib->ra);
+	if (bmcast) {
+		pattrib->mac_id = 1;
+		pattrib->psta = rtw_get_bcmc_stainfo(padapter);
+	} else {
+		pattrib->mac_id = 0;
+		pattrib->psta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
+	}
+	pattrib->mbssid = 0;
+	
+	pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->pktlen;
+
+	//3 2. allocate xmit buffer
+	pkt_size = pattrib->last_txcmdsz;
+
+	if (pmp_priv->tx.pallocated_buf)
+		rtw_mfree(pmp_priv->tx.pallocated_buf, pmp_priv->tx.buf_size);
+	pmp_priv->tx.write_size = pkt_size;
+	pmp_priv->tx.buf_size = pkt_size + XMITBUF_ALIGN_SZ;
+	pmp_priv->tx.pallocated_buf = rtw_zmalloc(pmp_priv->tx.buf_size);
+	if (pmp_priv->tx.pallocated_buf == NULL) {
+		DBG_871X("%s: malloc(%d) fail!!\n", __func__, pmp_priv->tx.buf_size);
+		return;
+	}
+	pmp_priv->tx.buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pmp_priv->tx.pallocated_buf), XMITBUF_ALIGN_SZ);
+	ptr = pmp_priv->tx.buf;
+
+	_rtw_memset(pmp_priv->tx.desc, 0, TXDESC_SIZE);
+	pkt_start = ptr;
+	pkt_end = pkt_start + pkt_size;
+
+	//3 3. init TX descriptor
+#if defined(CONFIG_RTL8188E)
+	if(IS_HARDWARE_TYPE_8188E(padapter))
+		fill_tx_desc_8188e(padapter);
+#endif
+
+#if defined(CONFIG_RTL8814A)
+	if(IS_HARDWARE_TYPE_8814A(padapter)) 
+		fill_tx_desc_8814a(padapter);
+#endif /* defined(CONFIG_RTL8814A) */
+
+#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
+	if(IS_HARDWARE_TYPE_8812(padapter) || IS_HARDWARE_TYPE_8821(padapter)) 
+		fill_tx_desc_8812a(padapter);
+#endif
+
+#if defined(CONFIG_RTL8192E)
+	if(IS_HARDWARE_TYPE_8192E(padapter))
+		fill_tx_desc_8192e(padapter);
+#endif
+#if defined(CONFIG_RTL8723B)
+	if(IS_HARDWARE_TYPE_8723B(padapter))
+		fill_tx_desc_8723b(padapter);
+#endif
+#if defined(CONFIG_RTL8703B)
+	if (IS_HARDWARE_TYPE_8703B(padapter))
+		fill_tx_desc_8703b(padapter);
+#endif
+	
+#if defined(CONFIG_RTL8188F)
+	if (IS_HARDWARE_TYPE_8188F(padapter))
+		fill_tx_desc_8188f(padapter);
+#endif
+
+	//3 4. make wlan header, make_wlanhdr()
+	hdr = (struct rtw_ieee80211_hdr *)pkt_start;
+	SetFrameSubType(&hdr->frame_ctl, pattrib->subtype);
+	//
+	SetFrDs(&hdr->frame_ctl);
+	_rtw_memcpy(hdr->addr1, pattrib->dst, ETH_ALEN); // DA
+	_rtw_memcpy(hdr->addr2, pattrib->src, ETH_ALEN); // SA
+	_rtw_memcpy(hdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN); // RA, BSSID
+
+	//3 5. make payload
+	ptr = pkt_start + pattrib->hdrlen;
+
+	switch (pmp_priv->tx.payload) {
+		case 0:
+			payload = 0x00;
+			break;
+		case 1:
+			payload = 0x5a;
+			break;
+		case 2:
+			payload = 0xa5;
+			break;
+		case 3:
+			payload = 0xff;
+			break;
+		default:
+			payload = 0x00;
+			break;
+	}
+	pmp_priv->TXradomBuffer = rtw_zmalloc(4096);
+	if(pmp_priv->TXradomBuffer == NULL)
+	{
+		DBG_871X("mp create random buffer fail!\n");
+		goto exit;
+	}
+	
+	
+	for(i=0;i<4096;i++)
+		pmp_priv->TXradomBuffer[i] = rtw_random32() %0xFF;
+	
+	//startPlace = (u32)(rtw_random32() % 3450);
+	_rtw_memcpy(ptr, pmp_priv->TXradomBuffer,pkt_end - ptr);
+	//_rtw_memset(ptr, payload, pkt_end - ptr);
+	rtw_mfree(pmp_priv->TXradomBuffer,4096);
+	
+	//3 6. start thread
+#ifdef PLATFORM_LINUX
+	pmp_priv->tx.PktTxThread = kthread_run(mp_xmit_packet_thread, pmp_priv, "RTW_MP_THREAD");
+	if (IS_ERR(pmp_priv->tx.PktTxThread))
+		DBG_871X("Create PktTx Thread Fail !!!!!\n");
+#endif
+#ifdef PLATFORM_FREEBSD
+{
+	struct proc *p;
+	struct thread *td;
+	pmp_priv->tx.PktTxThread = kproc_kthread_add(mp_xmit_packet_thread, pmp_priv,
+					&p, &td, RFHIGHPID, 0, "MPXmitThread", "MPXmitThread");
+
+	if (pmp_priv->tx.PktTxThread < 0)
+		DBG_871X("Create PktTx Thread Fail !!!!!\n");
+}
+#endif
+
+	Rtw_MPSetMacTxEDCA(padapter);
+exit:
+	return;
+}
+
+void SetPacketRx(PADAPTER pAdapter, u8 bStartRx, u8 bAB)
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(pAdapter);
+	struct mp_priv *pmppriv = &pAdapter->mppriv;
+	u8	type;
+	type = _HW_STATE_AP_;
+	if(bStartRx)
+	{
+#ifdef CONFIG_RTL8723B
+		PHY_SetMacReg(pAdapter, 0xe70, BIT23|BIT22, 0x3);// Power on adc  (in RX_WAIT_CCA state)
+		write_bbreg(pAdapter, 0xa01, BIT0, bDisable);// improve Rx performance by jerry	
+#endif
+		if(	pmppriv->bSetRxBssid == _TRUE ){
+			//pHalData->ReceiveConfig = RCR_APM | RCR_AM | RCR_AB |RCR_CBSSID_DATA| RCR_CBSSID_BCN| RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYST_RXFF;	 
+			pHalData->ReceiveConfig = RCR_AAP | RCR_APM | RCR_AM | RCR_AB |RCR_AMF | RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL | RCR_APP_MIC | RCR_APP_PHYST_RXFF  ;
+			pHalData->ReceiveConfig |= ACRC32; 
+			
+			DBG_8192C("%s , pmppriv->network_macaddr =%x %x %x %x %x %x\n",__func__,
+								pmppriv->network_macaddr[0],pmppriv->network_macaddr[1],pmppriv->network_macaddr[2],pmppriv->network_macaddr[3],pmppriv->network_macaddr[4],pmppriv->network_macaddr[5]);
+			//Set_MSR(pAdapter, WIFI_FW_AP_STATE);
+			//rtw_hal_set_hwreg(pAdapter, HW_VAR_BSSID, pmppriv->network_macaddr);
+			//rtw_hal_set_hwreg(pAdapter, HW_VAR_SET_OPMODE, (u8 *)(&type));
+		}
+		else
+		{
+		pHalData->ReceiveConfig = AAP | APM | AM | AB | APP_ICV | ADF | AMF | HTC_LOC_CTRL | APP_MIC | APP_PHYSTS;
+		pHalData->ReceiveConfig |= ACRC32;
+		rtw_write32(pAdapter, REG_RCR, pHalData->ReceiveConfig);
+		// Accept all data frames
+		rtw_write16(pAdapter, REG_RXFLTMAP2, 0xFFFF);
+		// Accept CRC error and destination address
+		}
+	}
+	else
+	{
+#ifdef CONFIG_RTL8723B
+		PHY_SetMacReg(pAdapter, 0xe70, BIT23|BIT22, 0x00);// Power off adc  (in RX_WAIT_CCA state)
+		write_bbreg(pAdapter, 0xa01, BIT0, bEnable);// improve Rx performance by jerry	
+#endif
+		rtw_write32(pAdapter, REG_RCR, 0);
+	}
+
+	if (bAB)
+		rtw_write32(pAdapter, REG_RCR, rtw_read32(pAdapter, REG_RCR)|RCR_AB);
+	else
+		rtw_write32(pAdapter, REG_RCR, rtw_read32(pAdapter, REG_RCR)&(~RCR_AB));
+}
+
+void ResetPhyRxPktCount(PADAPTER pAdapter)
+{
+	u32 i, phyrx_set = 0;
+
+	for (i = 0; i <= 0xF; i++) {
+		phyrx_set = 0;
+		phyrx_set |= _RXERR_RPT_SEL(i);	//select
+		phyrx_set |= RXERR_RPT_RST;	// set counter to zero
+		rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
+	}
+}
+
+static u32 GetPhyRxPktCounts(PADAPTER pAdapter, u32 selbit)
+{
+	//selection
+	u32 phyrx_set = 0, count = 0;
+
+	phyrx_set = _RXERR_RPT_SEL(selbit & 0xF);
+	rtw_write32(pAdapter, REG_RXERR_RPT, phyrx_set);
+
+	//Read packet count
+	count = rtw_read32(pAdapter, REG_RXERR_RPT) & RXERR_COUNTER_MASK;
+
+	return count;
+}
+
+u32 GetPhyRxPktReceived(PADAPTER pAdapter)
+{
+	u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
+
+	OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_OK);
+	CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_OK);
+	HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_OK);
+
+	return OFDM_cnt + CCK_cnt + HT_cnt;
+}
+
+u32 GetPhyRxPktCRC32Error(PADAPTER pAdapter)
+{
+	u32 OFDM_cnt = 0, CCK_cnt = 0, HT_cnt = 0;
+
+	OFDM_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_OFDM_MPDU_FAIL);
+	CCK_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_CCK_MPDU_FAIL);
+	HT_cnt = GetPhyRxPktCounts(pAdapter, RXERR_TYPE_HT_MPDU_FAIL);
+
+	return OFDM_cnt + CCK_cnt + HT_cnt;
+}
+
+//reg 0x808[9:0]: FFT data x
+//reg 0x808[22]:  0  -->  1  to get 1 FFT data y
+//reg 0x8B4[15:0]: FFT data y report
+static u32 rtw_GetPSDData(PADAPTER pAdapter, u32 point)
+{
+	u32 psd_val=0;
+	
+#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A) || defined(CONFIG_RTL8814A)
+	u16 psd_reg = 0x910;
+	u16 psd_regL= 0xF44;
+#else	
+	u16 psd_reg = 0x808;
+	u16 psd_regL= 0x8B4;
+#endif
+
+	psd_val = rtw_read32(pAdapter, psd_reg);
+
+	psd_val &= 0xFFBFFC00;
+	psd_val |= point;
+
+	rtw_write32(pAdapter, psd_reg, psd_val);
+	rtw_mdelay_os(1);
+	psd_val |= 0x00400000;
+
+	rtw_write32(pAdapter, psd_reg, psd_val);
+	rtw_mdelay_os(1);
+
+	psd_val = rtw_read32(pAdapter, psd_regL);
+	psd_val &= 0x0000FFFF;
+
+	return psd_val;
+}
+
+/*
+ * pts	start_point_min		stop_point_max
+ * 128	64			64 + 128 = 192
+ * 256	128			128 + 256 = 384
+ * 512	256			256 + 512 = 768
+ * 1024	512			512 + 1024 = 1536
+ *
+ */
+u32 mp_query_psd(PADAPTER pAdapter, u8 *data)
+{
+	u32 i, psd_pts=0, psd_start=0, psd_stop=0;
+	u32 psd_data=0;
+
+
+#ifdef PLATFORM_LINUX
+	if (!netif_running(pAdapter->pnetdev)) {
+		RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! interface not opened!\n"));
+		return 0;
+	}
+#endif
+
+	if (check_fwstate(&pAdapter->mlmepriv, WIFI_MP_STATE) == _FALSE) {
+		RT_TRACE(_module_mp_, _drv_warning_, ("mp_query_psd: Fail! not in MP mode!\n"));
+		return 0;
+	}
+
+	if (strlen(data) == 0) { //default value
+		psd_pts = 128;
+		psd_start = 64;
+		psd_stop = 128;   
+	} else {
+		sscanf(data, "pts=%d,start=%d,stop=%d", &psd_pts, &psd_start, &psd_stop);
+	}
+	
+	data[0]='\0';
+
+	i = psd_start;
+	while (i < psd_stop)
+	{
+		if (i >= psd_pts) {
+			psd_data = rtw_GetPSDData(pAdapter, i-psd_pts);
+		} else {
+			psd_data = rtw_GetPSDData(pAdapter, i);
+		}
+		sprintf(data, "%s%x ", data, psd_data);
+		i++;
+	}
+
+	#ifdef CONFIG_LONG_DELAY_ISSUE
+	rtw_msleep_os(100);
+	#else
+	rtw_mdelay_os(100);
+	#endif
+
+	return strlen(data)+1;
+}
+
+
+#if 0
+void _rtw_mp_xmit_priv (struct xmit_priv *pxmitpriv)
+{
+	   int i,res;
+	  _adapter *padapter = pxmitpriv->adapter;
+	struct xmit_frame	*pxmitframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
+	struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+	
+	u32 max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+	u32 num_xmit_extbuf = NR_XMIT_EXTBUFF;
+	if(padapter->registrypriv.mp_mode ==0)
+	{
+		max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+		num_xmit_extbuf = NR_XMIT_EXTBUFF;
+	}
+	else
+	{
+			max_xmit_extbuf_size = 6000;
+			num_xmit_extbuf = 8;
+	}
+
+	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+	for(i=0; i<num_xmit_extbuf; i++)
+	{
+		rtw_os_xmit_resource_free(padapter, pxmitbuf,(max_xmit_extbuf_size + XMITBUF_ALIGN_SZ), _FALSE);
+		
+		pxmitbuf++;
+	}
+
+	if(pxmitpriv->pallocated_xmit_extbuf) {
+		rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+	}
+
+	if(padapter->registrypriv.mp_mode ==0)
+	{
+			max_xmit_extbuf_size = 6000;
+			num_xmit_extbuf = 8;
+	}
+	else
+	{
+		max_xmit_extbuf_size = MAX_XMIT_EXTBUF_SZ;
+		num_xmit_extbuf = NR_XMIT_EXTBUFF;
+	}
+	
+	// Init xmit extension buff
+	_rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
+
+	pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(num_xmit_extbuf * sizeof(struct xmit_buf) + 4);
+	
+	if (pxmitpriv->pallocated_xmit_extbuf  == NULL){
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("alloc xmit_extbuf fail!\n"));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmit_extbuf), 4);
+
+	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+
+	for (i = 0; i < num_xmit_extbuf; i++)
+	{
+		_rtw_init_listhead(&pxmitbuf->list);
+
+		pxmitbuf->priv_data = NULL;
+		pxmitbuf->padapter = padapter;
+		pxmitbuf->buf_tag = XMITBUF_MGNT;
+
+		if((res=rtw_os_xmit_resource_alloc(padapter, pxmitbuf,max_xmit_extbuf_size + XMITBUF_ALIGN_SZ, _TRUE)) == _FAIL) {
+			res= _FAIL;
+			goto exit;
+		}
+		
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxmitbuf->phead = pxmitbuf->pbuf;
+		pxmitbuf->pend = pxmitbuf->pbuf + max_xmit_extbuf_size;
+		pxmitbuf->len = 0;
+		pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+#endif
+
+		rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
+		#ifdef DBG_XMIT_BUF_EXT
+		pxmitbuf->no=i;
+		#endif
+		pxmitbuf++;
+		
+	}
+
+	pxmitpriv->free_xmit_extbuf_cnt = num_xmit_extbuf;
+
+exit:
+	;
+}
+#endif
+
+
+ULONG getPowerDiffByRate8188E(
+	IN	PADAPTER	pAdapter,
+	IN	u1Byte		CurrChannel,
+	IN	ULONG		RfPath
+	)
+{
+	PMPT_CONTEXT			pMptCtx = &(pAdapter->mppriv.MptCtx);
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(pAdapter);
+	ULONG	PwrGroup=0;
+	ULONG	TxPower=0, Limit=0;
+	ULONG	Pathmapping = (RfPath == ODM_RF_PATH_A?0:8);
+
+	switch(pHalData->EEPROMRegulatory)
+	{
+		case 0: // driver-defined maximum power offset for longer communication range
+				// refer to power by rate table
+			PwrGroup = 0;
+			Limit = 0xff;
+			break;
+		case 1: // Power-limit table-defined maximum power offset range 
+				// choosed by min(power by rate, power limit).
+			{
+				if(pHalData->pwrGroupCnt == 1)
+					PwrGroup = 0;
+				if(pHalData->pwrGroupCnt >= 3)
+				{
+					if(CurrChannel <= 3)
+						PwrGroup = 0;
+					else if(CurrChannel >= 4 && CurrChannel <= 9)
+						PwrGroup = 1;
+					else if(CurrChannel > 9)
+						PwrGroup = 2;
+						
+					if(pHalData->CurrentChannelBW == CHANNEL_WIDTH_20)
+						PwrGroup++;
+					else
+						PwrGroup+=4;
+				}
+				Limit = 0xff;
+			}
+			break;
+		case 2: // not support power offset by rate.
+				// don't increase any power diff
+			PwrGroup = 0;
+			Limit = 0;
+			break;
+		default:
+			PwrGroup = 0;
+			Limit = 0xff;
+			break;
+	}
+
+
+	{
+		switch(pMptCtx->MptRateIndex)
+		{
+			case MPT_RATE_1M:
+			case MPT_RATE_2M:
+			case MPT_RATE_55M:
+			case MPT_RATE_11M:
+				//CCK rates, don't add any tx power index.
+				//RT_DISP(FPHY, PHY_TXPWR,("CCK rates!\n"));
+				break;
+			case MPT_RATE_6M:	//0xe00 [31:0] = 18M,12M,09M,06M
+				TxPower += ((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0+Pathmapping])&0xff);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x, OFDM 6M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0], TxPower));
+				break;
+			case MPT_RATE_9M:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0+Pathmapping])&0xff00)>>8);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x, OFDM 9M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0], TxPower));
+				break;
+			case MPT_RATE_12M:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0+Pathmapping])&0xff0000)>>16);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x, OFDM 12M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0], TxPower));
+				break;
+			case MPT_RATE_18M:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0+Pathmapping])&0xff000000)>>24);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x, OFDM 24M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][0], TxPower));
+				break;
+			case MPT_RATE_24M:	//0xe04[31:0] = 54M,48M,36M,24M
+				TxPower += ((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1+Pathmapping])&0xff);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x, OFDM 24M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1], TxPower));
+				break;
+			case MPT_RATE_36M:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1+Pathmapping])&0xff00)>>8);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x, OFDM 36M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1], TxPower));
+				break;
+			case MPT_RATE_48M:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1+Pathmapping])&0xff0000)>>16);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x, OFDM 48M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1], TxPower));
+				break;
+			case MPT_RATE_54M:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1+Pathmapping])&0xff000000)>>24);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x, OFDM 54M, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][1], TxPower));
+				break;
+			case MPT_RATE_MCS0: //0xe10[31:0]= MCS=03,02,01,00
+				TxPower += ((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2+Pathmapping])&0xff);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x, MCS0, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2], TxPower));
+				break;
+			case MPT_RATE_MCS1:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2+Pathmapping])&0xff00)>>8);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x, MCS1, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2], TxPower));
+				break;
+			case MPT_RATE_MCS2:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2+Pathmapping])&0xff0000)>>16);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x, MCS2, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2], TxPower));
+				break;
+			case MPT_RATE_MCS3:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2+Pathmapping])&0xff000000)>>24);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x, MCS3, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][2], TxPower));
+				break;
+			case MPT_RATE_MCS4: //0xe14[31:0]= MCS=07,06,05,04
+				TxPower += ((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3+Pathmapping])&0xff);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x, MCS4, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3], TxPower));
+				break;
+			case MPT_RATE_MCS5:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3+Pathmapping])&0xff00)>>8);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x, MCS5, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3], TxPower));
+				break;
+			case MPT_RATE_MCS6:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3+Pathmapping])&0xff0000)>>16);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x, MCS6, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3], TxPower));
+				break;
+			case MPT_RATE_MCS7:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3+Pathmapping])&0xff000000)>>24);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x, MCS7, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][3], TxPower));
+				break;
+				
+			case MPT_RATE_MCS8: //0xe18[31:0]= MCS=11,10,09,08
+				TxPower += ((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4+Pathmapping])&0xff);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x, MCS8, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4], TxPower));
+				break;
+			case MPT_RATE_MCS9:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4+Pathmapping])&0xff00)>>8);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x, MCS9, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4], TxPower));
+				break;
+			case MPT_RATE_MCS10:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4+Pathmapping])&0xff0000)>>16);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x, MCS10, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4], TxPower));
+				break;
+			case MPT_RATE_MCS11:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4+Pathmapping])&0xff000000)>>24);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x, MCS11, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][4], TxPower));
+				break;
+			case MPT_RATE_MCS12:	//0xe1c[31:0]= MCS=15,14,13,12
+				TxPower += ((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5+Pathmapping])&0xff);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x, MCS12, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5], TxPower));
+				break;
+			case MPT_RATE_MCS13:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5+Pathmapping])&0xff00)>>8);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x, MCS13, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5], TxPower));
+				break;
+			case MPT_RATE_MCS14:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5+Pathmapping])&0xff0000)>>16);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x, MCS14, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5], TxPower));
+				break;
+			case MPT_RATE_MCS15:
+				TxPower += (((pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5+Pathmapping])&0xff000000)>>24);
+				//RT_DISP(FPHY, PHY_TXPWR,("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x, MCS15, TxPower = %d\n", 
+				//	PwrGroup, pHalData->MCSTxPowerLevelOriginalOffset[PwrGroup][5], TxPower));
+				break;
+			default:
+				break;
+		}
+	}
+
+	if(TxPower > Limit)
+		TxPower = Limit;
+
+	return TxPower;
+}
+
+
+
+static	ULONG
+mpt_ProQueryCalTxPower_8188E(
+	IN	PADAPTER		pAdapter,
+	IN	u1Byte			RfPath	
+	)
+{
+	HAL_DATA_TYPE		*pHalData = GET_HAL_DATA(pAdapter);
+	u1Byte				TxCount=TX_1S, i = 0;	//default set to 1S
+	//PMGNT_INFO			pMgntInfo = &(pAdapter->MgntInfo); 
+	ULONG				TxPower = 1, PwrGroup=0, PowerDiffByRate=0;
+	ULONG				TxPowerCCK = 1, TxPowerOFDM = 1, TxPowerBW20 = 1, TxPowerBW40 = 1 ; 
+	PMPT_CONTEXT		pMptCtx = &(pAdapter->mppriv.MptCtx);
+	u1Byte				CurrChannel = pHalData->CurrentChannel;
+	u1Byte				index = (CurrChannel -1);	
+	u1Byte				rf_path=(RfPath), rfPath;
+	u1Byte				limit = 0, rate = 0;
+
+	if(HAL_IsLegalChannel(pAdapter, CurrChannel) == FALSE)
+	{
+		CurrChannel = 1;
+	}	
+	
+	if(pMptCtx->MptRateIndex <= MPT_RATE_11M )
+	{
+		TxPower = pHalData->Index24G_CCK_Base[rf_path][index];	
+	}
+	else if(pMptCtx->MptRateIndex >= MPT_RATE_6M &&
+		pMptCtx->MptRateIndex <= MPT_RATE_54M )
+	{				
+		TxPower = pHalData->Index24G_BW40_Base[rf_path][index];
+	}
+	else if(pMptCtx->MptRateIndex >= MPT_RATE_MCS0 &&
+		pMptCtx->MptRateIndex <= MPT_RATE_MCS7 )
+	{
+		TxPower = pHalData->Index24G_BW40_Base[rf_path][index];
+	}
+	
+	//RT_DISP(FPHY, PHY_TXPWR, ("HT40 rate(%d) Tx power(RF-%c) = 0x%x\n", pMptCtx->MptRateIndex, ((rf_path==0)?'A':'B'), TxPower));
+
+
+	if(pMptCtx->MptRateIndex >= MPT_RATE_6M &&
+		pMptCtx->MptRateIndex <= MPT_RATE_54M )
+	{
+		TxPower += pHalData->OFDM_24G_Diff[rf_path][TxCount];
+		///RT_DISP(FPHY, PHY_TXPWR, ("+OFDM_PowerDiff(RF-%c) = 0x%x\n", ((rf_path==0)?'A':'B'), 
+		//	pHalData->OFDM_24G_Diff[rf_path][TxCount]));
+	}
+
+	if(pMptCtx->MptRateIndex >= MPT_RATE_MCS0)
+	{
+		if (pHalData->CurrentChannelBW == CHANNEL_WIDTH_20)
+		{
+			TxPower += pHalData->BW20_24G_Diff[rf_path][TxCount];
+		//	RT_DISP(FPHY, PHY_TXPWR, ("+HT20_PowerDiff(RF-%c) = 0x%x\n", ((rf_path==0)?'A':'B'), 
+		//		pHalData->BW20_24G_Diff[rf_path][TxCount]));
+		}
+	}
+
+
+#ifdef ENABLE_POWER_BY_RATE
+	PowerDiffByRate = getPowerDiffByRate8188E(pAdapter, CurrChannel, RfPath);
+#else	
+	PowerDiffByRate = 0;
+#endif
+
+	// 2012/11/02 Awk: add power limit mechansim
+	if( pMptCtx->MptRateIndex <= MPT_RATE_11M )
+	{
+		rate = MGN_1M;
+	}
+	else if(pMptCtx->MptRateIndex >= MPT_RATE_6M &&
+		pMptCtx->MptRateIndex <= MPT_RATE_54M )
+	{				
+		rate = MGN_54M;
+	}
+	else if(pMptCtx->MptRateIndex >= MPT_RATE_MCS0 &&
+		pMptCtx->MptRateIndex <= MPT_RATE_MCS7 )
+	{
+		rate = MGN_MCS7;
+	}
+
+	limit = (u8)PHY_GetTxPowerLimit(pAdapter, pMptCtx->RegTxPwrLimit, 
+								   pHalData->CurrentBandType, 
+								   pHalData->CurrentChannelBW,RfPath, 
+								   rate, CurrChannel);
+
+	//RT_DISP(FPHY, PHY_TXPWR, ("+PowerDiffByRate(RF-%c) = 0x%x\n", ((rf_path==0)?'A':'B'), 
+	//	PowerDiffByRate));
+	TxPower += PowerDiffByRate;
+	//RT_DISP(FPHY, PHY_TXPWR, ("PowerDiffByRate limit value(RF-%c) = %d\n", ((rf_path==0)?'A':'B'), 
+	//	limit));
+
+	TxPower +=  limit > (s8) PowerDiffByRate ? PowerDiffByRate : limit;
+
+	return TxPower; 
+}
+
+
+u8 
+MptToMgntRate(
+	IN	ULONG	MptRateIdx
+	)
+{
+// Mapped to MGN_XXX defined in MgntGen.h
+	switch (MptRateIdx) 
+	{
+		/* CCK rate. */
+		case	MPT_RATE_1M:			return MGN_1M;		
+		case	MPT_RATE_2M:			return MGN_2M;		
+		case	MPT_RATE_55M:			return MGN_5_5M;	
+		case	MPT_RATE_11M:			return MGN_11M; 	
+											   
+		/* OFDM rate. */					   
+		case	MPT_RATE_6M:			return MGN_6M; 
+		case	MPT_RATE_9M:			return MGN_9M; 
+		case	MPT_RATE_12M:			return MGN_12M;
+		case	MPT_RATE_18M:			return MGN_18M;
+		case	MPT_RATE_24M:			return MGN_24M; 	
+		case	MPT_RATE_36M:			return MGN_36M;
+		case	MPT_RATE_48M:			return MGN_48M;
+		case	MPT_RATE_54M:			return MGN_54M;
+											   
+		/* HT rate. */						   
+		case	MPT_RATE_MCS0:			return MGN_MCS0; 
+		case	MPT_RATE_MCS1:			return MGN_MCS1; 
+		case	MPT_RATE_MCS2:			return MGN_MCS2; 
+		case	MPT_RATE_MCS3:			return MGN_MCS3; 
+		case	MPT_RATE_MCS4:			return MGN_MCS4;	
+		case	MPT_RATE_MCS5:			return MGN_MCS5;	
+		case	MPT_RATE_MCS6:			return MGN_MCS6;	
+		case	MPT_RATE_MCS7:			return MGN_MCS7;	
+		case	MPT_RATE_MCS8:			return MGN_MCS8;	
+		case	MPT_RATE_MCS9:			return MGN_MCS9;	
+		case	MPT_RATE_MCS10: 		return MGN_MCS10;	
+		case	MPT_RATE_MCS11: 		return MGN_MCS11;	
+		case	MPT_RATE_MCS12: 		return MGN_MCS12;	
+		case	MPT_RATE_MCS13: 		return MGN_MCS13;	
+		case	MPT_RATE_MCS14: 		return MGN_MCS14;	
+		case	MPT_RATE_MCS15: 		return MGN_MCS15;	
+		case	MPT_RATE_MCS16: 		return MGN_MCS16;
+		case	MPT_RATE_MCS17: 		return MGN_MCS17;
+		case	MPT_RATE_MCS18: 		return MGN_MCS18;
+		case	MPT_RATE_MCS19: 		return MGN_MCS19;
+		case	MPT_RATE_MCS20: 		return MGN_MCS20;
+		case	MPT_RATE_MCS21: 		return MGN_MCS21;
+		case	MPT_RATE_MCS22: 		return MGN_MCS22;
+		case	MPT_RATE_MCS23: 		return MGN_MCS23;
+		case	MPT_RATE_MCS24: 		return MGN_MCS24;
+		case	MPT_RATE_MCS25: 		return MGN_MCS25;
+		case	MPT_RATE_MCS26: 		return MGN_MCS26;
+		case	MPT_RATE_MCS27: 		return MGN_MCS27;
+		case	MPT_RATE_MCS28: 		return MGN_MCS28;
+		case	MPT_RATE_MCS29: 		return MGN_MCS29;
+		case	MPT_RATE_MCS30: 		return MGN_MCS30;
+		case	MPT_RATE_MCS31: 		return MGN_MCS31;
+											   
+		/* VHT rate. */ 					   
+		case	MPT_RATE_VHT1SS_MCS0:	return MGN_VHT1SS_MCS0;
+		case	MPT_RATE_VHT1SS_MCS1:	return MGN_VHT1SS_MCS1;
+		case	MPT_RATE_VHT1SS_MCS2:	return MGN_VHT1SS_MCS2;
+		case	MPT_RATE_VHT1SS_MCS3:	return MGN_VHT1SS_MCS3;
+		case	MPT_RATE_VHT1SS_MCS4:	return MGN_VHT1SS_MCS4;
+		case	MPT_RATE_VHT1SS_MCS5:	return MGN_VHT1SS_MCS5;
+		case	MPT_RATE_VHT1SS_MCS6:	return MGN_VHT1SS_MCS6;
+		case	MPT_RATE_VHT1SS_MCS7:	return MGN_VHT1SS_MCS7;
+		case	MPT_RATE_VHT1SS_MCS8:	return MGN_VHT1SS_MCS8;
+		case	MPT_RATE_VHT1SS_MCS9:	return MGN_VHT1SS_MCS9;
+		case	MPT_RATE_VHT2SS_MCS0:	return MGN_VHT2SS_MCS0; 
+		case	MPT_RATE_VHT2SS_MCS1:	return MGN_VHT2SS_MCS1; 
+		case	MPT_RATE_VHT2SS_MCS2:	return MGN_VHT2SS_MCS2; 
+		case	MPT_RATE_VHT2SS_MCS3:	return MGN_VHT2SS_MCS3; 
+		case	MPT_RATE_VHT2SS_MCS4:	return MGN_VHT2SS_MCS4; 
+		case	MPT_RATE_VHT2SS_MCS5:	return MGN_VHT2SS_MCS5; 
+		case	MPT_RATE_VHT2SS_MCS6:	return MGN_VHT2SS_MCS6; 
+		case	MPT_RATE_VHT2SS_MCS7:	return MGN_VHT2SS_MCS7; 
+		case	MPT_RATE_VHT2SS_MCS8:	return MGN_VHT2SS_MCS8; 
+		case	MPT_RATE_VHT2SS_MCS9:	return MGN_VHT2SS_MCS9; 
+		case	MPT_RATE_VHT3SS_MCS0:	return MGN_VHT3SS_MCS0; 
+		case	MPT_RATE_VHT3SS_MCS1:	return MGN_VHT3SS_MCS1; 
+		case	MPT_RATE_VHT3SS_MCS2:	return MGN_VHT3SS_MCS2; 
+		case	MPT_RATE_VHT3SS_MCS3:	return MGN_VHT3SS_MCS3; 
+		case	MPT_RATE_VHT3SS_MCS4:	return MGN_VHT3SS_MCS4; 
+		case	MPT_RATE_VHT3SS_MCS5:	return MGN_VHT3SS_MCS5; 
+		case	MPT_RATE_VHT3SS_MCS6:	return MGN_VHT3SS_MCS6; 
+		case	MPT_RATE_VHT3SS_MCS7:	return MGN_VHT3SS_MCS7; 
+		case	MPT_RATE_VHT3SS_MCS8:	return MGN_VHT3SS_MCS8; 
+		case	MPT_RATE_VHT3SS_MCS9:	return MGN_VHT3SS_MCS9; 
+		case	MPT_RATE_VHT4SS_MCS0:	return MGN_VHT4SS_MCS0; 
+		case	MPT_RATE_VHT4SS_MCS1:	return MGN_VHT4SS_MCS1; 
+		case	MPT_RATE_VHT4SS_MCS2:	return MGN_VHT4SS_MCS2; 
+		case	MPT_RATE_VHT4SS_MCS3:	return MGN_VHT4SS_MCS3; 
+		case	MPT_RATE_VHT4SS_MCS4:	return MGN_VHT4SS_MCS4; 
+		case	MPT_RATE_VHT4SS_MCS5:	return MGN_VHT4SS_MCS5; 
+		case	MPT_RATE_VHT4SS_MCS6:	return MGN_VHT4SS_MCS6; 
+		case	MPT_RATE_VHT4SS_MCS7:	return MGN_VHT4SS_MCS7; 
+		case	MPT_RATE_VHT4SS_MCS8:	return MGN_VHT4SS_MCS8; 
+		case	MPT_RATE_VHT4SS_MCS9:	return MGN_VHT4SS_MCS9; 
+		
+		case	MPT_RATE_LAST:	// fully automatiMGN_VHT2SS_MCS1;	
+		default:					  
+			DBG_871X("<===MptToMgntRate(), Invalid Rate: %d!!\n", MptRateIdx);
+			return 0x0; 					   
+	}										   
+}											   
+
+u8 rtw_mpRateParseFunc(PADAPTER pAdapter, u8 *targetStr)
+{
+	u16 i=0;
+ 	u8* rateindex_Array[] = { "1M","2M","5.5M","11M","6M","9M","12M","18M","24M","36M","48M","54M",
+ 								"HTMCS0","HTMCS1","HTMCS2","HTMCS3","HTMCS4","HTMCS5","HTMCS6","HTMCS7",
+ 								"HTMCS8","HTMCS9","HTMCS10","HTMCS11","HTMCS12","HTMCS13","HTMCS14","HTMCS15",
+ 								"HTMCS16","HTMCS17","HTMCS18","HTMCS19","HTMCS20","HTMCS21","HTMCS22","HTMCS23",
+ 								"HTMCS24","HTMCS25","HTMCS26","HTMCS27","HTMCS28","HTMCS29","HTMCS30","HTMCS31",
+ 								"VHT1MCS0","VHT1MCS1","VHT1MCS2","VHT1MCS3","VHT1MCS4","VHT1MCS5","VHT1MCS6","VHT1MCS7","VHT1MCS8","VHT1MCS9",
+ 								"VHT2MCS0","VHT2MCS1","VHT2MCS2","VHT2MCS3","VHT2MCS4","VHT2MCS5","VHT2MCS6","VHT2MCS7","VHT2MCS8","VHT2MCS9",
+ 								"VHT3MCS0","VHT3MCS1","VHT3MCS2","VHT3MCS3","VHT3MCS4","VHT3MCS5","VHT3MCS6","VHT3MCS7","VHT3MCS8","VHT3MCS9",
+ 								"VHT4MCS0","VHT4MCS1","VHT4MCS2","VHT4MCS3","VHT4MCS4","VHT4MCS5","VHT4MCS6","VHT4MCS7","VHT4MCS8","VHT4MCS9"};
+
+	for(i=0;i<=83;i++){	
+		if(strcmp(targetStr, rateindex_Array[i]) == 0){
+			DBG_871X("%s , index = %d \n",__func__ ,i);
+			return i;
+		}
+	}
+	
+	printk("%s ,please input a Data RATE String as:",__func__);
+	for(i=0;i<=83;i++){	
+		printk("%s ",rateindex_Array[i]);
+		if(i%10==0)
+			printk("\n");
+	}	
+	return _FAIL;
+}
+
+ULONG mpt_ProQueryCalTxPower(
+	PADAPTER	pAdapter,
+		u8		RfPath
+	)
+{
+
+	HAL_DATA_TYPE	*pHalData	= GET_HAL_DATA(pAdapter);
+	PMPT_CONTEXT		pMptCtx = &(pAdapter->mppriv.MptCtx);
+
+	ULONG			TxPower = 1, PwrGroup=0, PowerDiffByRate=0;	
+	u1Byte			limit = 0, rate = 0;
+	
+	#if defined(CONFIG_RTL8188E)
+	if (IS_HARDWARE_TYPE_8188E(pAdapter))
+	{
+		//return mpt_ProQueryCalTxPower_8188E(pAdapter, RfPath);
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8188E(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+
+	}
+	#endif
+	
+	#if defined(CONFIG_RTL8723B)	
+	if( IS_HARDWARE_TYPE_8723B(pAdapter) )
+	{
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8723B(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+	}
+	#endif
+	
+	#if defined(CONFIG_RTL8192E)
+	if( IS_HARDWARE_TYPE_8192E(pAdapter) )
+	{
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8192E(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+	}
+	#endif
+	#if defined(CONFIG_RTL8812A) || defined(CONFIG_RTL8821A)
+	if( IS_HARDWARE_TYPE_JAGUAR(pAdapter) )
+	{
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8812A(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+	}
+	#endif
+	#if defined(CONFIG_RTL8814A)
+	if ( IS_HARDWARE_TYPE_8814A(pAdapter) )
+	{
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8814A(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+	}
+	#endif
+	#if defined(CONFIG_RTL8703B)
+	if (IS_HARDWARE_TYPE_8703B(pAdapter)) {
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8703B(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+	}
+	#endif
+
+	#if defined(CONFIG_RTL8188F)
+	if (IS_HARDWARE_TYPE_8188F(pAdapter)) {
+		rate = MptToMgntRate(pAdapter->mppriv.rateidx);
+		TxPower = PHY_GetTxPowerIndex_8188F(pAdapter, RfPath, rate, 
+										pHalData->CurrentChannelBW, pHalData->CurrentChannel);
+	}
+	#endif
+
+	DBG_8192C("txPower=%d ,CurrentChannelBW=%d ,CurrentChannel=%d ,rate =%d\n",
+			  TxPower, pHalData->CurrentChannelBW, pHalData->CurrentChannel, rate);
+
+	pAdapter->mppriv.txpoweridx = (u8)TxPower;
+	pMptCtx->TxPwrLevel[ODM_RF_PATH_A] = (u8)TxPower;
+	pMptCtx->TxPwrLevel[ODM_RF_PATH_B] = (u8)TxPower;
+	pMptCtx->TxPwrLevel[ODM_RF_PATH_C] = (u8)TxPower;
+	pMptCtx->TxPwrLevel[ODM_RF_PATH_D]  = (u8)TxPower;
+	hal_mpt_SetTxPower(pAdapter);
+
+	return TxPower;
+}
+#endif
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp_ioctl.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp_ioctl.c
new file mode 100644
index 000000000..ff0c66b38
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_mp_ioctl.c
@@ -0,0 +1,2946 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_MP_IOCTL_C_
+
+#include <drv_types.h>
+#include <rtw_mp_ioctl.h>
+#include "../hal/phydm/phydm_precomp.h"
+
+//****************  oid_rtl_seg_81_85   section start ****************
+NDIS_STATUS oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->information_buf_len < sizeof(u8))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	if (poid_par_priv->type_of_oid == SET_OID) {
+		Adapter->registrypriv.wireless_mode = *(u8*)poid_par_priv->information_buf;
+	} else if (poid_par_priv->type_of_oid == QUERY_OID) {
+		*(u8*)poid_par_priv->information_buf = Adapter->registrypriv.wireless_mode;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+		 RT_TRACE(_module_mp_, _drv_info_, ("-query Wireless Mode=%d\n", Adapter->registrypriv.wireless_mode));
+	} else {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+	}
+
+_func_exit_;
+
+	return status;
+}
+//****************  oid_rtl_seg_81_87_80   section start ****************
+NDIS_STATUS oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL oldirql;
+#endif
+	struct bb_reg_param *pbbreg;
+	u16 offset;
+	u32 value;
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_write_bb_reg_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
+
+	offset = (u16)(pbbreg->offset) & 0xFFF; //0ffset :0x800~0xfff
+	if (offset < BB_REG_BASE_ADDR) offset |= BB_REG_BASE_ADDR;
+
+	value = pbbreg->value;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("oid_rt_pro_write_bb_reg_hdl: offset=0x%03X value=0x%08X\n",
+		  offset, value));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	write_bbreg(Adapter, offset, 0xFFFFFFFF, value);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL oldirql;
+#endif
+	struct bb_reg_param *pbbreg;
+	u16 offset;
+	u32 value;
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_read_bb_reg_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
+
+	offset = (u16)(pbbreg->offset) & 0xFFF; //0ffset :0x800~0xfff
+	if (offset < BB_REG_BASE_ADDR) offset |= BB_REG_BASE_ADDR;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	value = read_bbreg(Adapter, offset, 0xFFFFFFFF);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	pbbreg->value = value;
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-oid_rt_pro_read_bb_reg_hdl: offset=0x%03X value:0x%08X\n",
+		  offset, value));
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL oldirql;
+#endif
+	struct rf_reg_param *pbbreg;
+	u8 path;
+	u8 offset;
+	u32 value;
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_write_rf_reg_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
+
+	if (pbbreg->path >= MAX_RF_PATH_NUMS)
+		return NDIS_STATUS_NOT_ACCEPTED;
+	if (pbbreg->offset > 0xFF)
+		return NDIS_STATUS_NOT_ACCEPTED;
+	if (pbbreg->value > 0xFFFFF)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	path = (u8)pbbreg->path;
+	offset = (u8)pbbreg->offset;
+	value = pbbreg->value;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("oid_rt_pro_write_rf_reg_hdl: path=%d offset=0x%02X value=0x%05X\n",
+		  path, offset, value));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+ 	write_rfreg(Adapter, path, offset, value);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL oldirql;
+#endif
+	struct rf_reg_param *pbbreg;
+	u8 path;
+	u8 offset;
+	u32 value;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_read_rf_reg_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
+
+	if (pbbreg->path >= MAX_RF_PATH_NUMS)
+		return NDIS_STATUS_NOT_ACCEPTED;
+	if (pbbreg->offset > 0xFF)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	path = (u8)pbbreg->path;
+	offset = (u8)pbbreg->offset;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	value = read_rfreg(Adapter, path, offset);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	pbbreg->value = value;
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-oid_rt_pro_read_rf_reg_hdl: path=%d offset=0x%02X value=0x%05X\n",
+		  path, offset, value));
+
+_func_exit_;
+
+	return status;
+}
+//****************  oid_rtl_seg_81_87_00   section end****************
+//------------------------------------------------------------------------------
+
+//****************  oid_rtl_seg_81_80_00   section start ****************
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		ratevalue;//4
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("+oid_rt_pro_set_data_rate_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len != sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	ratevalue = *((u32*)poid_par_priv->information_buf);//4
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("oid_rt_pro_set_data_rate_hdl: data rate idx=%d\n", ratevalue));
+	if (ratevalue >= MPT_RATE_LAST)
+		return NDIS_STATUS_INVALID_DATA;
+
+	Adapter->mppriv.rateidx = ratevalue;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetDataRate(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		mode;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_start_test_hdl\n"));
+
+	if (Adapter->registrypriv.mp_mode == 0)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	//IQCalibrateBcut(Adapter);
+
+	mode = *((u32*)poid_par_priv->information_buf);
+	Adapter->mppriv.mode = mode;// 1 for loopback
+
+	if (mp_start_test(Adapter) == _FAIL) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		goto exit;
+	}
+
+exit:
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("-oid_rt_pro_start_test_hdl: mp_mode=%d\n", Adapter->mppriv.mode));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+Set OID_RT_PRO_STOP_TEST\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	mp_stop_test(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("-Set OID_RT_PRO_STOP_TEST\n"));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		Channel;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_set_channel_direct_call_hdl\n"));
+
+	if (poid_par_priv->information_buf_len != sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	if (poid_par_priv->type_of_oid == QUERY_OID) {
+		*((u32*)poid_par_priv->information_buf) = Adapter->mppriv.channel;
+		return NDIS_STATUS_SUCCESS;
+	}
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	Channel = *((u32*)poid_par_priv->information_buf);
+	RT_TRACE(_module_mp_, _drv_notice_, ("oid_rt_pro_set_channel_direct_call_hdl: Channel=%d\n", Channel));
+	if (Channel > 14)
+		return NDIS_STATUS_NOT_ACCEPTED;
+	Adapter->mppriv.channel = Channel;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetChannel(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u16		bandwidth;
+	u16		channel_offset;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("+oid_rt_set_bandwidth_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	bandwidth = *((u32*)poid_par_priv->information_buf);//4
+	channel_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+	if (bandwidth != CHANNEL_WIDTH_40)
+		bandwidth = CHANNEL_WIDTH_20;
+	padapter->mppriv.bandwidth = (u8)bandwidth;
+	padapter->mppriv.prime_channel_offset = (u8)channel_offset;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetBandwidth(padapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-oid_rt_set_bandwidth_hdl: bandwidth=%d channel_offset=%d\n",
+		  bandwidth, channel_offset));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		antenna;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_set_antenna_bb_hdl\n"));
+
+	if (poid_par_priv->information_buf_len != sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	if (poid_par_priv->type_of_oid == SET_OID)
+	{
+		antenna = *(u32*)poid_par_priv->information_buf;
+
+		Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
+		Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
+		RT_TRACE(_module_mp_, _drv_notice_,
+			 ("oid_rt_pro_set_antenna_bb_hdl: tx_ant=0x%04x rx_ant=0x%04x\n",
+			  Adapter->mppriv.antenna_tx, Adapter->mppriv.antenna_rx));
+
+		_irqlevel_changed_(&oldirql, LOWER);
+		SetAntenna(Adapter);
+		_irqlevel_changed_(&oldirql, RAISE);
+	} else {
+		antenna = (Adapter->mppriv.antenna_tx << 16)|Adapter->mppriv.antenna_rx;
+		*(u32*)poid_par_priv->information_buf = antenna;
+	}
+
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		tx_pwr_idx;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+oid_rt_pro_set_tx_power_control_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len != sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	tx_pwr_idx = *((u32*)poid_par_priv->information_buf);
+	if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	Adapter->mppriv.txpoweridx = (u8)tx_pwr_idx;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("oid_rt_pro_set_tx_power_control_hdl: idx=0x%2x\n",
+		  Adapter->mppriv.txpoweridx));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetTxPower(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+
+//------------------------------------------------------------------------------
+//****************  oid_rtl_seg_81_80_20   section start ****************
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid !=QUERY_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+	if (poid_par_priv->information_buf_len == sizeof(ULONG)) {
+		*(ULONG*)poid_par_priv->information_buf =  Adapter->mppriv.tx_pktcount;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	} else {
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	RT_TRACE(_module_mp_, _drv_alert_, ("===> oid_rt_pro_query_rx_packet_received_hdl.\n"));
+	if (poid_par_priv->information_buf_len == sizeof(ULONG)) {
+		*(ULONG*)poid_par_priv->information_buf =  Adapter->mppriv.rx_pktcount;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+		RT_TRACE(_module_mp_, _drv_alert_, ("recv_ok:%d \n",Adapter->mppriv.rx_pktcount));
+	} else {
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	RT_TRACE(_module_mp_, _drv_alert_, ("===> oid_rt_pro_query_rx_packet_crc32_error_hdl.\n"));
+	if (poid_par_priv->information_buf_len == sizeof(ULONG)) {
+		*(ULONG*)poid_par_priv->information_buf =  Adapter->mppriv.rx_crcerrpktcount;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+		RT_TRACE(_module_mp_, _drv_alert_, ("recv_err:%d \n",Adapter->mppriv.rx_crcerrpktcount));
+	} else {
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+
+NDIS_STATUS oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+	RT_TRACE(_module_mp_, _drv_alert_, ("===> oid_rt_pro_reset_tx_packet_sent_hdl.\n"));
+	Adapter->mppriv.tx_pktcount = 0;
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+	{
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+	if (poid_par_priv->information_buf_len == sizeof(ULONG)) {
+		Adapter->mppriv.rx_pktcount = 0;
+		Adapter->mppriv.rx_crcerrpktcount = 0;
+	} else {
+		status = NDIS_STATUS_INVALID_LENGTH;
+	}
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	ResetPhyRxPktCount(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+oid_rt_get_phy_rx_packet_received_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len != sizeof(ULONG))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	*(ULONG*)poid_par_priv->information_buf = GetPhyRxPktReceived(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("-oid_rt_get_phy_rx_packet_received_hdl: recv_ok=%d\n", *(ULONG*)poid_par_priv->information_buf));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+oid_rt_get_phy_rx_packet_crc32_error_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+
+	if (poid_par_priv->information_buf_len != sizeof(ULONG))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	*(ULONG*)poid_par_priv->information_buf = GetPhyRxPktCRC32Error(Adapter);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("-oid_rt_get_phy_rx_packet_crc32_error_hdl: recv_err=%d\n", *(ULONG*)poid_par_priv->information_buf));
+
+_func_exit_;
+
+	return status;
+}
+//****************  oid_rtl_seg_81_80_20   section end ****************
+NDIS_STATUS oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		bStartTest;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_set_continuous_tx_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	bStartTest = *((u32*)poid_par_priv->information_buf);
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetContinuousTx(Adapter,(u8)bStartTest);
+	if (bStartTest) {
+		struct mp_priv *pmp_priv = &Adapter->mppriv;
+		if (pmp_priv->tx.stop == 0) {
+			pmp_priv->tx.stop = 1;
+			DBG_871X("%s: pkt tx is running...\n", __func__);
+			rtw_msleep_os(5);
+		}
+		pmp_priv->tx.stop = 0;
+		pmp_priv->tx.count = 1;
+		SetPacketTx(Adapter);
+	}
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		bStartTest;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_alert_, ("+oid_rt_pro_set_single_carrier_tx_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	bStartTest = *((u32*)poid_par_priv->information_buf);
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetSingleCarrierTx(Adapter, (u8)bStartTest);
+	if (bStartTest) {
+		struct mp_priv *pmp_priv = &Adapter->mppriv;
+		if (pmp_priv->tx.stop == 0) {
+			pmp_priv->tx.stop = 1;
+			DBG_871X("%s: pkt tx is running...\n", __func__);
+			rtw_msleep_os(5);
+		}
+		pmp_priv->tx.stop = 0;
+		pmp_priv->tx.count = 1;
+		SetPacketTx(Adapter);
+	}
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32		bStartTest;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_set_carrier_suppression_tx_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	bStartTest = *((u32*)poid_par_priv->information_buf);
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
+	if (bStartTest) {
+		struct mp_priv *pmp_priv = &Adapter->mppriv;
+		if (pmp_priv->tx.stop == 0) {
+			pmp_priv->tx.stop = 1;
+			DBG_871X("%s: pkt tx is running...\n", __func__);
+			rtw_msleep_os(5);
+		}
+		pmp_priv->tx.stop = 0;
+		pmp_priv->tx.count = 1;
+		SetPacketTx(Adapter);
+	}
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32 		bStartTest;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_alert_, ("+oid_rt_pro_set_single_tone_tx_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	bStartTest = *((u32*)poid_par_priv->information_buf);
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetSingleToneTx(Adapter,(u8)bStartTest);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_pro_set_modulation_hdl(struct oid_par_priv* poid_par_priv)
+{
+	return 0;
+}
+
+NDIS_STATUS oid_rt_pro_trigger_gpio_hdl(struct oid_par_priv *poid_par_priv)
+{
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	rtw_hal_set_hwreg(Adapter, HW_VAR_TRIGGER_GPIO_0, 0);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//****************  oid_rtl_seg_81_80_00   section end ****************
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro8711_join_bss_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	PNDIS_802_11_SSID pssid;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	*poid_par_priv->bytes_needed = (u32)sizeof(NDIS_802_11_SSID);
+	*poid_par_priv->bytes_rw = 0;
+	if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pssid = (PNDIS_802_11_SSID)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (mp_start_joinbss(Adapter, pssid) == _FAIL)
+		status = NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = sizeof(NDIS_802_11_SSID);
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	pRW_Reg 	RegRWStruct;
+	u32		offset, width;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("+oid_rt_pro_read_register_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	RegRWStruct = (pRW_Reg)poid_par_priv->information_buf;
+	offset = RegRWStruct->offset;
+	width = RegRWStruct->width;
+
+	if (offset > 0xFFF)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	switch (width) {
+		case 1:
+			RegRWStruct->value = rtw_read8(Adapter, offset);
+			break;
+		case 2:
+			RegRWStruct->value = rtw_read16(Adapter, offset);
+			break;
+		default:
+			width = 4;
+			RegRWStruct->value = rtw_read32(Adapter, offset);
+			break;
+	}
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("oid_rt_pro_read_register_hdl: offset:0x%04X value:0x%X\n",
+		  offset, RegRWStruct->value));
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = width;
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	pRW_Reg 	RegRWStruct;
+	u32		offset, width, value;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("+oid_rt_pro_write_register_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	RegRWStruct = (pRW_Reg)poid_par_priv->information_buf;
+	offset = RegRWStruct->offset;
+	width = RegRWStruct->width;
+	value = RegRWStruct->value;
+
+	if (offset > 0xFFF)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	switch (RegRWStruct->width)
+	{
+		case 1:
+			if (value > 0xFF) {
+				status = NDIS_STATUS_NOT_ACCEPTED;
+				break;
+			}
+			rtw_write8(padapter, offset, (u8)value);
+			break;
+		case 2:
+			if (value > 0xFFFF) {
+				status = NDIS_STATUS_NOT_ACCEPTED;
+				break;
+			}
+			rtw_write16(padapter, offset, (u16)value);
+			break;
+		case 4:
+			rtw_write32(padapter, offset, value);
+			break;
+		default:
+			status = NDIS_STATUS_NOT_ACCEPTED;
+			break;
+	}
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("-oid_rt_pro_write_register_hdl: offset=0x%08X width=%d value=0x%X\n",
+		  offset, width, value));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_burst_read_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	pBurst_RW_Reg	pBstRwReg;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_burst_read_register_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	pBstRwReg = (pBurst_RW_Reg)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	rtw_read_mem(padapter, pBstRwReg->offset, (u32)pBstRwReg->len, pBstRwReg->Data);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("-oid_rt_pro_burst_read_register_hdl\n"));
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_burst_write_register_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	pBurst_RW_Reg	pBstRwReg;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_burst_write_register_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	pBstRwReg = (pBurst_RW_Reg)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	rtw_write_mem(padapter, pBstRwReg->offset, (u32)pBstRwReg->len, pBstRwReg->Data);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_info_, ("-oid_rt_pro_burst_write_register_hdl\n"));
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_write_txcmd_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	PADAPTER	Adapter = (PADAPTER)( poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+
+	TX_CMD_Desc	*TxCmd_Info;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+Set OID_RT_PRO_WRITE_TXCMD\n"));
+
+	TxCmd_Info=(TX_CMD_Desc*)poid_par_priv->information_buf;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("WRITE_TXCMD:Addr=%.8X\n", TxCmd_Info->offset));
+  	RT_TRACE(_module_mp_, _drv_info_, ("WRITE_TXCMD:1.)%.8X\n", (ULONG)TxCmd_Info->TxCMD.value[0]));
+	RT_TRACE(_module_mp_, _drv_info_, ("WRITE_TXCMD:2.)%.8X\n", (ULONG)TxCmd_Info->TxCMD.value[1]));
+	RT_TRACE(_module_mp_, _drv_info_, (("WRITE_TXCMD:3.)%.8X\n", (ULONG)TxCmd_Info->TxCMD.value[2]));
+	RT_TRACE(_module_mp_, _drv_info_, ("WRITE_TXCMD:4.)%.8X\n", (ULONG)TxCmd_Info->TxCMD.value[3]));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	rtw_write32(Adapter, TxCmd_Info->offset + 0, (unsigned int)TxCmd_Info->TxCMD.value[0]);
+	rtw_write32(Adapter, TxCmd_Info->offset + 4, (unsigned int)TxCmd_Info->TxCMD.value[1]);
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-Set OID_RT_PRO_WRITE_TXCMD: status=0x%08X\n", status));
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_read16_eeprom_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	pEEPROM_RWParam pEEPROM;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+Query OID_RT_PRO_READ16_EEPROM\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	pEEPROM = (pEEPROM_RWParam)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	pEEPROM->value = eeprom_read16(padapter, (u16)(pEEPROM->offset >> 1));
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_,  _drv_notice_,
+		 ("-Query OID_RT_PRO_READ16_EEPROM: offset=0x%x value=0x%x\n",
+		  pEEPROM->offset, pEEPROM->value));
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_write16_eeprom_hdl (struct oid_par_priv *poid_par_priv)
+{
+#if 0
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	pEEPROM_RWParam pEEPROM;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+Set OID_RT_PRO_WRITE16_EEPROM\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	pEEPROM = (pEEPROM_RWParam)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	eeprom_write16(padapter, (u16)(pEEPROM->offset >> 1), pEEPROM->value);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro8711_wi_poll_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)( poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	struct mp_wiparam *pwi_param;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(struct mp_wiparam))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	if (Adapter->mppriv.workparam.bcompleted == _FALSE)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	pwi_param = (struct mp_wiparam *)poid_par_priv->information_buf;
+
+	_rtw_memcpy(pwi_param, &Adapter->mppriv.workparam, sizeof(struct mp_wiparam));
+	Adapter->mppriv.act_in_progress = _FALSE;
+//	RT_TRACE(_module_mp_, _drv_info_, ("rf:%x\n", pwiparam->IoValue));
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro8711_pkt_loss_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)( poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro8711_pkt_loss_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(uint)*2) {
+		RT_TRACE(_module_mp_, _drv_err_, ("-oid_rt_pro8711_pkt_loss_hdl: buf_len=%d\n", (int)poid_par_priv->information_buf_len));
+		return NDIS_STATUS_INVALID_LENGTH;
+	}
+
+	if (*(uint*)poid_par_priv->information_buf == 1)//init==1
+		Adapter->mppriv.rx_pktloss = 0;
+
+	*((uint*)poid_par_priv->information_buf+1) = Adapter->mppriv.rx_pktloss;
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_rd_attrib_mem_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)( poid_par_priv->adapter_context);
+	struct io_queue *pio_queue = (struct io_queue *)Adapter->pio_queue;
+	struct intf_hdl	*pintfhdl = &pio_queue->intf;
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+#ifdef CONFIG_SDIO_HCI
+	void (*_attrib_read)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+#endif
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+Query OID_RT_RD_ATTRIB_MEM\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+#ifdef CONFIG_SDIO_HCI
+	_irqlevel_changed_(&oldirql, LOWER);
+{
+	u32 *plmem = (u32*)poid_par_priv->information_buf+2;
+	_attrib_read = pintfhdl->io_ops._attrib_read;
+	_attrib_read(pintfhdl, *((u32*)poid_par_priv->information_buf),
+				*((u32*)poid_par_priv->information_buf+1), (u8*)plmem);
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+}
+	_irqlevel_changed_(&oldirql, RAISE);
+#endif
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_wr_attrib_mem_hdl (struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	struct io_queue *pio_queue = (struct io_queue *)Adapter->pio_queue;
+	struct intf_hdl	*pintfhdl = &pio_queue->intf;
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+#ifdef CONFIG_SDIO_HCI
+	void (*_attrib_write)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *pmem);
+#endif
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+#ifdef CONFIG_SDIO_HCI
+	_irqlevel_changed_(&oldirql, LOWER);
+{
+	u32 *plmem = (u32*)poid_par_priv->information_buf + 2;
+	_attrib_write = pintfhdl->io_ops._attrib_write;
+	_attrib_write(pintfhdl, *(u32*)poid_par_priv->information_buf,
+				*((u32*)poid_par_priv->information_buf+1), (u8*)plmem);
+}
+	_irqlevel_changed_(&oldirql, RAISE);
+#endif
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS  oid_rt_pro_set_rf_intfs_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+OID_RT_PRO_SET_RF_INTFS\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (rtw_setrfintfs_cmd(Adapter, *(unsigned char*)poid_par_priv->information_buf) == _FAIL)
+		status = NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_poll_rx_status_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_rtw_memcpy(poid_par_priv->information_buf, (unsigned char*)&Adapter->mppriv.rxstat, sizeof(struct recv_stat));
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_cfg_debug_message_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	PCFG_DBG_MSG_STRUCT pdbg_msg;
+
+_func_enter_;
+
+//	RT_TRACE(0xffffffffff,_drv_alert_,("===> oid_rt_pro_cfg_debug_message_hdl.\n"));
+
+#if 0//#ifdef CONFIG_DEBUG_RTL871X
+
+	pdbg_msg = (PCFG_DBG_MSG_STRUCT)(poid_par_priv->information_buf);
+
+	if (poid_par_priv->type_of_oid == SET_OID) {
+		RT_TRACE(0xffffffffff, _drv_alert_,
+			 ("===>Set level :0x%08x, H32:0x%08x L32:0x%08x\n",
+			  pdbg_msg->DebugLevel, pdbg_msg->DebugComponent_H32, pdbg_msg->DebugComponent_L32));
+
+		GlobalDebugLevel = pdbg_msg->DebugLevel;
+		GlobalDebugComponents = (pdbg_msg->DebugComponent_H32 << 32) | pdbg_msg->DebugComponent_L32;
+		RT_TRACE(0xffffffffff, _drv_alert_,
+			 ("===> Set level :0x%08x, component:0x%016x\n",
+			  GlobalDebugLevel, (u32)GlobalDebugComponents));
+	} else {
+		pdbg_msg->DebugLevel = GlobalDebugLevel;
+		pdbg_msg->DebugComponent_H32 = (u32)(GlobalDebugComponents >> 32);
+		pdbg_msg->DebugComponent_L32 = (u32)GlobalDebugComponents;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+		RT_TRACE(0xffffffffff, _drv_alert_,
+			 ("===>Query level:0x%08x H32:0x%08x L32:0x%08x\n",
+			  (u32)pdbg_msg->DebugLevel, (u32)pdbg_msg->DebugComponent_H32, (u32)pdbg_msg->DebugComponent_L32));
+	}
+
+#endif
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_data_rate_ex_hdl(struct oid_par_priv *poid_par_priv)
+{
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+OID_RT_PRO_SET_DATA_RATE_EX\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (rtw_setdatarate_cmd(Adapter, poid_par_priv->information_buf) !=_SUCCESS)
+		status = NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//-----------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	u8 thermal = 0;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_get_thermal_meter_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	GetThermalMeter(Adapter, &thermal);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*(u32*)poid_par_priv->information_buf = (u32)thermal;
+	*poid_par_priv->bytes_rw = sizeof(u32);
+
+_func_exit_;
+
+	return status;
+}
+//-----------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_read_tssi_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_read_tssi_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (Adapter->mppriv.act_in_progress == _TRUE)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u8))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	//init workparam
+	Adapter->mppriv.act_in_progress = _TRUE;
+	Adapter->mppriv.workparam.bcompleted = _FALSE;
+	Adapter->mppriv.workparam.act_type = MPT_READ_TSSI;
+	Adapter->mppriv.workparam.io_offset = 0;
+	Adapter->mppriv.workparam.io_value = 0xFFFFFFFF;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (!rtw_gettssi_cmd(Adapter,0, (u8*)&Adapter->mppriv.workparam.io_value))
+		status = NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_power_tracking_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+
+_func_enter_;
+
+//	if (poid_par_priv->type_of_oid != SET_OID)
+//		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u8))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	if (poid_par_priv->type_of_oid == SET_OID) {
+		u8 enable;
+
+		enable = *(u8*)poid_par_priv->information_buf;
+		RT_TRACE(_module_mp_, _drv_notice_,
+			 ("+oid_rt_pro_set_power_tracking_hdl: enable=%d\n", enable));
+
+		SetPowerTracking(Adapter, enable);
+	} else {
+		GetPowerTracking(Adapter, (u8*)poid_par_priv->information_buf);
+	}
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//-----------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_basic_rate_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u32 ratevalue;
+	u8 datarates[NumRates];
+	int i;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+OID_RT_PRO_SET_BASIC_RATE\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+#if 0
+	ratevalue = *((u32*)poid_par_priv->information_buf);
+
+	for (i = 0; i < NumRates; i++) {
+		if (ratevalue == mpdatarate[i])
+			datarates[i] = mpdatarate[i];
+		else
+			datarates[i] = 0xff;
+		RT_TRACE(_module_rtl871x_ioctl_c_, _drv_info_, ("basicrate_inx=%d\n", datarates[i]));
+	}
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (rtw_setbasicrate_cmd(padapter, datarates) != _SUCCESS)
+		status = NDIS_STATUS_NOT_ACCEPTED;
+
+	_irqlevel_changed_(&oldirql, RAISE);
+#endif
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-OID_RT_PRO_SET_BASIC_RATE: status=0x%08X\n", status));
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_qry_pwrstate_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < 8)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	*poid_par_priv->bytes_rw = 8;
+	_rtw_memcpy(poid_par_priv->information_buf, &(adapter_to_pwrctl(Adapter)->pwr_mode), 8);
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-oid_rt_pro_qry_pwrstate_hdl: pwr_mode=%d smart_ps=%d\n",
+		  adapter_to_pwrctl(Adapter)->pwr_mode, adapter_to_pwrctl(Adapter)->smart_ps));
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_set_pwrstate_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	uint pwr_mode, smart_ps;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+Set OID_RT_PRO_SET_PWRSTATE\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	*poid_par_priv->bytes_rw = 0;
+	*poid_par_priv->bytes_needed = 8;
+
+	if (poid_par_priv->information_buf_len < 8)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pwr_mode = *(uint *)(poid_par_priv->information_buf);
+	smart_ps = *(uint *)((int)poid_par_priv->information_buf + 4);
+
+	*poid_par_priv->bytes_rw = 8;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_h2c_set_rate_table_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	struct setratable_parm *prate_table;
+	u8		res;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	*poid_par_priv->bytes_needed  = sizeof(struct setratable_parm);
+	if (poid_par_priv->information_buf_len < sizeof(struct setratable_parm))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	prate_table = (struct setratable_parm*)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	res = rtw_setrttbl_cmd(Adapter, prate_table);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	if (res == _FAIL)
+		status = NDIS_STATUS_FAILURE;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_h2c_get_rate_table_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	#if 0
+			struct mp_wi_cntx *pmp_wi_cntx=&(Adapter->mppriv.wi_cntx);
+			u8 res=_SUCCESS;
+			DEBUG_INFO(("===> Set OID_RT_PRO_H2C_GET_RATE_TABLE.\n"));
+
+			if(pmp_wi_cntx->bmp_wi_progress ==_TRUE){
+				DEBUG_ERR(("\n mp workitem is progressing, not allow to set another workitem right now!!!\n"));
+				Status = NDIS_STATUS_NOT_ACCEPTED;
+				break;
+			}
+			else{
+				pmp_wi_cntx->bmp_wi_progress=_TRUE;
+				pmp_wi_cntx->param.bcompleted=_FALSE;
+				pmp_wi_cntx->param.act_type=MPT_GET_RATE_TABLE;
+				pmp_wi_cntx->param.io_offset=0x0;
+				pmp_wi_cntx->param.bytes_cnt=sizeof(struct getratable_rsp);
+				pmp_wi_cntx->param.io_value=0xffffffff;
+
+				res=rtw_getrttbl_cmd(Adapter,(struct getratable_rsp *)pmp_wi_cntx->param.data);
+				*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+				if(res != _SUCCESS)
+				{
+					Status = NDIS_STATUS_NOT_ACCEPTED;
+				}
+			}
+			DEBUG_INFO(("\n <=== Set OID_RT_PRO_H2C_GET_RATE_TABLE.\n"));
+	#endif
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+
+//****************  oid_rtl_seg_87_12_00   section start ****************
+NDIS_STATUS oid_rt_pro_encryption_ctrl_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	struct security_priv *psecuritypriv = &Adapter->securitypriv;
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	ENCRY_CTRL_STATE encry_mode;
+
+
+	*poid_par_priv->bytes_needed = sizeof(u8);
+	if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	if (poid_par_priv->type_of_oid == SET_OID)
+	{
+		encry_mode = *((u8*)poid_par_priv->information_buf);
+		switch (encry_mode)
+		{
+			case HW_CONTROL:
+				#if 0
+				Adapter->registrypriv.software_decrypt=_FALSE;
+				Adapter->registrypriv.software_encrypt=_FALSE;
+				#else
+				psecuritypriv->sw_decrypt = _FALSE;
+				psecuritypriv->sw_encrypt = _FALSE;
+				#endif
+				break;
+			case SW_CONTROL:
+				#if 0
+				Adapter->registrypriv.software_decrypt=_TRUE;
+				Adapter->registrypriv.software_encrypt=_TRUE;
+				#else
+				psecuritypriv->sw_decrypt = _TRUE;
+				psecuritypriv->sw_encrypt = _TRUE;
+				#endif
+				break;
+			case HW_ENCRY_SW_DECRY:
+				#if 0
+				Adapter->registrypriv.software_decrypt=_TRUE;
+				Adapter->registrypriv.software_encrypt=_FALSE;
+				#else
+				psecuritypriv->sw_decrypt = _TRUE;
+				psecuritypriv->sw_encrypt = _FALSE;
+				#endif
+				break;
+			case SW_ENCRY_HW_DECRY:
+				#if 0
+				Adapter->registrypriv.software_decrypt=_FALSE;
+				Adapter->registrypriv.software_encrypt=_TRUE;
+				#else
+				psecuritypriv->sw_decrypt = _FALSE;
+				psecuritypriv->sw_encrypt = _TRUE;
+				#endif
+				break;
+		}
+
+		RT_TRACE(_module_rtl871x_ioctl_c_, _drv_notice_,
+			 ("-oid_rt_pro_encryption_ctrl_hdl: SET encry_mode=0x%x sw_encrypt=0x%x sw_decrypt=0x%x\n",
+			  encry_mode, psecuritypriv->sw_encrypt, psecuritypriv->sw_decrypt));
+	}
+	else {
+		#if 0
+		if (Adapter->registrypriv.software_encrypt == _FALSE) {
+			if (Adapter->registrypriv.software_decrypt == _FALSE)
+				encry_mode = HW_CONTROL;
+			else
+				encry_mode = HW_ENCRY_SW_DECRY;
+		}
+		else {
+			if (Adapter->registrypriv.software_decrypt == _FALSE)
+				encry_mode = SW_ENCRY_HW_DECRY;
+			else
+				encry_mode = SW_CONTROL;
+		}
+		#else
+
+		if ((psecuritypriv->sw_encrypt == _FALSE) && (psecuritypriv->sw_decrypt == _FALSE))
+			encry_mode = HW_CONTROL;
+		else if ((psecuritypriv->sw_encrypt == _FALSE) && (psecuritypriv->sw_decrypt == _TRUE))
+			encry_mode = HW_ENCRY_SW_DECRY;
+		else if ((psecuritypriv->sw_encrypt == _TRUE) && (psecuritypriv->sw_decrypt == _FALSE))
+			encry_mode = SW_ENCRY_HW_DECRY;
+		else if ((psecuritypriv->sw_encrypt == _TRUE) && (psecuritypriv->sw_decrypt == _TRUE))
+			encry_mode = SW_CONTROL;
+
+		#endif
+
+		*(u8*)poid_par_priv->information_buf =  encry_mode;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+		RT_TRACE(_module_mp_, _drv_notice_,
+			 ("-oid_rt_pro_encryption_ctrl_hdl: QUERY encry_mode=0x%x\n",
+			  encry_mode));
+	}
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_add_sta_info_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	struct sta_info *psta = NULL;
+	UCHAR 		*macaddr;
+
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	*poid_par_priv->bytes_needed = ETH_ALEN;
+	if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	macaddr = (UCHAR *) poid_par_priv->information_buf ;
+
+	RT_TRACE(_module_rtl871x_ioctl_c_,_drv_notice_,
+		 ("OID_RT_PRO_ADD_STA_INFO: addr="MAC_FMT"\n", MAC_ARG(macaddr) ));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	psta = rtw_get_stainfo(&Adapter->stapriv, macaddr);
+
+	if (psta == NULL) { // the sta have been in sta_info_queue => do nothing
+		psta = rtw_alloc_stainfo(&Adapter->stapriv, macaddr);
+
+		if (psta == NULL) {
+			RT_TRACE(_module_rtl871x_ioctl_c_,_drv_err_,("Can't alloc sta_info when OID_RT_PRO_ADD_STA_INFO\n"));
+			status = NDIS_STATUS_FAILURE;
+		}
+	} else { //(between drv has received this event before and  fw have not yet to set key to CAM_ENTRY)
+		RT_TRACE(_module_rtl871x_ioctl_c_, _drv_err_,
+			("Error: OID_RT_PRO_ADD_STA_INFO: sta has been in sta_hash_queue \n"));
+	}
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_dele_sta_info_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	struct sta_info *psta = NULL;
+	UCHAR		*macaddr;
+
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	*poid_par_priv->bytes_needed = ETH_ALEN;
+	if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	macaddr = (UCHAR *) poid_par_priv->information_buf ;
+	RT_TRACE(_module_rtl871x_ioctl_c_,_drv_notice_,
+		 ("+OID_RT_PRO_ADD_STA_INFO: addr="MAC_FMT"\n", MAC_ARG(macaddr) ));
+
+	psta = rtw_get_stainfo(&Adapter->stapriv, macaddr);
+	if (psta != NULL) {
+		//_enter_critical(&(Adapter->stapriv.sta_hash_lock), &irqL);
+		rtw_free_stainfo(Adapter, psta);
+		//_exit_critical(&(Adapter->stapriv.sta_hash_lock), &irqL);
+	}
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+#if 0
+static u32 mp_query_drv_var(_adapter *padapter, u8 offset, u32 var)
+{
+#ifdef CONFIG_SDIO_HCI
+
+	if (offset == 1) {
+		u16 tmp_blk_num;
+		tmp_blk_num = rtw_read16(padapter, SDIO_RX0_RDYBLK_NUM);
+		RT_TRACE(_module_mp_, _drv_err_, ("Query Information, mp_query_drv_var  SDIO_RX0_RDYBLK_NUM=0x%x   dvobj.rxblknum=0x%x\n", tmp_blk_num, adapter_to_dvobj(padapter)->rxblknum));
+		if (adapter_to_dvobj(padapter)->rxblknum != tmp_blk_num) {
+			RT_TRACE(_module_mp_,_drv_err_, ("Query Information, mp_query_drv_var  call recv rx\n"));
+		//	sd_recv_rxfifo(padapter);
+		}
+	}
+
+#if 0
+	if(offset <=100){  //For setting data rate and query data rate
+		if(offset==100){ //For query data rate
+			RT_TRACE(_module_mp_, _drv_emerg_, ("\n mp_query_drv_var: offset(%d): query rate=0x%.2x \n",offset,padapter->registrypriv.tx_rate));
+			var=padapter->registrypriv.tx_rate;
+
+		}
+		else if(offset<0x1d){  //For setting data rate
+			padapter->registrypriv.tx_rate=offset;
+			var=padapter->registrypriv.tx_rate;
+			padapter->registrypriv.use_rate=_TRUE;
+			RT_TRACE(_module_mp_, _drv_emerg_, ("\n mp_query_drv_var: offset(%d): set rate=0x%.2x \n",offset,padapter->registrypriv.tx_rate));
+		}
+		else{ //not use the data rate
+			padapter->registrypriv.use_rate=_FALSE;
+			RT_TRACE(_module_mp_, _drv_emerg_, ("\n mp_query_drv_var: offset(%d) out of rate range\n",offset));
+		}
+	}
+	else if (offset<=110){  //for setting debug level
+		RT_TRACE(_module_mp_, _drv_emerg_, (" mp_query_drv_var: offset(%d) for set debug level\n",offset));
+		if(offset==110){ //For query data rate
+			RT_TRACE(_module_mp_, _drv_emerg_, (" mp_query_drv_var: offset(%d): query dbg level=0x%.2x \n",offset,padapter->registrypriv.dbg_level));
+			padapter->registrypriv.dbg_level=GlobalDebugLevel;
+			var=padapter->registrypriv.dbg_level;
+		}
+		else if(offset<110 && offset>100){
+			RT_TRACE(_module_mp_, _drv_emerg_, (" mp_query_drv_var: offset(%d): set dbg level=0x%.2x \n",offset,offset-100));
+			padapter->registrypriv.dbg_level=GlobalDebugLevel=offset-100;
+			var=padapter->registrypriv.dbg_level;
+			RT_TRACE(_module_mp_, _drv_emerg_, (" mp_query_drv_var(_drv_emerg_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_alert_, (" mp_query_drv_var(_drv_alert_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_crit_, (" mp_query_drv_var(_drv_crit_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_err_, (" mp_query_drv_var(_drv_err_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_warning_, (" mp_query_drv_var(_drv_warning_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_notice_, (" mp_query_drv_var(_drv_notice_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_info_, (" mp_query_drv_var(_drv_info_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+			RT_TRACE(_module_mp_, _drv_debug_, (" mp_query_drv_var(_drv_debug_): offset(%d): set dbg level=0x%.2x \n",offset,GlobalDebugLevel));
+
+		}
+	}
+	else if(offset >110 &&offset <116){
+		if(115==offset){
+			RT_TRACE(_module_mp_, _drv_emerg_, (" mp_query_drv_var(_drv_emerg_): offset(%d): query TRX access type: [tx_block_mode=%x,rx_block_mode=%x]\n",\
+															offset, adapter_to_dvobj(padapter)->tx_block_mode, adapter_to_dvobj(padapter)->rx_block_mode));
+		}
+		else {
+			switch(offset){
+				case 111:
+					adapter_to_dvobj(padapter)->tx_block_mode=1;
+					adapter_to_dvobj(padapter)->rx_block_mode=1;
+					RT_TRACE(_module_mp_, _drv_emerg_, \
+						(" mp_query_drv_var(_drv_emerg_): offset(%d): SET TRX access type:(TX block/RX block) [tx_block_mode=%x,rx_block_mode=%x]\n",\
+						offset, adapter_to_dvobj(padapter)->tx_block_mode, adapter_to_dvobj(padapter)->rx_block_mode));
+					break;
+				case 112:
+					adapter_to_dvobj(padapter)->tx_block_mode=1;
+					adapter_to_dvobj(padapter)->rx_block_mode=0;
+					RT_TRACE(_module_mp_, _drv_emerg_, \
+						(" mp_query_drv_var(_drv_emerg_): offset(%d): SET TRX access type:(TX block/RX byte) [tx_block_mode=%x,rx_block_mode=%x]\n",\
+						offset, adapter_to_dvobj(padapter)->tx_block_mode, adapter_to_dvobj(padapter)->rx_block_mode));
+					break;
+				case 113:
+					adapter_to_dvobj(padapter)->tx_block_mode=0;
+					adapter_to_dvobj(padapter)->rx_block_mode=1;
+					RT_TRACE(_module_mp_, _drv_emerg_, \
+						(" mp_query_drv_var(_drv_emerg_): offset(%d): SET TRX access type:(TX byte/RX block) [tx_block_mode=%x,rx_block_mode=%x]\n",\
+						offset, adapter_to_dvobj(padapter)->tx_block_mode, adapter_to_dvobj(padapter)->rx_block_mode));
+					break;
+				case 114:
+					adapter_to_dvobj(padapter)->tx_block_mode=0;
+					adapter_to_dvobj(padapter)->rx_block_mode=0;
+					RT_TRACE(_module_mp_, _drv_emerg_, \
+						(" mp_query_drv_var(_drv_emerg_): offset(%d): SET TRX access type:(TX byte/RX byte) [tx_block_mode=%x,rx_block_mode=%x]\n",\
+						offset, adapter_to_dvobj(padapter)->tx_block_mode, adapter_to_dvobj(padapter)->rx_block_mode));
+					break;
+				default :
+					break;
+
+			}
+
+		}
+
+	}
+	else if(offset>=127){
+		u64	prnt_dbg_comp;
+		u8   chg_idx;
+		u64	tmp_dbg_comp;
+		chg_idx=offset-0x80;
+		tmp_dbg_comp=BIT(chg_idx);
+		prnt_dbg_comp=padapter->registrypriv.dbg_component= GlobalDebugComponents;
+		RT_TRACE(_module_mp_, _drv_emerg_, (" 1: mp_query_drv_var: offset(%d;0x%x):for dbg conpoment prnt_dbg_comp=0x%.16x GlobalDebugComponents=0x%.16x padapter->registrypriv.dbg_component=0x%.16x\n",offset,offset,prnt_dbg_comp,GlobalDebugComponents,padapter->registrypriv.dbg_component));
+		if(offset==127){
+	//		prnt_dbg_comp=padapter->registrypriv.dbg_component= GlobalDebugComponents;
+			var=(u32)(padapter->registrypriv.dbg_component);
+			RT_TRACE(0xffffffff, _drv_emerg_, ("2: mp_query_drv_var: offset(%d;0x%x):for query dbg conpoment=0x%x(l) 0x%x(h)  GlobalDebugComponents=0x%x(l) 0x%x(h) \n",offset,offset,padapter->registrypriv.dbg_component,prnt_dbg_comp));
+			prnt_dbg_comp=GlobalDebugComponents;
+			RT_TRACE(0xffffffff, _drv_emerg_, ("2-1: mp_query_drv_var: offset(%d;0x%x):for query dbg conpoment=0x%x(l) 0x%x(h)  GlobalDebugComponents=0x%x(l) 0x%x(h)\n",offset,offset,padapter->registrypriv.dbg_component,prnt_dbg_comp));
+			prnt_dbg_comp=GlobalDebugComponents=padapter->registrypriv.dbg_component;
+			RT_TRACE(0xffffffff, _drv_emerg_, ("2-2: mp_query_drv_var: offset(%d;0x%x):for query dbg conpoment=0x%x(l) 0x%x(h)  GlobalDebugComponents=0x%x(l) 0x%x(h)\n",offset,offset,padapter->registrypriv.dbg_component,prnt_dbg_comp));
+
+		}
+		else{
+			RT_TRACE(0xffffffff, _drv_emerg_, ("3: mp_query_drv_var: offset(%d;0x%x):for query dbg conpoment=0x%x(l) 0x%x(h) GlobalDebugComponents=0x%x(l) 0x%x(h) chg_idx=%d\n",offset,offset,padapter->registrypriv.dbg_component,prnt_dbg_comp,chg_idx));
+			prnt_dbg_comp=GlobalDebugComponents;
+			RT_TRACE(0xffffffff, _drv_emerg_,("3-1: mp_query_drv_var: offset(%d;0x%x):for query dbg conpoment=0x%x(l) 0x%x(h)  GlobalDebugComponents=0x%x(l) 0x%x(h) chg_idx=%d\n",offset,offset,padapter->registrypriv.dbg_component,prnt_dbg_comp,chg_idx));// ("3-1: mp_query_drv_var: offset(%d;0x%x):before set dbg conpoment=0x%x chg_idx=%d or0x%x BIT(chg_idx[%d]=0x%x)\n",offset,offset,prnt_dbg_comp,chg_idx,chg_idx,(chg_idx),tmp_dbg_comp)
+			prnt_dbg_comp=GlobalDebugComponents=padapter->registrypriv.dbg_component;
+			RT_TRACE(0xffffffff, _drv_emerg_, ("3-2: mp_query_drv_var: offset(%d;0x%x):for query dbg conpoment=0x%x(l) 0x%x(h)  GlobalDebugComponents=0x%x(l) 0x%x(h)\n",offset,offset,padapter->registrypriv.dbg_component,prnt_dbg_comp));
+
+			if(GlobalDebugComponents&tmp_dbg_comp){
+				//this bit is already set, now clear it
+				GlobalDebugComponents=GlobalDebugComponents&(~tmp_dbg_comp);
+			}
+			else{
+				//this bit is not set, now set it.
+				GlobalDebugComponents =GlobalDebugComponents|tmp_dbg_comp;
+			}
+			RT_TRACE(0xffffffff, _drv_emerg_, ("4: mp_query_drv_var: offset(%d;0x%x):before set dbg conpoment tmp_dbg_comp=0x%x GlobalDebugComponents=0x%x(l) 0x%x(h)",offset,offset,tmp_dbg_comp,prnt_dbg_comp));
+			prnt_dbg_comp=GlobalDebugComponents;
+			RT_TRACE(0xffffffff, _drv_emerg_, ("4-1: mp_query_drv_var: offset(%d;0x%x):before set dbg conpoment tmp_dbg_comp=0x%x GlobalDebugComponents=0x%x(l) 0x%x(h)",offset,offset,tmp_dbg_comp,prnt_dbg_comp));
+
+			RT_TRACE(_module_rtl871x_xmit_c_, _drv_emerg_, ("0: mp_query_drv_var(_module_rtl871x_xmit_c_:0): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,prnt_dbg_comp));
+			RT_TRACE(_module_xmit_osdep_c_, _drv_emerg_, ("1: mp_query_drv_var(_module_xmit_osdep_c_:1): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_emerg_, ("2: mp_query_drv_var(_module_rtl871x_recv_c_:2): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_recv_osdep_c_, _drv_emerg_, ("3: mp_query_drv_var(_module_recv_osdep_c_:3): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_mlme_c_, _drv_emerg_, ("4: mp_query_drv_var(_module_rtl871x_mlme_c_:4): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_mlme_osdep_c_, _drv_emerg_, (" 5:mp_query_drv_var(_module_mlme_osdep_c_:5): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_sta_mgt_c_, _drv_emerg_, ("6: mp_query_drv_var(_module_rtl871x_sta_mgt_c_:6): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_cmd_c_, _drv_emerg_, ("7: mp_query_drv_var(_module_rtl871x_cmd_c_:7): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_cmd_osdep_c_, _drv_emerg_, ("8: mp_query_drv_var(_module_cmd_osdep_c_:8): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_io_c_, _drv_emerg_, ("9: mp_query_drv_var(_module_rtl871x_io_c_:9): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_io_osdep_c_, _drv_emerg_, ("10: mp_query_drv_var(_module_io_osdep_c_:10): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_os_intfs_c_, _drv_emerg_, ("11: mp_query_drv_var(_module_os_intfs_c_:11): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_security_c_, _drv_emerg_, ("12: mp_query_drv_var(_module_rtl871x_security_c_:12): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_eeprom_c_, _drv_emerg_, ("13: mp_query_drv_var(_module_rtl871x_eeprom_c_:13): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_hal_init_c_, _drv_emerg_, ("14: mp_query_drv_var(_module_hal_init_c_:14): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_hci_hal_init_c_, _drv_emerg_, ("15: mp_query_drv_var(_module_hci_hal_init_c_:15): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_ioctl_c_, _drv_emerg_, ("16: mp_query_drv_var(_module_rtl871x_ioctl_c_:16): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_ioctl_set_c_, _drv_emerg_, ("17: mp_query_drv_var(_module_rtl871x_ioctl_set_c_:17): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_ioctl_query_c_, _drv_emerg_, ("18: mp_query_drv_var(_module_rtl871x_ioctl_query_c_:18): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_emerg_, ("19: mp_query_drv_var(_module_rtl871x_pwrctrl_c_:19): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_hci_intfs_c_, _drv_emerg_, ("20: mp_query_drv_var(_module_hci_intfs_c_:20): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_hci_ops_c_, _drv_emerg_, ("21: mp_query_drv_var(_module_hci_ops_c_:21): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_osdep_service_c_, _drv_emerg_, ("22: mp_query_drv_var(_module_osdep_service_c_:22): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_mp_, _drv_emerg_, ("23: mp_query_drv_var(_module_mp_:23): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			RT_TRACE(_module_hci_ops_os_c_, _drv_emerg_, ("24: mp_query_drv_var(_module_hci_ops_os_c_:24): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+			var=(u32)(GlobalDebugComponents);
+			//GlobalDebugComponents=padapter->registrypriv.dbg_component;
+			RT_TRACE(0xffffffff, _drv_emerg_, (" ==mp_query_drv_var(_module_mp_): offset(%d;0x%x):before set dbg conpoment=0x%x(l) 0x%x(h)\n",offset,offset,GlobalDebugComponents));
+
+		}
+	}
+	else{
+		RT_TRACE(_module_mp_, _drv_emerg_, ("\n mp_query_drv_var: offset(%d) >110\n",offset));
+	}
+#endif
+#endif
+
+	return var;
+}
+#endif
+
+NDIS_STATUS oid_rt_pro_query_dr_variable_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER		Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL			oldirql;
+#endif
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+
+	DR_VARIABLE_STRUCT	*pdrv_var;
+
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	*poid_par_priv->bytes_needed = sizeof(DR_VARIABLE_STRUCT);
+	if (poid_par_priv->information_buf_len < *poid_par_priv->bytes_needed)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+Query Information, OID_RT_PRO_QUERY_DR_VARIABLE\n"));
+
+	pdrv_var = (struct _DR_VARIABLE_STRUCT_ *)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	pdrv_var->variable = mp_query_drv_var(Adapter, pdrv_var->offset, pdrv_var->variable);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("-oid_rt_pro_query_dr_variable_hdl: offset=0x%x valule=0x%x\n",
+		  pdrv_var->offset, pdrv_var->variable));
+
+	return status;
+#else
+	return 0;
+#endif
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	RT_TRACE(_module_mp_, _drv_err_, ("oid_rt_pro_rx_packet_type_hdl...................\n"));
+
+	if (poid_par_priv->information_buf_len < sizeof (UCHAR)) {
+		status = NDIS_STATUS_INVALID_LENGTH;
+		*poid_par_priv->bytes_needed = sizeof(UCHAR);
+		return status;
+	}
+
+	if (poid_par_priv->type_of_oid == SET_OID) {
+		Adapter->mppriv.rx_with_status = *(UCHAR *) poid_par_priv->information_buf;
+		RT_TRACE(_module_rtl871x_ioctl_c_,_drv_err_, ("Query Information, OID_RT_PRO_RX_PACKET_TYPE:%d \n",\
+												Adapter->mppriv.rx_with_status));
+
+		RT_TRACE(_module_rtl871x_ioctl_c_,_drv_err_,("MAC addr=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x  \n",
+			Adapter->eeprompriv.mac_addr[0],Adapter->eeprompriv.mac_addr[1],Adapter->eeprompriv.mac_addr[2],\
+			Adapter->eeprompriv.mac_addr[3],Adapter->eeprompriv.mac_addr[4],Adapter->eeprompriv.mac_addr[5]));
+
+	}
+	else {
+		*(UCHAR *) poid_par_priv->information_buf = Adapter->mppriv.rx_with_status;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+		RT_TRACE(_module_rtl871x_ioctl_c_,_drv_err_, ("Query Information, OID_RT_PRO_RX_PACKET_TYPE:%d \n", \
+												Adapter->mppriv.rx_with_status));
+
+		//*(u32 *)&Adapter->eeprompriv.mac_addr[0]=rtw_read32(Adapter, 0x10250050);
+		//*(u16 *)&Adapter->eeprompriv.mac_addr[4]=rtw_read16(Adapter, 0x10250054);
+		RT_TRACE(_module_rtl871x_ioctl_c_,_drv_err_,("MAC addr=0x%x:0x%x:0x%x:0x%x:0x%x:0x%x  \n",
+			Adapter->eeprompriv.mac_addr[0],Adapter->eeprompriv.mac_addr[1],Adapter->eeprompriv.mac_addr[2],\
+			Adapter->eeprompriv.mac_addr[3],Adapter->eeprompriv.mac_addr[4],Adapter->eeprompriv.mac_addr[5]));
+	}
+#endif
+
+	return NDIS_STATUS_SUCCESS;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL oldirql;
+#endif
+	PEFUSE_ACCESS_STRUCT pefuse;
+	u8 *data;
+	u16 addr = 0, cnts = 0, max_available_size = 0;
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(EFUSE_ACCESS_STRUCT))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	pefuse = (PEFUSE_ACCESS_STRUCT)poid_par_priv->information_buf;
+	addr = pefuse->start_addr;
+	cnts = pefuse->cnts;
+	data = pefuse->data;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		("+oid_rt_pro_read_efuse_hd: buf_len=%d addr=%d cnts=%d\n",
+		 poid_par_priv->information_buf_len, addr, cnts));
+
+	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
+
+	if ((addr + cnts) > max_available_size) {
+		RT_TRACE(_module_mp_, _drv_err_, ("!oid_rt_pro_read_efuse_hdl: parameter error!\n"));
+		return NDIS_STATUS_NOT_ACCEPTED;
+	}
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	if (rtw_efuse_access(Adapter, _FALSE, addr, cnts, data) == _FAIL) {
+		RT_TRACE(_module_mp_, _drv_err_, ("!oid_rt_pro_read_efuse_hdl: rtw_efuse_access FAIL!\n"));
+		status = NDIS_STATUS_FAILURE;
+	} else
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL oldirql;
+#endif
+	PEFUSE_ACCESS_STRUCT pefuse;
+	u8 *data;
+	u16 addr = 0, cnts = 0, max_available_size = 0;
+	NDIS_STATUS status = NDIS_STATUS_SUCCESS;
+	PADAPTER Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	pefuse = (PEFUSE_ACCESS_STRUCT)poid_par_priv->information_buf;
+	addr = pefuse->start_addr;
+	cnts = pefuse->cnts;
+	data = pefuse->data;
+
+	RT_TRACE(_module_mp_, _drv_notice_,
+		 ("+oid_rt_pro_write_efuse_hdl: buf_len=%d addr=0x%04x cnts=%d\n",
+		  poid_par_priv->information_buf_len, addr, cnts));
+
+	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, (PVOID)&max_available_size, _FALSE);
+
+	if ((addr + cnts) > max_available_size) {
+		RT_TRACE(_module_mp_, _drv_err_, ("!oid_rt_pro_write_efuse_hdl: parameter error"));
+		return NDIS_STATUS_NOT_ACCEPTED;
+	}
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	if (rtw_efuse_access(Adapter, _TRUE, addr, cnts, data) == _FAIL)
+		status = NDIS_STATUS_FAILURE;
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_rw_efuse_pgpkt_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	PPGPKT_STRUCT	ppgpkt;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+//	RT_TRACE(_module_mp_, _drv_info_, ("+oid_rt_pro_rw_efuse_pgpkt_hdl\n"));
+
+	*poid_par_priv->bytes_rw = 0;
+
+	if (poid_par_priv->information_buf_len < sizeof(PGPKT_STRUCT))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	ppgpkt = (PPGPKT_STRUCT)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (poid_par_priv->type_of_oid == QUERY_OID)
+	{
+		RT_TRACE(_module_mp_, _drv_notice_,
+			("oid_rt_pro_rw_efuse_pgpkt_hdl: Read offset=0x%x\n",\
+			ppgpkt->offset));
+
+		Efuse_PowerSwitch(Adapter, _FALSE, _TRUE);
+		if (Efuse_PgPacketRead(Adapter, ppgpkt->offset, ppgpkt->data, _FALSE) == _TRUE)
+			*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+		else
+			status = NDIS_STATUS_FAILURE;
+		Efuse_PowerSwitch(Adapter, _FALSE, _FALSE);
+	} else {
+		RT_TRACE(_module_mp_, _drv_notice_,
+			("oid_rt_pro_rw_efuse_pgpkt_hdl: Write offset=0x%x word_en=0x%x\n",\
+			ppgpkt->offset, ppgpkt->word_en));
+
+		Efuse_PowerSwitch(Adapter, _TRUE, _TRUE);
+		if (Efuse_PgPacketWrite(Adapter, ppgpkt->offset, ppgpkt->word_en, ppgpkt->data, _FALSE) == _TRUE)
+			*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+		else
+			status = NDIS_STATUS_FAILURE;
+		Efuse_PowerSwitch(Adapter, _TRUE, _FALSE);
+	}
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("-oid_rt_pro_rw_efuse_pgpkt_hdl: status=0x%08X\n", status));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u16 size;
+	u8 ret;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len <sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	ret = efuse_GetCurrentSize(Adapter, &size);
+	_irqlevel_changed_(&oldirql, RAISE);
+	if (ret == _SUCCESS) {
+		*(u32*)poid_par_priv->information_buf = size;
+		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+	} else
+		status = NDIS_STATUS_FAILURE;
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	*(u32*)poid_par_priv->information_buf = efuse_GetMaxSize(Adapter);
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("-oid_rt_get_efuse_max_size_hdl: size=%d status=0x%08X\n",
+		  *(int*)poid_par_priv->information_buf, status));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_info_, ("+oid_rt_pro_efuse_hdl\n"));
+
+	if (poid_par_priv->type_of_oid == QUERY_OID)
+		status = oid_rt_pro_read_efuse_hdl(poid_par_priv);
+	else
+		status = oid_rt_pro_write_efuse_hdl(poid_par_priv);
+
+	RT_TRACE(_module_mp_, _drv_info_, ("-oid_rt_pro_efuse_hdl: status=0x%08X\n", status));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u8		*data;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+	u16	mapLen=0;
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_pro_efuse_map_hdl\n"));
+
+	EFUSE_GetEfuseDefinition(Adapter, EFUSE_WIFI, TYPE_EFUSE_MAP_LEN, (PVOID)&mapLen, _FALSE);
+
+	*poid_par_priv->bytes_rw = 0;
+
+	if (poid_par_priv->information_buf_len < mapLen)
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	data = (u8*)poid_par_priv->information_buf;
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	if (poid_par_priv->type_of_oid == QUERY_OID)
+	{
+		RT_TRACE(_module_mp_, _drv_info_,
+			("oid_rt_pro_efuse_map_hdl: READ\n"));
+
+		if (rtw_efuse_map_read(Adapter, 0, mapLen, data) == _SUCCESS)
+			*poid_par_priv->bytes_rw = mapLen;
+		else {
+			RT_TRACE(_module_mp_, _drv_err_,
+				("oid_rt_pro_efuse_map_hdl: READ fail\n"));
+			status = NDIS_STATUS_FAILURE;
+		}
+	} else {
+		// SET_OID
+		RT_TRACE(_module_mp_, _drv_info_,
+			("oid_rt_pro_efuse_map_hdl: WRITE\n"));
+
+		if (rtw_efuse_map_write(Adapter, 0, mapLen, data) == _SUCCESS)
+			*poid_par_priv->bytes_rw = mapLen;
+		else {
+			RT_TRACE(_module_mp_, _drv_err_,
+				("oid_rt_pro_efuse_map_hdl: WRITE fail\n"));
+			status = NDIS_STATUS_FAILURE;
+		}
+	}
+
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("-oid_rt_pro_efuse_map_hdl: status=0x%08X\n", status));
+
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_set_crystal_cap_hdl(struct oid_par_priv *poid_par_priv)
+{
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+
+	u32		crystal_cap = 0;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len <sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	crystal_cap = *((u32*)poid_par_priv->information_buf);//4
+	if (crystal_cap > 0xf)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	Adapter->mppriv.curr_crystalcap = crystal_cap;
+
+	_irqlevel_changed_(&oldirql,LOWER);
+	SetCrystalCap(Adapter);
+	_irqlevel_changed_(&oldirql,RAISE);
+
+_func_exit_;
+
+#endif
+	return status;
+}
+
+NDIS_STATUS oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u8		rx_pkt_type;
+//	u32		rcr_val32;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+//	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+_func_enter_;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+oid_rt_set_rx_packet_type_hdl\n"));
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u8))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	rx_pkt_type = *((u8*)poid_par_priv->information_buf);//4
+
+	RT_TRACE(_module_mp_, _drv_info_, ("rx_pkt_type: %x\n",rx_pkt_type ));
+#if 0
+	_irqlevel_changed_(&oldirql, LOWER);
+#if 0
+	rcr_val8 = rtw_read8(Adapter, 0x10250048);//RCR
+	rcr_val8 &= ~(RCR_AB|RCR_AM|RCR_APM|RCR_AAP);
+
+	if(rx_pkt_type == RX_PKT_BROADCAST){
+		rcr_val8 |= (RCR_AB | RCR_ACRC32 );
+	}
+	else if(rx_pkt_type == RX_PKT_DEST_ADDR){
+		rcr_val8 |= (RCR_AAP| RCR_AM |RCR_ACRC32);
+	}
+	else if(rx_pkt_type == RX_PKT_PHY_MATCH){
+		rcr_val8 |= (RCR_APM|RCR_ACRC32);
+	}
+	else{
+		rcr_val8 &= ~(RCR_AAP|RCR_APM|RCR_AM|RCR_AB|RCR_ACRC32);
+	}
+	rtw_write8(padapter, 0x10250048,rcr_val8);
+#else
+	rcr_val32 = rtw_read32(padapter, RCR);//RCR = 0x10250048
+	rcr_val32 &= ~(RCR_CBSSID|RCR_AB|RCR_AM|RCR_APM|RCR_AAP);
+#if 0
+	if(rx_pkt_type == RX_PKT_BROADCAST){
+		rcr_val32 |= (RCR_AB|RCR_AM|RCR_APM|RCR_AAP|RCR_ACRC32);
+	}
+	else if(rx_pkt_type == RX_PKT_DEST_ADDR){
+		//rcr_val32 |= (RCR_CBSSID|RCR_AAP|RCR_AM|RCR_ACRC32);
+		rcr_val32 |= (RCR_CBSSID|RCR_APM|RCR_ACRC32);
+	}
+	else if(rx_pkt_type == RX_PKT_PHY_MATCH){
+		rcr_val32 |= (RCR_APM|RCR_ACRC32);
+		//rcr_val32 |= (RCR_AAP|RCR_ACRC32);
+	}
+	else{
+		rcr_val32 &= ~(RCR_AAP|RCR_APM|RCR_AM|RCR_AB|RCR_ACRC32);
+	}
+#else
+	switch (rx_pkt_type)
+	{
+		case RX_PKT_BROADCAST :
+			rcr_val32 |= (RCR_AB|RCR_AM|RCR_APM|RCR_AAP|RCR_ACRC32);
+			break;
+		case RX_PKT_DEST_ADDR :
+			rcr_val32 |= (RCR_AB|RCR_AM|RCR_APM|RCR_AAP|RCR_ACRC32);
+			break;
+		case RX_PKT_PHY_MATCH:
+			rcr_val32 |= (RCR_APM|RCR_ACRC32);
+			break;
+		default:
+			rcr_val32 &= ~(RCR_AAP|RCR_APM|RCR_AM|RCR_AB|RCR_ACRC32);
+			break;
+	}
+
+	if (rx_pkt_type == RX_PKT_DEST_ADDR) {
+		padapter->mppriv.check_mp_pkt = 1;
+	} else {
+		padapter->mppriv.check_mp_pkt = 0;
+	}
+#endif
+	rtw_write32(padapter, RCR, rcr_val32);
+
+#endif
+	_irqlevel_changed_(&oldirql, RAISE);
+#endif
+_func_exit_;
+
+	return status;
+}
+
+NDIS_STATUS oid_rt_pro_set_tx_agc_offset_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+
+	u32 		txagc;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len < sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	txagc = *(u32*)poid_par_priv->information_buf;
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("oid_rt_pro_set_tx_agc_offset_hdl: 0x%08x\n", txagc));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+	SetTxAGCOffset(Adapter, txagc);
+	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+
+NDIS_STATUS oid_rt_pro_set_pkt_test_mode_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	PADAPTER		Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+
+	NDIS_STATUS		status = NDIS_STATUS_SUCCESS;
+
+	struct mlme_priv	*pmlmepriv = &Adapter->mlmepriv;
+	struct mp_priv		*pmppriv = &Adapter->mppriv;
+	u32 			type;
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID)
+		return NDIS_STATUS_NOT_ACCEPTED;
+
+	if (poid_par_priv->information_buf_len <sizeof(u32))
+		return NDIS_STATUS_INVALID_LENGTH;
+
+	type = *(u32*)poid_par_priv->information_buf;
+
+	if (_LOOPBOOK_MODE_ == type) {
+		pmppriv->mode = type;
+		set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); //append txdesc
+		RT_TRACE(_module_mp_, _drv_info_, ("test mode change to loopback mode:0x%08x.\n", get_fwstate(pmlmepriv)));
+	} else if (_2MAC_MODE_ == type){
+		pmppriv->mode = type;
+		_clr_fwstate_(pmlmepriv, WIFI_MP_LPBK_STATE);
+		RT_TRACE(_module_mp_, _drv_info_, ("test mode change to 2mac mode:0x%08x.\n", get_fwstate(pmlmepriv)));
+	} else
+		status = NDIS_STATUS_NOT_ACCEPTED;
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+
+unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
+{
+	PMP_XMIT_PARM pparm;
+	PADAPTER padapter;
+	struct mp_priv *pmp_priv;
+	struct pkt_attrib *pattrib;
+
+	RT_TRACE(_module_mp_, _drv_notice_, ("+%s\n", __func__));
+
+	pparm = (PMP_XMIT_PARM)poid_par_priv->information_buf;
+	padapter = (PADAPTER)poid_par_priv->adapter_context;
+	pmp_priv = &padapter->mppriv;
+
+	if (poid_par_priv->type_of_oid == QUERY_OID) {
+		pparm->enable = !pmp_priv->tx.stop;
+		pparm->count = pmp_priv->tx.sended;
+	} else {
+		if (pparm->enable == 0) {
+			pmp_priv->tx.stop = 1;
+		} else if (pmp_priv->tx.stop == 1) {
+			pmp_priv->tx.stop = 0;
+			pmp_priv->tx.count = pparm->count;
+			pmp_priv->tx.payload = pparm->payload_type;
+			pattrib = &pmp_priv->tx.attrib;
+			pattrib->pktlen = pparm->length;
+			_rtw_memcpy(pattrib->dst, pparm->da, ETH_ALEN);
+			SetPacketTx(padapter);
+		} else
+			return NDIS_STATUS_FAILURE;
+	}
+
+	return NDIS_STATUS_SUCCESS;
+}
+
+#if 0
+unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
+{
+	unsigned char *pframe, *pmp_pkt;
+	struct ethhdr *pethhdr;
+	struct pkt_attrib *pattrib;
+	struct rtw_ieee80211_hdr *pwlanhdr;
+	unsigned short *fctrl;
+	int llc_sz, payload_len;
+	struct mp_xmit_frame *pxframe=  NULL;
+	struct mp_xmit_packet *pmp_xmitpkt = (struct mp_xmit_packet*)param;
+	u8 addr3[] = {0x02, 0xE0, 0x4C, 0x87, 0x66, 0x55};
+
+//	DBG_871X("+mp_ioctl_xmit_packet_hdl\n");
+
+	pxframe = alloc_mp_xmitframe(&padapter->mppriv);
+	if (pxframe == NULL)
+	{
+		DEBUG_ERR(("Can't alloc pmpframe %d:%s\n", __LINE__, __FILE__));
+		return -1;
+	}
+
+	//mp_xmit_pkt
+	payload_len = pmp_xmitpkt->len - 14;
+	pmp_pkt = (unsigned char*)pmp_xmitpkt->mem;
+	pethhdr = (struct ethhdr *)pmp_pkt;
+
+	//DBG_871X("payload_len=%d, pkt_mem=0x%x\n", pmp_xmitpkt->len, (void*)pmp_xmitpkt->mem);
+
+	//DBG_871X("pxframe=0x%x\n", (void*)pxframe);
+	//DBG_871X("pxframe->mem=0x%x\n", (void*)pxframe->mem);
+
+	//update attribute
+	pattrib = &pxframe->attrib;
+	memset((u8 *)(pattrib), 0, sizeof (struct pkt_attrib));
+	pattrib->pktlen = pmp_xmitpkt->len;
+	pattrib->ether_type = ntohs(pethhdr->h_proto);
+	pattrib->hdrlen = 24;
+	pattrib->nr_frags = 1;
+	pattrib->priority = 0;
+#ifndef CONFIG_MP_LINUX
+	if(IS_MCAST(pethhdr->h_dest))
+		pattrib->mac_id = 4;
+	else
+		pattrib->mac_id = 5;
+#else
+	pattrib->mac_id = 5;
+#endif
+
+	//
+	memset(pxframe->mem, 0 , WLANHDR_OFFSET);
+	pframe = (u8 *)(pxframe->mem) + WLANHDR_OFFSET;
+
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+	SetFrameSubType(pframe, WIFI_DATA);
+
+	_rtw_memcpy(pwlanhdr->addr1, pethhdr->h_dest, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, pethhdr->h_source, ETH_ALEN);
+
+	_rtw_memcpy(pwlanhdr->addr3, addr3, ETH_ALEN);
+
+	pwlanhdr->seq_ctl = 0;
+	pframe += pattrib->hdrlen;
+
+	llc_sz= rtw_put_snap(pframe, pattrib->ether_type);
+	pframe += llc_sz;
+
+	_rtw_memcpy(pframe, (void*)(pmp_pkt+14),  payload_len);
+
+	pattrib->last_txcmdsz = pattrib->hdrlen + llc_sz + payload_len;
+
+	DEBUG_INFO(("issuing mp_xmit_frame, tx_len=%d, ether_type=0x%x\n", pattrib->last_txcmdsz, pattrib->ether_type));
+	xmit_mp_frame(padapter, pxframe);
+
+	return _SUCCESS;
+}
+#endif
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
+{
+#ifdef PLATFORM_OS_XP
+	_irqL		oldirql;
+#endif
+	u8		bpwrup;
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+#ifdef PLATFORM_LINUX
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+	PADAPTER	padapter = (PADAPTER)(poid_par_priv->adapter_context);
+#endif
+#endif
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != SET_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("\n ===> Setoid_rt_set_power_down_hdl.\n"));
+
+	_irqlevel_changed_(&oldirql, LOWER);
+
+	bpwrup = *(u8 *)poid_par_priv->information_buf;
+	//CALL  the power_down function
+#ifdef PLATFORM_LINUX
+#if defined(CONFIG_RTL8712) //Linux MP insmod unknown symbol
+	dev_power_down(padapter,bpwrup); 
+#endif
+#endif
+	_irqlevel_changed_(&oldirql, RAISE);
+
+	//DEBUG_ERR(("\n <=== Query OID_RT_PRO_READ_REGISTER.
+	//	Add:0x%08x Width:%d Value:0x%08x\n",RegRWStruct->offset,RegRWStruct->width,RegRWStruct->value));
+
+_func_exit_;
+
+	return status;
+}
+//------------------------------------------------------------------------------
+NDIS_STATUS oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
+{
+#if 0
+	NDIS_STATUS	status = NDIS_STATUS_SUCCESS;
+	PADAPTER	Adapter = (PADAPTER)(poid_par_priv->adapter_context);
+//#ifdef PLATFORM_OS_XP
+//	_irqL		oldirql;
+//#endif
+
+_func_enter_;
+
+	if (poid_par_priv->type_of_oid != QUERY_OID) {
+		status = NDIS_STATUS_NOT_ACCEPTED;
+		return status;
+	}
+	if (poid_par_priv->information_buf_len < sizeof(u32)) {
+		status = NDIS_STATUS_INVALID_LENGTH;
+		return status;
+	}
+
+	RT_TRACE(_module_mp_, _drv_info_,
+		 ("\n ===> oid_rt_get_power_mode_hdl.\n"));
+
+//	_irqlevel_changed_(&oldirql, LOWER);
+	*(int*)poid_par_priv->information_buf = Adapter->registrypriv.low_power ? POWER_LOW : POWER_NORMAL;
+	*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
+//	_irqlevel_changed_(&oldirql, RAISE);
+
+_func_exit_;
+
+	return status;
+#else
+	return 0;
+#endif
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_odm.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_odm.c
new file mode 100644
index 000000000..7b733a9a5
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_odm.c
@@ -0,0 +1,461 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2013 Realtek Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+
+#include <rtw_odm.h>
+#include <hal_data.h>
+
+const char *odm_comp_str[] = {
+	/* BIT0 */"ODM_COMP_DIG",
+	/* BIT1 */"ODM_COMP_RA_MASK",
+	/* BIT2 */"ODM_COMP_DYNAMIC_TXPWR",
+	/* BIT3 */"ODM_COMP_FA_CNT",
+	/* BIT4 */"ODM_COMP_RSSI_MONITOR",
+	/* BIT5 */"ODM_COMP_CCK_PD",
+	/* BIT6 */"ODM_COMP_ANT_DIV",
+	/* BIT7 */"ODM_COMP_PWR_SAVE",
+	/* BIT8 */"ODM_COMP_PWR_TRAIN",
+	/* BIT9 */"ODM_COMP_RATE_ADAPTIVE",
+	/* BIT10 */"ODM_COMP_PATH_DIV",
+	/* BIT11 */"ODM_COMP_PSD",
+	/* BIT12 */"ODM_COMP_DYNAMIC_PRICCA",
+	/* BIT13 */"ODM_COMP_RXHP",
+	/* BIT14 */"ODM_COMP_MP",
+	/* BIT15 */"ODM_COMP_CFO_TRACKING",
+	/* BIT16 */"ODM_COMP_ACS",
+	/* BIT17 */"PHYDM_COMP_ADAPTIVITY",
+	/* BIT18 */"PHYDM_COMP_RA_DBG",
+	/* BIT19 */"PHYDM_COMP_TXBF",
+	/* BIT20 */"ODM_COMP_EDCA_TURBO",
+	/* BIT21 */"ODM_COMP_EARLY_MODE",
+	/* BIT22 */"ODM_FW_DEBUG_TRACE",
+	/* BIT23 */NULL,
+	/* BIT24 */"ODM_COMP_TX_PWR_TRACK",
+	/* BIT25 */"ODM_COMP_RX_GAIN_TRACK",
+	/* BIT26 */"ODM_COMP_CALIBRATION",
+	/* BIT27 */NULL,
+	/* BIT28 */"ODM_PHY_CONFIG",
+	/* BIT29 */"BEAMFORMING_DEBUG",
+	/* BIT30 */"ODM_COMP_COMMON",
+	/* BIT31 */"ODM_COMP_INIT",
+	/* BIT32 */"ODM_COMP_NOISY_DETECT",
+};
+
+#define RTW_ODM_COMP_MAX 33
+
+const char *odm_ability_str[] = {
+	/* BIT0 */"ODM_BB_DIG",
+	/* BIT1 */"ODM_BB_RA_MASK",
+	/* BIT2 */"ODM_BB_DYNAMIC_TXPWR",
+	/* BIT3 */"ODM_BB_FA_CNT",
+	/* BIT4 */"ODM_BB_RSSI_MONITOR",
+	/* BIT5 */"ODM_BB_CCK_PD",
+	/* BIT6 */"ODM_BB_ANT_DIV",
+	/* BIT7 */"ODM_BB_PWR_SAVE",
+	/* BIT8 */"ODM_BB_PWR_TRAIN",
+	/* BIT9 */"ODM_BB_RATE_ADAPTIVE",
+	/* BIT10 */"ODM_BB_PATH_DIV",
+	/* BIT11 */"ODM_BB_PSD",
+	/* BIT12 */"ODM_BB_RXHP",
+	/* BIT13 */"ODM_BB_ADAPTIVITY",
+	/* BIT14 */"ODM_BB_CFO_TRACKING",
+	/* BIT15 */"ODM_BB_NHM_CNT",
+	/* BIT16 */"ODM_BB_PRIMARY_CCA",
+	/* BIT17 */"ODM_BB_TXBF",
+	/* BIT18 */NULL,
+	/* BIT19 */NULL,
+	/* BIT20 */"ODM_MAC_EDCA_TURBO",
+	/* BIT21 */"ODM_MAC_EARLY_MODE",
+	/* BIT22 */NULL,
+	/* BIT23 */NULL,
+	/* BIT24 */"ODM_RF_TX_PWR_TRACK",
+	/* BIT25 */"ODM_RF_RX_GAIN_TRACK",
+	/* BIT26 */"ODM_RF_CALIBRATION",
+};
+
+#define RTW_ODM_ABILITY_MAX 27
+
+const char *odm_dbg_level_str[] = {
+	NULL,
+	"ODM_DBG_OFF",
+	"ODM_DBG_SERIOUS",
+	"ODM_DBG_WARNING",
+	"ODM_DBG_LOUD",
+	"ODM_DBG_TRACE",
+};
+
+#define RTW_ODM_DBG_LEVEL_NUM 6
+
+void rtw_odm_dbg_comp_msg(void *sel, _adapter *adapter)
+{
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &pHalData->odmpriv;
+	int cnt = 0;
+	u64 dbg_comp = 0;
+	int i;
+
+	rtw_hal_get_odm_var(adapter, HAL_ODM_DBG_FLAG, &dbg_comp, NULL);
+
+	DBG_871X_SEL_NL(sel, "odm.DebugComponents = 0x%016llx\n", dbg_comp);
+	for (i=0;i<RTW_ODM_COMP_MAX;i++) {
+		if (odm_comp_str[i])
+			DBG_871X_SEL_NL(sel, "%cBIT%-2d %s\n",
+				(BIT0 << i) & dbg_comp ? '+' : ' ', i, odm_comp_str[i]);
+	}
+}
+
+inline void rtw_odm_dbg_comp_set(_adapter *adapter, u64 comps)
+{
+	rtw_hal_set_odm_var(adapter, HAL_ODM_DBG_FLAG, &comps, _FALSE);
+}
+
+void rtw_odm_dbg_level_msg(void *sel, _adapter *adapter)
+{
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &pHalData->odmpriv;
+	int cnt = 0;
+	u32 dbg_level = 0;
+	int i;
+
+	rtw_hal_get_odm_var(adapter, HAL_ODM_DBG_LEVEL, &dbg_level, NULL);
+	DBG_871X_SEL_NL(sel, "odm.DebugLevel = %u\n", dbg_level);
+	for (i=0;i<RTW_ODM_DBG_LEVEL_NUM;i++) {
+		if (odm_dbg_level_str[i])
+			DBG_871X_SEL_NL(sel, "%u %s\n", i, odm_dbg_level_str[i]);
+	}
+}
+
+inline void rtw_odm_dbg_level_set(_adapter *adapter, u32 level)
+{
+	rtw_hal_set_odm_var(adapter, HAL_ODM_DBG_LEVEL, &level, _FALSE);
+}
+
+void rtw_odm_ability_msg(void *sel, _adapter *adapter)
+{
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &pHalData->odmpriv;
+	int cnt = 0;
+	u32 ability = 0;
+	int i;
+
+	ability = rtw_phydm_ability_get(adapter);
+	DBG_871X_SEL_NL(sel, "odm.SupportAbility = 0x%08x\n", ability);
+	for (i=0;i<RTW_ODM_ABILITY_MAX;i++) {
+		if (odm_ability_str[i])
+			DBG_871X_SEL_NL(sel, "%cBIT%-2d %s\n",
+				(BIT0 << i) & ability ? '+' : ' ', i, odm_ability_str[i]);
+	}
+}
+
+inline void rtw_odm_ability_set(_adapter *adapter, u32 ability)
+{
+	rtw_phydm_ability_set(adapter, ability);
+}
+
+/* set ODM_CMNINFO_IC_TYPE based on chip_type */
+void rtw_odm_init_ic_type(_adapter *adapter)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &hal_data->odmpriv;
+	u4Byte ic_type = chip_type_to_odm_ic_type(rtw_get_chip_type(adapter));
+
+	rtw_warn_on(!ic_type);
+
+	ODM_CmnInfoInit(odm, ODM_CMNINFO_IC_TYPE, ic_type);
+}
+
+void rtw_odm_adaptivity_ver_msg(void *sel, _adapter *adapter)
+{
+	DBG_871X_SEL_NL(sel, "ADAPTIVITY_VERSION "ADAPTIVITY_VERSION"\n");
+}
+
+#define RTW_ADAPTIVITY_EN_DISABLE 0
+#define RTW_ADAPTIVITY_EN_ENABLE 1
+
+void rtw_odm_adaptivity_en_msg(void *sel, _adapter *adapter)
+{
+	struct registry_priv *regsty = &adapter->registrypriv;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &hal_data->odmpriv;
+
+	DBG_871X_SEL_NL(sel, "RTW_ADAPTIVITY_EN_");
+
+	if (regsty->adaptivity_en == RTW_ADAPTIVITY_EN_DISABLE) {
+		DBG_871X_SEL(sel, "DISABLE\n");
+	} else if (regsty->adaptivity_en == RTW_ADAPTIVITY_EN_ENABLE) {
+		DBG_871X_SEL(sel, "ENABLE\n");
+	} else {
+		DBG_871X_SEL(sel, "INVALID\n");
+	}
+}
+
+#define RTW_ADAPTIVITY_MODE_NORMAL 0
+#define RTW_ADAPTIVITY_MODE_CARRIER_SENSE 1
+
+void rtw_odm_adaptivity_mode_msg(void *sel, _adapter *adapter)
+{
+	struct registry_priv *regsty = &adapter->registrypriv;
+
+	DBG_871X_SEL_NL(sel, "RTW_ADAPTIVITY_MODE_");
+
+	if (regsty->adaptivity_mode == RTW_ADAPTIVITY_MODE_NORMAL) {
+		DBG_871X_SEL(sel, "NORMAL\n");
+	} else if (regsty->adaptivity_mode == RTW_ADAPTIVITY_MODE_CARRIER_SENSE) {
+		DBG_871X_SEL(sel, "CARRIER_SENSE\n");
+	} else {
+		DBG_871X_SEL(sel, "INVALID\n");
+	}
+}
+
+#define RTW_ADAPTIVITY_DML_DISABLE 0
+#define RTW_ADAPTIVITY_DML_ENABLE 1
+
+void rtw_odm_adaptivity_dml_msg(void *sel, _adapter *adapter)
+{
+	struct registry_priv *regsty = &adapter->registrypriv;
+
+	DBG_871X_SEL_NL(sel, "RTW_ADAPTIVITY_DML_");
+
+	if (regsty->adaptivity_dml == RTW_ADAPTIVITY_DML_DISABLE) {
+		DBG_871X_SEL(sel, "DISABLE\n");
+	} else if (regsty->adaptivity_dml == RTW_ADAPTIVITY_DML_ENABLE) {
+		DBG_871X_SEL(sel, "ENABLE\n");
+	} else {
+		DBG_871X_SEL(sel, "INVALID\n");
+	}
+}
+
+void rtw_odm_adaptivity_dc_backoff_msg(void *sel, _adapter *adapter)
+{
+	struct registry_priv *regsty = &adapter->registrypriv;
+
+	DBG_871X_SEL_NL(sel, "RTW_ADAPTIVITY_DC_BACKOFF:%u\n", regsty->adaptivity_dc_backoff);
+}
+
+void rtw_odm_adaptivity_config_msg(void *sel, _adapter *adapter)
+{
+	rtw_odm_adaptivity_ver_msg(sel, adapter);
+	rtw_odm_adaptivity_en_msg(sel, adapter);
+	rtw_odm_adaptivity_mode_msg(sel, adapter);
+	rtw_odm_adaptivity_dml_msg(sel, adapter);
+	rtw_odm_adaptivity_dc_backoff_msg(sel, adapter);
+}
+
+bool rtw_odm_adaptivity_needed(_adapter *adapter)
+{
+	struct registry_priv *regsty = &adapter->registrypriv;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	bool ret = _FALSE;
+
+	if (regsty->adaptivity_en == RTW_ADAPTIVITY_EN_ENABLE)
+		ret = _TRUE;
+
+	return ret;
+}
+
+void rtw_odm_adaptivity_parm_msg(void *sel, _adapter *adapter)
+{
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &pHalData->odmpriv;
+
+	rtw_odm_adaptivity_config_msg(sel, adapter);
+
+	DBG_871X_SEL_NL(sel, "%10s %16s %16s %22s %12s\n"
+		, "TH_L2H_ini", "TH_EDCCA_HL_diff", "TH_L2H_ini_mode2", "TH_EDCCA_HL_diff_mode2", "EDCCA_enable");
+	DBG_871X_SEL_NL(sel, "0x%-8x %-16d 0x%-14x %-22d %-12d\n"
+		, (u8)odm->TH_L2H_ini
+		, odm->TH_EDCCA_HL_diff
+		, (u8)odm->TH_L2H_ini_mode2
+		, odm->TH_EDCCA_HL_diff_mode2
+		, odm->EDCCA_enable
+	);
+
+	DBG_871X_SEL_NL(sel, "%15s %9s\n", "AdapEnableState", "Adap_Flag");
+	DBG_871X_SEL_NL(sel, "%-15x %-9x\n"
+		, odm->Adaptivity_enable
+		, odm->adaptivity_flag
+	);
+}
+
+void rtw_odm_adaptivity_parm_set(_adapter *adapter, s8 TH_L2H_ini, s8 TH_EDCCA_HL_diff, s8 TH_L2H_ini_mode2, s8 TH_EDCCA_HL_diff_mode2, u8 EDCCA_enable)
+{
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &pHalData->odmpriv;
+
+	odm->TH_L2H_ini = TH_L2H_ini;
+	odm->TH_EDCCA_HL_diff = TH_EDCCA_HL_diff;
+	odm->TH_L2H_ini_mode2 = TH_L2H_ini_mode2;
+	odm->TH_EDCCA_HL_diff_mode2 = TH_EDCCA_HL_diff_mode2;
+	odm->EDCCA_enable = EDCCA_enable;
+}
+
+void rtw_odm_get_perpkt_rssi(void *sel, _adapter *adapter)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	DM_ODM_T *odm = &(hal_data->odmpriv);	
+	
+	DBG_871X_SEL_NL(sel,"RxRate = %s, RSSI_A = %d(%%), RSSI_B = %d(%%)\n", 
+	HDATA_RATE(odm->RxRate), odm->RSSI_A, odm->RSSI_B);	
+}
+
+
+void rtw_odm_acquirespinlock(_adapter *adapter,	RT_SPINLOCK_TYPE type)
+{
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(adapter);
+	_irqL irqL;
+
+	switch(type)
+	{
+		case RT_IQK_SPINLOCK:
+			_enter_critical_bh(&pHalData->IQKSpinLock, &irqL);
+		default:
+			break;
+	}
+}
+
+void rtw_odm_releasespinlock(_adapter *adapter,	RT_SPINLOCK_TYPE type)
+{
+	PHAL_DATA_TYPE	pHalData = GET_HAL_DATA(adapter);
+	_irqL irqL;
+
+	switch(type)
+	{
+		case RT_IQK_SPINLOCK:
+			_exit_critical_bh(&pHalData->IQKSpinLock, &irqL);
+		default:
+			break;
+	}
+}
+
+#ifdef CONFIG_DFS_MASTER
+VOID rtw_odm_radar_detect_reset(_adapter *adapter)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	PDM_ODM_T pDM_Odm = &(hal_data->odmpriv);
+
+	if (pDM_Odm->SupportICType & ODM_RTL8192D) {
+		ODM_SetBBReg(pDM_Odm, 0xc84 , BIT25, 0);
+		ODM_SetBBReg(pDM_Odm, 0xc84 , BIT25, 1);
+	} else if (pDM_Odm->SupportICType & ODM_RTL8821) {
+		ODM_SetBBReg(pDM_Odm, 0x924 , BIT15, 0);
+		ODM_SetBBReg(pDM_Odm, 0x924 , BIT15, 1);
+	} else {
+		/* not supported yet */
+		rtw_warn_on(1);
+	}
+}
+
+VOID rtw_odm_radar_detect_disable(_adapter *adapter)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	PDM_ODM_T pDM_Odm = &(hal_data->odmpriv);
+
+	if (pDM_Odm->SupportICType & ODM_RTL8192D)
+		ODM_SetBBReg(pDM_Odm, 0xc84 , BIT25, 0);
+	else if (pDM_Odm->SupportICType & ODM_RTL8821)
+		ODM_SetBBReg(pDM_Odm, 0x924 , BIT15, 0);
+	else
+		rtw_warn_on(1);
+}
+
+/* called after ch, bw is set, chance to adjust parameter for different ch conditions */
+VOID rtw_odm_radar_detect_enable(_adapter *adapter)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	PDM_ODM_T pDM_Odm = &(hal_data->odmpriv);
+
+	if (pDM_Odm->SupportICType & ODM_RTL8192D) {
+		ODM_SetBBReg(pDM_Odm, 0xc38, BIT23 | BIT22, 2);
+		ODM_SetBBReg(pDM_Odm, 0x814, bMaskDWord, 0x04cc4d10);
+		ODM_SetBBReg(pDM_Odm, 0xc8c, BIT23 | BIT22, 3);
+		ODM_SetBBReg(pDM_Odm, 0xc30, 0xf, 0xa);
+		ODM_SetBBReg(pDM_Odm, 0xcdc, 0xf0000, 4);
+	} else if (pDM_Odm->SupportICType & ODM_RTL8821) {
+		ODM_SetBBReg(pDM_Odm, 0x814, 0x3fffffff, 0x04cc4d10);
+		ODM_SetBBReg(pDM_Odm, 0x834, bMaskByte0, 0x06);
+		ODM_SetBBReg(pDM_Odm, 0x918, bMaskDWord, 0x1c16ecdf);
+		ODM_SetBBReg(pDM_Odm, 0x924, bMaskDWord, 0x0152a400);
+		ODM_SetBBReg(pDM_Odm, 0x91c, bMaskDWord, 0x0fa21a20);
+		ODM_SetBBReg(pDM_Odm, 0x920, bMaskDWord, 0xe0f57204);
+	} else {
+		/* not supported yet */
+		rtw_warn_on(1);
+	}
+
+	rtw_odm_radar_detect_reset(adapter);
+}
+
+BOOLEAN rtw_odm_radar_detect(_adapter *adapter)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	PDM_ODM_T pDM_Odm = &(hal_data->odmpriv);
+	BOOLEAN enable_DFS = FALSE;
+	BOOLEAN bypass = FALSE;
+	BOOLEAN radar_detected = FALSE;
+
+	static u8Byte last_tx_unicast = 0;
+	static u8Byte last_rx_unicast = 0;
+	static u8Byte throughput = 0;
+	int tp_th = ((*pDM_Odm->pBandWidth == ODM_BW40M) ? 45 : 20); /*refer AP team's testing number*/
+
+	throughput = (*(pDM_Odm->pNumTxBytesUnicast) - last_tx_unicast) + (*(pDM_Odm->pNumRxBytesUnicast) - last_rx_unicast);
+	last_tx_unicast = *(pDM_Odm->pNumTxBytesUnicast);
+	last_rx_unicast = *(pDM_Odm->pNumRxBytesUnicast);
+
+	if (throughput>>18 > tp_th) {
+		if (pDM_Odm->SupportICType & ODM_RTL8192D)
+			ODM_SetBBReg(pDM_Odm, 0xcdc, BIT8|BIT9, 0);
+		bypass = TRUE;
+	} else {
+		if (pDM_Odm->SupportICType & ODM_RTL8192D)
+			ODM_SetBBReg(pDM_Odm, 0xcdc, BIT8|BIT9, 1);
+	}
+
+	if (pDM_Odm->SupportICType & ODM_RTL8192D) {
+		if (ODM_GetBBReg(pDM_Odm , 0xc84, BIT25))
+			enable_DFS = TRUE;
+	} else if (pDM_Odm->SupportICType & ODM_RTL8821) {
+		if (ODM_GetBBReg(pDM_Odm , 0x924, BIT15))
+			enable_DFS = TRUE;
+	}
+
+	if (pDM_Odm->SupportICType & ODM_RTL8192D) {
+		if (ODM_GetBBReg(pDM_Odm , 0xcf8, BIT23))
+			radar_detected = TRUE;
+	} else if (pDM_Odm->SupportICType & ODM_RTL8821) {
+		if (ODM_GetBBReg(pDM_Odm , 0xf98, BIT17))
+			radar_detected = TRUE;
+	}
+
+	ODM_RT_TRACE(pDM_Odm, ODM_COMP_COMMON, ODM_DBG_LOUD
+		, ("Radar detect: enable_DFS:%d, radar_detected:%d, bypass:%d\n"
+			, enable_DFS, radar_detected, bypass));
+	if (0)
+		DBG_871X("Radar detect: enable_DFS:%d, radar_detected:%d, bypass:%d(throughput:%llu, tp_th:%d)\n"
+			, enable_DFS, radar_detected, bypass, throughput, tp_th);
+
+	if (enable_DFS && radar_detected)
+		rtw_odm_radar_detect_reset(adapter);
+
+exit:
+	return (enable_DFS && radar_detected && !bypass);
+}
+#endif /* CONFIG_DFS_MASTER */
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_p2p.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_p2p.c
new file mode 100644
index 000000000..1917acbdd
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_p2p.c
@@ -0,0 +1,5624 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_P2P_C_
+
+#include <drv_types.h>
+
+#ifdef CONFIG_P2P
+
+int rtw_p2p_is_channel_list_ok( u8 desired_ch, u8* ch_list, u8 ch_cnt )
+{
+	int found = 0, i = 0;
+
+	for( i = 0; i < ch_cnt; i++ )
+	{
+		if ( ch_list[ i ] == desired_ch )
+		{
+			found = 1;
+			break;
+		}
+	}
+	return( found );
+}
+
+int is_any_client_associated(_adapter *padapter)
+{
+	return padapter->stapriv.asoc_list_cnt ? _TRUE : _FALSE;
+}
+
+static u32 go_add_group_info_attr(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	_irqL irqL;
+	_list	*phead, *plist;
+	u32 len=0;
+	u16 attr_len = 0;
+	u8 tmplen, *pdata_attr, *pstart, *pcur;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = pwdinfo->padapter;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	pdata_attr = rtw_zmalloc(MAX_P2P_IE_LEN);
+
+	if(NULL == pdata_attr){
+		DBG_871X("%s pdata_attr malloc failed \n", __FUNCTION__);
+		goto _exit;
+	}
+	
+	pstart = pdata_attr;
+	pcur = pdata_attr;
+
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+	phead = &pstapriv->asoc_list;
+	plist = get_next(phead);
+
+	//look up sta asoc_queue
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)	
+	{		
+		psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		
+		plist = get_next(plist);
+		
+
+		if(psta->is_p2p_device)
+		{
+			tmplen = 0;
+			
+			pcur++;
+		
+			//P2P device address
+			_rtw_memcpy(pcur, psta->dev_addr, ETH_ALEN);
+			pcur += ETH_ALEN;
+
+			//P2P interface address
+			_rtw_memcpy(pcur, psta->hwaddr, ETH_ALEN);
+			pcur += ETH_ALEN;
+
+			*pcur = psta->dev_cap;
+			pcur++;
+
+			//*(u16*)(pcur) = cpu_to_be16(psta->config_methods);
+			RTW_PUT_BE16(pcur, psta->config_methods);
+			pcur += 2;
+
+			_rtw_memcpy(pcur, psta->primary_dev_type, 8);
+			pcur += 8;
+
+			*pcur = psta->num_of_secdev_type;
+			pcur++;
+
+			_rtw_memcpy(pcur, psta->secdev_types_list, psta->num_of_secdev_type*8);
+			pcur += psta->num_of_secdev_type*8;
+			
+			if(psta->dev_name_len>0)
+			{
+				//*(u16*)(pcur) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+				RTW_PUT_BE16(pcur, WPS_ATTR_DEVICE_NAME);
+				pcur += 2;
+
+				//*(u16*)(pcur) = cpu_to_be16( psta->dev_name_len );
+				RTW_PUT_BE16(pcur, psta->dev_name_len);
+				pcur += 2;
+
+				_rtw_memcpy(pcur, psta->dev_name, psta->dev_name_len);
+				pcur += psta->dev_name_len;
+			}
+
+
+			tmplen = (u8)(pcur-pstart);
+			
+			*pstart = (tmplen-1);
+
+			attr_len += tmplen;
+
+			//pstart += tmplen;
+			pstart = pcur;
+			
+		}
+		
+		
+	}
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+
+	if(attr_len>0)
+	{
+		len = rtw_set_p2p_attr_content(pbuf, P2P_ATTR_GROUP_INFO, attr_len, pdata_attr);
+	}
+
+	rtw_mfree(pdata_attr, MAX_P2P_IE_LEN);
+	
+_exit:
+	return len;
+
+}
+
+static void issue_group_disc_req(struct wifidirect_info *pwdinfo, u8 *da)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	_adapter *padapter = pwdinfo->padapter;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);	
+	unsigned char category = RTW_WLAN_CATEGORY_P2P;//P2P action frame	
+	u32	p2poui = cpu_to_be32(P2POUI);
+	u8	oui_subtype = P2P_GO_DISC_REQUEST;
+	u8	dialogToken=0;
+
+	DBG_871X("[%s]\n", __FUNCTION__);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	//Build P2P action frame header
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));		
+
+	//there is no IE in this P2P action frame
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+}
+
+static void issue_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
+{	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	_adapter *padapter = pwdinfo->padapter;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);	
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_DEVDISC_RESP;
+	u8 p2pie[8] = { 0x00 };
+	u32 p2pielen = 0;	
+
+	DBG_871X("[%s]\n", __FUNCTION__);
+	
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, pwdinfo->device_addr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, pwdinfo->device_addr, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	//Build P2P public action frame header
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));		
+
+
+	//Build P2P IE
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	// P2P_ATTR_STATUS
+	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
+	
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &pattrib->pktlen);	
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+}
+
+static void issue_p2p_provision_resp(struct wifidirect_info *pwdinfo, u8* raddr, u8* frame_body, u16 config_method)
+{
+	_adapter *padapter = pwdinfo->padapter;
+	unsigned char category = RTW_WLAN_CATEGORY_PUBLIC;
+	u8			action = P2P_PUB_ACTION_ACTION;
+	u8			dialogToken = frame_body[7];	//	The Dialog Token of provisioning discovery request frame.
+	u32			p2poui = cpu_to_be32(P2POUI);
+	u8			oui_subtype = P2P_PROVISION_DISC_RESP;
+	u8			wpsie[ 100 ] = { 0x00 };
+	u8			wpsielen = 0;
+#ifdef CONFIG_WFD
+	u32					wfdielen = 0;
+#endif
+	
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, raddr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, adapter_mac_addr(padapter), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(action), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));		
+
+	wpsielen = 0;
+	//	WPS OUI
+	//*(u32*) ( wpsie ) = cpu_to_be32( WPSOUI );
+	RTW_PUT_BE32(wpsie, WPSOUI);
+	wpsielen += 4;
+
+#if 0
+	//	WPS version
+	//	Type:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_VER1 );
+	wpsielen += 2;
+
+	//	Length:
+	*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0001 );
+	wpsielen += 2;
+
+	//	Value:
+	wpsie[wpsielen++] = WPS_VERSION_1;	//	Version 1.0
+#endif
+
+	//	Config Method
+	//	Type:
+	//*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( WPS_ATTR_CONF_METHOD );
+	RTW_PUT_BE16(wpsie + wpsielen, WPS_ATTR_CONF_METHOD);
+	wpsielen += 2;
+
+	//	Length:
+	//*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( 0x0002 );
+	RTW_PUT_BE16(wpsie + wpsielen, 0x0002);
+	wpsielen += 2;
+
+	//	Value:
+	//*(u16*) ( wpsie + wpsielen ) = cpu_to_be16( config_method );
+	RTW_PUT_BE16(wpsie + wpsielen, config_method);
+	wpsielen += 2;
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wpsielen, (unsigned char *) wpsie, &pattrib->pktlen );	
+
+#ifdef CONFIG_WFD
+	wfdielen = build_provdisc_resp_wfd_ie(pwdinfo, pframe);
+	pframe += wfdielen;
+	pattrib->pktlen += wfdielen;
+#endif
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	return;
+
+}
+
+static void issue_p2p_presence_resp(struct wifidirect_info *pwdinfo, u8 *da, u8 status, u8 dialogToken)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl;
+	_adapter *padapter = pwdinfo->padapter;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);	
+	unsigned char category = RTW_WLAN_CATEGORY_P2P;//P2P action frame	
+	u32	p2poui = cpu_to_be32(P2POUI);
+	u8	oui_subtype = P2P_PRESENCE_RESPONSE;	
+	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
+	u8 noa_attr_content[32] = { 0x00 };
+	u32 p2pielen = 0;
+
+	DBG_871X("[%s]\n", __FUNCTION__);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+	{
+		return;
+	}
+
+	//update attribute
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, pwdinfo->interface_addr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, pwdinfo->interface_addr, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	//Build P2P action frame header
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 4, (unsigned char *) &(p2poui), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(oui_subtype), &(pattrib->pktlen));	
+	pframe = rtw_set_fixed_ie(pframe, 1, &(dialogToken), &(pattrib->pktlen));	
+
+
+	//Add P2P IE header
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//Add Status attribute in P2P IE 
+	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status);
+
+	//Add NoA attribute in P2P IE
+	noa_attr_content[0] = 0x1;//index
+	noa_attr_content[1] = 0x0;//CTWindow and OppPS Parameters
+	
+	//todo: Notice of Absence Descriptor(s)
+	
+	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_NOA, 2, noa_attr_content);
+
+
+
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, p2pielen, p2pie, &(pattrib->pktlen));
+
+	
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+
+}
+
+u32 build_beacon_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
+	u16 capability=0;
+	u32 len=0, p2pielen = 0;
+	
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+
+	//	According to the P2P Specification, the beacon frame should contain 3 P2P attributes
+	//	1. P2P Capability
+	//	2. P2P Device ID
+	//	3. Notice of Absence ( NOA )	
+
+	//	P2P Capability ATTR
+	//	Type:
+	//	Length:
+	//	Value:
+	//	Device Capability Bitmap, 1 byte
+	//	Be able to participate in additional P2P Groups and
+	//	support the P2P Invitation Procedure	
+	//	Group Capability Bitmap, 1 byte	
+	capability = P2P_DEVCAP_INVITATION_PROC|P2P_DEVCAP_CLIENT_DISCOVERABILITY;
+	capability |=  ((P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS) << 8);
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+		capability |= (P2P_GRPCAP_GROUP_FORMATION<<8);
+
+	capability = cpu_to_le16(capability);
+
+	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_CAPABILITY, 2, (u8*)&capability);
+
+	
+	// P2P Device ID ATTR
+	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_DEVICE_ID, ETH_ALEN, pwdinfo->device_addr);
+
+	
+	// Notice of Absence ATTR
+	//	Type: 
+	//	Length:
+	//	Value:
+	
+	//go_add_noa_attr(pwdinfo);
+	
+	
+	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
+	
+	
+	return len;
+	
+}
+
+#ifdef CONFIG_WFD
+u32 build_beacon_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u16 val16=0;
+	u32 len=0, wfdielen = 0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110812
+	//	According to the WFD Specification, the beacon frame should contain 4 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID
+	//	3. Coupled Sink Information
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+
+	if ( P2P_ROLE_GO == pwdinfo->role )
+	{
+		if ( is_any_client_associated( pwdinfo->padapter ) )
+		{
+			//	WFD primary sink + WiFi Direct mode + WSD (WFD Service Discovery)
+			val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD;
+			RTW_PUT_BE16(wfdie + wfdielen, val16);			
+		}
+		else
+		{
+			//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD (WFD Service Discovery)
+			val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+			RTW_PUT_BE16(wfdie + wfdielen, val16);
+		}
+
+	}
+	else
+	{
+		//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+		val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+		RTW_PUT_BE16(wfdie + wfdielen, val16);
+	}
+	
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_probe_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u16 val16=0;
+	u32 len=0, wfdielen = 0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110812
+	//	According to the WFD Specification, the probe request frame should contain 4 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID
+	//	3. Coupled Sink Information
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+
+	if ( 1 == pwdinfo->wfd_tdls_enable )
+	{
+		//	WFD primary sink + available for WFD session + WiFi TDLS mode + WSC ( WFD Service Discovery )	
+		val16 = pwfd_info->wfd_device_type | 
+						WFD_DEVINFO_SESSION_AVAIL | 
+						WFD_DEVINFO_WSD |
+						WFD_DEVINFO_PC_TDLS;
+		RTW_PUT_BE16(wfdie + wfdielen, val16 );
+	}
+	else
+	{
+		//	WFD primary sink + available for WFD session + WiFi Direct mode + WSC ( WFD Service Discovery )	
+		val16 = pwfd_info->wfd_device_type |
+						WFD_DEVINFO_SESSION_AVAIL | 
+						WFD_DEVINFO_WSD;
+		RTW_PUT_BE16(wfdie + wfdielen, val16 );
+	}
+
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_probe_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 tunneled)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110812
+	//	According to the WFD Specification, the probe response frame should contain 4 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID
+	//	3. Coupled Sink Information
+	//	4. WFD Session Information
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode
+	
+	if (  _TRUE == pwdinfo->session_available )
+	{
+		if ( P2P_ROLE_GO == pwdinfo->role )
+		{
+			if ( is_any_client_associated( pwdinfo->padapter ) )
+			{
+				if ( pwdinfo->wfd_tdls_enable )
+				{
+					//	TDLS mode + WSD ( WFD Service Discovery )
+					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
+				}
+				else
+				{
+					//	WiFi Direct mode + WSD ( WFD Service Discovery )
+					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
+				}				
+			}
+			else
+			{
+				if ( pwdinfo->wfd_tdls_enable )
+				{
+					//	available for WFD session + TDLS mode + WSD ( WFD Service Discovery )
+					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
+				}
+				else
+				{
+					//	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+					RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
+				}				
+			}
+		}
+		else
+		{
+			if ( pwdinfo->wfd_tdls_enable )
+			{
+				//	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+				RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
+			}
+			else
+			{
+
+				//	available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+				RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
+			}
+		}
+	}
+	else
+	{
+		if ( pwdinfo->wfd_tdls_enable )
+		{
+			RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD |WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_HDCP_SUPPORT);
+		}
+		else
+		{
+			RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_HDCP_SUPPORT);
+		}
+
+	}
+
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+	{
+		//	WFD Session Information ATTR
+		//	Type:
+		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
+
+		//	Length:
+		//	Note: In the WFD specification, the size of length field is 2.
+		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
+		wfdielen += 2;
+
+		//	Todo: to add the list of WFD device info descriptor in WFD group.
+
+	}
+#ifdef CONFIG_CONCURRENT_MODE
+#ifdef CONFIG_TDLS
+	if ( ( tunneled == 0 ) && ( padapter->pbuddy_adapter->wdinfo.wfd_tdls_enable == 1 ) )
+	{
+		//	Alternative MAC Address ATTR
+		//	Type:
+		wfdie[ wfdielen++ ] = WFD_ATTR_ALTER_MAC;
+
+		//	Length:
+		//	Note: In the WFD specification, the size of length field is 2.
+		RTW_PUT_BE16(wfdie + wfdielen,  ETH_ALEN );
+		wfdielen += 2;
+
+		//	Value:
+		//	Alternative MAC Address
+		_rtw_memcpy(wfdie + wfdielen, adapter_mac_addr(padapter->pbuddy_adapter), ETH_ALEN);
+		//	This mac address is used to make the WFD session when TDLS is enable.
+
+		wfdielen += ETH_ALEN;
+	}
+#endif // CONFIG_TDLS
+#endif // CONFIG_CONCURRENT_MODE
+
+	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_assoc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u16 val16=0;
+	u32 len=0, wfdielen = 0;
+	_adapter 					*padapter = NULL;
+	struct mlme_priv			*pmlmepriv = NULL;
+	struct wifi_display_info		*pwfd_info = NULL;
+
+	padapter = pwdinfo->padapter;
+	pmlmepriv = &padapter->mlmepriv;
+	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+		goto exit;
+
+	/* WFD OUI */
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110812
+	//	According to the WFD Specification, the probe request frame should contain 4 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID
+	//	3. Coupled Sink Information
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_assoc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110812
+	//	According to the WFD Specification, the probe request frame should contain 4 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID
+	//	3. Coupled Sink Information
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_nego_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_nego_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_nego_confirm_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + WiFi Direct mode + WSD ( WFD Service Discovery ) + WFD Session Available
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_WSD | WFD_DEVINFO_SESSION_AVAIL;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+
+	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_invitation_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	if ( P2P_ROLE_GO == pwdinfo->role )
+	{
+		//	WFD Session Information ATTR
+		//	Type:
+		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
+
+		//	Length:
+		//	Note: In the WFD specification, the size of length field is 2.
+		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
+		wfdielen += 2;
+
+		//	Todo: to add the list of WFD device info descriptor in WFD group.
+
+	}
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_invitation_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u16 val16=0;
+	u32 len=0, wfdielen = 0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	if ( P2P_ROLE_GO == pwdinfo->role )
+	{
+		//	WFD Session Information ATTR
+		//	Type:
+		wfdie[ wfdielen++ ] = WFD_ATTR_SESSION_INFO;
+
+		//	Length:
+		//	Note: In the WFD specification, the size of length field is 2.
+		RTW_PUT_BE16(wfdie + wfdielen, 0x0000);
+		wfdielen += 2;
+
+		//	Todo: to add the list of WFD device info descriptor in WFD group.
+
+	}
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_provdisc_req_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the provision discovery request frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+
+u32 build_provdisc_resp_wfd_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 len=0, wfdielen = 0;
+	u16 val16=0;
+	_adapter *padapter = pwdinfo->padapter;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info*	pwfd_info = padapter->wdinfo.wfd_info;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+	//	WFD OUI
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	//	WFA WFD v1.0
+
+	//	Commented by Albert 20110825
+	//	According to the WFD Specification, the provision discovery response frame should contain 3 WFD attributes
+	//	1. WFD Device Information
+	//	2. Associated BSSID ( Optional )
+	//	3. Local IP Adress ( Optional )
+
+
+	//	WFD Device Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value1:
+	//	WFD device information
+	//	WFD primary sink + available for WFD session + WiFi Direct mode + WSD ( WFD Service Discovery )
+	val16 = pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL | WFD_DEVINFO_WSD;
+	RTW_PUT_BE16(wfdie + wfdielen, val16);
+	wfdielen += 2;
+
+	//	Value2:
+	//	Session Management Control Port
+	//	Default TCP port for RTSP messages is 554
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->rtsp_ctrlport );
+	wfdielen += 2;
+
+	//	Value3:
+	//	WFD Device Maximum Throughput
+	//	300Mbps is the maximum throughput
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	//	Associated BSSID ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	//	Value:
+	//	Associated BSSID
+	if ( check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE )
+	{
+		_rtw_memcpy( wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN );
+	}
+	else
+	{
+		_rtw_memset( wfdie + wfdielen, 0x00, ETH_ALEN );
+	}
+
+	wfdielen += ETH_ALEN;
+
+	//	Coupled Sink Information ATTR
+	//	Type:
+	wfdie[ wfdielen++ ] = WFD_ATTR_COUPLED_SINK_INFO;
+
+	//	Length:
+	//	Note: In the WFD specification, the size of length field is 2.
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0007);
+	wfdielen += 2;
+
+	//	Value:
+	//	Coupled Sink Status bitmap
+	//	Not coupled/available for Coupling
+	wfdie[ wfdielen++ ] = 0;
+	//  MAC Addr.
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+	wfdie[ wfdielen++ ] = 0;
+
+	rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, &len);
+
+exit:
+	return len;
+}
+#endif /* CONFIG_WFD */
+
+u32 build_probe_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
+	u32 len=0, p2pielen = 0;	
+#ifdef CONFIG_INTEL_WIDI
+	struct mlme_priv *pmlmepriv = &(pwdinfo->padapter->mlmepriv);
+	u8 zero_array_check[L2SDTA_SERVICE_VE_LEN] = { 0x00 };
+	u8 widi_version = 0, i = 0;
+
+	if( _rtw_memcmp( pmlmepriv->sa_ext, zero_array_check, L2SDTA_SERVICE_VE_LEN ) == _FALSE )
+	{
+		widi_version = 35;
+	}
+	else if( pmlmepriv->num_p2p_sdt != 0 )
+	{
+		widi_version = 40;
+	}
+#endif //CONFIG_INTEL_WIDI
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20100907
+	//	According to the P2P Specification, the probe response frame should contain 5 P2P attributes
+	//	1. P2P Capability
+	//	2. Extended Listen Timing
+	//	3. Notice of Absence ( NOA )	( Only GO needs this )
+	//	4. Device Info
+	//	5. Group Info	( Only GO need this )
+
+	//	P2P Capability ATTR
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+	//	Length:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
+	p2pielen += 2;
+
+	//	Value:
+	//	Device Capability Bitmap, 1 byte
+	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+	
+	//	Group Capability Bitmap, 1 byte
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+	{
+		p2pie[ p2pielen ] = (P2P_GRPCAP_GO | P2P_GRPCAP_INTRABSS);
+
+		if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_PROVISIONING_ING))
+			p2pie[ p2pielen ] |= P2P_GRPCAP_GROUP_FORMATION;
+
+		p2pielen++;
+	}
+	else if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) )
+	{
+		//	Group Capability Bitmap, 1 byte
+		if ( pwdinfo->persistent_supported )
+			p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+		else
+			p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
+	}
+
+	//	Extended Listen Timing ATTR
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_EX_LISTEN_TIMING;
+
+	//	Length:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0004 );
+	RTW_PUT_LE16(p2pie + p2pielen, 0x0004);
+	p2pielen += 2;
+
+	//	Value:
+	//	Availability Period
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+	RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
+	p2pielen += 2;
+
+	//	Availability Interval
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0xFFFF );
+	RTW_PUT_LE16(p2pie + p2pielen, 0xFFFF);
+	p2pielen += 2;
+
+
+	// Notice of Absence ATTR
+	//	Type: 
+	//	Length:
+	//	Value:
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+	{
+		//go_add_noa_attr(pwdinfo);
+	}	
+
+	//	Device Info ATTR
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
+	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+#ifdef CONFIG_INTEL_WIDI
+	if( widi_version == 35 )
+	{
+		RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 + pwdinfo->device_name_len);
+	}
+	else if( widi_version == 40 )
+	{
+		RTW_PUT_LE16(p2pie + p2pielen, 21 + 8 * pmlmepriv->num_p2p_sdt + pwdinfo->device_name_len);
+	}
+	else
+#endif //CONFIG_INTEL_WIDI
+	RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
+	p2pielen += 2;
+
+	//	Value:
+	//	P2P Device Address
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );
+	p2pielen += ETH_ALEN;
+
+	//	Config Method
+	//	This field should be big endian. Noted by P2P specification.
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->supported_wps_cm );
+	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->supported_wps_cm);
+	p2pielen += 2;
+
+#ifdef CONFIG_INTEL_WIDI
+	if( widi_version == 40 )
+	{
+		//	Primary Device Type
+		//	Category ID
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+		RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_cid );
+		p2pielen += 2;
+
+		//	OUI
+		//*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+		RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
+		p2pielen += 4;
+
+		//	Sub Category ID
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+		RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_pdt_scid);
+		p2pielen += 2;
+	}
+	else
+#endif //CONFIG_INTEL_WIDI
+	{
+		//	Primary Device Type
+		//	Category ID
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+		RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
+		p2pielen += 2;
+
+		//	OUI
+		//*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+		RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
+		p2pielen += 4;
+
+		//	Sub Category ID
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+		RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
+		p2pielen += 2;
+	}
+
+	//	Number of Secondary Device Types
+#ifdef CONFIG_INTEL_WIDI
+	if( widi_version == 35 )
+	{
+		p2pie[ p2pielen++ ] = 0x01;
+		
+		RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_DISPLAYS);
+		p2pielen += 2;
+
+		RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI);
+		p2pielen += 4;
+
+		RTW_PUT_BE16(p2pie + p2pielen, P2P_SCID_WIDI_CONSUMER_SINK);
+		p2pielen += 2;
+	}
+	else if( widi_version == 40 )
+	{
+		p2pie[ p2pielen++ ] = pmlmepriv->num_p2p_sdt;
+		for( ; i < pmlmepriv->num_p2p_sdt; i++ )
+		{
+			RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_cid[i]);
+			p2pielen += 2;
+
+			RTW_PUT_BE32(p2pie + p2pielen, INTEL_DEV_TYPE_OUI);
+			p2pielen += 4;
+
+			RTW_PUT_BE16(p2pie + p2pielen, pmlmepriv->p2p_sdt_scid[i]);
+			p2pielen += 2;
+		}
+	}
+	else
+#endif //CONFIG_INTEL_WIDI
+	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
+
+	//	Device Name
+	//	Type:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+	RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
+	p2pielen += 2;
+
+	//	Length:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
+	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
+	p2pielen += pwdinfo->device_name_len;
+
+	// Group Info ATTR
+	//	Type:
+	//	Length:
+	//	Value:
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+	{
+		p2pielen += go_add_group_info_attr(pwdinfo, p2pie + p2pielen);
+	}
+
+	
+	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
+	
+
+	return len;
+	
+}
+
+u32 build_prov_disc_request_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8* pssid, u8 ussidlen, u8* pdev_raddr )
+{
+	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
+	u32 len=0, p2pielen = 0;	
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	//	Commented by Albert 20110301
+	//	According to the P2P Specification, the provision discovery request frame should contain 3 P2P attributes
+	//	1. P2P Capability
+	//	2. Device Info
+	//	3. Group ID ( When joining an operating P2P Group )
+
+	//	P2P Capability ATTR
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_CAPABILITY;
+
+	//	Length:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 0x0002 );
+	RTW_PUT_LE16(p2pie + p2pielen, 0x0002);
+	p2pielen += 2;
+
+	//	Value:
+	//	Device Capability Bitmap, 1 byte
+	p2pie[ p2pielen++ ] = DMP_P2P_DEVCAP_SUPPORT;
+	
+	//	Group Capability Bitmap, 1 byte
+	if ( pwdinfo->persistent_supported )
+		p2pie[ p2pielen++ ] = P2P_GRPCAP_PERSISTENT_GROUP | DMP_P2P_GRPCAP_SUPPORT;
+	else
+		p2pie[ p2pielen++ ] = DMP_P2P_GRPCAP_SUPPORT;
+
+
+	//	Device Info ATTR
+	//	Type:
+	p2pie[ p2pielen++ ] = P2P_ATTR_DEVICE_INFO;
+
+	//	Length:
+	//	21 -> P2P Device Address (6bytes) + Config Methods (2bytes) + Primary Device Type (8bytes) 
+	//	+ NumofSecondDevType (1byte) + WPS Device Name ID field (2bytes) + WPS Device Name Len field (2bytes)
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( 21 + pwdinfo->device_name_len );
+	RTW_PUT_LE16(p2pie + p2pielen, 21 + pwdinfo->device_name_len);
+	p2pielen += 2;
+
+	//	Value:
+	//	P2P Device Address
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_addr, ETH_ALEN );
+	p2pielen += ETH_ALEN;
+
+	//	Config Method
+	//	This field should be big endian. Noted by P2P specification.
+	if ( pwdinfo->ui_got_wps_info == P2P_GOT_WPSINFO_PBC )
+	{
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_PBC );
+		RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_PBC);
+	}
+	else
+	{
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_CONFIG_METHOD_DISPLAY );
+		RTW_PUT_BE16(p2pie + p2pielen, WPS_CONFIG_METHOD_DISPLAY);
+	}
+
+	p2pielen += 2;
+
+	//	Primary Device Type
+	//	Category ID
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_CID_MULIT_MEDIA );
+	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_CID_MULIT_MEDIA);
+	p2pielen += 2;
+
+	//	OUI
+	//*(u32*) ( p2pie + p2pielen ) = cpu_to_be32( WPSOUI );
+	RTW_PUT_BE32(p2pie + p2pielen, WPSOUI);
+	p2pielen += 4;
+
+	//	Sub Category ID
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_PDT_SCID_MEDIA_SERVER );
+	RTW_PUT_BE16(p2pie + p2pielen, WPS_PDT_SCID_MEDIA_SERVER);
+	p2pielen += 2;
+
+	//	Number of Secondary Device Types
+	p2pie[ p2pielen++ ] = 0x00;	//	No Secondary Device Type List
+
+	//	Device Name
+	//	Type:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( WPS_ATTR_DEVICE_NAME );
+	RTW_PUT_BE16(p2pie + p2pielen, WPS_ATTR_DEVICE_NAME);
+	p2pielen += 2;
+
+	//	Length:
+	//*(u16*) ( p2pie + p2pielen ) = cpu_to_be16( pwdinfo->device_name_len );
+	RTW_PUT_BE16(p2pie + p2pielen, pwdinfo->device_name_len);
+	p2pielen += 2;
+
+	//	Value:
+	_rtw_memcpy( p2pie + p2pielen, pwdinfo->device_name, pwdinfo->device_name_len );
+	p2pielen += pwdinfo->device_name_len;
+
+	if ( rtw_p2p_chk_role(pwdinfo, P2P_ROLE_CLIENT) )
+	{
+		//	Added by Albert 2011/05/19
+		//	In this case, the pdev_raddr is the device address of the group owner.
+		
+		//	P2P Group ID ATTR
+		//	Type:
+		p2pie[ p2pielen++ ] = P2P_ATTR_GROUP_ID;
+
+		//	Length:
+		//*(u16*) ( p2pie + p2pielen ) = cpu_to_le16( ETH_ALEN + ussidlen );
+		RTW_PUT_LE16(p2pie + p2pielen, ETH_ALEN + ussidlen);
+		p2pielen += 2;
+
+		//	Value:
+		_rtw_memcpy( p2pie + p2pielen, pdev_raddr, ETH_ALEN );
+		p2pielen += ETH_ALEN;
+
+		_rtw_memcpy( p2pie + p2pielen, pssid, ussidlen );
+		p2pielen += ussidlen;
+		
+	}
+
+	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
+	
+
+	return len;
+	
+}
+
+
+u32 build_assoc_resp_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf, u8 status_code)
+{
+	u8 p2pie[ MAX_P2P_IE_LEN] = { 0x00 };
+	u32 len=0, p2pielen = 0;	
+
+	//	P2P OUI
+	p2pielen = 0;
+	p2pie[ p2pielen++ ] = 0x50;
+	p2pie[ p2pielen++ ] = 0x6F;
+	p2pie[ p2pielen++ ] = 0x9A;
+	p2pie[ p2pielen++ ] = 0x09;	//	WFA P2P v1.0
+
+	// According to the P2P Specification, the Association response frame should contain 2 P2P attributes
+	//	1. Status
+	//	2. Extended Listen Timing (optional)
+
+
+	//	Status ATTR
+	p2pielen += rtw_set_p2p_attr_content(&p2pie[p2pielen], P2P_ATTR_STATUS, 1, &status_code);
+
+
+	// Extended Listen Timing ATTR
+	//	Type:
+	//	Length:
+	//	Value:
+
+
+	pbuf = rtw_set_ie(pbuf, _VENDOR_SPECIFIC_IE_, p2pielen, (unsigned char *) p2pie, &len);
+	
+	return len;
+	
+}
+
+u32 build_deauth_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pbuf)
+{
+	u32 len=0;
+	
+	return len;
+}
+
+u32 process_probe_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{	
+	u8 *p;
+	u32 ret=_FALSE;
+	u8 *p2pie;
+	u32	p2pielen = 0;
+	int ssid_len=0, rate_cnt = 0;
+
+	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SUPPORTEDRATES_IE_, (int *)&rate_cnt,
+			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);
+
+	if ( rate_cnt <= 4 )
+	{
+		int i, g_rate =0;
+
+		for( i = 0; i < rate_cnt; i++ )
+		{
+			if ( ( ( *( p + 2 + i ) & 0xff ) != 0x02 ) &&
+				( ( *( p + 2 + i ) & 0xff ) != 0x04 ) &&
+				( ( *( p + 2 + i ) & 0xff ) != 0x0B ) &&
+				( ( *( p + 2 + i ) & 0xff ) != 0x16 ) )
+			{
+				g_rate = 1;
+			}
+		}
+
+		if ( g_rate == 0 )
+		{
+			//	There is no OFDM rate included in SupportedRates IE of this probe request frame
+			//	The driver should response this probe request.
+			return ret;
+		}
+	}
+	else
+	{
+		//	rate_cnt > 4 means the SupportRates IE contains the OFDM rate because the count of CCK rates are 4.
+		//	We should proceed the following check for this probe request.
+	}
+
+	//	Added comments by Albert 20100906
+	//	There are several items we should check here.
+	//	1. This probe request frame must contain the P2P IE. (Done)
+	//	2. This probe request frame must contain the wildcard SSID. (Done)
+	//	3. Wildcard BSSID. (Todo)
+	//	4. Destination Address. ( Done in mgt_dispatcher function )
+	//	5. Requested Device Type in WSC IE. (Todo)
+	//	6. Device ID attribute in P2P IE. (Todo)
+
+	p = rtw_get_ie(pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_, _SSID_IE_, (int *)&ssid_len,
+			len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_);	
+
+	ssid_len &= 0xff;	//	Just last 1 byte is valid for ssid len of the probe request
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE) || rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+	{
+		if((p2pie=rtw_get_p2p_ie( pframe + WLAN_HDR_A3_LEN + _PROBEREQ_IE_OFFSET_ , len - WLAN_HDR_A3_LEN - _PROBEREQ_IE_OFFSET_ , NULL, &p2pielen)))
+		{
+			if ( (p != NULL) && _rtw_memcmp( ( void * ) ( p+2 ), ( void * ) pwdinfo->p2p_wildcard_ssid , 7 ))
+			{
+				//todo:
+				//Check Requested Device Type attributes in WSC IE.
+				//Check Device ID attribute in P2P IE
+
+				ret = _TRUE;			
+			}
+			else if ( (p != NULL) && ( ssid_len == 0 ) )
+			{
+				ret = _TRUE;
+			}
+		}
+		else
+		{
+			//non -p2p device
+		}
+		
+	}	
+
+	
+	return ret;
+	
+}
+
+u32 process_assoc_req_p2p_ie(struct wifidirect_info *pwdinfo, u8 *pframe, uint len, struct sta_info *psta)
+{
+	u8 status_code = P2P_STATUS_SUCCESS;
+	u8 *pbuf, *pattr_content=NULL;
+	u32 attr_contentlen = 0;
+	u16 cap_attr=0;
+	unsigned short	frame_type, ie_offset=0;
+	u8 * ies;
+	u32 ies_len;
+	u8 * p2p_ie;
+	u32	p2p_ielen = 0;
+
+	if(!rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+		return P2P_STATUS_FAIL_REQUEST_UNABLE;
+
+	frame_type = GetFrameSubType(pframe);
+	if (frame_type == WIFI_ASSOCREQ)
+	{
+		ie_offset = _ASOCREQ_IE_OFFSET_;
+	}	
+	else // WIFI_REASSOCREQ
+	{
+		ie_offset = _REASOCREQ_IE_OFFSET_;
+	}
+	
+	ies = pframe + WLAN_HDR_A3_LEN + ie_offset;
+	ies_len = len - WLAN_HDR_A3_LEN - ie_offset;
+
+	p2p_ie = rtw_get_p2p_ie(ies , ies_len , NULL, &p2p_ielen);
+
+	if ( !p2p_ie )
+	{
+		DBG_8192C( "[%s] P2P IE not Found!!\n", __FUNCTION__ );
+		status_code =  P2P_STATUS_FAIL_INVALID_PARAM;
+	}
+	else
+	{
+		DBG_8192C( "[%s] P2P IE Found!!\n", __FUNCTION__ );
+	}
+	
+	while ( p2p_ie )
+	{
+		//Check P2P Capability ATTR
+		if( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*) &attr_contentlen) )
+		{
+			DBG_8192C( "[%s] Got P2P Capability Attr!!\n", __FUNCTION__ );
+			cap_attr = le16_to_cpu(cap_attr);
+			psta->dev_cap = cap_attr&0xff;
+		}
+
+		//Check Extended Listen Timing ATTR
+	
+
+		//Check P2P Device Info ATTR
+		if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO, NULL, (uint*)&attr_contentlen))
+		{
+			DBG_8192C( "[%s] Got P2P DEVICE INFO Attr!!\n", __FUNCTION__ );		
+			pattr_content = pbuf = rtw_zmalloc(attr_contentlen);
+			if(pattr_content)
+			{
+				u8 num_of_secdev_type;
+				u16 dev_name_len;
+			
+		
+				rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_INFO , pattr_content, (uint*)&attr_contentlen);
+
+				_rtw_memcpy(psta->dev_addr, 	pattr_content, ETH_ALEN);//P2P Device Address
+
+				pattr_content += ETH_ALEN;
+
+				_rtw_memcpy(&psta->config_methods, pattr_content, 2);//Config Methods
+				psta->config_methods = be16_to_cpu(psta->config_methods);
+
+				pattr_content += 2;
+
+				_rtw_memcpy(psta->primary_dev_type, pattr_content, 8);
+
+				pattr_content += 8;
+
+				num_of_secdev_type = *pattr_content;
+				pattr_content += 1;
+
+				if(num_of_secdev_type==0)
+				{
+					psta->num_of_secdev_type = 0;
+				}
+				else
+				{
+					u32 len;
+
+					psta->num_of_secdev_type = num_of_secdev_type;
+
+					len = (sizeof(psta->secdev_types_list)<(num_of_secdev_type*8)) ? (sizeof(psta->secdev_types_list)) : (num_of_secdev_type*8);
+
+					_rtw_memcpy(psta->secdev_types_list, pattr_content, len);
+	
+					pattr_content += (num_of_secdev_type*8);
+				}
+
+
+				//dev_name_len = attr_contentlen - ETH_ALEN - 2 - 8 - 1 - (num_of_secdev_type*8);
+				psta->dev_name_len=0;
+				if(WPS_ATTR_DEVICE_NAME == be16_to_cpu(*(u16*)pattr_content))
+				{				
+					dev_name_len = be16_to_cpu(*(u16*)(pattr_content+2));
+
+					psta->dev_name_len = (sizeof(psta->dev_name)<dev_name_len) ? sizeof(psta->dev_name):dev_name_len;
+
+					_rtw_memcpy(psta->dev_name, pattr_content+4, psta->dev_name_len);
+				}
+
+				rtw_mfree(pbuf, attr_contentlen);
+
+			}
+
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+		
+	}
+
+	return status_code;
+
+}
+
+u32 process_p2p_devdisc_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+	u8 *frame_body;
+	u8 status, dialogToken;
+	struct sta_info *psta = NULL;
+	_adapter *padapter = pwdinfo->padapter;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *p2p_ie;
+	u32	p2p_ielen = 0;	
+	
+	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+	dialogToken = frame_body[7];
+	status = P2P_STATUS_FAIL_UNKNOWN_P2PGROUP;
+		
+	if ( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)) )
+	{
+		u8 groupid[ 38 ] = { 0x00 };
+		u8 dev_addr[ETH_ALEN] = { 0x00 };		
+		u32	attr_contentlen = 0;
+
+		if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen))
+		{
+			if(_rtw_memcmp(pwdinfo->device_addr, groupid, ETH_ALEN) && 
+				_rtw_memcmp(pwdinfo->p2p_group_ssid, groupid+ETH_ALEN, pwdinfo->p2p_group_ssid_len))
+			{
+				attr_contentlen=0;
+				if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_DEVICE_ID, dev_addr, &attr_contentlen))
+				{
+					_irqL irqL;
+					_list	*phead, *plist;					
+
+					_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+					phead = &pstapriv->asoc_list;
+					plist = get_next(phead);
+
+					//look up sta asoc_queue
+					while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)	
+					{		
+						psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
+		
+						plist = get_next(plist);
+
+						if(psta->is_p2p_device && (psta->dev_cap&P2P_DEVCAP_CLIENT_DISCOVERABILITY) &&
+							_rtw_memcmp(psta->dev_addr, dev_addr, ETH_ALEN))
+						{
+
+							//_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+							//issue GO Discoverability Request
+							issue_group_disc_req(pwdinfo, psta->hwaddr);
+							//_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+							
+							status = P2P_STATUS_SUCCESS;
+							
+							break;
+						}
+						else
+						{
+							status = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+						}
+		
+					}				
+					_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
+					
+				}
+				else
+				{
+					status = P2P_STATUS_FAIL_INVALID_PARAM;
+				}
+
+			}
+			else
+			{
+				status = P2P_STATUS_FAIL_INVALID_PARAM;
+			}
+			
+		}	
+		
+	}
+
+	
+	//issue Device Discoverability Response
+	issue_p2p_devdisc_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
+	
+	
+	return (status==P2P_STATUS_SUCCESS) ? _TRUE:_FALSE;
+	
+}
+
+u32 process_p2p_devdisc_resp(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+	return _TRUE;
+}
+
+u8 process_p2p_provdisc_req(struct wifidirect_info *pwdinfo,  u8 *pframe, uint len )
+{
+	u8 *frame_body;
+	u8 *wpsie;
+	uint	wps_ielen = 0, attr_contentlen = 0;
+	u16	uconfig_method = 0;
+	
+
+	frame_body = (pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+	if ( (wpsie=rtw_get_wps_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)) )
+	{
+		if ( rtw_get_wps_attr_content( wpsie, wps_ielen, WPS_ATTR_CONF_METHOD , ( u8* ) &uconfig_method, &attr_contentlen) )
+		{
+			uconfig_method = be16_to_cpu( uconfig_method );
+			switch( uconfig_method )
+			{
+				case WPS_CM_DISPLYA:
+				{
+					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
+					break;
+				}
+				case WPS_CM_LABEL:
+				{
+					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "lab", 3 );
+					break;
+				}
+				case WPS_CM_PUSH_BUTTON:
+				{
+					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );
+					break;
+				}
+				case WPS_CM_KEYPAD:
+				{
+					_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );
+					break;
+				}
+			}
+			issue_p2p_provision_resp( pwdinfo, GetAddr2Ptr(pframe), frame_body, uconfig_method);
+		}
+	}
+	DBG_871X( "[%s] config method = %s\n", __FUNCTION__, pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req );
+	return _TRUE;
+	
+}
+	
+u8 process_p2p_provdisc_resp(struct wifidirect_info *pwdinfo,  u8 *pframe)
+{
+
+	return _TRUE;
+}
+
+u8 rtw_p2p_get_peer_ch_list(struct wifidirect_info *pwdinfo, u8 *ch_content, u8 ch_cnt, u8 *peer_ch_list)
+{
+	u8 i = 0, j = 0;
+	u8 temp = 0;
+	u8 ch_no = 0;
+	ch_content += 3;
+	ch_cnt -= 3;
+
+	while( ch_cnt > 0)
+	{
+		ch_content += 1;
+		ch_cnt -= 1;
+		temp = *ch_content;
+		for( i = 0 ; i < temp ; i++, j++ )
+		{
+			peer_ch_list[j] = *( ch_content + 1 + i );
+		}
+		ch_content += (temp + 1);
+		ch_cnt -= (temp + 1);
+		ch_no += temp ;
+	}
+
+	return ch_no;
+}
+
+u8 rtw_p2p_check_peer_oper_ch(struct mlme_ext_priv *pmlmeext, u8 ch)
+{
+	u8 i = 0;
+
+	for( i = 0; i < pmlmeext->max_chan_nums; i++ )
+	{
+		if ( pmlmeext->channel_set[ i ].ChannelNum == ch )
+		{
+			return _SUCCESS;
+		}
+	}
+
+	return _FAIL;
+}
+
+u8 rtw_p2p_ch_inclusion(struct mlme_ext_priv *pmlmeext, u8 *peer_ch_list, u8 peer_ch_num, u8 *ch_list_inclusioned)
+{
+	int	i = 0, j = 0, temp = 0;
+	u8 ch_no = 0;
+
+	for( i = 0; i < peer_ch_num; i++ )
+	{
+		for( j = temp; j < pmlmeext->max_chan_nums; j++ )
+		{
+			if( *( peer_ch_list + i ) == pmlmeext->channel_set[ j ].ChannelNum )
+			{
+				ch_list_inclusioned[ ch_no++ ] = *( peer_ch_list + i );
+				temp = j;
+				break;
+			}
+		}
+	}
+
+	return ch_no;
+}
+
+u8 process_p2p_group_negotation_req( struct wifidirect_info *pwdinfo, u8 *pframe, uint len )
+{
+	_adapter *padapter = pwdinfo->padapter;
+	u8	result = P2P_STATUS_SUCCESS;
+	u32	p2p_ielen = 0, wps_ielen = 0;
+	u8 * ies;
+	u32 ies_len;
+	u8 *p2p_ie;
+	u8 *wpsie;
+	u16		wps_devicepassword_id = 0x0000;
+	uint	wps_devicepassword_id_len = 0;
+#ifdef CONFIG_WFD
+#ifdef CONFIG_TDLS
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+#endif // CONFIG_TDLS	
+#endif // CONFIG_WFD
+#ifdef CONFIG_CONCURRENT_MODE
+	_adapter				*pbuddy_adapter = pwdinfo->padapter->pbuddy_adapter;
+	struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+	struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+	struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+#endif
+
+	if ( (wpsie=rtw_get_wps_ie( pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &wps_ielen)) )
+	{
+		//	Commented by Kurt 20120113
+		//	If some device wants to do p2p handshake without sending prov_disc_req
+		//	We have to get peer_req_cm from here.
+		if(_rtw_memcmp( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "000", 3) )
+		{
+			rtw_get_wps_attr_content( wpsie, wps_ielen, WPS_ATTR_DEVICE_PWID, (u8*) &wps_devicepassword_id, &wps_devicepassword_id_len);
+			wps_devicepassword_id = be16_to_cpu( wps_devicepassword_id );
+
+			if ( wps_devicepassword_id == WPS_DPID_USER_SPEC )
+			{
+				_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "dis", 3 );
+			}
+			else if ( wps_devicepassword_id == WPS_DPID_REGISTRAR_SPEC )
+			{
+				_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pad", 3 );	
+			}
+			else
+			{
+				_rtw_memcpy( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, "pbc", 3 );	
+			}
+		}
+	}
+	else
+	{
+		DBG_871X( "[%s] WPS IE not Found!!\n", __FUNCTION__ );
+		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+		return( result );
+	}
+
+	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+					
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+
+	if ( !p2p_ie )
+	{
+		DBG_871X( "[%s] P2P IE not Found!!\n", __FUNCTION__ );
+		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+	}
+	
+	while ( p2p_ie )
+	{
+		u8	attr_content = 0x00;
+		u32	attr_contentlen = 0;
+		u8	ch_content[100] = { 0x00 };
+		uint	ch_cnt = 0;
+		u8	peer_ch_list[100] = { 0x00 };
+		u8	peer_ch_num = 0;
+		u8	ch_list_inclusioned[100] = { 0x00 };
+		u8	ch_num_inclusioned = 0;
+		u16	cap_attr;
+		u8 listen_ch_attr[5] = { 0x00 };
+
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_ING);
+
+		//Check P2P Capability ATTR
+		if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen) )
+		{
+			cap_attr = le16_to_cpu(cap_attr);
+	
+#if defined(CONFIG_WFD) && defined(CONFIG_TDLS)
+			if(!(cap_attr & P2P_GRPCAP_INTRABSS) )
+				ptdlsinfo->ap_prohibited = _TRUE;
+#endif //defined(CONFIG_WFD) && defined(CONFIG_TDLS)
+		}
+
+		if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen) )
+		{
+			DBG_871X( "[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01 );
+			pwdinfo->peer_intent = attr_content;	//	include both intent and tie breaker values.
+
+			if ( pwdinfo->intent == ( pwdinfo->peer_intent >> 1 ) )
+			{
+				//	Try to match the tie breaker value
+				if ( pwdinfo->intent == P2P_MAX_INTENT )
+				{
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+					result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
+				}
+				else
+				{
+					if ( attr_content & 0x01 )
+					{
+						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+					}
+					else
+					{
+						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+					}
+				}							
+			}
+			else if ( pwdinfo->intent > ( pwdinfo->peer_intent >> 1 ) )
+			{
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+			}
+			else
+			{
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+			}
+
+			if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+			{
+				//	Store the group id information.
+				_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN );
+				_rtw_memcpy( pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );		
+			}
+		}
+
+		if (rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, (u8 *)listen_ch_attr, (uint *) &attr_contentlen) && attr_contentlen == 5)
+			pwdinfo->nego_req_info.peer_ch = listen_ch_attr[4];
+		
+		DBG_871X(FUNC_ADPT_FMT" listen channel :%u\n", FUNC_ADPT_ARG(padapter), pwdinfo->nego_req_info.peer_ch);
+
+		attr_contentlen = 0;
+		if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen ) )
+		{
+			if ( attr_contentlen != ETH_ALEN )
+			{
+				_rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN );
+			}
+		}
+
+		if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, ch_content, &ch_cnt) )
+		{
+			peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, ch_content, ch_cnt, peer_ch_list);
+			ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
+
+			if( ch_num_inclusioned == 0)
+			{
+				DBG_871X( "[%s] No common channel in channel list!\n", __FUNCTION__ );
+				result = P2P_STATUS_FAIL_NO_COMMON_CH;
+				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+				break;
+			}
+
+			if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+			{
+				if ( !rtw_p2p_is_channel_list_ok( pwdinfo->operating_channel, 
+												ch_list_inclusioned, ch_num_inclusioned) )
+				{
+#ifdef CONFIG_CONCURRENT_MODE
+					if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+					{
+						DBG_871X( "[%s] desired channel NOT Found!\n", __FUNCTION__ );
+						result = P2P_STATUS_FAIL_NO_COMMON_CH;
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+						break;
+					}
+					else
+#endif //CONFIG_CONCURRENT_MODE
+					{
+						u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
+						attr_contentlen = 0;
+
+						if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
+						{		
+							peer_operating_ch = operatingch_info[4];
+						}
+
+						if ( rtw_p2p_is_channel_list_ok( peer_operating_ch, 
+														ch_list_inclusioned, ch_num_inclusioned) )
+						{
+							/**
+							 *	Change our operating channel as peer's for compatibility.
+							 */
+							pwdinfo->operating_channel = peer_operating_ch;
+							DBG_871X( "[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
+						}
+						else
+						{
+							// Take first channel of ch_list_inclusioned as operating channel
+							pwdinfo->operating_channel = ch_list_inclusioned[0];
+							DBG_871X( "[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
+						}
+					}
+
+				}
+			}
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+	}
+
+	if (pwdinfo->ui_got_wps_info == P2P_NO_WPSINFO) {
+		result = P2P_STATUS_FAIL_INFO_UNAVAILABLE;
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_TX_INFOR_NOREADY);
+		return result;
+	}
+
+	#ifdef CONFIG_WFD
+	rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
+	#endif
+
+	return( result );
+}
+
+u8 process_p2p_group_negotation_resp( struct wifidirect_info *pwdinfo, u8 *pframe, uint len )
+{
+	_adapter *padapter = pwdinfo->padapter;
+	u8	result = P2P_STATUS_SUCCESS;
+	u32	p2p_ielen, wps_ielen;
+	u8 * ies;
+	u32 ies_len;
+	u8 * p2p_ie;
+#ifdef CONFIG_WFD
+#ifdef CONFIG_TDLS
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+#endif // CONFIG_TDLS	
+#endif // CONFIG_WFD
+
+	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+	//	Be able to know which one is the P2P GO and which one is P2P client.
+					
+	if ( rtw_get_wps_ie( ies, ies_len, NULL, &wps_ielen) )
+	{
+
+	}
+	else
+	{
+		DBG_871X( "[%s] WPS IE not Found!!\n", __FUNCTION__ );
+		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+	}
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+	if ( !p2p_ie )
+	{
+		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+		result = P2P_STATUS_FAIL_INCOMPATIBLE_PARAM;
+	}
+	else
+	{
+
+		u8	attr_content = 0x00;
+		u32	attr_contentlen = 0;
+		u8	operatingch_info[5] = { 0x00 };
+		uint	ch_cnt = 0;
+		u8	ch_content[100] = { 0x00 };
+		u8	groupid[ 38 ];
+		u16	cap_attr;
+		u8	peer_ch_list[100] = { 0x00 };
+		u8	peer_ch_num = 0;
+		u8	ch_list_inclusioned[100] = { 0x00 };
+		u8	ch_num_inclusioned = 0;
+
+		while ( p2p_ie )	//	Found the P2P IE.
+		{
+
+			//Check P2P Capability ATTR
+			if(rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CAPABILITY, (u8*)&cap_attr, (uint*)&attr_contentlen) )
+			{
+				cap_attr = le16_to_cpu(cap_attr);
+#ifdef CONFIG_TDLS
+				if(!(cap_attr & P2P_GRPCAP_INTRABSS) )
+					ptdlsinfo->ap_prohibited = _TRUE;
+#endif // CONFIG_TDLS
+			}
+
+			rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
+			if ( attr_contentlen == 1 )
+			{			
+				DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
+				if ( attr_content == P2P_STATUS_SUCCESS )
+				{
+					//	Do nothing.
+				}
+				else
+				{
+					if ( P2P_STATUS_FAIL_INFO_UNAVAILABLE == attr_content ) {
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_RX_INFOR_NOREADY);
+					} else {
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+					}
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+					result = attr_content;
+					break;
+				}
+			}
+
+			//	Try to get the peer's interface address
+			attr_contentlen = 0;
+			if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_INTENTED_IF_ADDR, pwdinfo->p2p_peer_interface_addr, &attr_contentlen ) )
+			{
+				if ( attr_contentlen != ETH_ALEN )
+				{
+					_rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN );
+				}
+			}
+			
+			//	Try to get the peer's intent and tie breaker value.
+			attr_content = 0x00;
+			attr_contentlen = 0;
+			if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT , &attr_content, &attr_contentlen) )
+			{
+				DBG_871X( "[%s] GO Intent = %d, tie = %d\n", __FUNCTION__, attr_content >> 1, attr_content & 0x01 );
+				pwdinfo->peer_intent = attr_content;	//	include both intent and tie breaker values.
+
+				if ( pwdinfo->intent == ( pwdinfo->peer_intent >> 1 ) )
+				{
+					//	Try to match the tie breaker value
+					if ( pwdinfo->intent == P2P_MAX_INTENT )
+					{
+						rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+						result = P2P_STATUS_FAIL_BOTH_GOINTENT_15;
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+					}
+					else
+					{
+						rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+						rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+						if ( attr_content & 0x01 )
+						{
+							rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+						}
+						else
+						{
+							rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+						}
+					}							
+				}
+				else if ( pwdinfo->intent > ( pwdinfo->peer_intent >> 1 ) )
+				{
+					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+				}
+				else
+				{
+					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+					rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+				}
+
+				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+				{
+					//	Store the group id information.
+					_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, pwdinfo->device_addr, ETH_ALEN );
+					_rtw_memcpy( pwdinfo->groupid_info.ssid, pwdinfo->nego_ssid, pwdinfo->nego_ssidlen );
+		
+				}
+			}
+			
+			//	Try to get the operation channel information
+					
+			attr_contentlen = 0;
+			if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen))
+			{
+				DBG_871X( "[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4] );
+				pwdinfo->peer_operating_ch = operatingch_info[4];
+			}
+			
+			//	Try to get the channel list information
+			if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, pwdinfo->channel_list_attr, &pwdinfo->channel_list_attr_len ) )
+			{
+				DBG_871X( "[%s] channel list attribute found, len = %d\n", __FUNCTION__,  pwdinfo->channel_list_attr_len );
+
+				peer_ch_num = rtw_p2p_get_peer_ch_list(pwdinfo, pwdinfo->channel_list_attr, pwdinfo->channel_list_attr_len, peer_ch_list);
+				ch_num_inclusioned = rtw_p2p_ch_inclusion(&padapter->mlmeextpriv, peer_ch_list, peer_ch_num, ch_list_inclusioned);
+
+				if( ch_num_inclusioned == 0)
+				{
+					DBG_871X( "[%s] No common channel in channel list!\n", __FUNCTION__ );
+					result = P2P_STATUS_FAIL_NO_COMMON_CH;
+					rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+					break;
+				}
+
+				if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_GO))
+				{
+					if ( !rtw_p2p_is_channel_list_ok( pwdinfo->operating_channel, 
+													ch_list_inclusioned, ch_num_inclusioned) )
+					{
+#ifdef CONFIG_CONCURRENT_MODE
+						if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+						{
+							DBG_871X( "[%s] desired channel NOT Found!\n", __FUNCTION__ );
+							result = P2P_STATUS_FAIL_NO_COMMON_CH;
+							rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+							break;
+						}
+						else
+#endif //CONFIG_CONCURRENT_MODE
+						{
+							u8 operatingch_info[5] = { 0x00 }, peer_operating_ch = 0;
+							attr_contentlen = 0;
+
+							if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
+							{		
+								peer_operating_ch = operatingch_info[4];
+							}
+
+							if ( rtw_p2p_is_channel_list_ok( peer_operating_ch, 
+															ch_list_inclusioned, ch_num_inclusioned) )
+							{
+								/**
+								 *	Change our operating channel as peer's for compatibility.
+								 */
+								pwdinfo->operating_channel = peer_operating_ch;
+								DBG_871X( "[%s] Change op ch to %02x as peer's\n", __FUNCTION__, pwdinfo->operating_channel);
+							}
+							else
+							{
+								// Take first channel of ch_list_inclusioned as operating channel
+								pwdinfo->operating_channel = ch_list_inclusioned[0];
+								DBG_871X( "[%s] Change op ch to %02x\n", __FUNCTION__, pwdinfo->operating_channel);
+							}
+						}
+
+					}
+				}
+
+			}
+			else
+			{
+				DBG_871X( "[%s] channel list attribute not found!\n", __FUNCTION__);
+			}
+
+			//	Try to get the group id information if peer is GO
+			attr_contentlen = 0;
+			_rtw_memset( groupid, 0x00, 38 );
+			if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen) )
+			{
+				_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN );
+				_rtw_memcpy( pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN );
+			}
+			
+			//Get the next P2P IE
+			p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+		}
+		
+	}
+
+	#ifdef CONFIG_WFD
+	rtw_process_wfd_ies(padapter, pframe + _PUBLIC_ACTION_IE_OFFSET_, len - _PUBLIC_ACTION_IE_OFFSET_, __func__);
+	#endif
+
+	return( result );
+
+}
+
+u8 process_p2p_group_negotation_confirm( struct wifidirect_info *pwdinfo, u8 *pframe, uint len )
+{
+	u8 * ies;
+	u32 ies_len;
+	u8 * p2p_ie;
+	u32	p2p_ielen = 0;
+	u8	result = P2P_STATUS_SUCCESS;
+	ies = pframe + _PUBLIC_ACTION_IE_OFFSET_;
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+	while ( p2p_ie )	//	Found the P2P IE.
+	{
+		u8	attr_content = 0x00, operatingch_info[5] = { 0x00 };
+		u8	groupid[ 38 ] = { 0x00 };
+		u32	attr_contentlen = 0;
+
+		pwdinfo->negotiation_dialog_token = 1;
+		rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, &attr_content, &attr_contentlen);
+		if ( attr_contentlen == 1 )
+		{
+			DBG_871X( "[%s] Status = %d\n", __FUNCTION__, attr_content );
+			result = attr_content;
+
+			if ( attr_content == P2P_STATUS_SUCCESS )
+			{
+				u8	bcancelled = 0;
+																
+				_cancel_timer( &pwdinfo->restore_p2p_state_timer, &bcancelled );
+
+				//	Commented by Albert 20100911
+				//	Todo: Need to handle the case which both Intents are the same.
+				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+				rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+				if ( ( pwdinfo->intent ) > ( pwdinfo->peer_intent >> 1 ) )
+				{
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+				}
+				else if ( ( pwdinfo->intent ) < ( pwdinfo->peer_intent >> 1 ) )
+				{
+					rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+				}
+				else
+				{
+					//	Have to compare the Tie Breaker
+					if ( pwdinfo->peer_intent & 0x01 )
+					{
+						rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+					}
+					else
+					{
+						rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+					}
+				}								
+				
+#ifdef CONFIG_CONCURRENT_MODE
+				if ( check_buddy_fwstate(pwdinfo->padapter , _FW_LINKED ) )
+				{
+					//	Switch back to the AP channel soon.
+					_set_timer( &pwdinfo->ap_p2p_switch_timer, 100 );
+				}
+#endif				
+			}
+			else
+			{
+				rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+				rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_FAIL);
+				break;
+			}
+		}
+
+		//	Try to get the group id information
+		attr_contentlen = 0;
+		_rtw_memset( groupid, 0x00, 38 );
+		if ( rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, groupid, &attr_contentlen) )
+		{
+			DBG_871X( "[%s] Ssid = %s, ssidlen = %zu\n", __FUNCTION__, &groupid[ETH_ALEN], strlen(&groupid[ETH_ALEN]) );
+			_rtw_memcpy( pwdinfo->groupid_info.go_device_addr, &groupid[0], ETH_ALEN );
+			_rtw_memcpy( pwdinfo->groupid_info.ssid, &groupid[6], attr_contentlen - ETH_ALEN );			
+		}
+
+		attr_contentlen = 0;
+		if ( rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, operatingch_info, &attr_contentlen) )
+		{		
+			DBG_871X( "[%s] Peer's operating channel = %d\n", __FUNCTION__, operatingch_info[4] );
+			pwdinfo->peer_operating_ch = operatingch_info[4];
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+		
+	}
+
+	return( result );
+}
+
+u8 process_p2p_presence_req(struct wifidirect_info *pwdinfo, u8 *pframe, uint len)
+{
+	u8 *frame_body;	
+	u8 dialogToken=0;
+	u8 status = P2P_STATUS_SUCCESS;
+	
+	frame_body = (unsigned char *)(pframe + sizeof(struct rtw_ieee80211_hdr_3addr));
+
+	dialogToken = frame_body[6];
+
+	//todo: check NoA attribute
+
+	issue_p2p_presence_resp(pwdinfo, GetAddr2Ptr(pframe), status, dialogToken);
+
+	return _TRUE;
+}
+
+void find_phase_handler( _adapter*	padapter )
+{
+	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	NDIS_802_11_SSID 	ssid;
+	_irqL				irqL;
+	u8					_status = 0;
+
+_func_enter_;
+
+	_rtw_memset((unsigned char*)&ssid, 0, sizeof(NDIS_802_11_SSID));
+	_rtw_memcpy(ssid.Ssid, pwdinfo->p2p_wildcard_ssid, P2P_WILDCARD_SSID_LEN );
+	ssid.SsidLength = P2P_WILDCARD_SSID_LEN;
+
+	rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH);
+		
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+	_status = rtw_sitesurvey_cmd(padapter, &ssid, 1, NULL, 0);
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+
+
+_func_exit_;
+}
+
+void p2p_concurrent_handler(  _adapter* padapter );
+
+void restore_p2p_state_handler( _adapter*	padapter )
+{
+	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+
+_func_enter_;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL))
+	{
+		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+	}
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
+		struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+		struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;	
+	
+		if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ) || rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_RSP))
+		{
+			set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+			
+			issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
+		}
+	}
+#endif
+
+	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+	
+	if(rtw_p2p_chk_role(pwdinfo, P2P_ROLE_DEVICE))
+	{
+#ifdef CONFIG_CONCURRENT_MODE
+		p2p_concurrent_handler( padapter );
+#else
+		//	In the P2P client mode, the driver should not switch back to its listen channel
+		//	because this P2P client should stay at the operating channel of P2P GO.
+		set_channel_bwmode( padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+#endif
+	}
+_func_exit_;
+}
+
+void pre_tx_invitereq_handler( _adapter*	padapter )
+{
+	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
+	u8	val8 = 1;
+_func_enter_;
+
+	set_channel_bwmode(padapter, pwdinfo->invitereq_info.peer_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));	
+	issue_probereq_p2p(padapter, NULL);
+	_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+	
+_func_exit_;
+}
+
+void pre_tx_provdisc_handler( _adapter*	padapter )
+{
+	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
+	u8	val8 = 1;
+_func_enter_;
+
+	set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+	issue_probereq_p2p(padapter, NULL);
+	_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+	
+_func_exit_;
+}
+
+void pre_tx_negoreq_handler( _adapter*	padapter )
+{
+	struct wifidirect_info  *pwdinfo = &padapter->wdinfo;
+	u8	val8 = 1;
+_func_enter_;
+
+	set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+	rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));	
+	issue_probereq_p2p(padapter, NULL);
+	_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+	
+_func_exit_;
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+void p2p_concurrent_handler( _adapter*	padapter )
+{
+	struct wifidirect_info	*pwdinfo = &padapter->wdinfo;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);	
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	//_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
+	//struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+	//struct mlme_priv		*pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+	//struct mlme_ext_priv	*pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+	u8					val8;
+_func_enter_;
+
+	if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+	{
+		PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;			
+		struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+		pwdinfo->operating_channel = pbuddy_mlmeext->cur_channel;
+
+		if( pwdinfo->driver_interface == DRIVER_CFG80211 )
+		{
+			DBG_871X("%s, switch ch back to buddy's cur_channel=%d\n", __func__, pbuddy_mlmeext->cur_channel);
+
+			set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+
+			if (check_buddy_fwstate(padapter, WIFI_FW_STATION_STATE))
+				issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
+		}
+		else if( pwdinfo->driver_interface == DRIVER_WEXT )
+		{
+			if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE))
+			{
+				//	Now, the driver stays on the AP's channel.
+				//	If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel.
+				if ( pwdinfo->ext_listen_period > 0 )
+				{
+					DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period );
+
+					if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel )
+					{
+						//	Will switch to listen channel so that need to send the NULL data with PW bit to AP.
+						issue_nulldata(pbuddy_adapter, NULL, 1, 3, 500);
+						set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+					}
+
+					rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+					if(!check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&
+					!(pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+					{
+						val8 = 1;
+						rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+					}
+					//	Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not.
+					_set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_period );
+				}
+			}
+			else if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) || 
+					rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
+					( rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE ) ||
+					rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ) )
+			{
+				//	Now, the driver is in the listen state of P2P mode.
+				DBG_8192C( "[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval );
+
+				//	Commented by Albert 2012/11/01
+				//	If the AP's channel is the same as the listen channel, we should still be in the listen state
+				//	Other P2P device is still able to find this device out even this device is in the AP's channel.
+				//	So, configure this device to be able to receive the probe request frame and set it to listen state.
+				if ( pbuddy_mlmeext->cur_channel != pwdinfo->listen_channel )
+				{
+					set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+					if(!check_buddy_mlmeinfo_state(padapter, WIFI_FW_AP_STATE) &&!(pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)
+					{						
+						val8 = 0;
+						rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+					}
+					rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
+					issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
+				}
+
+				//	Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not.
+				_set_timer( &pwdinfo->ap_p2p_switch_timer, pwdinfo->ext_listen_interval );
+			}
+			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK))
+			{
+				//	The driver had finished the P2P handshake successfully.
+				val8 = 0;
+				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+				set_channel_bwmode(padapter, pbuddy_mlmeext->cur_channel, pbuddy_mlmeext->cur_ch_offset, pbuddy_mlmeext->cur_bwmode);
+				issue_nulldata(pbuddy_adapter, NULL, 0, 3, 500);
+			}
+			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
+			{
+				val8 = 1;
+				set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+				issue_probereq_p2p(padapter, NULL);
+				_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+			}
+			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE)
+			{
+				val8 = 1;
+				set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+				issue_probereq_p2p(padapter, NULL);
+				_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+			}		
+			else if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) && pwdinfo->invitereq_info.benable == _TRUE)
+			{
+				/*
+				val8 = 1;
+			set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
+				rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
+				issue_probereq_p2p(padapter, NULL);
+				_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+				*/
+			}
+		}
+	}
+	else
+	{
+		set_channel_bwmode( padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);	
+	}
+
+_func_exit_;
+}
+#endif
+
+#ifdef CONFIG_IOCTL_CFG80211
+static void ro_ch_handler(_adapter *padapter)
+{
+	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	u8 ch, bw, offset;
+_func_enter_;
+
+	if (rtw_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
+				FUNC_ADPT_ARG(padapter), ch, bw, offset);
+	}
+	else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
+		ch = pwdinfo->listen_channel;
+		bw = CHANNEL_WIDTH_20;
+		offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
+				FUNC_ADPT_ARG(padapter), ch, bw, offset);
+	}
+	else {
+		ch = pcfg80211_wdinfo->restore_channel;
+		bw = CHANNEL_WIDTH_20;
+		offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+		if (0)
+			DBG_871X(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
+				FUNC_ADPT_ARG(padapter), ch, bw, offset);
+	}
+
+	set_channel_bwmode(padapter, ch, offset, bw);
+
+	rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
+#ifdef CONFIG_DEBUG_CFG80211
+	DBG_871X("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
+#endif
+
+	pcfg80211_wdinfo->is_ro_ch = _FALSE;
+	pcfg80211_wdinfo->last_ro_ch_time = rtw_get_current_time();
+
+	DBG_871X("cfg80211_remain_on_channel_expired cookie:0x%llx, ch=%d, bw=%d, offset=%d\n"
+		, pcfg80211_wdinfo->remain_on_ch_cookie
+		, rtw_get_oper_ch(padapter), rtw_get_oper_bw(padapter), rtw_get_oper_choffset(padapter));
+
+	rtw_cfg80211_remain_on_channel_expired(padapter, 
+		pcfg80211_wdinfo->remain_on_ch_cookie, 
+		&pcfg80211_wdinfo->remain_on_ch_channel,
+		pcfg80211_wdinfo->remain_on_ch_type, GFP_KERNEL);
+
+_func_exit_;
+}
+
+static void ro_ch_timer_process (struct timer_list *t)
+{
+	_adapter *adapter = from_timer(adapter, t,
+						  cfg80211_wdinfo.remain_on_ch_timer);
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
+
+	//printk("%s \n", __FUNCTION__);
+	
+#ifdef	CONFIG_CONCURRENT_MODE
+	ATOMIC_SET(&pwdev_priv->ro_ch_to, 1);
+#endif
+
+	p2p_protocol_wk_cmd( adapter, P2P_RO_CH_WK);
+}
+
+static void rtw_change_p2pie_op_ch(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
+{
+	u8 *ies, *p2p_ie;
+	u32 ies_len, p2p_ielen;
+	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+
+	while ( p2p_ie ) {
+		u32	attr_contentlen = 0;
+		u8 *pattr = NULL;
+
+		//Check P2P_ATTR_OPERATING_CH
+		attr_contentlen = 0;
+		pattr = NULL;
+		if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL)
+		{
+			*(pattr+4) = ch;
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+	}
+}
+
+static void rtw_change_p2pie_ch_list(_adapter *padapter, const u8 *frame_body, u32 len, u8 ch)
+{
+	u8 *ies, *p2p_ie;
+	u32 ies_len, p2p_ielen;
+	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+
+	while (p2p_ie) {
+		u32	attr_contentlen = 0;
+		u8 *pattr = NULL;
+
+		//Check P2P_ATTR_CH_LIST
+		if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL) {
+			int i;
+			u32 num_of_ch;
+			u8 *pattr_temp = pattr + 3 ;
+
+			attr_contentlen -= 3;
+			
+			while (attr_contentlen>0) {
+				num_of_ch = *(pattr_temp+1);
+
+				for(i=0; i<num_of_ch; i++)
+					*(pattr_temp+2+i) = ch;
+
+				pattr_temp += (2+num_of_ch);
+				attr_contentlen -= (2+num_of_ch);
+			}
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+	}
+}
+
+static bool rtw_chk_p2pie_ch_list_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
+{
+	bool fit = _FALSE;
+#ifdef CONFIG_CONCURRENT_MODE
+	u8 *ies, *p2p_ie;
+	u32 ies_len, p2p_ielen;
+	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+	u8 buddy_ch = pbuddy_mlmeext->cur_channel;
+
+	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+
+	while (p2p_ie) {
+		u32	attr_contentlen = 0;
+		u8 *pattr = NULL;
+
+		//Check P2P_ATTR_CH_LIST
+		if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL) {
+			int i;
+			u32 num_of_ch;
+			u8 *pattr_temp = pattr + 3 ;
+
+			attr_contentlen -= 3;
+
+			while (attr_contentlen>0) {
+				num_of_ch = *(pattr_temp+1);
+
+				for(i=0; i<num_of_ch; i++) {
+					if (*(pattr_temp+2+i) == buddy_ch) {
+						DBG_871X(FUNC_ADPT_FMT" ch_list fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), buddy_ch);
+						fit = _TRUE;
+						break;
+					}
+				}
+
+				pattr_temp += (2+num_of_ch);
+				attr_contentlen -= (2+num_of_ch);
+			}
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+	}
+#endif
+	return fit;
+}
+
+static bool rtw_chk_p2pie_op_ch_with_buddy(_adapter *padapter, const u8 *frame_body, u32 len)
+{
+	bool fit = _FALSE;
+#ifdef CONFIG_CONCURRENT_MODE
+	u8 *ies, *p2p_ie;
+	u32 ies_len, p2p_ielen;
+	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;
+	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+	u8 buddy_ch = pbuddy_mlmeext->cur_channel;
+
+	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+
+	while (p2p_ie) {
+		u32	attr_contentlen = 0;
+		u8 *pattr = NULL;
+
+		//Check P2P_ATTR_OPERATING_CH
+		attr_contentlen = 0;
+		pattr = NULL;
+		if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL) {
+			if (*(pattr+4) == buddy_ch) {
+				DBG_871X(FUNC_ADPT_FMT" op_ch fit buddy_ch:%u\n", FUNC_ADPT_ARG(padapter), buddy_ch);
+				fit = _TRUE;
+				break;
+			}
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+	}
+#endif
+	return fit;
+}
+
+static void rtw_cfg80211_adjust_p2pie_channel(_adapter *padapter, const u8 *frame_body, u32 len)
+{
+#ifdef CONFIG_CONCURRENT_MODE
+	u8 *ies, *p2p_ie;
+	u32 ies_len, p2p_ielen;
+	PADAPTER pbuddy_adapter = padapter->pbuddy_adapter;			
+	struct mlme_ext_priv *pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+
+	ies = (u8*)(frame_body + _PUBLIC_ACTION_IE_OFFSET_);
+	ies_len = len - _PUBLIC_ACTION_IE_OFFSET_;
+					
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen );
+
+	while ( p2p_ie )
+	{	
+		u32	attr_contentlen = 0;
+		u8 *pattr = NULL;
+				
+		//Check P2P_ATTR_CH_LIST
+		if((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, (uint*)&attr_contentlen))!=NULL)
+		{
+			int i;
+			u32 num_of_ch;
+			u8 *pattr_temp = pattr + 3 ;
+
+			attr_contentlen -= 3;
+			
+			while(attr_contentlen>0)
+			{				
+				num_of_ch = *(pattr_temp+1);
+								
+				for(i=0; i<num_of_ch; i++)
+					*(pattr_temp+2+i) = pbuddy_mlmeext->cur_channel;//forcing to the same channel
+
+				pattr_temp += (2+num_of_ch);
+				attr_contentlen -= (2+num_of_ch);
+			}	
+		}
+
+		//Check P2P_ATTR_OPERATING_CH
+		attr_contentlen = 0;
+		pattr = NULL;
+		if((pattr = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, (uint*)&attr_contentlen))!=NULL)
+		{
+			*(pattr+4) = pbuddy_mlmeext->cur_channel;//forcing to the same channel			
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+		
+	}
+
+#endif
+}
+
+#ifdef CONFIG_WFD
+u32 rtw_xframe_build_wfd_ie(struct xmit_frame *xframe)
+{
+	_adapter *adapter = xframe->padapter;
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
+	u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 *frame_tail = frame + xframe->attrib.pktlen;
+	u8 category, action, OUI_Subtype, dialogToken = 0;
+	u32	wfdielen = 0;
+
+	category = frame_body[0];
+	if (category == RTW_WLAN_CATEGORY_PUBLIC) {
+		action = frame_body[1];
+		if (action == ACT_PUBLIC_VENDOR
+			&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
+		) {
+			OUI_Subtype = frame_body[6];
+			dialogToken = frame_body[7];
+
+			switch (OUI_Subtype) {
+			case P2P_GO_NEGO_REQ:
+				wfdielen = build_nego_req_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_GO_NEGO_RESP:
+				wfdielen = build_nego_resp_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_GO_NEGO_CONF:
+				wfdielen = build_nego_confirm_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_INVIT_REQ:
+				wfdielen = build_invitation_req_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_INVIT_RESP:
+				wfdielen = build_invitation_resp_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_PROVISION_DISC_REQ:
+				wfdielen = build_provdisc_req_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_PROVISION_DISC_RESP:
+				wfdielen = build_provdisc_resp_wfd_ie(wdinfo, frame_tail);
+				break;
+			case P2P_DEVDISC_REQ:
+			case P2P_DEVDISC_RESP:
+			default:
+				break;
+			}
+
+		}
+	} else if (category == RTW_WLAN_CATEGORY_P2P) {
+		OUI_Subtype = frame_body[5];
+		dialogToken = frame_body[6];
+
+		#ifdef CONFIG_DEBUG_CFG80211
+		DBG_871X("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n"
+			, cpu_to_be32(*((u32 *)(frame_body + 1))), OUI_Subtype, dialogToken);
+		#endif
+
+		switch (OUI_Subtype) {
+		case P2P_NOTICE_OF_ABSENCE:
+			break;
+		case P2P_PRESENCE_REQUEST:
+			break;
+		case P2P_PRESENCE_RESPONSE:
+			break;
+		case P2P_GO_DISC_REQUEST:
+			break;
+		default:
+			break;
+		}
+	} else {
+		DBG_871X("%s, action frame category=%d\n", __func__, category);
+	}
+
+	xframe->attrib.pktlen += wfdielen;
+
+	return wfdielen;
+}
+#endif /* CONFIG_WFD */
+
+bool rtw_xframe_del_wfd_ie(struct xmit_frame *xframe)
+{
+#define DBG_XFRAME_DEL_WFD_IE 0
+
+	_adapter *adapter = xframe->padapter;
+	u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
+	u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 *frame_tail = frame + xframe->attrib.pktlen;
+	u8 category, action, OUI_Subtype;
+	u8 *ies = NULL;
+	uint ies_len_ori = 0;
+	uint ies_len = 0;
+
+	category = frame_body[0];
+	if (category == RTW_WLAN_CATEGORY_PUBLIC) {
+		action = frame_body[1];
+		if (action == ACT_PUBLIC_VENDOR
+			&& _rtw_memcmp(frame_body + 2, P2P_OUI, 4) == _TRUE
+		) {
+			OUI_Subtype = frame_body[6];
+
+			switch (OUI_Subtype) {
+			case P2P_GO_NEGO_REQ:
+			case P2P_GO_NEGO_RESP:
+			case P2P_GO_NEGO_CONF:
+			case P2P_INVIT_REQ:
+			case P2P_INVIT_RESP:
+			case P2P_PROVISION_DISC_REQ:
+			case P2P_PROVISION_DISC_RESP:
+				ies = frame_body + 8;
+				ies_len_ori = frame_tail - (frame_body + 8);
+				break;
+			}
+		}
+	}
+
+	if (ies && ies_len_ori) {
+		ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_XFRAME_DEL_WFD_IE ? __func__ : NULL);
+		xframe->attrib.pktlen -= (ies_len_ori - ies_len);
+	}
+
+	return ies_len_ori != ies_len;
+}
+
+/*
+* rtw_xframe_chk_wfd_ie -
+*
+*/
+void rtw_xframe_chk_wfd_ie(struct xmit_frame *xframe)
+{
+	_adapter *adapter = xframe->padapter;
+	u8 *frame = xframe->buf_addr + TXDESC_OFFSET;
+	u8 *frame_body = frame + sizeof(struct rtw_ieee80211_hdr_3addr);
+	u8 *frame_tail = frame + xframe->attrib.pktlen;
+
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	u8 build = 0;
+	u8 del = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		del = 1;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (_TRUE == wdinfo->wfd_info->wfd_enable)
+#endif
+		del = build = 1;
+
+	if (del)
+		rtw_xframe_del_wfd_ie(xframe);
+
+#ifdef CONFIG_WFD
+	if (build)
+		rtw_xframe_build_wfd_ie(xframe);
+#endif
+}
+
+u8 *dump_p2p_attr_ch_list(u8 *p2p_ie, uint p2p_ielen, u8 *buf, u32 buf_len)
+{
+	uint attr_contentlen = 0;
+	u8 *pattr = NULL;
+	int w_sz = 0;
+	u8 ch_cnt = 0;
+	u8 ch_list[40];
+	bool continuous = _FALSE;
+
+	if ((pattr=rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_CH_LIST, NULL, &attr_contentlen))!=NULL) {
+		int i, j;
+		u32 num_of_ch;
+		u8 *pattr_temp = pattr + 3 ;
+
+		attr_contentlen -= 3;
+
+		_rtw_memset(ch_list, 0, 40);
+
+		while (attr_contentlen>0) {
+			num_of_ch = *(pattr_temp+1);
+
+			for(i=0; i<num_of_ch; i++) {
+				for (j=0;j<ch_cnt;j++) {
+					if (ch_list[j] == *(pattr_temp+2+i))
+						break;
+				}
+				if (j>=ch_cnt)
+					ch_list[ch_cnt++] = *(pattr_temp+2+i);
+
+			}
+
+			pattr_temp += (2+num_of_ch);
+			attr_contentlen -= (2+num_of_ch);
+		}
+
+		for (j=0;j<ch_cnt;j++) {
+			if (j == 0) {
+				w_sz += snprintf(buf+w_sz, buf_len-w_sz, "%u", ch_list[j]);
+			} else if (ch_list[j] - ch_list[j-1] != 1) {
+				w_sz += snprintf(buf+w_sz, buf_len-w_sz, ", %u", ch_list[j]);
+			} else if (j != ch_cnt-1 && ch_list[j+1] - ch_list[j] == 1) {
+				/* empty */
+			} else {
+				w_sz += snprintf(buf+w_sz, buf_len-w_sz, "-%u", ch_list[j]);
+			}
+		}
+	}
+	return buf;
+}
+
+/*
+ * return _TRUE if requester is GO, _FALSE if responder is GO
+ */
+bool rtw_p2p_nego_intent_compare(u8 req, u8 resp)
+{
+	if (req>>1 == resp >>1)
+		return  req&0x01 ? _TRUE : _FALSE;
+	else if (req>>1 > resp>>1)
+		return _TRUE;
+	else
+		return _FALSE;
+}
+
+int rtw_p2p_check_frames(_adapter *padapter, const u8 *buf, u32 len, u8 tx)
+{
+	int is_p2p_frame = (-1);
+	unsigned char	*frame_body;
+	u8 category, action, OUI_Subtype, dialogToken=0;
+	u8 *p2p_ie = NULL;
+	uint p2p_ielen = 0;
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
+	int status = -1;
+	u8 ch_list_buf[128] = {'\0'};
+	int op_ch = -1;
+	int listen_ch = -1;
+	u8 intent = 0;
+	
+	frame_body = (unsigned char *)(buf + sizeof(struct rtw_ieee80211_hdr_3addr));	
+	category = frame_body[0];
+	//just for check
+	if(category == RTW_WLAN_CATEGORY_PUBLIC)
+	{
+		action = frame_body[1];
+		if (action == ACT_PUBLIC_VENDOR
+			&& _rtw_memcmp(frame_body+2, P2P_OUI, 4) == _TRUE
+		)
+		{
+			OUI_Subtype = frame_body[6];
+			dialogToken = frame_body[7];
+			is_p2p_frame = OUI_Subtype;
+			#ifdef CONFIG_DEBUG_CFG80211
+			DBG_871X("ACTION_CATEGORY_PUBLIC: ACT_PUBLIC_VENDOR, OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
+				cpu_to_be32( *( ( u32* ) ( frame_body + 2 ) ) ), OUI_Subtype, dialogToken);
+			#endif
+
+			p2p_ie = rtw_get_p2p_ie(
+				(u8 *)buf+sizeof(struct rtw_ieee80211_hdr_3addr)+_PUBLIC_ACTION_IE_OFFSET_,
+				len-sizeof(struct rtw_ieee80211_hdr_3addr)-_PUBLIC_ACTION_IE_OFFSET_,
+				NULL, &p2p_ielen);
+
+			switch( OUI_Subtype )//OUI Subtype
+			{
+				u8 *cont;
+				uint cont_len;
+				case P2P_GO_NEGO_REQ:
+				{
+					struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info;
+
+					if (tx) {
+						#ifdef CONFIG_DRV_ISSUE_PROV_REQ // IOT FOR S2
+						if(pwdev_priv->provdisc_req_issued == _FALSE)
+							rtw_cfg80211_issue_p2p_provision_request(padapter, buf, len);
+						#endif //CONFIG_DRV_ISSUE_PROV_REQ
+
+						//pwdev_priv->provdisc_req_issued = _FALSE;
+
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED))
+							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
+						#endif
+					}
+
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
+						op_ch = *(cont+4);
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_LISTEN_CH, NULL, &cont_len)))
+						listen_ch = *(cont+4);
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len)))
+						intent = *cont;
+
+					if (nego_info->token != dialogToken)
+						rtw_wdev_nego_info_init(nego_info);
+
+					_rtw_memcpy(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN);
+					nego_info->active = tx ? 1 : 0;
+					nego_info->token = dialogToken;
+					nego_info->req_op_ch = op_ch;
+					nego_info->req_listen_ch = listen_ch;
+					nego_info->req_intent = intent;
+					nego_info->state = 0;
+
+					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
+					DBG_871X("RTW_%s:P2P_GO_NEGO_REQ, dialogToken=%d, intent:%u%s, listen_ch:%d, op_ch:%d, ch_list:%s\n",
+							(tx==_TRUE)?"Tx":"Rx", dialogToken, (intent>>1), intent&0x1 ? "+" : "-", listen_ch, op_ch, ch_list_buf);
+
+					if (!tx) {
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED)
+							&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE)
+						{
+							DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
+							rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
+						}
+						#endif
+					}
+
+					break;
+				}
+				case P2P_GO_NEGO_RESP:
+				{
+					struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info;
+
+					if (tx) {
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED))
+							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
+						#endif
+					}
+
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
+						op_ch = *(cont+4);
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_GO_INTENT, NULL, &cont_len)))
+						intent = *cont;
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
+						status = *cont;
+
+					if (nego_info->token == dialogToken && nego_info->state == 0
+						&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
+					) {
+						nego_info->status = (status==-1) ? 0xff : status;
+						nego_info->rsp_op_ch= op_ch;
+						nego_info->rsp_intent = intent;
+						nego_info->state = 1;
+						if (status != 0)
+							nego_info->token = 0; /* init */
+					}
+
+					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
+					DBG_871X("RTW_%s:P2P_GO_NEGO_RESP, dialogToken=%d, intent:%u%s, status:%d, op_ch:%d, ch_list:%s\n",
+							(tx==_TRUE)?"Tx":"Rx", dialogToken, (intent>>1), intent&0x1 ? "+" : "-", status, op_ch, ch_list_buf);
+
+					if (!tx) {
+						pwdev_priv->provdisc_req_issued = _FALSE;
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED)
+							&& rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE)
+						{
+							DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
+							rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
+						}
+						#endif
+					}
+
+					break;
+				}
+				case P2P_GO_NEGO_CONF:
+				{
+					struct rtw_wdev_nego_info* nego_info = &pwdev_priv->nego_info;
+					bool is_go = _FALSE;
+
+					if (tx) {
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED))
+							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
+						#endif
+					}
+
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
+						op_ch = *(cont+4);
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
+						status = *cont;
+
+					if (nego_info->token == dialogToken && nego_info->state == 1
+						&& _rtw_memcmp(nego_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
+					) {
+						nego_info->status = (status==-1) ? 0xff : status;
+						nego_info->conf_op_ch = (op_ch==-1) ? 0 : op_ch;
+						nego_info->state = 2;
+
+						if (status == 0) {
+							if (rtw_p2p_nego_intent_compare(nego_info->req_intent, nego_info->rsp_intent) ^ !tx)
+								is_go = _TRUE;
+						}
+
+						nego_info->token = 0; /* init */
+					}
+
+					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
+					DBG_871X("RTW_%s:P2P_GO_NEGO_CONF, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n",
+						(tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch, ch_list_buf);
+
+					if (!tx) {
+					}
+
+					break;
+				}
+				case P2P_INVIT_REQ:
+				{
+					struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
+					int flags = -1;
+
+					if (tx) {
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED))
+							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
+						#endif
+					}
+
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_INVITATION_FLAGS, NULL, &cont_len)))
+						flags = *cont;
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
+						op_ch = *(cont+4);
+
+					if (invit_info->token != dialogToken)
+						rtw_wdev_invit_info_init(invit_info);
+
+					_rtw_memcpy(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN);
+					invit_info->active = tx ? 1 : 0;
+					invit_info->token = dialogToken;
+					invit_info->flags = (flags==-1) ? 0x0 : flags;
+					invit_info->req_op_ch= op_ch;
+					invit_info->state = 0;
+
+					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
+					DBG_871X("RTW_%s:P2P_INVIT_REQ, dialogToken=%d, flags:0x%02x, op_ch:%d, ch_list:%s\n",
+							(tx==_TRUE)?"Tx":"Rx", dialogToken, flags, op_ch, ch_list_buf);
+
+					if (!tx) {
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED)) {
+							if (op_ch != -1 && rtw_chk_p2pie_op_ch_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
+								DBG_871X(FUNC_ADPT_FMT" op_ch:%u has no intersect with buddy\n", FUNC_ADPT_ARG(padapter), op_ch);
+								rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
+							} else if (rtw_chk_p2pie_ch_list_with_buddy(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr)) == _FALSE) {
+								DBG_871X(FUNC_ADPT_FMT" ch_list has no intersect with buddy\n", FUNC_ADPT_ARG(padapter));
+								rtw_change_p2pie_ch_list(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr), 0);
+							}
+						}
+						#endif
+					}
+
+					break;
+				}
+				case P2P_INVIT_RESP:
+				{
+					struct rtw_wdev_invit_info* invit_info = &pwdev_priv->invit_info;
+
+					if (tx) {
+						#if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_CFG80211_ONECHANNEL_UNDER_CONCURRENT)
+						if(check_buddy_fwstate(padapter, _FW_LINKED))
+							rtw_cfg80211_adjust_p2pie_channel(padapter, frame_body, len-sizeof(struct rtw_ieee80211_hdr_3addr));
+						#endif
+					}
+
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len)))
+					{
+#ifdef CONFIG_P2P_INVITE_IOT
+						if(tx && *cont==7)
+						{
+							DBG_871X("TX_P2P_INVITE_RESP, status is no common channel, change to unknown group\n");
+							*cont = 8; //unknow group status
+						}
+#endif //CONFIG_P2P_INVITE_IOT
+						status = *cont;
+					}	
+					if ((cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_OPERATING_CH, NULL, &cont_len)))
+						op_ch = *(cont+4);
+
+					if (invit_info->token == dialogToken && invit_info->state == 0
+						&& _rtw_memcmp(invit_info->peer_mac, tx ? GetAddr1Ptr(buf) : GetAddr2Ptr(buf), ETH_ALEN) == _TRUE
+					) {
+						invit_info->status = (status==-1) ? 0xff : status;
+						invit_info->rsp_op_ch= op_ch;
+						invit_info->state = 1;
+						invit_info->token = 0; /* init */
+					}
+
+					dump_p2p_attr_ch_list(p2p_ie, p2p_ielen, ch_list_buf, 128);
+					DBG_871X("RTW_%s:P2P_INVIT_RESP, dialogToken=%d, status:%d, op_ch:%d, ch_list:%s\n",
+							(tx==_TRUE)?"Tx":"Rx", dialogToken, status, op_ch, ch_list_buf);
+
+					if (!tx) {
+					}
+
+					break;
+				}
+				case P2P_DEVDISC_REQ:
+					DBG_871X("RTW_%s:P2P_DEVDISC_REQ, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken);
+					break;
+				case P2P_DEVDISC_RESP:
+					cont = rtw_get_p2p_attr_content(p2p_ie, p2p_ielen, P2P_ATTR_STATUS, NULL, &cont_len);
+					DBG_871X("RTW_%s:P2P_DEVDISC_RESP, dialogToken=%d, status:%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken, cont?*cont:-1);
+					break;
+				case P2P_PROVISION_DISC_REQ:
+				{
+					size_t frame_body_len = len - sizeof(struct rtw_ieee80211_hdr_3addr);
+					u8 *p2p_ie;
+					uint p2p_ielen = 0;
+					uint contentlen = 0;
+					
+					DBG_871X("RTW_%s:P2P_PROVISION_DISC_REQ, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken);
+
+					//if(tx)
+					{
+						pwdev_priv->provdisc_req_issued = _FALSE;
+					
+						if( (p2p_ie=rtw_get_p2p_ie( frame_body + _PUBLIC_ACTION_IE_OFFSET_, frame_body_len - _PUBLIC_ACTION_IE_OFFSET_, NULL, &p2p_ielen)))
+						{	
+
+							if(rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_GROUP_ID, NULL, &contentlen))
+							{
+								pwdev_priv->provdisc_req_issued = _FALSE;//case: p2p_client join p2p GO
+							}
+							else
+							{
+								#ifdef CONFIG_DEBUG_CFG80211
+								DBG_871X("provdisc_req_issued is _TRUE\n");
+								#endif //CONFIG_DEBUG_CFG80211
+								pwdev_priv->provdisc_req_issued = _TRUE;//case: p2p_devices connection before Nego req.
+							}
+												
+						}						
+					}				
+				}	
+					break;
+				case P2P_PROVISION_DISC_RESP:
+					DBG_871X("RTW_%s:P2P_PROVISION_DISC_RESP, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", dialogToken);
+					break;
+				default:
+					DBG_871X("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx==_TRUE)?"Tx":"Rx", OUI_Subtype, dialogToken);
+					break;	
+			}
+
+		}
+		
+	}	
+	else if(category == RTW_WLAN_CATEGORY_P2P)
+	{
+		OUI_Subtype = frame_body[5];
+		dialogToken = frame_body[6];
+
+		#ifdef CONFIG_DEBUG_CFG80211
+		DBG_871X("ACTION_CATEGORY_P2P: OUI=0x%x, OUI_Subtype=%d, dialogToken=%d\n",
+			cpu_to_be32( *( ( u32* ) ( frame_body + 1 ) ) ), OUI_Subtype, dialogToken);
+		#endif
+
+		is_p2p_frame = OUI_Subtype;
+
+		switch(OUI_Subtype)
+		{
+			case P2P_NOTICE_OF_ABSENCE:
+				DBG_871X("RTW_%s:P2P_NOTICE_OF_ABSENCE, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
+				break;			
+			case P2P_PRESENCE_REQUEST:
+				DBG_871X("RTW_%s:P2P_PRESENCE_REQUEST, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
+				break;			
+			case P2P_PRESENCE_RESPONSE:
+				DBG_871X("RTW_%s:P2P_PRESENCE_RESPONSE, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
+				break;			
+			case P2P_GO_DISC_REQUEST:
+				DBG_871X("RTW_%s:P2P_GO_DISC_REQUEST, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", dialogToken);
+				break;			
+			default:
+				DBG_871X("RTW_%s:OUI_Subtype=%d, dialogToken=%d\n", (tx==_TRUE)?"TX":"RX", OUI_Subtype, dialogToken);
+				break;			
+		}	
+
+	}	
+	else
+	{
+		DBG_871X("RTW_%s:action frame category=%d\n", (tx==_TRUE)?"TX":"RX", category);
+	}
+
+	return is_p2p_frame;
+}
+
+void rtw_init_cfg80211_wifidirect_info( _adapter*	padapter)
+{
+	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
+
+	_rtw_memset(pcfg80211_wdinfo, 0x00, sizeof(struct cfg80211_wifidirect_info) );
+    
+	timer_setup( &pcfg80211_wdinfo->remain_on_ch_timer, ro_ch_timer_process, 0);
+}
+#endif //CONFIG_IOCTL_CFG80211	
+
+void p2p_protocol_wk_hdl(_adapter *padapter, int intCmdType)
+{
+	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
+	
+_func_enter_;
+
+	switch(intCmdType)
+	{
+		case P2P_FIND_PHASE_WK:
+		{
+			find_phase_handler( padapter );
+			break;
+		}
+		case P2P_RESTORE_STATE_WK:
+		{
+			restore_p2p_state_handler( padapter );
+			break;
+		}
+		case P2P_PRE_TX_PROVDISC_PROCESS_WK:
+		{
+#ifdef CONFIG_CONCURRENT_MODE
+			if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+			{
+				p2p_concurrent_handler( padapter );
+			}
+			else
+			{
+				pre_tx_provdisc_handler( padapter );
+			}
+#else
+			pre_tx_provdisc_handler( padapter );
+#endif
+			break;
+		}
+		case P2P_PRE_TX_INVITEREQ_PROCESS_WK:
+		{
+#ifdef CONFIG_CONCURRENT_MODE
+			if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+			{
+				p2p_concurrent_handler( padapter );
+			}
+			else
+			{
+				pre_tx_invitereq_handler( padapter );
+			}
+#else			
+			pre_tx_invitereq_handler( padapter );
+#endif
+			break;
+		}
+		case P2P_PRE_TX_NEGOREQ_PROCESS_WK:
+		{
+#ifdef CONFIG_CONCURRENT_MODE
+			if ( check_buddy_fwstate(padapter, _FW_LINKED ) )
+			{
+				p2p_concurrent_handler( padapter );
+			}
+			else
+			{
+				pre_tx_negoreq_handler( padapter );
+			}
+#else			
+			pre_tx_negoreq_handler( padapter );
+#endif
+			break;
+		}
+#ifdef CONFIG_P2P
+#ifdef CONFIG_CONCURRENT_MODE
+		case P2P_AP_P2P_CH_SWITCH_PROCESS_WK:
+		{
+			p2p_concurrent_handler( padapter );
+			break;
+		}		
+#endif
+#endif
+#ifdef CONFIG_IOCTL_CFG80211
+		case P2P_RO_CH_WK:
+		{
+			ro_ch_handler( padapter );
+			break;
+		}		
+#endif //CONFIG_IOCTL_CFG80211		
+
+	}
+	
+_func_exit_;
+}
+
+int process_p2p_cross_connect_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
+{
+	int ret = _TRUE;
+	u8 * ies;
+	u32 ies_len;
+	u8 * p2p_ie;
+	u32	p2p_ielen = 0;
+	u8	p2p_attr[MAX_P2P_IE_LEN] = { 0x00 };// NoA length should be n*(13) + 2
+	u32	attr_contentlen = 0;
+
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+
+_func_enter_;
+
+	if(IELength <= _BEACON_IE_OFFSET_)
+		return ret;
+	
+	ies = IEs + _BEACON_IE_OFFSET_;
+	ies_len = IELength - _BEACON_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen);
+	
+	while(p2p_ie)
+	{
+		// Get P2P Manageability IE.
+		if(rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_MANAGEABILITY, p2p_attr, &attr_contentlen))
+		{
+			if ((p2p_attr[0]&(BIT(0)|BIT(1))) == 0x01) {
+				ret = _FALSE; 
+			}
+			break;
+		}
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+	}
+
+_func_exit_;
+	return ret;
+}
+
+#ifdef CONFIG_P2P_PS
+void process_p2p_ps_ie(PADAPTER padapter, u8 *IEs, u32 IELength)
+{
+	u8 * ies;
+	u32 ies_len;
+	u8 * p2p_ie;
+	u32	p2p_ielen = 0;
+	u8	noa_attr[MAX_P2P_IE_LEN] = { 0x00 };// NoA length should be n*(13) + 2
+	u32	attr_contentlen = 0;
+	
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+	u8	find_p2p = _FALSE, find_p2p_ps = _FALSE;
+	u8	noa_offset, noa_num, noa_index;
+
+_func_enter_;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+	{
+		return;
+	}
+#ifdef CONFIG_CONCURRENT_MODE
+	if(padapter->iface_type != IFACE_PORT0) 
+		return;
+#endif
+	if(IELength <= _BEACON_IE_OFFSET_)
+		return;
+	
+	ies = IEs + _BEACON_IE_OFFSET_;
+	ies_len = IELength - _BEACON_IE_OFFSET_;
+
+	p2p_ie = rtw_get_p2p_ie( ies, ies_len, NULL, &p2p_ielen);
+	
+	while(p2p_ie)
+	{
+		find_p2p = _TRUE;
+		// Get Notice of Absence IE.
+		if(rtw_get_p2p_attr_content( p2p_ie, p2p_ielen, P2P_ATTR_NOA, noa_attr, &attr_contentlen))
+		{
+			find_p2p_ps = _TRUE;
+			noa_index = noa_attr[0];
+
+			if( (pwdinfo->p2p_ps_mode == P2P_PS_NONE) ||
+				(noa_index != pwdinfo->noa_index) )// if index change, driver should reconfigure related setting.
+			{
+				pwdinfo->noa_index = noa_index;
+				pwdinfo->opp_ps = noa_attr[1] >> 7;
+				pwdinfo->ctwindow = noa_attr[1] & 0x7F;
+
+				noa_offset = 2;
+				noa_num = 0;
+				// NoA length should be n*(13) + 2
+				if(attr_contentlen > 2)
+				{
+					while(noa_offset < attr_contentlen)
+					{
+						//_rtw_memcpy(&wifidirect_info->noa_count[noa_num], &noa_attr[noa_offset], 1);
+						pwdinfo->noa_count[noa_num] = noa_attr[noa_offset];
+						noa_offset += 1;
+
+						_rtw_memcpy(&pwdinfo->noa_duration[noa_num], &noa_attr[noa_offset], 4);
+						noa_offset += 4;
+
+						_rtw_memcpy(&pwdinfo->noa_interval[noa_num], &noa_attr[noa_offset], 4);
+						noa_offset += 4;
+
+						_rtw_memcpy(&pwdinfo->noa_start_time[noa_num], &noa_attr[noa_offset], 4);
+						noa_offset += 4;
+
+						noa_num++;
+					}
+				}
+				pwdinfo->noa_num = noa_num;
+
+				if( pwdinfo->opp_ps == 1 )
+				{
+					pwdinfo->p2p_ps_mode = P2P_PS_CTWINDOW;
+					// driver should wait LPS for entering CTWindow
+					if(adapter_to_pwrctl(padapter)->bFwCurrentInPSMode == _TRUE)
+					{
+						p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
+					}
+				}
+				else if( pwdinfo->noa_num > 0 )
+				{
+					pwdinfo->p2p_ps_mode = P2P_PS_NOA;
+					p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 1);
+				}
+				else if( pwdinfo->p2p_ps_mode > P2P_PS_NONE)
+				{
+					p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
+				}
+			}
+
+			break; // find target, just break.
+		}
+
+		//Get the next P2P IE
+		p2p_ie = rtw_get_p2p_ie(p2p_ie+p2p_ielen, ies_len -(p2p_ie -ies + p2p_ielen), NULL, &p2p_ielen);
+
+	}
+
+	if(find_p2p == _TRUE)
+	{
+		if( (pwdinfo->p2p_ps_mode > P2P_PS_NONE) && (find_p2p_ps == _FALSE) )
+		{
+			p2p_ps_wk_cmd(padapter, P2P_PS_DISABLE, 1);
+		}
+	}
+
+_func_exit_;
+}
+
+void p2p_ps_wk_hdl(_adapter *padapter, u8 p2p_ps_state)
+{
+	struct pwrctrl_priv		*pwrpriv = adapter_to_pwrctl(padapter);
+	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
+	
+_func_enter_;
+
+	// Pre action for p2p state
+	switch(p2p_ps_state)
+	{
+		case P2P_PS_DISABLE:
+			pwdinfo->p2p_ps_state = p2p_ps_state;
+			
+			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
+
+			pwdinfo->noa_index = 0;
+			pwdinfo->ctwindow = 0;
+			pwdinfo->opp_ps = 0;
+			pwdinfo->noa_num = 0;
+			pwdinfo->p2p_ps_mode = P2P_PS_NONE;
+			if(pwrpriv->bFwCurrentInPSMode == _TRUE)
+			{
+				if(pwrpriv->smart_ps == 0)
+				{
+					pwrpriv->smart_ps = 2;
+					rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
+				}
+			}
+			break;
+		case P2P_PS_ENABLE:
+			if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
+				pwdinfo->p2p_ps_state = p2p_ps_state;
+				
+				if( pwdinfo->ctwindow > 0 )
+				{
+					if(pwrpriv->smart_ps != 0)
+					{
+						pwrpriv->smart_ps = 0;
+						DBG_871X("%s(): Enter CTW, change SmartPS\n", __FUNCTION__);
+						rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&(pwrpriv->pwr_mode)));
+					}
+				}
+				rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
+			}
+			break;
+		case P2P_PS_SCAN:
+		case P2P_PS_SCAN_DONE:
+		case P2P_PS_ALLSTASLEEP:
+			if (pwdinfo->p2p_ps_mode > P2P_PS_NONE) {
+				pwdinfo->p2p_ps_state = p2p_ps_state;
+				rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_P2P_PS_OFFLOAD, (u8 *)(&p2p_ps_state));
+			}
+			break;
+		default:
+			break;
+	}
+
+_func_exit_;
+}
+
+u8 p2p_ps_wk_cmd(_adapter*padapter, u8 p2p_ps_state, u8 enqueue)
+{
+	struct cmd_obj	*ph2c;
+	struct drvextra_cmd_parm	*pdrvextra_cmd_parm;
+	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
+	struct cmd_priv	*pcmdpriv = &padapter->cmdpriv;
+	u8	res = _SUCCESS;
+	
+_func_enter_;
+
+	if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE) 
+#ifdef CONFIG_CONCURRENT_MODE
+		|| (padapter->iface_type != IFACE_PORT0) 
+#endif
+		)
+	{
+		return res;
+	}
+
+	if(enqueue)
+	{
+		ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj));	
+		if(ph2c==NULL){
+			res= _FAIL;
+			goto exit;
+		}
+		
+		pdrvextra_cmd_parm = (struct drvextra_cmd_parm*)rtw_zmalloc(sizeof(struct drvextra_cmd_parm)); 
+		if(pdrvextra_cmd_parm==NULL){
+			rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+			res= _FAIL;
+			goto exit;
+		}
+
+		pdrvextra_cmd_parm->ec_id = P2P_PS_WK_CID;
+		pdrvextra_cmd_parm->type = p2p_ps_state;
+		pdrvextra_cmd_parm->size = 0;
+		pdrvextra_cmd_parm->pbuf = NULL;
+
+		init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
+
+		res = rtw_enqueue_cmd(pcmdpriv, ph2c);
+	}
+	else
+	{
+		p2p_ps_wk_hdl(padapter, p2p_ps_state);
+	}
+	
+exit:
+	
+_func_exit_;
+
+	return res;
+
+}
+#endif // CONFIG_P2P_PS
+
+static void reset_ch_sitesurvey_timer_process (void *FunctionContext)
+{
+	_adapter *adapter = (_adapter *)FunctionContext;
+	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return;
+
+	DBG_871X( "[%s] In\n", __FUNCTION__ );
+	//	Reset the operation channel information
+	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
+#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->rx_invitereq_info.operation_ch[1] = 0;
+	pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
+	pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
+#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH 
+	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
+}
+
+static void reset_ch_sitesurvey_timer_process2 (void *FunctionContext)
+{
+	_adapter *adapter = (_adapter *)FunctionContext;
+	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return;
+
+	DBG_871X( "[%s] In\n", __FUNCTION__ );
+	//	Reset the operation channel information
+	pwdinfo->p2p_info.operation_ch[0] = 0;
+#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->p2p_info.operation_ch[1] = 0;
+	pwdinfo->p2p_info.operation_ch[2] = 0;
+	pwdinfo->p2p_info.operation_ch[3] = 0;
+#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->p2p_info.scan_op_ch_only = 0;
+}
+
+static void restore_p2p_state_timer_process (void *FunctionContext)
+{
+	_adapter *adapter = (_adapter *)FunctionContext;
+	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return; 
+	
+	p2p_protocol_wk_cmd( adapter, P2P_RESTORE_STATE_WK );
+}
+
+static void pre_tx_scan_timer_process (void *FunctionContext)
+{
+	_adapter 							*adapter = (_adapter *) FunctionContext;
+	struct	wifidirect_info				*pwdinfo = &adapter->wdinfo;
+	_irqL							irqL;
+	struct mlme_priv					*pmlmepriv = &adapter->mlmepriv;
+	u8								_status = 0;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return;
+	
+	_enter_critical_bh(&pmlmepriv->lock, &irqL);
+
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ))
+	{
+		if ( _TRUE == pwdinfo->tx_prov_disc_info.benable )	//	the provision discovery request frame is trigger to send or not
+		{
+			p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_PROVDISC_PROCESS_WK );			
+			//issue_probereq_p2p(adapter, NULL);
+			//_set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
+		}
+	}
+	else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING))
+	{
+		if ( _TRUE == pwdinfo->nego_req_info.benable )
+		{
+			p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_NEGOREQ_PROCESS_WK );
+		}
+	}
+	else if ( rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ ) )
+	{
+		if ( _TRUE == pwdinfo->invitereq_info.benable )
+		{
+			p2p_protocol_wk_cmd( adapter, P2P_PRE_TX_INVITEREQ_PROCESS_WK );
+		}
+	}
+	else
+	{
+		DBG_8192C( "[%s] p2p_state is %d, ignore!!\n", __FUNCTION__, rtw_p2p_state(pwdinfo) );
+	}
+	
+	_exit_critical_bh(&pmlmepriv->lock, &irqL);
+}
+
+static void find_phase_timer_process (void *FunctionContext)
+{
+	_adapter *adapter = (_adapter *)FunctionContext;
+	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return;
+
+	adapter->wdinfo.find_phase_state_exchange_cnt++;
+
+	p2p_protocol_wk_cmd( adapter, P2P_FIND_PHASE_WK );
+}
+
+#ifdef CONFIG_CONCURRENT_MODE
+void ap_p2p_switch_timer_process (void *FunctionContext)
+{
+	_adapter *adapter = (_adapter *)FunctionContext;
+	struct	wifidirect_info		*pwdinfo = &adapter->wdinfo;
+#ifdef CONFIG_IOCTL_CFG80211	
+	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
+#endif
+
+	if(rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
+#endif
+
+	p2p_protocol_wk_cmd( adapter, P2P_AP_P2P_CH_SWITCH_PROCESS_WK );
+}
+#endif
+
+void reset_global_wifidirect_info( _adapter* padapter )
+{
+	struct wifidirect_info	*pwdinfo;
+
+	pwdinfo = &padapter->wdinfo;
+	pwdinfo->persistent_supported = 0;
+	pwdinfo->session_available = _TRUE;
+	rtw_tdls_wfd_enable(padapter, 0);
+	pwdinfo->wfd_tdls_weaksec = _TRUE;
+}
+
+#ifdef CONFIG_WFD
+int rtw_init_wifi_display_info(_adapter* padapter)
+{
+	int	res = _SUCCESS;
+	struct wifi_display_info *pwfd_info = &padapter->wfd_info;
+
+	// Used in P2P and TDLS
+	pwfd_info->init_rtsp_ctrlport = 554;
+#ifdef CONFIG_IOCTL_CFG80211
+	pwfd_info->rtsp_ctrlport = 0;
+#else
+	pwfd_info->rtsp_ctrlport = pwfd_info->init_rtsp_ctrlport; /* set non-zero value for legacy wfd */
+#endif
+	pwfd_info->tdls_rtsp_ctrlport = 0;
+	pwfd_info->peer_rtsp_ctrlport = 0;	//	Reset to 0
+	pwfd_info->wfd_enable = _FALSE;
+	pwfd_info->wfd_device_type = WFD_DEVINFO_PSINK;
+	pwfd_info->scan_result_type = SCAN_RESULT_P2P_ONLY;
+
+	// Used in P2P
+	pwfd_info->peer_session_avail = _TRUE;
+	pwfd_info->wfd_pc = _FALSE;
+
+	// Used in TDLS
+	_rtw_memset( pwfd_info->ip_address, 0x00, 4 );
+	_rtw_memset( pwfd_info->peer_ip_address, 0x00, 4 );
+	return res;
+
+}
+
+inline void rtw_wfd_enable(_adapter *adapter, bool on)
+{
+	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
+
+	if (on) {
+		wfdinfo->rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
+		wfdinfo->wfd_enable = _TRUE;
+
+	} else {
+		wfdinfo->wfd_enable = _FALSE;
+		wfdinfo->rtsp_ctrlport = 0;
+	}
+}
+
+inline void rtw_wfd_set_ctrl_port(_adapter *adapter, u16 port)
+{
+	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
+
+	wfdinfo->init_rtsp_ctrlport = port;
+	if (wfdinfo->wfd_enable == _TRUE)
+		wfdinfo->rtsp_ctrlport = port;
+	if (adapter->wdinfo.wfd_tdls_enable == 1)
+		wfdinfo->tdls_rtsp_ctrlport = port;
+}
+
+inline void rtw_tdls_wfd_enable(_adapter *adapter, bool on)
+{
+	struct wifi_display_info *wfdinfo = &adapter->wfd_info;
+
+	if (on) {
+		wfdinfo->tdls_rtsp_ctrlport = wfdinfo->init_rtsp_ctrlport;
+		adapter->wdinfo.wfd_tdls_enable = 1;
+
+	} else {
+		adapter->wdinfo.wfd_tdls_enable = 0;
+		wfdinfo->tdls_rtsp_ctrlport = 0;
+	}
+}
+
+u32 rtw_append_beacon_wfd_ie(_adapter *adapter, u8 *pbuf)
+{
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	u8 build_ie_by_self = 0;
+	u32 len = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (_TRUE == wdinfo->wfd_info->wfd_enable)
+#endif
+		build_ie_by_self = 1;
+
+	if (build_ie_by_self)
+		len = build_beacon_wfd_ie(wdinfo, pbuf);
+#ifdef CONFIG_IOCTL_CFG80211
+	else if (mlme->wfd_beacon_ie && mlme->wfd_beacon_ie_len > 0) {
+		len = mlme->wfd_beacon_ie_len;
+		_rtw_memcpy(pbuf, mlme->wfd_beacon_ie, len);
+	}
+#endif
+
+exit:
+	return len;
+}
+
+u32 rtw_append_probe_req_wfd_ie(_adapter *adapter, u8 *pbuf)
+{
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	u8 build_ie_by_self = 0;
+	u32 len = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (_TRUE == wdinfo->wfd_info->wfd_enable)
+#endif
+		build_ie_by_self = 1;
+
+	if (build_ie_by_self)
+		len = build_probe_req_wfd_ie(wdinfo, pbuf);
+#ifdef CONFIG_IOCTL_CFG80211
+	else if (mlme->wfd_probe_req_ie && mlme->wfd_probe_req_ie_len > 0) {
+		len = mlme->wfd_probe_req_ie_len;
+		_rtw_memcpy(pbuf, mlme->wfd_probe_req_ie, len);
+	}
+#endif
+
+exit:
+	return len;
+}
+
+u32 rtw_append_probe_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
+{
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	u8 build_ie_by_self = 0;
+	u32 len = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (_TRUE == wdinfo->wfd_info->wfd_enable)
+#endif
+		build_ie_by_self = 1;
+
+	if (build_ie_by_self)
+		len = build_probe_resp_wfd_ie(wdinfo, pbuf, 0);
+#ifdef CONFIG_IOCTL_CFG80211
+	else if (mlme->wfd_probe_resp_ie && mlme->wfd_probe_resp_ie_len > 0) {
+		len = mlme->wfd_probe_resp_ie_len;
+		_rtw_memcpy(pbuf, mlme->wfd_probe_resp_ie, len);
+	}
+#endif
+
+exit:
+	return len;
+}
+
+u32 rtw_append_assoc_req_wfd_ie(_adapter *adapter, u8 *pbuf)
+{
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	u8 build_ie_by_self = 0;
+	u32 len = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (_TRUE == wdinfo->wfd_info->wfd_enable)
+#endif
+		build_ie_by_self = 1;
+
+	if (build_ie_by_self)
+		len = build_assoc_req_wfd_ie(wdinfo, pbuf);
+#ifdef CONFIG_IOCTL_CFG80211
+	else if (mlme->wfd_assoc_req_ie && mlme->wfd_assoc_req_ie_len > 0) {
+		len = mlme->wfd_assoc_req_ie_len;
+		_rtw_memcpy(pbuf, mlme->wfd_assoc_req_ie, len);
+	}
+#endif
+
+exit:
+	return len;
+}
+
+u32 rtw_append_assoc_resp_wfd_ie(_adapter *adapter, u8 *pbuf)
+{
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+	struct mlme_priv *mlme = &adapter->mlmepriv;
+	u8 build_ie_by_self = 0;
+	u32 len = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		goto exit;
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (_TRUE == wdinfo->wfd_info->wfd_enable)
+#endif
+		build_ie_by_self = 1;
+
+	if (build_ie_by_self)
+		len = build_assoc_resp_wfd_ie(wdinfo, pbuf);
+#ifdef CONFIG_IOCTL_CFG80211
+	else if (mlme->wfd_assoc_resp_ie && mlme->wfd_assoc_resp_ie_len > 0) {
+		len = mlme->wfd_assoc_resp_ie_len;
+		_rtw_memcpy(pbuf, mlme->wfd_assoc_resp_ie, len);
+	}
+#endif
+
+exit:
+	return len;
+}
+
+#endif /* CONFIG_WFD */
+
+void rtw_init_wifidirect_timers(_adapter* padapter)
+{
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+	//_init_timer( &pwdinfo->find_phase_timer, padapter->pnetdev, find_phase_timer_process, padapter );
+	//_init_timer( &pwdinfo->restore_p2p_state_timer, padapter->pnetdev, restore_p2p_state_timer_process, padapter );
+	//_init_timer( &pwdinfo->pre_tx_scan_timer, padapter->pnetdev, pre_tx_scan_timer_process, padapter );
+	//_init_timer( &pwdinfo->reset_ch_sitesurvey, padapter->pnetdev, reset_ch_sitesurvey_timer_process, padapter );
+	//_init_timer( &pwdinfo->reset_ch_sitesurvey2, padapter->pnetdev, reset_ch_sitesurvey_timer_process2, padapter );
+#ifdef CONFIG_CONCURRENT_MODE
+	//_init_timer( &pwdinfo->ap_p2p_switch_timer, padapter->pnetdev, ap_p2p_switch_timer_process, padapter );
+#endif
+}
+
+void rtw_init_wifidirect_addrs(_adapter* padapter, u8 *dev_addr, u8 *iface_addr)
+{
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+
+	/*init device&interface address */
+	if (dev_addr) {
+		_rtw_memcpy(pwdinfo->device_addr, dev_addr, ETH_ALEN);
+	}
+	if (iface_addr) {
+		_rtw_memcpy(pwdinfo->interface_addr, iface_addr, ETH_ALEN);
+	}
+#endif
+}
+
+void init_wifidirect_info( _adapter* padapter, enum P2P_ROLE role)
+{
+	struct wifidirect_info	*pwdinfo;
+#ifdef CONFIG_WFD
+	struct wifi_display_info	*pwfd_info = &padapter->wfd_info;
+#endif
+#ifdef CONFIG_CONCURRENT_MODE
+	_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
+	struct wifidirect_info	*pbuddy_wdinfo = NULL;
+	struct mlme_priv		*pbuddy_mlmepriv = NULL;
+	struct mlme_ext_priv	*pbuddy_mlmeext = NULL;
+#endif
+
+	pwdinfo = &padapter->wdinfo;
+
+	pwdinfo->padapter = padapter;
+	
+	//	1, 6, 11 are the social channel defined in the WiFi Direct specification.
+	pwdinfo->social_chan[0] = 1;
+	pwdinfo->social_chan[1] = 6;
+	pwdinfo->social_chan[2] = 11;
+	pwdinfo->social_chan[3] = 0;	//	channel 0 for scanning ending in site survey function.
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if (pbuddy_adapter) {
+		pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+		pbuddy_mlmepriv = &pbuddy_adapter->mlmepriv;
+		pbuddy_mlmeext = &pbuddy_adapter->mlmeextpriv;
+	}
+
+	if ( ( check_buddy_fwstate(padapter, _FW_LINKED ) == _TRUE ) && 
+	      ( ( pbuddy_mlmeext->cur_channel == 1) || ( pbuddy_mlmeext->cur_channel == 6 ) || ( pbuddy_mlmeext->cur_channel == 11 ) )
+	   )
+	{
+		//	Use the AP's channel as the listen channel
+		//	This will avoid the channel switch between AP's channel and listen channel.
+		pwdinfo->listen_channel = pbuddy_mlmeext->cur_channel;
+	}
+	else
+#endif //CONFIG_CONCURRENT_MODE
+	{
+		//	Use the channel 11 as the listen channel
+		pwdinfo->listen_channel = 11;
+	}
+
+	if (role == P2P_ROLE_DEVICE)
+	{
+		rtw_p2p_set_role(pwdinfo, P2P_ROLE_DEVICE);
+		#ifdef CONFIG_CONCURRENT_MODE
+		if ( check_buddy_fwstate(padapter, _FW_LINKED ) == _TRUE )
+		{
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
+		}
+		else
+		#endif
+		{
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
+		}
+		pwdinfo->intent = 1;
+		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_LISTEN);
+	}
+	else if (role == P2P_ROLE_CLIENT)
+	{
+		rtw_p2p_set_role(pwdinfo, P2P_ROLE_CLIENT);
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+		pwdinfo->intent = 1;
+		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+	}	
+	else if (role == P2P_ROLE_GO)
+	{
+		rtw_p2p_set_role(pwdinfo, P2P_ROLE_GO);
+		rtw_p2p_set_state(pwdinfo, P2P_STATE_GONEGO_OK);
+		pwdinfo->intent = 15;
+		rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_GONEGO_OK);
+	}
+
+//	Use the OFDM rate in the P2P probe response frame. ( 6(B), 9(B), 12, 18, 24, 36, 48, 54 )	
+	pwdinfo->support_rate[0] = 0x8c;	//	6(B)
+	pwdinfo->support_rate[1] = 0x92;	//	9(B)
+	pwdinfo->support_rate[2] = 0x18;	//	12
+	pwdinfo->support_rate[3] = 0x24;	//	18
+	pwdinfo->support_rate[4] = 0x30;	//	24
+	pwdinfo->support_rate[5] = 0x48;	//	36
+	pwdinfo->support_rate[6] = 0x60;	//	48
+	pwdinfo->support_rate[7] = 0x6c;	//	54
+
+	_rtw_memcpy( ( void* ) pwdinfo->p2p_wildcard_ssid, "DIRECT-", 7 );
+
+	_rtw_memset( pwdinfo->device_name, 0x00, WPS_MAX_DEVICE_NAME_LEN );
+	pwdinfo->device_name_len = 0;
+
+	_rtw_memset( &pwdinfo->invitereq_info, 0x00, sizeof( struct tx_invite_req_info ) );
+	pwdinfo->invitereq_info.token = 3;	//	Token used for P2P invitation request frame.
+	
+	_rtw_memset( &pwdinfo->inviteresp_info, 0x00, sizeof( struct tx_invite_resp_info ) );
+	pwdinfo->inviteresp_info.token = 0;
+
+	pwdinfo->profileindex = 0;
+	_rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
+
+	rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
+
+	pwdinfo->listen_dwell = ( u8 ) (( rtw_get_current_time() % 3 ) + 1);
+	//DBG_8192C( "[%s] listen_dwell time is %d00ms\n", __FUNCTION__, pwdinfo->listen_dwell );
+
+	_rtw_memset( &pwdinfo->tx_prov_disc_info, 0x00, sizeof( struct tx_provdisc_req_info ) );
+	pwdinfo->tx_prov_disc_info.wps_config_method_request = WPS_CM_NONE;
+
+	_rtw_memset( &pwdinfo->nego_req_info, 0x00, sizeof( struct tx_nego_req_info ) );
+
+	pwdinfo->device_password_id_for_nego = WPS_DPID_PBC;
+	pwdinfo->negotiation_dialog_token = 1;
+
+	_rtw_memset( pwdinfo->nego_ssid, 0x00, WLAN_SSID_MAXLEN );
+	pwdinfo->nego_ssidlen = 0;
+
+	pwdinfo->ui_got_wps_info = P2P_NO_WPSINFO;
+#ifdef CONFIG_WFD
+	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY  | WPS_CONFIG_METHOD_PBC;
+	pwdinfo->wfd_info = pwfd_info;
+#else
+	pwdinfo->supported_wps_cm = WPS_CONFIG_METHOD_DISPLAY | WPS_CONFIG_METHOD_PBC | WPS_CONFIG_METHOD_KEYPAD;
+#endif //CONFIG_WFD
+	pwdinfo->channel_list_attr_len = 0;
+	_rtw_memset( pwdinfo->channel_list_attr, 0x00, 100 );
+
+	_rtw_memset( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, 0x00, 4 );
+	_rtw_memset( pwdinfo->rx_prov_disc_info.strconfig_method_desc_of_prov_disc_req, '0', 3 );
+	_rtw_memset( &pwdinfo->groupid_info, 0x00, sizeof( struct group_id_info ) );
+#ifdef CONFIG_CONCURRENT_MODE
+#ifdef CONFIG_IOCTL_CFG80211
+	pwdinfo->ext_listen_interval = 1000; //The interval to be available with legacy AP during p2p0-find/scan
+	pwdinfo->ext_listen_period = 3000; //The time period to be available for P2P during nego
+#else //!CONFIG_IOCTL_CFG80211
+	//pwdinfo->ext_listen_interval = 3000;
+	//pwdinfo->ext_listen_period = 400;
+	pwdinfo->ext_listen_interval = 1000;
+	pwdinfo->ext_listen_period = 1000;
+#endif //!CONFIG_IOCTL_CFG80211
+#endif
+
+// Commented by Kurt 20130319
+// For WiDi purpose: Use CFG80211 interface but controled WFD/RDS frame by driver itself.
+#ifdef CONFIG_IOCTL_CFG80211
+	pwdinfo->driver_interface = DRIVER_CFG80211;
+#else
+	pwdinfo->driver_interface = DRIVER_WEXT;
+#endif //CONFIG_IOCTL_CFG80211
+
+	pwdinfo->wfd_tdls_enable = 0;
+	_rtw_memset( pwdinfo->p2p_peer_interface_addr, 0x00, ETH_ALEN );
+	_rtw_memset( pwdinfo->p2p_peer_device_addr, 0x00, ETH_ALEN );
+
+	pwdinfo->rx_invitereq_info.operation_ch[0] = 0;
+	pwdinfo->rx_invitereq_info.operation_ch[1] = 0;	//	Used to indicate the scan end in site survey function
+#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->rx_invitereq_info.operation_ch[2] = 0;
+	pwdinfo->rx_invitereq_info.operation_ch[3] = 0;
+	pwdinfo->rx_invitereq_info.operation_ch[4] = 0;
+#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->rx_invitereq_info.scan_op_ch_only = 0;
+	pwdinfo->p2p_info.operation_ch[0] = 0;
+	pwdinfo->p2p_info.operation_ch[1] = 0;			//	Used to indicate the scan end in site survey function
+#ifdef CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->p2p_info.operation_ch[2] = 0;
+	pwdinfo->p2p_info.operation_ch[3] = 0;
+	pwdinfo->p2p_info.operation_ch[4] = 0;
+#endif //CONFIG_P2P_OP_CHK_SOCIAL_CH
+	pwdinfo->p2p_info.scan_op_ch_only = 0;
+}
+
+#ifdef CONFIG_DBG_P2P
+
+/**
+ * rtw_p2p_role_txt - Get the p2p role name as a text string
+ * @role: P2P role
+ * Returns: The state name as a printable text string
+ */
+const char * rtw_p2p_role_txt(enum P2P_ROLE role)
+{
+	switch (role) {
+	case P2P_ROLE_DISABLE:
+		return "P2P_ROLE_DISABLE";
+	case P2P_ROLE_DEVICE:
+		return "P2P_ROLE_DEVICE";
+	case P2P_ROLE_CLIENT:
+		return "P2P_ROLE_CLIENT";
+	case P2P_ROLE_GO:
+		return "P2P_ROLE_GO";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+/**
+ * rtw_p2p_state_txt - Get the p2p state name as a text string
+ * @state: P2P state
+ * Returns: The state name as a printable text string
+ */
+const char * rtw_p2p_state_txt(enum P2P_STATE state)
+{
+	switch (state) {
+	case P2P_STATE_NONE:
+		return "P2P_STATE_NONE";
+	case P2P_STATE_IDLE:
+		return "P2P_STATE_IDLE";
+	case P2P_STATE_LISTEN:
+		return "P2P_STATE_LISTEN";
+	case P2P_STATE_SCAN:
+		return "P2P_STATE_SCAN";
+	case P2P_STATE_FIND_PHASE_LISTEN:
+		return "P2P_STATE_FIND_PHASE_LISTEN";
+	case P2P_STATE_FIND_PHASE_SEARCH:
+		return "P2P_STATE_FIND_PHASE_SEARCH";
+	case P2P_STATE_TX_PROVISION_DIS_REQ:
+		return "P2P_STATE_TX_PROVISION_DIS_REQ";
+	case P2P_STATE_RX_PROVISION_DIS_RSP:
+		return "P2P_STATE_RX_PROVISION_DIS_RSP";
+	case P2P_STATE_RX_PROVISION_DIS_REQ:
+		return "P2P_STATE_RX_PROVISION_DIS_REQ";
+	case P2P_STATE_GONEGO_ING:
+		return "P2P_STATE_GONEGO_ING";
+	case P2P_STATE_GONEGO_OK:
+		return "P2P_STATE_GONEGO_OK";
+	case P2P_STATE_GONEGO_FAIL:
+		return "P2P_STATE_GONEGO_FAIL";
+	case P2P_STATE_RECV_INVITE_REQ_MATCH:
+		return "P2P_STATE_RECV_INVITE_REQ_MATCH";
+	case P2P_STATE_PROVISIONING_ING:
+		return "P2P_STATE_PROVISIONING_ING";
+	case P2P_STATE_PROVISIONING_DONE:
+		return "P2P_STATE_PROVISIONING_DONE";
+	case P2P_STATE_TX_INVITE_REQ:
+		return "P2P_STATE_TX_INVITE_REQ";
+	case P2P_STATE_RX_INVITE_RESP_OK:
+		return "P2P_STATE_RX_INVITE_RESP_OK";
+	case P2P_STATE_RECV_INVITE_REQ_DISMATCH:
+		return "P2P_STATE_RECV_INVITE_REQ_DISMATCH";
+	case P2P_STATE_RECV_INVITE_REQ_GO:
+		return "P2P_STATE_RECV_INVITE_REQ_GO";
+	case P2P_STATE_RECV_INVITE_REQ_JOIN:
+		return "P2P_STATE_RECV_INVITE_REQ_JOIN";
+	case P2P_STATE_RX_INVITE_RESP_FAIL:
+		return "P2P_STATE_RX_INVITE_RESP_FAIL";
+	case P2P_STATE_RX_INFOR_NOREADY:
+		return "P2P_STATE_RX_INFOR_NOREADY";
+	case P2P_STATE_TX_INFOR_NOREADY:
+		return "P2P_STATE_TX_INFOR_NOREADY";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+void dbg_rtw_p2p_set_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
+{
+	if(!_rtw_p2p_chk_state(wdinfo, state)) {
+		enum P2P_STATE old_state = _rtw_p2p_state(wdinfo);
+		_rtw_p2p_set_state(wdinfo, state);
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_state from %s to %s\n", caller, line
+			, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
+		);
+	} else {
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_state to same state %s\n", caller, line
+			, rtw_p2p_state_txt(_rtw_p2p_state(wdinfo))
+		);
+	}
+}
+void dbg_rtw_p2p_set_pre_state(struct wifidirect_info *wdinfo, enum P2P_STATE state, const char *caller, int line)
+{
+	if(_rtw_p2p_pre_state(wdinfo) != state) {
+		enum P2P_STATE old_state = _rtw_p2p_pre_state(wdinfo); 
+		_rtw_p2p_set_pre_state(wdinfo, state);
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_pre_state from %s to %s\n", caller, line
+			, rtw_p2p_state_txt(old_state), rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
+		);
+	} else {
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_pre_state to same state %s\n", caller, line
+			, rtw_p2p_state_txt(_rtw_p2p_pre_state(wdinfo))
+		);
+	}
+}
+#if 0
+void dbg_rtw_p2p_restore_state(struct wifidirect_info *wdinfo, const char *caller, int line)
+{
+	if(wdinfo->pre_p2p_state != -1) {
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d restore from %s to %s\n", caller, line
+			, p2p_state_str[wdinfo->p2p_state], p2p_state_str[wdinfo->pre_p2p_state]
+		);
+		_rtw_p2p_restore_state(wdinfo);
+	} else {
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d restore no pre state, cur state %s\n", caller, line
+			, p2p_state_str[wdinfo->p2p_state]
+		);		
+	}
+}
+#endif
+void dbg_rtw_p2p_set_role(struct wifidirect_info *wdinfo, enum P2P_ROLE role, const char *caller, int line)
+{
+	if(wdinfo->role != role) {
+		enum P2P_ROLE old_role = wdinfo->role;
+		_rtw_p2p_set_role(wdinfo, role);
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_role from %s to %s\n", caller, line
+			, rtw_p2p_role_txt(old_role), rtw_p2p_role_txt(wdinfo->role)
+		);
+	} else {
+		DBG_871X("[CONFIG_DBG_P2P]%s:%d set_role to same role %s\n", caller, line
+			, rtw_p2p_role_txt(wdinfo->role)
+		);
+	}
+}
+#endif //CONFIG_DBG_P2P
+
+
+int rtw_p2p_enable(_adapter *padapter, enum P2P_ROLE role)
+{
+	int ret = _SUCCESS;
+	struct wifidirect_info *pwdinfo= &(padapter->wdinfo);
+
+	if (role == P2P_ROLE_DEVICE || role == P2P_ROLE_CLIENT|| role == P2P_ROLE_GO)
+	{
+		u8 channel, ch_offset;
+		u16 bwmode;
+
+#ifdef CONFIG_CONCURRENT_MODE
+		_adapter				*pbuddy_adapter = padapter->pbuddy_adapter;
+		struct wifidirect_info	*pbuddy_wdinfo = &pbuddy_adapter->wdinfo;
+		//	Commented by Albert 2011/12/30
+		//	The driver just supports 1 P2P group operation.
+		//	So, this function will do nothing if the buddy adapter had enabled the P2P function.
+		if(!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE))
+		{
+			//	The buddy adapter had enabled the P2P function.
+			return ret;
+		}
+#endif //CONFIG_CONCURRENT_MODE
+
+		//leave IPS/Autosuspend
+		if (_FAIL == rtw_pwr_wakeup(padapter)) {
+			ret = _FAIL;
+			goto exit;
+		}
+
+		//	Added by Albert 2011/03/22
+		//	In the P2P mode, the driver should not support the b mode.
+		//	So, the Tx packet shouldn't use the CCK rate
+		update_tx_basic_rate(padapter, WIRELESS_11AGN);
+
+		//Enable P2P function
+		init_wifidirect_info(padapter, role);
+				
+		rtw_hal_set_odm_var(padapter,HAL_ODM_P2P_STATE,NULL,_TRUE);
+		#ifdef CONFIG_WFD
+		if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+			rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _TRUE);
+		#endif
+		
+	}
+	else if (role == P2P_ROLE_DISABLE)
+	{
+#ifdef CONFIG_INTEL_WIDI
+		if( padapter->mlmepriv.p2p_reject_disable == _TRUE )
+			return ret;
+#endif //CONFIG_INTEL_WIDI
+
+#ifdef CONFIG_IOCTL_CFG80211
+		if( padapter->wdinfo.driver_interface == DRIVER_CFG80211 )
+			adapter_wdev_data(padapter)->p2p_enabled = _FALSE;
+#endif //CONFIG_IOCTL_CFG80211
+
+
+		//Disable P2P function
+		if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		{
+			_cancel_timer_ex( &pwdinfo->find_phase_timer );
+			_cancel_timer_ex( &pwdinfo->restore_p2p_state_timer );
+			_cancel_timer_ex( &pwdinfo->pre_tx_scan_timer);
+			_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey);
+			_cancel_timer_ex( &pwdinfo->reset_ch_sitesurvey2);
+			reset_ch_sitesurvey_timer_process( padapter );
+			reset_ch_sitesurvey_timer_process2( padapter );
+			#ifdef CONFIG_CONCURRENT_MODE			
+			_cancel_timer_ex( &pwdinfo->ap_p2p_switch_timer);
+			#endif
+			rtw_p2p_set_state(pwdinfo, P2P_STATE_NONE);
+			rtw_p2p_set_pre_state(pwdinfo, P2P_STATE_NONE);
+			rtw_p2p_set_role(pwdinfo, P2P_ROLE_DISABLE);
+			_rtw_memset(&pwdinfo->rx_prov_disc_info, 0x00, sizeof(struct rx_provdisc_req_info));
+
+			/* Remove profiles in wifidirect_info structure. */
+			_rtw_memset( &pwdinfo->profileinfo[ 0 ], 0x00, sizeof( struct profile_info ) * P2P_MAX_PERSISTENT_GROUP_NUM );
+			pwdinfo->profileindex = 0;
+		}
+
+		rtw_hal_set_odm_var(padapter,HAL_ODM_P2P_STATE,NULL,_FALSE);
+		#ifdef CONFIG_WFD
+		if (hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+			rtw_hal_set_odm_var(padapter, HAL_ODM_WIFI_DISPLAY_STATE, NULL, _FALSE);
+		#endif
+
+		if (_FAIL == rtw_pwr_wakeup(padapter)) {
+			ret = _FAIL;
+			goto exit;
+		}
+
+		//Restore to initial setting.
+		update_tx_basic_rate(padapter, padapter->registrypriv.wireless_mode);
+
+#ifdef CONFIG_INTEL_WIDI
+		rtw_reset_widi_info(padapter);
+#endif //CONFIG_INTEL_WIDI
+
+		//For WiDi purpose.
+#ifdef CONFIG_IOCTL_CFG80211
+		pwdinfo->driver_interface = DRIVER_CFG80211;
+#else
+		pwdinfo->driver_interface = DRIVER_WEXT;
+#endif //CONFIG_IOCTL_CFG80211
+
+	}
+	
+exit:	
+	return ret;
+}
+
+#endif //CONFIG_P2P
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_pwrctrl.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_pwrctrl.c
new file mode 100644
index 000000000..9b1536574
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_pwrctrl.c
@@ -0,0 +1,2698 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_PWRCTRL_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+#include <hal_com_h2c.h>
+
+int rtw_fw_ps_state(PADAPTER padapter)
+{
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	int ret=_FAIL, dont_care=0;
+	u16 fw_ps_state=0;
+	u32 start_time;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct registry_priv  *registry_par = &padapter->registrypriv;
+	
+	if(registry_par->check_fw_ps != 1)
+		return _SUCCESS;
+	
+	_enter_pwrlock(&pwrpriv->check_32k_lock);
+	
+	if (RTW_CANNOT_RUN(padapter)) {
+		DBG_871X("%s: bSurpriseRemoved=%s , hw_init_completed=%d, bDriverStopped=%s\n", __func__
+			, rtw_is_surprise_removed(padapter)?"True":"False"
+			, rtw_get_hw_init_completed(padapter)
+			, rtw_is_drv_stopped(padapter)?"True":"False");
+		goto exit_fw_ps_state;
+	}
+	rtw_hal_set_hwreg(padapter, HW_VAR_SET_REQ_FW_PS, (u8 *)&dont_care);
+	{
+		//4. if 0x88[7]=1, driver set cmd to leave LPS/IPS. 
+		//Else, hw will keep in active mode.
+		//debug info:
+		//0x88[7] = 32kpermission, 
+		//0x88[6:0] = current_ps_state
+		//0x89[7:0] = last_rpwm
+
+		rtw_hal_get_hwreg(padapter, HW_VAR_FW_PS_STATE, (u8 *)&fw_ps_state);
+		
+		if((fw_ps_state & 0x80) == 0)
+			ret=_SUCCESS;
+		else
+		{
+			pdbgpriv->dbg_poll_fail_cnt++;
+			DBG_871X("%s: fw_ps_state=%04x \n", __FUNCTION__, fw_ps_state);
+		}
+	}
+
+
+exit_fw_ps_state:
+	_exit_pwrlock(&pwrpriv->check_32k_lock);
+	return ret;
+}
+
+#ifdef CONFIG_IPS
+void _ips_enter(_adapter * padapter)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+
+	pwrpriv->bips_processing = _TRUE;	
+
+	// syn ips_mode with request
+	pwrpriv->ips_mode = pwrpriv->ips_mode_req;
+	
+	pwrpriv->ips_enter_cnts++;	
+	DBG_871X("==>ips_enter cnts:%d\n",pwrpriv->ips_enter_cnts);
+
+	if(rf_off == pwrpriv->change_rfpwrstate )
+	{	
+		pwrpriv->bpower_saving = _TRUE;
+		DBG_871X("nolinked power save enter\n");
+
+		if(pwrpriv->ips_mode == IPS_LEVEL_2)
+			pwrpriv->bkeepfwalive = _TRUE;
+		
+		rtw_ips_pwr_down(padapter);
+		pwrpriv->rf_pwrstate = rf_off;
+	}	
+	pwrpriv->bips_processing = _FALSE;	
+	
+}
+
+void ips_enter(_adapter * padapter)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+
+
+#ifdef CONFIG_BT_COEXIST
+	rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
+#endif // CONFIG_BT_COEXIST
+
+	_enter_pwrlock(&pwrpriv->lock);
+	_ips_enter(padapter);
+	_exit_pwrlock(&pwrpriv->lock);
+}
+
+int _ips_leave(_adapter * padapter)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	int result = _SUCCESS;
+
+	if((pwrpriv->rf_pwrstate == rf_off) &&(!pwrpriv->bips_processing))
+	{
+		pwrpriv->bips_processing = _TRUE;
+		pwrpriv->change_rfpwrstate = rf_on;
+		pwrpriv->ips_leave_cnts++;
+		DBG_871X("==>ips_leave cnts:%d\n",pwrpriv->ips_leave_cnts);
+
+		if ((result = rtw_ips_pwr_up(padapter)) == _SUCCESS) {
+			pwrpriv->rf_pwrstate = rf_on;
+		}
+		DBG_871X("nolinked power save leave\n");
+		
+		DBG_871X("==> ips_leave.....LED(0x%08x)...\n",rtw_read32(padapter,0x4c));
+		pwrpriv->bips_processing = _FALSE;
+
+		pwrpriv->bkeepfwalive = _FALSE;
+		pwrpriv->bpower_saving = _FALSE;
+	}
+
+	return result;
+}
+
+int ips_leave(_adapter * padapter)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	int ret;
+
+	if(!is_primary_adapter(padapter))
+		return _SUCCESS;
+
+	_enter_pwrlock(&pwrpriv->lock);
+	ret = _ips_leave(padapter);
+#ifdef DBG_CHECK_FW_PS_STATE
+	if(rtw_fw_ps_state(padapter) == _FAIL)
+	{
+		DBG_871X("ips leave doesn't leave 32k\n");
+		pdbgpriv->dbg_leave_ips_fail_cnt++;
+	}
+#endif //DBG_CHECK_FW_PS_STATE
+	_exit_pwrlock(&pwrpriv->lock);
+
+	if (_SUCCESS == ret)
+		ODM_DMReset(&GET_HAL_DATA(padapter)->odmpriv);
+
+#ifdef CONFIG_BT_COEXIST
+	if (_SUCCESS == ret)
+		rtw_btcoex_IpsNotify(padapter, IPS_NONE);
+#endif // CONFIG_BT_COEXIST
+
+	return ret;
+}
+#endif /* CONFIG_IPS */
+
+#ifdef CONFIG_AUTOSUSPEND
+extern void autosuspend_enter(_adapter* padapter);	
+extern int autoresume_enter(_adapter* padapter);
+#endif
+
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+int rtw_hw_suspend(_adapter *padapter );
+int rtw_hw_resume(_adapter *padapter);
+#endif
+
+bool rtw_pwr_unassociated_idle(_adapter *adapter)
+{
+	_adapter *buddy = adapter->pbuddy_adapter;
+	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
+	struct xmit_priv *pxmit_priv = &adapter->xmitpriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &(adapter->wdinfo);
+#ifdef CONFIG_IOCTL_CFG80211
+	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &adapter->cfg80211_wdinfo;
+#endif
+#endif
+
+	bool ret = _FALSE;
+
+	if (adapter_to_pwrctl(adapter)->bpower_saving ==_TRUE ) {
+		//DBG_871X("%s: already in LPS or IPS mode\n", __func__);
+		goto exit;
+	}
+
+	if (adapter_to_pwrctl(adapter)->ips_deny_time >= rtw_get_current_time()) {
+		//DBG_871X("%s ips_deny_time\n", __func__);
+		goto exit;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
+		|| check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
+		|| check_fwstate(pmlmepriv, WIFI_AP_STATE)
+		|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
+		#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_P2P_IPS)
+		|| pcfg80211_wdinfo->is_ro_ch
+		#elif defined(CONFIG_P2P)
+		|| !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
+		#endif
+		#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
+		|| rtw_get_passing_time_ms(pcfg80211_wdinfo->last_ro_ch_time) < 3000
+		#endif
+	) {
+		goto exit;
+	}
+
+	/* consider buddy, if exist */
+	if (buddy) {
+		struct mlme_priv *b_pmlmepriv = &(buddy->mlmepriv);
+		#ifdef CONFIG_P2P
+		struct wifidirect_info *b_pwdinfo = &(buddy->wdinfo);
+		#ifdef CONFIG_IOCTL_CFG80211
+		struct cfg80211_wifidirect_info *b_pcfg80211_wdinfo = &buddy->cfg80211_wdinfo;
+		#endif
+		#endif
+
+		if (check_fwstate(b_pmlmepriv, WIFI_ASOC_STATE|WIFI_SITE_MONITOR)
+			|| check_fwstate(b_pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
+			|| check_fwstate(b_pmlmepriv, WIFI_AP_STATE)
+			|| check_fwstate(b_pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
+			#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_P2P_IPS)
+			|| b_pcfg80211_wdinfo->is_ro_ch
+			#elif defined(CONFIG_P2P)
+			|| !rtw_p2p_chk_state(b_pwdinfo, P2P_STATE_NONE)
+			#endif
+			#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211)
+			|| rtw_get_passing_time_ms(b_pcfg80211_wdinfo->last_ro_ch_time) < 3000
+			#endif
+		) {
+			goto exit;
+		}
+	}
+
+#if (MP_DRIVER == 1)
+	if (adapter->registrypriv.mp_mode == 1)
+		goto exit;
+#endif
+
+#ifdef CONFIG_INTEL_PROXIM
+	if(adapter->proximity.proxim_on==_TRUE){
+		return;
+	}
+#endif
+
+	if (pxmit_priv->free_xmitbuf_cnt != NR_XMITBUFF ||
+		pxmit_priv->free_xmit_extbuf_cnt != NR_XMIT_EXTBUFF) {
+		DBG_871X_LEVEL(_drv_always_, "There are some pkts to transmit\n");
+		DBG_871X_LEVEL(_drv_always_, "free_xmitbuf_cnt: %d, free_xmit_extbuf_cnt: %d\n", 
+			pxmit_priv->free_xmitbuf_cnt, pxmit_priv->free_xmit_extbuf_cnt);	
+		goto exit;
+	}
+
+	ret = _TRUE;
+
+exit:
+	return ret;
+}
+
+
+/*
+ * ATTENTION:
+ *	rtw_ps_processor() doesn't handle LPS.
+ */
+void rtw_ps_processor(_adapter*padapter)
+{
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+#endif //CONFIG_P2P
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+	rt_rf_power_state rfpwrstate;
+#endif //SUPPORT_HW_RFOFF_DETECTED
+	u32 ps_deny = 0;
+
+	_enter_pwrlock(&adapter_to_pwrctl(padapter)->lock);
+	ps_deny = rtw_ps_deny_get(padapter);
+	_exit_pwrlock(&adapter_to_pwrctl(padapter)->lock);
+	if (ps_deny != 0)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": ps_deny=0x%08X, skip power save!\n",
+			FUNC_ADPT_ARG(padapter), ps_deny);
+		goto exit;
+	}
+
+	if(pwrpriv->bInSuspend == _TRUE){//system suspend or autosuspend
+		pdbgpriv->dbg_ps_insuspend_cnt++;
+		DBG_871X("%s, pwrpriv->bInSuspend == _TRUE ignore this process\n",__FUNCTION__);
+		return;
+	}	
+
+	pwrpriv->ps_processing = _TRUE;
+
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+	if(pwrpriv->bips_processing == _TRUE)
+		goto exit;
+	
+	//DBG_871X("==> fw report state(0x%x)\n",rtw_read8(padapter,0x1ca));	
+	if(pwrpriv->bHWPwrPindetect) 
+	{
+	#ifdef CONFIG_AUTOSUSPEND
+		if(padapter->registrypriv.usbss_enable)
+		{
+			if(pwrpriv->rf_pwrstate == rf_on)
+			{
+				if(padapter->net_closed == _TRUE)
+					pwrpriv->ps_flag = _TRUE;
+
+				rfpwrstate = RfOnOffDetect(padapter);
+				DBG_871X("@@@@- #1  %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off");
+				if(rfpwrstate!= pwrpriv->rf_pwrstate)
+				{
+					if(rfpwrstate == rf_off)
+					{
+						pwrpriv->change_rfpwrstate = rf_off;
+						
+						pwrpriv->bkeepfwalive = _TRUE;	
+						pwrpriv->brfoffbyhw = _TRUE;						
+						
+						autosuspend_enter(padapter);							
+					}
+				}
+			}			
+		}
+		else
+	#endif //CONFIG_AUTOSUSPEND
+		{
+			rfpwrstate = RfOnOffDetect(padapter);
+			DBG_871X("@@@@- #2  %s==> rfstate:%s \n",__FUNCTION__,(rfpwrstate==rf_on)?"rf_on":"rf_off");
+
+			if(rfpwrstate!= pwrpriv->rf_pwrstate)
+			{
+				if(rfpwrstate == rf_off)
+				{	
+					pwrpriv->change_rfpwrstate = rf_off;														
+					pwrpriv->brfoffbyhw = _TRUE;
+					rtw_hw_suspend(padapter );	
+				}
+				else
+				{
+					pwrpriv->change_rfpwrstate = rf_on;
+					rtw_hw_resume(padapter );			
+				}
+				DBG_871X("current rf_pwrstate(%s)\n",(pwrpriv->rf_pwrstate == rf_off)?"rf_off":"rf_on");
+			}
+		}
+		pwrpriv->pwr_state_check_cnts ++;	
+	}
+#endif //SUPPORT_HW_RFOFF_DETECTED
+
+	if (pwrpriv->ips_mode_req == IPS_NONE)
+		goto exit;
+
+	if (rtw_pwr_unassociated_idle(padapter) == _FALSE)
+		goto exit;
+
+	if((pwrpriv->rf_pwrstate == rf_on) && ((pwrpriv->pwr_state_check_cnts%4)==0))
+	{
+		DBG_871X("==>%s .fw_state(%x)\n",__FUNCTION__,get_fwstate(pmlmepriv));
+		#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+		#else
+		pwrpriv->change_rfpwrstate = rf_off;
+		#endif
+		#ifdef CONFIG_AUTOSUSPEND
+		if(padapter->registrypriv.usbss_enable)
+		{
+			if(pwrpriv->bHWPwrPindetect) 
+				pwrpriv->bkeepfwalive = _TRUE;
+			
+			if(padapter->net_closed == _TRUE)
+				pwrpriv->ps_flag = _TRUE;
+
+			#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+			if (_TRUE==pwrpriv->bInternalAutoSuspend) {
+				DBG_871X("<==%s .pwrpriv->bInternalAutoSuspend)(%x)\n",__FUNCTION__,pwrpriv->bInternalAutoSuspend);
+			} else {
+				pwrpriv->change_rfpwrstate = rf_off;
+				DBG_871X("<==%s .pwrpriv->bInternalAutoSuspend)(%x) call autosuspend_enter\n",__FUNCTION__,pwrpriv->bInternalAutoSuspend);
+				autosuspend_enter(padapter);
+			}		
+			#else
+			autosuspend_enter(padapter);
+			#endif	//if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+		}		
+		else if(pwrpriv->bHWPwrPindetect)
+		{
+		}
+		else
+		#endif //CONFIG_AUTOSUSPEND
+		{
+			#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+			pwrpriv->change_rfpwrstate = rf_off;
+			#endif	//defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+
+			#ifdef CONFIG_IPS
+			ips_enter(padapter);			
+			#endif
+		}
+	}
+exit:
+#ifndef CONFIG_IPS_CHECK_IN_WD
+	rtw_set_pwr_state_check_timer(pwrpriv);
+#endif
+	pwrpriv->ps_processing = _FALSE;
+	return;
+}
+
+static void pwr_state_check_handler(struct timer_list *t)
+{
+	struct pwrctrl_priv *pwrctrlpriv =
+		from_timer(pwrctrlpriv, t, pwr_state_check_timer);
+	_adapter *padapter = pwrctrlpriv->adapter;
+
+	rtw_ps_cmd(padapter);
+}
+
+#ifdef CONFIG_LPS
+void	traffic_check_for_leave_lps(PADAPTER padapter, u8 tx, u32 tx_packets)
+{
+#ifdef CONFIG_CHECK_LEAVE_LPS
+	static u32 start_time = 0;
+	static u32 xmit_cnt = 0;
+	u8	bLeaveLPS = _FALSE;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+
+	
+
+	if(tx) //from tx
+	{
+		xmit_cnt += tx_packets;
+
+		if (start_time== 0)
+			start_time= rtw_get_current_time();
+
+		if (rtw_get_passing_time_ms(start_time) > 2000) // 2 sec == watch dog timer
+		{		
+			if(xmit_cnt > 8)
+			{
+				if ((adapter_to_pwrctl(padapter)->bLeisurePs) 
+					&& (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
+#ifdef CONFIG_BT_COEXIST
+					&& (rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
+#endif
+					)
+				{
+					//DBG_871X("leave lps via Tx = %d\n", xmit_cnt);			
+					bLeaveLPS = _TRUE;
+				}
+			}
+
+			start_time= rtw_get_current_time();
+			xmit_cnt = 0;
+		}
+
+	}
+	else // from rx path
+	{
+		if(pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod > 4/*2*/)
+		{
+			if ((adapter_to_pwrctl(padapter)->bLeisurePs)
+				&& (adapter_to_pwrctl(padapter)->pwr_mode != PS_MODE_ACTIVE)
+#ifdef CONFIG_BT_COEXIST		
+				&& (rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
+#endif
+				)
+			{	
+				//DBG_871X("leave lps via Rx = %d\n", pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);	
+				bLeaveLPS = _TRUE;
+			}
+		}	
+	}	
+
+	if(bLeaveLPS)
+	{
+		//DBG_871X("leave lps via %s, Tx = %d, Rx = %d \n", tx?"Tx":"Rx", pmlmepriv->LinkDetectInfo.NumTxOkInPeriod,pmlmepriv->LinkDetectInfo.NumRxUnicastOkInPeriod);	
+		//rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);
+		rtw_lps_ctrl_wk_cmd(padapter, tx?LPS_CTRL_TX_TRAFFIC_LEAVE:LPS_CTRL_RX_TRAFFIC_LEAVE, tx?0:1);
+	}
+#endif //CONFIG_CHECK_LEAVE_LPS
+}		
+
+/*
+ * Description:
+ *	This function MUST be called under power lock protect
+ *
+ * Parameters
+ *	padapter
+ *	pslv			power state level, only could be PS_STATE_S0 ~ PS_STATE_S4
+ *
+ */
+void rtw_set_rpwm(PADAPTER padapter, u8 pslv)
+{
+	u8	rpwm;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+#ifdef CONFIG_DETECT_CPWM_BY_POLLING
+	u8 cpwm_orig;
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+_func_enter_;
+
+	pslv = PS_STATE(pslv);
+
+#ifdef CONFIG_LPS_RPWM_TIMER
+	if (pwrpriv->brpwmtimeout == _TRUE)
+	{
+		DBG_871X("%s: RPWM timeout, force to set RPWM(0x%02X) again!\n", __FUNCTION__, pslv);
+	}
+	else
+#endif // CONFIG_LPS_RPWM_TIMER
+	{
+		if ( (pwrpriv->rpwm == pslv)
+#ifdef CONFIG_LPS_LCLK
+			|| ((pwrpriv->rpwm >= PS_STATE_S2)&&(pslv >= PS_STATE_S2))
+#endif
+			)
+		{
+			RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,
+				("%s: Already set rpwm[0x%02X], new=0x%02X!\n", __FUNCTION__, pwrpriv->rpwm, pslv));
+			return;
+		}
+	}
+
+	if (rtw_is_surprise_removed(padapter) ||
+		(!rtw_is_hw_init_completed(padapter)))
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+				("%s: SurpriseRemoved(%s) hw_init_completed(%s)\n"
+				, __func__
+				, rtw_is_surprise_removed(padapter)?"True":"False"
+				, rtw_is_hw_init_completed(padapter)?"True":"False"));
+
+		pwrpriv->cpwm = PS_STATE_S4;
+
+		return;
+	}
+
+	if (rtw_is_drv_stopped(padapter)) {
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+				 ("%s: change power state(0x%02X) when DriverStopped\n", __FUNCTION__, pslv));
+
+		if (pslv < PS_STATE_S2) {
+			RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+					 ("%s: Reject to enter PS_STATE(0x%02X) lower than S2 when DriverStopped!!\n", __FUNCTION__, pslv));
+			return;
+		}
+	}
+
+	rpwm = pslv | pwrpriv->tog;
+#ifdef CONFIG_LPS_LCLK
+	// only when from PS_STATE S0/S1 to S2 and higher needs ACK
+	if ((pwrpriv->cpwm < PS_STATE_S2) && (pslv >= PS_STATE_S2))
+		rpwm |= PS_ACK;
+#endif
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("rtw_set_rpwm: rpwm=0x%02x cpwm=0x%02x\n", rpwm, pwrpriv->cpwm));
+
+	pwrpriv->rpwm = pslv;
+
+#ifdef CONFIG_DETECT_CPWM_BY_POLLING
+	cpwm_orig = 0;
+	if (rpwm & PS_ACK)
+	{
+		rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
+	}
+#endif
+
+#if defined(CONFIG_LPS_RPWM_TIMER) && !defined(CONFIG_DETECT_CPWM_BY_POLLING)
+	if (rpwm & PS_ACK)
+		_set_timer(&pwrpriv->pwr_rpwm_timer, LPS_RPWM_WAIT_MS);
+#endif // CONFIG_LPS_RPWM_TIMER & !CONFIG_DETECT_CPWM_BY_POLLING
+	rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&rpwm));
+
+	pwrpriv->tog += 0x80;
+
+#ifdef CONFIG_LPS_LCLK
+	// No LPS 32K, No Ack
+	if (rpwm & PS_ACK)
+	{
+#ifdef CONFIG_DETECT_CPWM_BY_POLLING
+		u32 start_time;
+		u8 cpwm_now;
+		u8 poll_cnt=0;
+
+		start_time = rtw_get_current_time();
+
+		// polling cpwm
+		do {
+			rtw_msleep_os(1);
+			poll_cnt++;
+			cpwm_now = 0;
+			rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
+			if ((cpwm_orig ^ cpwm_now) & 0x80)
+			{
+				pwrpriv->cpwm = PS_STATE_S4;
+				pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
+#ifdef DBG_CHECK_FW_PS_STATE
+				DBG_871X("%s: polling cpwm OK! poll_cnt=%d, cpwm_orig=%02x, cpwm_now=%02x , 0x100=0x%x\n"
+				, __FUNCTION__,poll_cnt, cpwm_orig, cpwm_now, rtw_read8(padapter, REG_CR));
+				if(rtw_fw_ps_state(padapter) == _FAIL)
+				{
+					DBG_871X("leave 32k but fw state in 32k\n");
+					pdbgpriv->dbg_rpwm_toogle_cnt++;
+				}
+#endif //DBG_CHECK_FW_PS_STATE
+				break;
+			}
+
+			if (rtw_get_passing_time_ms(start_time) > LPS_RPWM_WAIT_MS)
+			{
+				DBG_871X("%s: polling cpwm timeout! poll_cnt=%d, cpwm_orig=%02x, cpwm_now=%02x \n", __FUNCTION__,poll_cnt, cpwm_orig, cpwm_now);
+#ifdef DBG_CHECK_FW_PS_STATE
+				if(rtw_fw_ps_state(padapter) == _FAIL)
+				{
+					DBG_871X("rpwm timeout and fw ps state in 32k\n");
+					pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
+				}
+#endif //DBG_CHECK_FW_PS_STATE
+#ifdef CONFIG_LPS_RPWM_TIMER
+				_set_timer(&pwrpriv->pwr_rpwm_timer, 1);
+#endif // CONFIG_LPS_RPWM_TIMER
+				break;
+			}
+		} while (1);
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+	}
+	else
+#endif // CONFIG_LPS_LCLK
+	{
+		pwrpriv->cpwm = pslv;
+	}
+
+_func_exit_;
+}
+
+u8 PS_RDY_CHECK(_adapter * padapter)
+{
+	u32 curr_time, delta_time;
+	struct pwrctrl_priv	*pwrpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+#ifdef CONFIG_P2P
+	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
+#ifdef CONFIG_IOCTL_CFG80211
+	struct cfg80211_wifidirect_info *pcfg80211_wdinfo = &padapter->cfg80211_wdinfo;
+#endif /* CONFIG_IOCTL_CFG80211 */
+#endif /* CONFIG_P2P */
+
+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
+	if(_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_mode)
+		return _TRUE;
+	else if(_TRUE == pwrpriv->bInSuspend && pwrpriv->wowlan_ap_mode)
+		return _TRUE;
+	else if (_TRUE == pwrpriv->bInSuspend)
+		return _FALSE;
+#else
+	if(_TRUE == pwrpriv->bInSuspend )
+		return _FALSE;
+#endif
+
+	curr_time = rtw_get_current_time();	
+
+	delta_time = curr_time -pwrpriv->DelayLPSLastTimeStamp;
+
+	if(delta_time < LPS_DELAY_TIME)
+	{		
+		return _FALSE;
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_SITE_MONITOR)
+		|| check_fwstate(pmlmepriv, WIFI_UNDER_LINKING|WIFI_UNDER_WPS)
+		|| check_fwstate(pmlmepriv, WIFI_AP_STATE)
+		|| check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE|WIFI_ADHOC_STATE)
+		#if defined(CONFIG_P2P) && defined(CONFIG_IOCTL_CFG80211) && defined(CONFIG_P2P_IPS)
+		|| pcfg80211_wdinfo->is_ro_ch
+		#elif defined(CONFIG_P2P)
+		|| !rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)
+		#endif
+		|| rtw_is_scan_deny(padapter)
+#ifdef CONFIG_TDLS
+		// TDLS link is established.
+		|| ( padapter->tdlsinfo.link_established == _TRUE )
+#endif // CONFIG_TDLS		
+	)
+		return _FALSE;
+
+	if( (padapter->securitypriv.dot11AuthAlgrthm == dot11AuthAlgrthm_8021X) && (padapter->securitypriv.binstallGrpkey == _FALSE) )
+	{
+		DBG_871X("Group handshake still in progress !!!\n");
+		return _FALSE;
+	}
+
+#ifdef CONFIG_IOCTL_CFG80211
+	if (!rtw_cfg80211_pwr_mgmt(padapter))
+		return _FALSE;
+#endif	
+
+	return _TRUE;
+}
+
+#if defined(CONFIG_FWLPS_IN_IPS)
+void rtw_set_fw_in_ips_mode(PADAPTER padapter, u8 enable)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	int cnt=0;
+	u32 start_time;
+	u8 val8 = 0;
+	u8 cpwm_orig = 0, cpwm_now = 0;
+	u8 parm[H2C_INACTIVE_PS_LEN]={0};
+
+	if (padapter->netif_up == _FALSE) {
+		DBG_871X("%s: ERROR, netif is down\n", __func__);
+		return;
+	}
+
+	//u8 cmd_param; //BIT0:enable, BIT1:NoConnect32k
+	if (enable) {
+#ifdef CONFIG_BT_COEXIST
+		rtw_btcoex_IpsNotify(padapter, pwrpriv->ips_mode_req);
+#endif
+		//Enter IPS
+		DBG_871X("%s: issue H2C to FW when entering IPS\n", __func__);
+
+#ifdef CONFIG_PNO_SUPPORT
+		parm[0] = 0x03;
+		parm[1] = pwrpriv->pnlo_info->fast_scan_iterations;
+		parm[2] = pwrpriv->pnlo_info->slow_scan_period;
+#else
+		parm[0] = 0x03;
+		parm[1] = 0x0;
+		parm[2] = 0x0;
+#endif//CONFIG_PNO_SUPPORT
+
+		rtw_hal_fill_h2c_cmd(padapter, //H2C_FWLPS_IN_IPS_,
+					H2C_INACTIVE_PS_,
+					H2C_INACTIVE_PS_LEN, parm);
+		//poll 0x1cc to make sure H2C command already finished by FW; MAC_0x1cc=0 means H2C done by FW.
+		do{
+			val8 = rtw_read8(padapter, REG_HMETFR);
+			cnt++;
+			DBG_871X("%s  polling REG_HMETFR=0x%x, cnt=%d \n",
+					__func__, val8, cnt);
+			rtw_mdelay_os(10);
+		}while(cnt<100 && (val8!=0));
+
+		//H2C done, enter 32k
+		if (val8 == 0) {
+			//ser rpwm to enter 32k
+			val8 = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1);
+			DBG_871X("%s: read rpwm=%02x\n", __FUNCTION__, val8);
+			val8 += 0x80;
+			val8 |= BIT(0);
+			rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1, val8);
+			DBG_871X("%s: write rpwm=%02x\n", __FUNCTION__, val8);
+			adapter_to_pwrctl(padapter)->tog = (val8 + 0x80) & 0x80;
+			cnt = val8 = 0;
+			if (parm[1] == 0 || parm[2] == 0) {
+				do {
+					val8 = rtw_read8(padapter, REG_CR);
+					cnt++;
+					DBG_871X("%s  polling 0x100=0x%x, cnt=%d \n",
+							__func__, val8, cnt);
+					DBG_871X("%s 0x08:%02x, 0x03:%02x\n",
+							__func__,
+							rtw_read8(padapter, 0x08),
+							rtw_read8(padapter, 0x03));
+					rtw_mdelay_os(10);
+				} while(cnt<20 && (val8!=0xEA));
+			}
+		}
+	} else {
+		//Leave IPS
+		DBG_871X("%s: Leaving IPS in FWLPS state\n", __func__);
+
+		//for polling cpwm
+		cpwm_orig = 0;
+		rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_orig);
+
+		//ser rpwm
+		val8 = rtw_read8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1);
+		val8 &= 0x80;
+		val8 += 0x80;
+		val8 |= BIT(6);
+		rtw_write8(padapter, SDIO_LOCAL_BASE|SDIO_REG_HRPWM1, val8);
+		DBG_871X("%s: write rpwm=%02x\n", __FUNCTION__, val8);
+		adapter_to_pwrctl(padapter)->tog = (val8 + 0x80) & 0x80;
+
+		//do polling cpwm
+		start_time = rtw_get_current_time();
+		do {
+
+			rtw_mdelay_os(1);
+
+			rtw_hal_get_hwreg(padapter, HW_VAR_CPWM, &cpwm_now);
+			if ((cpwm_orig ^ cpwm_now) & 0x80) {
+				break;
+			}
+
+			if (rtw_get_passing_time_ms(start_time) > 100)
+			{
+				DBG_871X("%s: polling cpwm timeout when leaving IPS in FWLPS state\n", __FUNCTION__);
+				break;
+			}
+		} while (1);
+
+		parm[0] = 0x0;
+		parm[1] = 0x0;
+		parm[2] = 0x0;
+		rtw_hal_fill_h2c_cmd(padapter, H2C_INACTIVE_PS_,
+					H2C_INACTIVE_PS_LEN, parm);
+#ifdef CONFIG_BT_COEXIST
+		rtw_btcoex_IpsNotify(padapter, IPS_NONE);
+#endif
+	}
+}
+#endif //CONFIG_PNO_SUPPORT
+
+void rtw_set_ps_mode(PADAPTER padapter, u8 ps_mode, u8 smart_ps, u8 bcn_ant_mode, const char *msg)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo = &( padapter->wdinfo );
+#endif //CONFIG_P2P
+#ifdef CONFIG_TDLS
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	_irqL irqL;
+	int i, j;
+	_list	*plist, *phead;
+	struct sta_info *ptdls_sta;
+#endif //CONFIG_TDLS
+
+_func_enter_;
+
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("%s: PowerMode=%d Smart_PS=%d\n",
+			  __FUNCTION__, ps_mode, smart_ps));
+
+	if(ps_mode > PM_Card_Disable) {
+		RT_TRACE(_module_rtl871x_pwrctrl_c_,_drv_err_,("ps_mode:%d error\n", ps_mode));
+		return;
+	}
+
+	if (pwrpriv->pwr_mode == ps_mode)
+	{
+		if (PS_MODE_ACTIVE == ps_mode) return;
+
+#ifndef CONFIG_BT_COEXIST
+		if ((pwrpriv->smart_ps == smart_ps) &&
+			(pwrpriv->bcn_ant_mode == bcn_ant_mode))
+		{
+			return;
+		}
+#endif // !CONFIG_BT_COEXIST
+	}
+
+#ifdef CONFIG_LPS_LCLK
+	_enter_pwrlock(&pwrpriv->lock);
+#endif
+
+	//if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
+	if(ps_mode == PS_MODE_ACTIVE)
+	{
+		if (1
+#ifdef CONFIG_BT_COEXIST
+			&& (((rtw_btcoex_IsBtControlLps(padapter) == _FALSE)
+#ifdef CONFIG_P2P_PS
+					&& (pwdinfo->opp_ps == 0)
+#endif // CONFIG_P2P_PS
+					)
+				|| ((rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
+					&& (rtw_btcoex_IsLpsOn(padapter) == _FALSE))
+				)
+#else // !CONFIG_BT_COEXIST
+#ifdef CONFIG_P2P_PS
+			&& (pwdinfo->opp_ps == 0)
+#endif // CONFIG_P2P_PS
+#endif // !CONFIG_BT_COEXIST
+			)
+		{
+			DBG_871X(FUNC_ADPT_FMT" Leave 802.11 power save - %s\n",
+				FUNC_ADPT_ARG(padapter), msg);
+
+			if (pwrpriv->lps_leave_cnts < UINT_MAX)
+				pwrpriv->lps_leave_cnts++;
+			else
+				pwrpriv->lps_leave_cnts = 0;
+#ifdef CONFIG_TDLS
+			for(i=0; i< NUM_STA; i++)
+			{
+				phead = &(pstapriv->sta_hash[i]);
+				plist = get_next(phead);
+
+				while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+				{
+					ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+
+					if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE )
+						issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);
+					plist = get_next(plist);
+				}
+			}
+#endif //CONFIG_TDLS
+
+			pwrpriv->pwr_mode = ps_mode;
+			rtw_set_rpwm(padapter, PS_STATE_S4);
+			
+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN) || defined(CONFIG_P2P_WOWLAN)
+			if (pwrpriv->wowlan_mode == _TRUE ||
+					pwrpriv->wowlan_ap_mode == _TRUE ||
+					pwrpriv->wowlan_p2p_mode == _TRUE)
+			{
+				u32 start_time, delay_ms;
+				u8 val8;
+				delay_ms = 20;
+				start_time = rtw_get_current_time();
+				do { 
+					rtw_hal_get_hwreg(padapter, HW_VAR_SYS_CLKR, &val8);
+					if (!(val8 & BIT(4))){ //0x08 bit4 =1 --> in 32k, bit4 = 0 --> leave 32k
+						pwrpriv->cpwm = PS_STATE_S4;
+						break;
+					}
+					if (rtw_get_passing_time_ms(start_time) > delay_ms)
+					{
+						DBG_871X("%s: Wait for FW 32K leave more than %u ms!!!\n", 
+								__FUNCTION__, delay_ms);
+						pdbgpriv->dbg_wow_leave_ps_fail_cnt++;
+						break;
+					}
+					rtw_usleep_os(100);
+				} while (1); 
+			}
+#endif
+			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
+			pwrpriv->bFwCurrentInPSMode = _FALSE;
+
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_LpsNotify(padapter, ps_mode);
+#endif // CONFIG_BT_COEXIST
+		}
+	}
+	else
+	{
+		if ((PS_RDY_CHECK(padapter) && check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE))
+#ifdef CONFIG_BT_COEXIST
+			|| ((rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
+				&& (rtw_btcoex_IsLpsOn(padapter) == _TRUE))
+#endif
+#ifdef CONFIG_P2P_WOWLAN
+			||( _TRUE == pwrpriv->wowlan_p2p_mode)
+#endif //CONFIG_P2P_WOWLAN
+			)
+		{
+			u8 pslv;
+
+			DBG_871X(FUNC_ADPT_FMT" Enter 802.11 power save - %s\n",
+				FUNC_ADPT_ARG(padapter), msg);
+
+			if (pwrpriv->lps_enter_cnts < UINT_MAX)
+				pwrpriv->lps_enter_cnts++;
+			else
+				pwrpriv->lps_enter_cnts = 0;
+#ifdef CONFIG_TDLS
+			for(i=0; i< NUM_STA; i++)
+			{
+				phead = &(pstapriv->sta_hash[i]);
+				plist = get_next(phead);
+
+				while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+				{
+					ptdls_sta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+
+					if( ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE )
+						issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 1, 0, 0);
+					plist = get_next(plist);
+				}
+			}
+#endif //CONFIG_TDLS
+
+#ifdef CONFIG_BT_COEXIST
+			rtw_btcoex_LpsNotify(padapter, ps_mode);
+#endif // CONFIG_BT_COEXIST
+
+			pwrpriv->bFwCurrentInPSMode = _TRUE;
+			pwrpriv->pwr_mode = ps_mode;
+			pwrpriv->smart_ps = smart_ps;
+			pwrpriv->bcn_ant_mode = bcn_ant_mode;
+			rtw_hal_set_hwreg(padapter, HW_VAR_H2C_FW_PWRMODE, (u8 *)(&ps_mode));
+
+#ifdef CONFIG_P2P_PS
+			// Set CTWindow after LPS
+			if(pwdinfo->opp_ps == 1)
+				p2p_ps_wk_cmd(padapter, P2P_PS_ENABLE, 0);
+#endif //CONFIG_P2P_PS
+
+			pslv = PS_STATE_S2;
+#ifdef CONFIG_LPS_LCLK
+			if (pwrpriv->alives == 0)
+				pslv = PS_STATE_S0;
+#endif // CONFIG_LPS_LCLK
+
+#ifdef CONFIG_BT_COEXIST
+			if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
+				&& (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
+			{
+				u8 val8;
+
+				val8 = rtw_btcoex_LpsVal(padapter);
+				if (val8 & BIT(4))
+					pslv = PS_STATE_S2;
+
+			}
+#endif // CONFIG_BT_COEXIST
+
+			rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+#ifdef CONFIG_LPS_LCLK
+	_exit_pwrlock(&pwrpriv->lock);
+#endif
+
+_func_exit_;
+}
+
+/*
+ * Return:
+ *	0:	Leave OK
+ *	-1:	Timeout
+ *	-2:	Other error
+ */
+s32 LPS_RF_ON_check(PADAPTER padapter, u32 delay_ms)
+{
+	u32 start_time;
+	u8 bAwake = _FALSE;
+	s32 err = 0;
+
+
+	start_time = rtw_get_current_time();
+	while (1)
+	{
+		rtw_hal_get_hwreg(padapter, HW_VAR_FWLPS_RF_ON, &bAwake);
+		if (_TRUE == bAwake)
+			break;
+
+		if (rtw_is_surprise_removed(padapter)) {
+			err = -2;
+			DBG_871X("%s: device surprise removed!!\n", __FUNCTION__);
+			break;
+		}
+
+		if (rtw_get_passing_time_ms(start_time) > delay_ms)
+		{
+			err = -1;
+			DBG_871X("%s: Wait for FW LPS leave more than %u ms!!!\n", __FUNCTION__, delay_ms);
+			break;
+		}
+		rtw_usleep_os(100);
+	}
+
+	return err;
+}
+
+//
+//	Description:
+//		Enter the leisure power save mode.
+//
+void LPS_Enter(PADAPTER padapter, const char *msg)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv	*pwrpriv = dvobj_to_pwrctl(dvobj);
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	_adapter *buddy = padapter->pbuddy_adapter;
+	int n_assoc_iface = 0;
+	int i;
+	char buf[32] = {0};
+
+_func_enter_;
+
+//	DBG_871X("+LeisurePSEnter\n");
+
+#ifdef CONFIG_BT_COEXIST
+	if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
+		return;
+#endif
+
+	/* Skip lps enter request if number of assocated adapters is not 1 */
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
+			n_assoc_iface++;
+	}
+	if (n_assoc_iface != 1)
+		return;
+
+	/* Skip lps enter request for adapter not port0 */
+	if (get_iface_type(padapter) != IFACE_PORT0)
+		return;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		if (PS_RDY_CHECK(dvobj->padapters[i]) == _FALSE)
+			return;
+	}
+
+#ifdef CONFIG_P2P_PS
+	if(padapter->wdinfo.p2p_ps_mode == P2P_PS_NOA)
+	{
+		return;//supporting p2p client ps NOA via H2C_8723B_P2P_PS_OFFLOAD 
+	}
+#endif //CONFIG_P2P_PS
+
+	if (pwrpriv->bLeisurePs)
+	{
+		// Idle for a while if we connect to AP a while ago.
+		if (pwrpriv->LpsIdleCount >= 2) //  4 Sec
+		{
+			if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
+			{
+				sprintf(buf, "WIFI-%s", msg);
+				pwrpriv->bpower_saving = _TRUE;
+				rtw_set_ps_mode(padapter, pwrpriv->power_mgnt, padapter->registrypriv.smart_ps, 0, buf);
+			}
+		}
+		else
+			pwrpriv->LpsIdleCount++;
+	}
+
+//	DBG_871X("-LeisurePSEnter\n");
+
+_func_exit_;
+}
+
+//
+//	Description:
+//		Leave the leisure power save mode.
+//
+void LPS_Leave(PADAPTER padapter, const char *msg)
+{
+#define LPS_LEAVE_TIMEOUT_MS 100
+
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv	*pwrpriv = dvobj_to_pwrctl(dvobj);
+	u32 start_time;
+	u8 bAwake = _FALSE;
+	char buf[32] = {0};
+	struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
+
+_func_enter_;
+
+//	DBG_871X("+LeisurePSLeave\n");
+
+#ifdef CONFIG_BT_COEXIST
+	if (rtw_btcoex_IsBtControlLps(padapter) == _TRUE)
+		return;
+#endif
+
+	if (pwrpriv->bLeisurePs)
+	{
+		if(pwrpriv->pwr_mode != PS_MODE_ACTIVE)
+		{
+			sprintf(buf, "WIFI-%s", msg);
+			rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, buf);
+
+			if(pwrpriv->pwr_mode == PS_MODE_ACTIVE)
+				LPS_RF_ON_check(padapter, LPS_LEAVE_TIMEOUT_MS);
+		}
+	}
+
+	pwrpriv->bpower_saving = _FALSE;
+#ifdef DBG_CHECK_FW_PS_STATE
+	if(rtw_fw_ps_state(padapter) == _FAIL)
+	{
+		DBG_871X("leave lps, fw in 32k\n");
+		pdbgpriv->dbg_leave_lps_fail_cnt++;
+	}
+#endif //DBG_CHECK_FW_PS_STATE
+//	DBG_871X("-LeisurePSLeave\n");
+
+_func_exit_;
+}
+#endif
+
+void LeaveAllPowerSaveModeDirect(PADAPTER Adapter)
+{
+	PADAPTER pri_padapter = GET_PRIMARY_ADAPTER(Adapter);
+	struct mlme_priv	*pmlmepriv = &(Adapter->mlmepriv);
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(Adapter);
+	struct dvobj_priv *psdpriv = Adapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+#ifndef CONFIG_DETECT_CPWM_BY_POLLING
+	u8 cpwm_orig, cpwm_now;
+	u32 start_time;
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+
+_func_enter_;
+
+	DBG_871X("%s.....\n",__FUNCTION__);
+
+	if (rtw_is_surprise_removed(Adapter)) {
+		DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=_TRUE Skip!\n", FUNC_ADPT_ARG(Adapter));
+		return;
+	}
+
+	if ((check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+#ifdef CONFIG_CONCURRENT_MODE
+		|| (check_buddy_fwstate(Adapter,_FW_LINKED) == _TRUE)
+#endif
+		)
+	{ //connect
+
+		if(pwrpriv->pwr_mode == PS_MODE_ACTIVE) {
+			DBG_871X("%s: Driver Already Leave LPS\n",__FUNCTION__);
+			return;
+		}
+
+#ifdef CONFIG_LPS_LCLK
+		_enter_pwrlock(&pwrpriv->lock);
+
+#ifndef CONFIG_DETECT_CPWM_BY_POLLING
+		cpwm_orig = 0;
+		rtw_hal_get_hwreg(Adapter, HW_VAR_CPWM, &cpwm_orig);
+#endif //CONFIG_DETECT_CPWM_BY_POLLING
+		rtw_set_rpwm(Adapter, PS_STATE_S4);
+
+#ifndef CONFIG_DETECT_CPWM_BY_POLLING
+
+		start_time = rtw_get_current_time();
+
+		// polling cpwm
+		do {
+			rtw_mdelay_os(1);
+
+			rtw_hal_get_hwreg(Adapter, HW_VAR_CPWM, &cpwm_now);
+			if ((cpwm_orig ^ cpwm_now) & 0x80)
+			{
+				pwrpriv->cpwm = PS_STATE_S4;
+				pwrpriv->cpwm_tog = cpwm_now & PS_TOGGLE;
+#ifdef DBG_CHECK_FW_PS_STATE
+				DBG_871X("%s: polling cpwm OK! cpwm_orig=%02x, cpwm_now=%02x, 0x100=0x%x \n"
+				, __FUNCTION__, cpwm_orig, cpwm_now, rtw_read8(Adapter, REG_CR));
+				if(rtw_fw_ps_state(Adapter) == _FAIL)
+				{
+					DBG_871X("%s: leave 32k but fw state in 32k\n", __FUNCTION__);
+					pdbgpriv->dbg_rpwm_toogle_cnt++;
+				}
+#endif //DBG_CHECK_FW_PS_STATE
+				break;
+			}
+
+			if (rtw_get_passing_time_ms(start_time) > LPS_RPWM_WAIT_MS)
+			{
+				DBG_871X("%s: polling cpwm timeout! cpwm_orig=%02x, cpwm_now=%02x \n", __FUNCTION__, cpwm_orig, cpwm_now);
+#ifdef DBG_CHECK_FW_PS_STATE
+				if(rtw_fw_ps_state(Adapter) == _FAIL)
+				{
+					DBG_871X("rpwm timeout and fw ps state in 32k\n");
+					pdbgpriv->dbg_rpwm_timeout_fail_cnt++;
+				}
+#endif //DBG_CHECK_FW_PS_STATE
+				break;
+			}
+		} while (1);
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+
+	_exit_pwrlock(&pwrpriv->lock);
+#endif
+
+#ifdef CONFIG_P2P_PS
+		p2p_ps_wk_cmd(pri_padapter, P2P_PS_DISABLE, 0);
+#endif //CONFIG_P2P_PS
+
+#ifdef CONFIG_LPS
+		rtw_lps_ctrl_wk_cmd(pri_padapter, LPS_CTRL_LEAVE, 0);
+#endif
+	}
+	else
+	{
+		if(pwrpriv->rf_pwrstate== rf_off)
+		{
+			#ifdef CONFIG_AUTOSUSPEND
+			if(Adapter->registrypriv.usbss_enable)
+			{
+				#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+				usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
+				#elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
+				adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user
+				#endif
+			}
+			else
+			#endif
+			{
+#if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) || defined(CONFIG_RTL8188E)
+				#ifdef CONFIG_IPS
+				if(_FALSE == ips_leave(pri_padapter))
+				{
+					DBG_871X("======> ips_leave fail.............\n");			
+				}
+				#endif
+#endif //CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD && CONFIG_RTL8188E)
+			}
+		}
+	}
+
+_func_exit_;
+}
+
+//
+// Description: Leave all power save mode: LPS, FwLPS, IPS if needed.
+// Move code to function by tynli. 2010.03.26. 
+//
+void LeaveAllPowerSaveMode(IN PADAPTER Adapter)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(Adapter);
+	struct mlme_priv	*pmlmepriv = &(Adapter->mlmepriv);
+	u8	enqueue = 0;
+	int n_assoc_iface = 0;
+	int i;
+
+_func_enter_;
+
+	//DBG_871X("%s.....\n",__FUNCTION__);
+
+	if (_FALSE == Adapter->bup)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": bup=%d Skip!\n",
+			FUNC_ADPT_ARG(Adapter), Adapter->bup);
+		return;
+	}
+
+	if (rtw_is_surprise_removed(Adapter)) {
+		DBG_871X(FUNC_ADPT_FMT ": bSurpriseRemoved=_TRUE Skip!\n", FUNC_ADPT_ARG(Adapter));
+		return;
+	}
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		if (check_fwstate(&(dvobj->padapters[i]->mlmepriv), WIFI_ASOC_STATE))
+			n_assoc_iface++;
+	}
+
+	if (n_assoc_iface)
+	{ //connect
+#ifdef CONFIG_LPS_LCLK
+		enqueue = 1;
+#endif
+
+#ifdef CONFIG_P2P_PS
+		p2p_ps_wk_cmd(Adapter, P2P_PS_DISABLE, enqueue);
+#endif //CONFIG_P2P_PS
+
+#ifdef CONFIG_LPS
+		rtw_lps_ctrl_wk_cmd(Adapter, LPS_CTRL_LEAVE, enqueue);
+#endif
+
+#ifdef CONFIG_LPS_LCLK
+		LPS_Leave_check(Adapter);
+#endif	
+	}
+	else
+	{
+		if(adapter_to_pwrctl(Adapter)->rf_pwrstate== rf_off)
+		{
+			#ifdef CONFIG_AUTOSUSPEND
+			if(Adapter->registrypriv.usbss_enable)
+			{
+				#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,35))
+				usb_disable_autosuspend(adapter_to_dvobj(Adapter)->pusbdev);
+				#elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,22) && LINUX_VERSION_CODE<=KERNEL_VERSION(2,6,34))
+				adapter_to_dvobj(Adapter)->pusbdev->autosuspend_disabled = Adapter->bDisableAutosuspend;//autosuspend disabled by the user
+				#endif
+			}
+			else
+			#endif
+			{
+#if defined(CONFIG_FWLPS_IN_IPS) || defined(CONFIG_SWLPS_IN_IPS) || (defined(CONFIG_PLATFORM_SPRD) && defined(CONFIG_RTL8188E))
+				#ifdef CONFIG_IPS
+				if(_FALSE == ips_leave(Adapter))
+				{
+					DBG_871X("======> ips_leave fail.............\n");			
+				}
+				#endif
+#endif //CONFIG_SWLPS_IN_IPS || (CONFIG_PLATFORM_SPRD && CONFIG_RTL8188E)
+			}				
+		}	
+	}
+
+_func_exit_;
+}
+
+#ifdef CONFIG_LPS_LCLK
+void LPS_Leave_check(
+	PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrpriv;
+	u32	start_time;
+	u8	bReady;
+
+_func_enter_;
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+
+	bReady = _FALSE;
+	start_time = rtw_get_current_time();
+
+	rtw_yield_os();
+	
+	while(1)
+	{
+		_enter_pwrlock(&pwrpriv->lock);
+
+		if (rtw_is_surprise_removed(padapter)
+			|| (!rtw_is_hw_init_completed(padapter))
+#ifdef CONFIG_USB_HCI
+			|| rtw_is_drv_stopped(padapter)
+#endif
+			|| (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
+			)
+		{
+			bReady = _TRUE;
+		}
+
+		_exit_pwrlock(&pwrpriv->lock);
+
+		if(_TRUE == bReady)
+			break;
+
+		if(rtw_get_passing_time_ms(start_time)>100)
+		{
+			DBG_871X("Wait for cpwm event  than 100 ms!!!\n");
+			break;
+		}
+		rtw_msleep_os(1);
+	}
+
+_func_exit_;
+}
+
+/*
+ * Caller:ISR handler...
+ *
+ * This will be called when CPWM interrupt is up.
+ *
+ * using to update cpwn of drv; and drv willl make a decision to up or down pwr level
+ */
+void cpwm_int_hdl(
+	PADAPTER padapter,
+	struct reportpwrstate_parm *preportpwrstate)
+{
+	struct pwrctrl_priv *pwrpriv;
+
+_func_enter_;
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+#if 0
+	if (pwrpriv->cpwm_tog == (preportpwrstate->state & PS_TOGGLE)) {
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_err_,
+				 ("cpwm_int_hdl: tog(old)=0x%02x cpwm(new)=0x%02x toggle bit didn't change!?\n",
+				  pwrpriv->cpwm_tog, preportpwrstate->state));
+		goto exit;
+	}
+#endif
+
+	_enter_pwrlock(&pwrpriv->lock);
+
+#ifdef CONFIG_LPS_RPWM_TIMER
+	if (pwrpriv->rpwm < PS_STATE_S2)
+	{
+		DBG_871X("%s: Redundant CPWM Int. RPWM=0x%02X CPWM=0x%02x\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
+		_exit_pwrlock(&pwrpriv->lock);
+		goto exit;
+	}
+#endif // CONFIG_LPS_RPWM_TIMER
+
+	pwrpriv->cpwm = PS_STATE(preportpwrstate->state);
+	pwrpriv->cpwm_tog = preportpwrstate->state & PS_TOGGLE;
+
+	if (pwrpriv->cpwm >= PS_STATE_S2)
+	{
+		if (pwrpriv->alives & CMD_ALIVE)
+			_rtw_up_sema(&padapter->cmdpriv.cmd_queue_sema);
+
+		if (pwrpriv->alives & XMIT_ALIVE)
+			_rtw_up_sema(&padapter->xmitpriv.xmit_sema);
+	}
+
+	_exit_pwrlock(&pwrpriv->lock);
+
+exit:
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("cpwm_int_hdl: cpwm=0x%02x\n", pwrpriv->cpwm));
+
+_func_exit_;
+}
+
+static void cpwm_event_callback(struct work_struct *work)
+{
+	struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, cpwm_event);
+	struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
+	_adapter *adapter = dvobj->padapters[IFACE_ID0];
+	struct reportpwrstate_parm report;
+
+	//DBG_871X("%s\n",__FUNCTION__);
+
+	report.state = PS_STATE_S2;
+	cpwm_int_hdl(adapter, &report);
+}
+
+#ifdef CONFIG_LPS_RPWM_TIMER
+static void rpwmtimeout_workitem_callback(struct work_struct *work)
+{
+	PADAPTER padapter;
+	struct dvobj_priv *dvobj;
+	struct pwrctrl_priv *pwrpriv;
+
+
+	pwrpriv = container_of(work, struct pwrctrl_priv, rpwmtimeoutwi);
+	dvobj = pwrctl_to_dvobj(pwrpriv);
+	padapter = dvobj->padapters[IFACE_ID0];
+//	DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
+
+	_enter_pwrlock(&pwrpriv->lock);
+	if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
+	{
+		DBG_871X("%s: rpwm=0x%02X cpwm=0x%02X CPWM done!\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
+		goto exit;
+	}
+	_exit_pwrlock(&pwrpriv->lock);
+
+	if (rtw_read8(padapter, 0x100) != 0xEA)
+	{
+#if 1
+		struct reportpwrstate_parm report;
+
+		report.state = PS_STATE_S2;
+		DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
+		cpwm_int_hdl(padapter, &report);
+#else
+		DBG_871X("\n%s: FW already leave 32K!\n\n", __func__);
+		cpwm_event_callback(&pwrpriv->cpwm_event);
+#endif
+		return;
+	}
+
+	_enter_pwrlock(&pwrpriv->lock);
+
+	if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
+	{
+		DBG_871X("%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
+		goto exit;
+	}
+	pwrpriv->brpwmtimeout = _TRUE;
+	rtw_set_rpwm(padapter, pwrpriv->rpwm);
+	pwrpriv->brpwmtimeout = _FALSE;
+
+exit:
+	_exit_pwrlock(&pwrpriv->lock);
+}
+
+/*
+ * This function is a timer handler, can't do any IO in it.
+ */
+static void pwr_rpwm_timeout_handler(struct timer_list *t)
+{
+	struct pwrctrl_priv *pwrpriv = from_timer(pwrpriv, t, pwr_rpwm_timer);
+
+	DBG_871X("+%s: rpwm=0x%02X cpwm=0x%02X\n", __func__, pwrpriv->rpwm, pwrpriv->cpwm);
+
+	if ((pwrpriv->rpwm == pwrpriv->cpwm) || (pwrpriv->cpwm >= PS_STATE_S2))
+	{
+		DBG_871X("+%s: cpwm=%d, nothing to do!\n", __func__, pwrpriv->cpwm);
+		return;
+	}
+
+	_set_workitem(&pwrpriv->rpwmtimeoutwi);
+}
+#endif // CONFIG_LPS_RPWM_TIMER
+
+__inline static void register_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
+{
+	pwrctrl->alives |= tag;
+}
+
+__inline static void unregister_task_alive(struct pwrctrl_priv *pwrctrl, u32 tag)
+{
+	pwrctrl->alives &= ~tag;
+}
+
+
+/*
+ * Description:
+ *	Check if the fw_pwrstate is okay for I/O.
+ *	If not (cpwm is less than S2), then the sub-routine
+ *	will raise the cpwm to be greater than or equal to S2.
+ *
+ *	Calling Context: Passive
+ *
+ *	Constraint:
+ *		1. this function will request pwrctrl->lock
+ * 
+ * Return Value:
+ *	_SUCCESS	hardware is ready for I/O
+ *	_FAIL		can't I/O right now
+ */
+s32 rtw_register_task_alive(PADAPTER padapter, u32 task)
+{
+	s32 res;
+	struct pwrctrl_priv *pwrctrl;
+	u8 pslv;
+
+_func_enter_;
+
+	res = _SUCCESS;
+	pwrctrl = adapter_to_pwrctl(padapter);
+	pslv = PS_STATE_S2;
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	register_task_alive(pwrctrl, task);
+
+	if (pwrctrl->bFwCurrentInPSMode == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+				 ("%s: task=0x%x cpwm=0x%02x alives=0x%08x\n",
+				  __FUNCTION__, task, pwrctrl->cpwm, pwrctrl->alives));
+
+		if (pwrctrl->cpwm < pslv)
+		{
+			if (pwrctrl->cpwm < PS_STATE_S2)
+				res = _FAIL;
+			if (pwrctrl->rpwm < pslv)
+				rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+#ifdef CONFIG_DETECT_CPWM_BY_POLLING
+	if (_FAIL == res)
+	{
+		if (pwrctrl->cpwm >= PS_STATE_S2)
+			res = _SUCCESS;
+	}
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+
+_func_exit_;
+
+	return res;	
+}
+
+/*
+ * Description:
+ *	If task is done, call this func. to power down firmware again.
+ *
+ *	Constraint:
+ *		1. this function will request pwrctrl->lock
+ *
+ * Return Value:
+ *	none
+ */
+void rtw_unregister_task_alive(PADAPTER padapter, u32 task)
+{
+	struct pwrctrl_priv *pwrctrl;
+	u8 pslv;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+	pslv = PS_STATE_S0;
+
+#ifdef CONFIG_BT_COEXIST
+	if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
+		&& (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
+	{
+		u8 val8;
+
+		val8 = rtw_btcoex_LpsVal(padapter);
+		if (val8 & BIT(4))
+			pslv = PS_STATE_S2;
+
+	}
+#endif // CONFIG_BT_COEXIST
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	unregister_task_alive(pwrctrl, task);
+
+	if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
+		&& (pwrctrl->bFwCurrentInPSMode == _TRUE))
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+				 ("%s: cpwm=0x%02x alives=0x%08x\n",
+				  __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
+
+		if (pwrctrl->cpwm > pslv)
+		{
+			if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
+				rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+}
+
+/*
+ * Caller: rtw_xmit_thread
+ * 
+ * Check if the fw_pwrstate is okay for xmit.
+ * If not (cpwm is less than S3), then the sub-routine
+ * will raise the cpwm to be greater than or equal to S3. 
+ *
+ * Calling Context: Passive
+ * 
+ * Return Value:
+ *	 _SUCCESS	rtw_xmit_thread can write fifo/txcmd afterwards.
+ *	 _FAIL		rtw_xmit_thread can not do anything.
+ */
+s32 rtw_register_tx_alive(PADAPTER padapter)
+{
+	s32 res;
+	struct pwrctrl_priv *pwrctrl;
+	u8 pslv;
+
+_func_enter_;
+
+	res = _SUCCESS;
+	pwrctrl = adapter_to_pwrctl(padapter);
+	pslv = PS_STATE_S2;
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	register_task_alive(pwrctrl, XMIT_ALIVE);
+
+	if (pwrctrl->bFwCurrentInPSMode == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+				 ("rtw_register_tx_alive: cpwm=0x%02x alives=0x%08x\n",
+				  pwrctrl->cpwm, pwrctrl->alives));
+
+		if (pwrctrl->cpwm < pslv)
+		{
+			if (pwrctrl->cpwm < PS_STATE_S2)
+				res = _FAIL;
+			if (pwrctrl->rpwm < pslv)
+				rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+#ifdef CONFIG_DETECT_CPWM_BY_POLLING
+	if (_FAIL == res)
+	{
+		if (pwrctrl->cpwm >= PS_STATE_S2)
+			res = _SUCCESS;
+	}
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+
+_func_exit_;
+
+	return res;	
+}
+
+/*
+ * Caller: rtw_cmd_thread
+ *
+ * Check if the fw_pwrstate is okay for issuing cmd.
+ * If not (cpwm should be is less than S2), then the sub-routine
+ * will raise the cpwm to be greater than or equal to S2.
+ *
+ * Calling Context: Passive
+ *
+ * Return Value:
+ *	_SUCCESS	rtw_cmd_thread can issue cmds to firmware afterwards.
+ *	_FAIL		rtw_cmd_thread can not do anything.
+ */
+s32 rtw_register_cmd_alive(PADAPTER padapter)
+{
+	s32 res;
+	struct pwrctrl_priv *pwrctrl;
+	u8 pslv;
+
+_func_enter_;
+
+	res = _SUCCESS;
+	pwrctrl = adapter_to_pwrctl(padapter);
+	pslv = PS_STATE_S2;
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	register_task_alive(pwrctrl, CMD_ALIVE);
+
+	if (pwrctrl->bFwCurrentInPSMode == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
+				 ("rtw_register_cmd_alive: cpwm=0x%02x alives=0x%08x\n",
+				  pwrctrl->cpwm, pwrctrl->alives));
+
+		if (pwrctrl->cpwm < pslv)
+		{
+			if (pwrctrl->cpwm < PS_STATE_S2)
+				res = _FAIL;
+			if (pwrctrl->rpwm < pslv)
+				rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+#ifdef CONFIG_DETECT_CPWM_BY_POLLING
+	if (_FAIL == res)
+	{
+		if (pwrctrl->cpwm >= PS_STATE_S2)
+			res = _SUCCESS;
+	}
+#endif // CONFIG_DETECT_CPWM_BY_POLLING
+
+_func_exit_;
+
+	return res;
+}
+
+/*
+ * Caller: rx_isr
+ *
+ * Calling Context: Dispatch/ISR
+ *
+ * Return Value:
+ *	_SUCCESS
+ *	_FAIL
+ */
+s32 rtw_register_rx_alive(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrl;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	register_task_alive(pwrctrl, RECV_ALIVE);
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("rtw_register_rx_alive: cpwm=0x%02x alives=0x%08x\n",
+			  pwrctrl->cpwm, pwrctrl->alives));
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+/*
+ * Caller: evt_isr or evt_thread
+ *
+ * Calling Context: Dispatch/ISR or Passive
+ *
+ * Return Value:
+ *	_SUCCESS
+ *	_FAIL
+ */
+s32 rtw_register_evt_alive(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrl;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	register_task_alive(pwrctrl, EVT_ALIVE);
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("rtw_register_evt_alive: cpwm=0x%02x alives=0x%08x\n",
+			  pwrctrl->cpwm, pwrctrl->alives));
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+/*
+ * Caller: ISR
+ *
+ * If ISR's txdone,
+ * No more pkts for TX,
+ * Then driver shall call this fun. to power down firmware again.
+ */
+void rtw_unregister_tx_alive(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrl;
+	u8 pslv;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+	pslv = PS_STATE_S0;
+
+#ifdef CONFIG_BT_COEXIST
+	if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
+		&& (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
+	{
+		u8 val8;
+
+		val8 = rtw_btcoex_LpsVal(padapter);
+		if (val8 & BIT(4))
+			pslv = PS_STATE_S2;
+
+	}
+#endif // CONFIG_BT_COEXIST
+
+#ifdef CONFIG_P2P_PS
+	if(padapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
+	{
+		pslv = PS_STATE_S2;
+	}
+#ifdef CONFIG_CONCURRENT_MODE
+	else if(rtw_buddy_adapter_up(padapter))
+	{
+		if(padapter->pbuddy_adapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
+			pslv = PS_STATE_S2;
+	}
+#endif
+#endif
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	unregister_task_alive(pwrctrl, XMIT_ALIVE);
+
+	if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
+		&& (pwrctrl->bFwCurrentInPSMode == _TRUE))
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+				 ("%s: cpwm=0x%02x alives=0x%08x\n",
+				  __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
+
+		if (pwrctrl->cpwm > pslv)
+		{
+			if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
+				rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+}
+
+/*
+ * Caller: ISR
+ *
+ * If all commands have been done,
+ * and no more command to do,
+ * then driver shall call this fun. to power down firmware again.
+ */
+void rtw_unregister_cmd_alive(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrl;
+	u8 pslv;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+	pslv = PS_STATE_S0;
+
+#ifdef CONFIG_BT_COEXIST
+	if ((rtw_btcoex_IsBtDisabled(padapter) == _FALSE)
+		&& (rtw_btcoex_IsBtControlLps(padapter) == _TRUE))
+	{
+		u8 val8;
+
+		val8 = rtw_btcoex_LpsVal(padapter);
+		if (val8 & BIT(4))
+			pslv = PS_STATE_S2;
+
+	}
+#endif // CONFIG_BT_COEXIST
+
+#ifdef CONFIG_P2P_PS
+	if(padapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
+	{
+		pslv = PS_STATE_S2;
+	}
+#ifdef CONFIG_CONCURRENT_MODE
+	else if(rtw_buddy_adapter_up(padapter))
+	{
+		if(padapter->pbuddy_adapter->wdinfo.p2p_ps_mode > P2P_PS_NONE)
+			pslv = PS_STATE_S2;
+	}
+#endif
+#endif
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	unregister_task_alive(pwrctrl, CMD_ALIVE);
+
+	if ((pwrctrl->pwr_mode != PS_MODE_ACTIVE)
+		&& (pwrctrl->bFwCurrentInPSMode == _TRUE))
+	{
+		RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_info_,
+				 ("%s: cpwm=0x%02x alives=0x%08x\n",
+				  __FUNCTION__, pwrctrl->cpwm, pwrctrl->alives));
+
+		if (pwrctrl->cpwm > pslv)
+		{
+			if ((pslv >= PS_STATE_S2) || (pwrctrl->alives == 0))
+				rtw_set_rpwm(padapter, pslv);
+		}
+	}
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+}
+
+/*
+ * Caller: ISR
+ */
+void rtw_unregister_rx_alive(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrl;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+
+	_enter_pwrlock(&pwrctrl->lock);
+
+	unregister_task_alive(pwrctrl, RECV_ALIVE);
+
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("rtw_unregister_rx_alive: cpwm=0x%02x alives=0x%08x\n",
+			  pwrctrl->cpwm, pwrctrl->alives));
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+}
+
+void rtw_unregister_evt_alive(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrl;
+
+_func_enter_;
+
+	pwrctrl = adapter_to_pwrctl(padapter);
+
+	unregister_task_alive(pwrctrl, EVT_ALIVE);
+
+	RT_TRACE(_module_rtl871x_pwrctrl_c_, _drv_notice_,
+			 ("rtw_unregister_evt_alive: cpwm=0x%02x alives=0x%08x\n",
+			  pwrctrl->cpwm, pwrctrl->alives));
+
+	_exit_pwrlock(&pwrctrl->lock);
+
+_func_exit_;
+}
+#endif	/* CONFIG_LPS_LCLK */
+
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+static void resume_workitem_callback(struct work_struct *work);
+#endif //CONFIG_RESUME_IN_WORKQUEUE
+
+void rtw_init_pwrctrl_priv(PADAPTER padapter)
+{
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+	int i = 0;
+	u8 val8 = 0;
+
+#if defined(CONFIG_CONCURRENT_MODE)
+	if (padapter->adapter_type != PRIMARY_ADAPTER)
+		return;
+#endif
+
+_func_enter_;
+
+#ifdef PLATFORM_WINDOWS
+	pwrctrlpriv->pnp_current_pwr_state=NdisDeviceStateD0;
+#endif
+
+	_init_pwrlock(&pwrctrlpriv->lock);
+	_init_pwrlock(&pwrctrlpriv->check_32k_lock);
+	pwrctrlpriv->rf_pwrstate = rf_on;
+	pwrctrlpriv->ips_enter_cnts=0;
+	pwrctrlpriv->ips_leave_cnts=0;
+	pwrctrlpriv->lps_enter_cnts=0;
+	pwrctrlpriv->lps_leave_cnts=0;
+	pwrctrlpriv->bips_processing = _FALSE;
+
+	pwrctrlpriv->ips_mode = padapter->registrypriv.ips_mode;
+	pwrctrlpriv->ips_mode_req = padapter->registrypriv.ips_mode;
+
+	pwrctrlpriv->pwr_state_check_interval = RTW_PWR_STATE_CHK_INTERVAL;
+	pwrctrlpriv->pwr_state_check_cnts = 0;
+	pwrctrlpriv->bInternalAutoSuspend = _FALSE;
+	pwrctrlpriv->bInSuspend = _FALSE;
+	pwrctrlpriv->bkeepfwalive = _FALSE;
+
+#ifdef CONFIG_AUTOSUSPEND
+#ifdef SUPPORT_HW_RFOFF_DETECTED
+	pwrctrlpriv->pwr_state_check_interval = (pwrctrlpriv->bHWPwrPindetect) ?1000:2000;		
+#endif
+#endif
+
+	pwrctrlpriv->LpsIdleCount = 0;
+	//pwrctrlpriv->FWCtrlPSMode =padapter->registrypriv.power_mgnt;// PS_MODE_MIN;
+	if (padapter->registrypriv.mp_mode == 1)
+		pwrctrlpriv->power_mgnt =PS_MODE_ACTIVE ;
+	else	
+		pwrctrlpriv->power_mgnt =padapter->registrypriv.power_mgnt;// PS_MODE_MIN;
+	pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
+
+	pwrctrlpriv->bFwCurrentInPSMode = _FALSE;
+
+	pwrctrlpriv->rpwm = 0;
+	pwrctrlpriv->cpwm = PS_STATE_S4;
+
+	pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
+	pwrctrlpriv->smart_ps = padapter->registrypriv.smart_ps;
+	pwrctrlpriv->bcn_ant_mode = 0;
+	pwrctrlpriv->dtim = 0;
+
+	pwrctrlpriv->tog = 0x80;
+
+#ifdef CONFIG_LPS_LCLK
+	rtw_hal_set_hwreg(padapter, HW_VAR_SET_RPWM, (u8 *)(&pwrctrlpriv->rpwm));
+
+	_init_workitem(&pwrctrlpriv->cpwm_event, cpwm_event_callback, NULL);
+
+#ifdef CONFIG_LPS_RPWM_TIMER
+	pwrctrlpriv->brpwmtimeout = _FALSE;
+	pwrctrlpriv->adapter = padapter;
+	_init_workitem(&pwrctrlpriv->rpwmtimeoutwi, rpwmtimeout_workitem_callback, NULL);
+	timer_setup(&pwrctrlpriv->pwr_rpwm_timer, pwr_rpwm_timeout_handler, 0);
+#endif // CONFIG_LPS_RPWM_TIMER
+#endif // CONFIG_LPS_LCLK
+
+	timer_setup(&pwrctrlpriv->pwr_state_check_timer,
+		    pwr_state_check_handler, 0);
+
+	pwrctrlpriv->wowlan_mode = _FALSE;
+	pwrctrlpriv->wowlan_ap_mode = _FALSE;
+	pwrctrlpriv->wowlan_p2p_mode = _FALSE;
+
+	#ifdef CONFIG_RESUME_IN_WORKQUEUE
+	_init_workitem(&pwrctrlpriv->resume_work, resume_workitem_callback, NULL);
+	pwrctrlpriv->rtw_workqueue = create_singlethread_workqueue("rtw_workqueue");
+	#endif //CONFIG_RESUME_IN_WORKQUEUE
+
+	#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
+	pwrctrlpriv->early_suspend.suspend = NULL;
+	rtw_register_early_suspend(pwrctrlpriv);
+	#endif //CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER
+
+#ifdef CONFIG_GPIO_WAKEUP
+	/*default low active*/
+	pwrctrlpriv->is_high_active = HIGH_ACTIVE;
+	val8 = (pwrctrlpriv->is_high_active == 0) ? 1 : 0;
+	rtw_hal_set_output_gpio(padapter, WAKEUP_GPIO_IDX, val8);
+	DBG_871X("%s: set GPIO_%d %d as default.\n",
+		 __func__, WAKEUP_GPIO_IDX, val8);
+#endif /* CONFIG_GPIO_WAKEUP */
+
+#ifdef CONFIG_WOWLAN
+	pwrctrlpriv->wowlan_pattern_idx = 0;
+	for (i = 0 ; i < MAX_WKFM_NUM; i++) {
+		_rtw_memset(pwrctrlpriv->patterns[i].content, '\0',
+				sizeof(pwrctrlpriv->patterns[i].content));
+		_rtw_memset(pwrctrlpriv->patterns[i].mask, '\0',
+				sizeof(pwrctrlpriv->patterns[i].mask));
+		pwrctrlpriv->patterns[i].len = 0;
+	}
+
+#ifdef CONFIG_PNO_SUPPORT
+	pwrctrlpriv->pno_inited = _FALSE;
+	pwrctrlpriv->pnlo_info = NULL;
+	pwrctrlpriv->pscan_info = NULL;
+	pwrctrlpriv->pno_ssid_list = NULL;
+	pwrctrlpriv->pno_in_resume = _TRUE;
+#endif /* CONFIG_PNO_SUPPORT */
+#endif /* CONFIG_WOWLAN */
+
+_func_exit_;
+
+}
+
+
+void rtw_free_pwrctrl_priv(PADAPTER adapter)
+{
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(adapter);
+
+#if defined(CONFIG_CONCURRENT_MODE)
+	if (adapter->adapter_type != PRIMARY_ADAPTER)
+		return;
+#endif	
+
+_func_enter_;
+
+	//_rtw_memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv));
+
+
+	#ifdef CONFIG_RESUME_IN_WORKQUEUE
+	if (pwrctrlpriv->rtw_workqueue) { 
+		flush_workqueue(pwrctrlpriv->rtw_workqueue);
+		destroy_workqueue(pwrctrlpriv->rtw_workqueue);
+	}
+	#endif
+
+#ifdef CONFIG_WOWLAN
+#ifdef CONFIG_PNO_SUPPORT
+	if (pwrctrlpriv->pnlo_info != NULL)
+		printk("****** pnlo_info memory leak********\n");
+
+	if (pwrctrlpriv->pscan_info != NULL)
+		printk("****** pscan_info memory leak********\n");
+
+	if (pwrctrlpriv->pno_ssid_list != NULL)
+		printk("****** pno_ssid_list memory leak********\n");
+#endif
+#endif /* CONFIG_WOWLAN */
+
+	#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
+	rtw_unregister_early_suspend(pwrctrlpriv);
+	#endif //CONFIG_HAS_EARLYSUSPEND || CONFIG_ANDROID_POWER
+
+	_free_pwrlock(&pwrctrlpriv->lock);
+	_free_pwrlock(&pwrctrlpriv->check_32k_lock);
+
+_func_exit_;
+}
+
+#ifdef CONFIG_RESUME_IN_WORKQUEUE
+extern int rtw_resume_process(_adapter *padapter);
+
+static void resume_workitem_callback(struct work_struct *work)
+{
+	struct pwrctrl_priv *pwrpriv = container_of(work, struct pwrctrl_priv, resume_work);
+	struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
+	_adapter *adapter = dvobj->padapters[IFACE_ID0];
+
+	DBG_871X("%s\n",__FUNCTION__);
+
+	rtw_resume_process(adapter);
+
+	rtw_resume_unlock_suspend();
+}
+
+void rtw_resume_in_workqueue(struct pwrctrl_priv *pwrpriv)
+{
+	// accquire system's suspend lock preventing from falliing asleep while resume in workqueue
+	//rtw_lock_suspend();
+
+	rtw_resume_lock_suspend();
+	
+	#if 1
+	queue_work(pwrpriv->rtw_workqueue, &pwrpriv->resume_work);	
+	#else
+	_set_workitem(&pwrpriv->resume_work);
+	#endif
+}
+#endif //CONFIG_RESUME_IN_WORKQUEUE
+
+#if defined(CONFIG_HAS_EARLYSUSPEND) || defined(CONFIG_ANDROID_POWER)
+inline bool rtw_is_earlysuspend_registered(struct pwrctrl_priv *pwrpriv)
+{
+	return (pwrpriv->early_suspend.suspend) ? _TRUE : _FALSE;
+}
+
+inline bool rtw_is_do_late_resume(struct pwrctrl_priv *pwrpriv)
+{
+	return (pwrpriv->do_late_resume) ? _TRUE : _FALSE;
+}
+
+inline void rtw_set_do_late_resume(struct pwrctrl_priv *pwrpriv, bool enable)
+{
+	pwrpriv->do_late_resume = enable;
+}
+#endif
+
+#ifdef CONFIG_HAS_EARLYSUSPEND
+extern int rtw_resume_process(_adapter *padapter);
+static void rtw_early_suspend(struct early_suspend *h)
+{
+	struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
+	DBG_871X("%s\n",__FUNCTION__);
+
+	rtw_set_do_late_resume(pwrpriv, _FALSE);
+}
+
+static void rtw_late_resume(struct early_suspend *h)
+{
+	struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
+	struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
+	_adapter *adapter = dvobj->padapters[IFACE_ID0];
+
+	DBG_871X("%s\n",__FUNCTION__);
+
+	if(pwrpriv->do_late_resume) {
+		rtw_set_do_late_resume(pwrpriv, _FALSE);
+		rtw_resume_process(adapter);
+	}
+}
+
+void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	//jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit
+	pwrpriv->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
+	pwrpriv->early_suspend.suspend = rtw_early_suspend;
+	pwrpriv->early_suspend.resume = rtw_late_resume;
+	register_early_suspend(&pwrpriv->early_suspend);	
+
+	
+}
+
+void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	rtw_set_do_late_resume(pwrpriv, _FALSE);
+
+	if (pwrpriv->early_suspend.suspend) 
+		unregister_early_suspend(&pwrpriv->early_suspend);
+
+	pwrpriv->early_suspend.suspend = NULL;
+	pwrpriv->early_suspend.resume = NULL;
+}
+#endif //CONFIG_HAS_EARLYSUSPEND
+
+#ifdef CONFIG_ANDROID_POWER
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+extern int rtw_resume_process(PADAPTER padapter);
+#endif
+static void rtw_early_suspend(android_early_suspend_t *h)
+{
+	struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
+	DBG_871X("%s\n",__FUNCTION__);
+
+	rtw_set_do_late_resume(pwrpriv, _FALSE);
+}
+
+static void rtw_late_resume(android_early_suspend_t *h)
+{
+	struct pwrctrl_priv *pwrpriv = container_of(h, struct pwrctrl_priv, early_suspend);
+	struct dvobj_priv *dvobj = pwrctl_to_dvobj(pwrpriv);
+	_adapter *adapter = dvobj->padapters[IFACE_ID0];
+
+	DBG_871X("%s\n",__FUNCTION__);
+	if(pwrpriv->do_late_resume) {
+		#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		rtw_set_do_late_resume(pwrpriv, _FALSE);
+		rtw_resume_process(adapter);
+		#endif
+	}
+}
+
+void rtw_register_early_suspend(struct pwrctrl_priv *pwrpriv)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	//jeff: set the early suspend level before blank screen, so we wll do late resume after scree is lit
+	pwrpriv->early_suspend.level = ANDROID_EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20;
+	pwrpriv->early_suspend.suspend = rtw_early_suspend;
+	pwrpriv->early_suspend.resume = rtw_late_resume;
+	android_register_early_suspend(&pwrpriv->early_suspend);	
+}
+
+void rtw_unregister_early_suspend(struct pwrctrl_priv *pwrpriv)
+{
+	DBG_871X("%s\n", __FUNCTION__);
+
+	rtw_set_do_late_resume(pwrpriv, _FALSE);
+
+	if (pwrpriv->early_suspend.suspend) 
+		android_unregister_early_suspend(&pwrpriv->early_suspend);
+
+	pwrpriv->early_suspend.suspend = NULL;
+	pwrpriv->early_suspend.resume = NULL;
+}
+#endif //CONFIG_ANDROID_POWER
+
+u8 rtw_interface_ps_func(_adapter *padapter,HAL_INTF_PS_FUNC efunc_id,u8* val)
+{
+	u8 bResult = _TRUE;
+	rtw_hal_intf_ps_func(padapter,efunc_id,val);
+	
+	return bResult;
+}
+
+
+inline void rtw_set_ips_deny(_adapter *padapter, u32 ms)
+{
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ms);
+}
+
+/*
+* rtw_pwr_wakeup - Wake the NIC up from: 1)IPS. 2)USB autosuspend
+* @adapter: pointer to _adapter structure
+* @ips_deffer_ms: the ms wiil prevent from falling into IPS after wakeup
+* Return _SUCCESS or _FAIL
+*/
+
+int _rtw_pwr_wakeup(_adapter *padapter, u32 ips_deffer_ms, const char *caller)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
+	struct mlme_priv *pmlmepriv;
+	int ret = _SUCCESS;
+	int i;
+	u32 start = rtw_get_current_time();
+
+	/* for LPS */
+	LeaveAllPowerSaveMode(padapter);
+
+	/* IPS still bound with primary adapter */
+	padapter = GET_PRIMARY_ADAPTER(padapter);
+	pmlmepriv = &padapter->mlmepriv;
+
+	if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms))
+		pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
+
+
+	if (pwrpriv->ps_processing) {
+		DBG_871X("%s wait ps_processing...\n", __func__);
+		while (pwrpriv->ps_processing && rtw_get_passing_time_ms(start) <= 3000)
+			rtw_msleep_os(10);
+		if (pwrpriv->ps_processing)
+			DBG_871X("%s wait ps_processing timeout\n", __func__);
+		else
+			DBG_871X("%s wait ps_processing done\n", __func__);
+	}
+
+#ifdef DBG_CONFIG_ERROR_DETECT
+	if (rtw_hal_sreset_inprogress(padapter)) {
+		DBG_871X("%s wait sreset_inprogress...\n", __func__);
+		while (rtw_hal_sreset_inprogress(padapter) && rtw_get_passing_time_ms(start) <= 4000)
+			rtw_msleep_os(10);
+		if (rtw_hal_sreset_inprogress(padapter))
+			DBG_871X("%s wait sreset_inprogress timeout\n", __func__);
+		else
+			DBG_871X("%s wait sreset_inprogress done\n", __func__);
+	}
+#endif
+
+	if (pwrpriv->bInternalAutoSuspend == _FALSE && pwrpriv->bInSuspend) {
+		DBG_871X("%s wait bInSuspend...\n", __func__);
+		while (pwrpriv->bInSuspend 
+			&& ((rtw_get_passing_time_ms(start) <= 3000 && !rtw_is_do_late_resume(pwrpriv))
+				|| (rtw_get_passing_time_ms(start) <= 500 && rtw_is_do_late_resume(pwrpriv)))
+		) {
+			rtw_msleep_os(10);
+		}
+		if (pwrpriv->bInSuspend)
+			DBG_871X("%s wait bInSuspend timeout\n", __func__);
+		else
+			DBG_871X("%s wait bInSuspend done\n", __func__);
+	}
+
+	//System suspend is not allowed to wakeup
+	if((pwrpriv->bInternalAutoSuspend == _FALSE) && (_TRUE == pwrpriv->bInSuspend )){
+		ret = _FAIL;
+		goto exit;
+	}
+
+	//block???
+	if((pwrpriv->bInternalAutoSuspend == _TRUE)  && (padapter->net_closed == _TRUE)) {
+		ret = _FAIL;
+		goto exit;
+	}
+
+	//I think this should be check in IPS, LPS, autosuspend functions...
+	if (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE)
+	{
+#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+		if(_TRUE==pwrpriv->bInternalAutoSuspend){
+			if(0==pwrpriv->autopm_cnt){
+			#if (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,33))				
+				if (usb_autopm_get_interface(adapter_to_dvobj(padapter)->pusbintf) < 0) 
+				{
+					DBG_871X( "can't get autopm: \n");
+				}			
+			#elif (LINUX_VERSION_CODE>=KERNEL_VERSION(2,6,20))				
+				usb_autopm_disable(adapter_to_dvobj(padapter)->pusbintf);
+			#else
+				usb_autoresume_device(adapter_to_dvobj(padapter)->pusbdev, 1);
+			#endif
+			pwrpriv->autopm_cnt++;
+			}
+#endif	//#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+		ret = _SUCCESS;
+		goto exit;
+#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+		}
+#endif	//#if defined (CONFIG_BT_COEXIST)&& defined (CONFIG_AUTOSUSPEND)
+	}	
+
+	if(rf_off == pwrpriv->rf_pwrstate )
+	{		
+#ifdef CONFIG_USB_HCI
+#ifdef CONFIG_AUTOSUSPEND
+		 if(pwrpriv->brfoffbyhw==_TRUE)
+		{
+			DBG_8192C("hw still in rf_off state ...........\n");
+			ret = _FAIL;
+			goto exit;
+		}
+		else if(padapter->registrypriv.usbss_enable)
+		{
+			DBG_8192C("%s call autoresume_enter....\n",__FUNCTION__);
+			if(_FAIL ==  autoresume_enter(padapter))
+			{
+				DBG_8192C("======> autoresume fail.............\n");
+				ret = _FAIL;
+				goto exit;
+			}	
+		}
+		else
+#endif
+#endif
+		{
+#ifdef CONFIG_IPS
+			DBG_8192C("%s call ips_leave....\n",__FUNCTION__);
+			if(_FAIL ==  ips_leave(padapter))
+			{
+				DBG_8192C("======> ips_leave fail.............\n");
+				ret = _FAIL;
+				goto exit;
+			}
+#endif
+		}
+	}
+
+	//TODO: the following checking need to be merged...
+	if (rtw_is_drv_stopped(padapter)
+		|| !padapter->bup
+		|| !rtw_is_hw_init_completed(padapter)
+	) {
+		DBG_8192C("%s: bDriverStopped=%s, bup=%d, hw_init_completed=%u\n"
+			, caller
+			, rtw_is_drv_stopped(padapter)?"True":"False"
+			, padapter->bup
+			, rtw_get_hw_init_completed(padapter));
+		ret= _FALSE;
+		goto exit;
+	}
+
+exit:
+	if (pwrpriv->ips_deny_time < rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms))
+		pwrpriv->ips_deny_time = rtw_get_current_time() + rtw_ms_to_systime(ips_deffer_ms);
+	return ret;
+
+}
+
+int rtw_pm_set_lps(_adapter *padapter, u8 mode)
+{
+	int	ret = 0;	
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+	
+	if ( mode < PS_MODE_NUM )
+	{
+		if(pwrctrlpriv->power_mgnt !=mode)
+		{
+			if(PS_MODE_ACTIVE == mode)
+			{
+				LeaveAllPowerSaveMode(padapter);
+			}
+			else
+			{
+				pwrctrlpriv->LpsIdleCount = 2;
+			}
+			pwrctrlpriv->power_mgnt = mode;
+			pwrctrlpriv->bLeisurePs = (PS_MODE_ACTIVE != pwrctrlpriv->power_mgnt)?_TRUE:_FALSE;
+		}
+	}
+	else
+	{
+		ret = -EINVAL;
+	}
+
+	return ret;
+}
+
+int rtw_pm_set_ips(_adapter *padapter, u8 mode)
+{
+	struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
+
+	if( mode == IPS_NORMAL || mode == IPS_LEVEL_2 ) {
+		rtw_ips_mode_req(pwrctrlpriv, mode);
+		DBG_871X("%s %s\n", __FUNCTION__, mode == IPS_NORMAL?"IPS_NORMAL":"IPS_LEVEL_2");
+		return 0;
+	} 
+	else if(mode ==IPS_NONE){
+		rtw_ips_mode_req(pwrctrlpriv, mode);
+		DBG_871X("%s %s\n", __FUNCTION__, "IPS_NONE");
+		if (!rtw_is_surprise_removed(padapter) && (_FAIL == rtw_pwr_wakeup(padapter)))
+			return -EFAULT;
+	}
+	else {
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * ATTENTION:
+ *	This function will request pwrctrl LOCK!
+ */
+void rtw_ps_deny(PADAPTER padapter, PS_DENY_REASON reason)
+{
+	struct pwrctrl_priv *pwrpriv;
+	s32 ret;
+
+
+//	DBG_871X("+" FUNC_ADPT_FMT ": Request PS deny for %d (0x%08X)\n",
+//		FUNC_ADPT_ARG(padapter), reason, BIT(reason));
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+
+	_enter_pwrlock(&pwrpriv->lock);
+	if (pwrpriv->ps_deny & BIT(reason))
+	{
+		DBG_871X(FUNC_ADPT_FMT ": [WARNING] Reason %d had been set before!!\n",
+			FUNC_ADPT_ARG(padapter), reason);
+	}
+	pwrpriv->ps_deny |= BIT(reason);
+	_exit_pwrlock(&pwrpriv->lock);
+
+//	DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
+//		FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny);
+}
+
+/*
+ * ATTENTION:
+ *	This function will request pwrctrl LOCK!
+ */
+void rtw_ps_deny_cancel(PADAPTER padapter, PS_DENY_REASON reason)
+{
+	struct pwrctrl_priv *pwrpriv;
+
+
+//	DBG_871X("+" FUNC_ADPT_FMT ": Cancel PS deny for %d(0x%08X)\n",
+//		FUNC_ADPT_ARG(padapter), reason, BIT(reason));
+
+	pwrpriv = adapter_to_pwrctl(padapter);
+
+	_enter_pwrlock(&pwrpriv->lock);
+	if ((pwrpriv->ps_deny & BIT(reason)) == 0)
+	{
+		DBG_871X(FUNC_ADPT_FMT ": [ERROR] Reason %d had been canceled before!!\n",
+			FUNC_ADPT_ARG(padapter), reason);
+	}
+	pwrpriv->ps_deny &= ~BIT(reason);
+	_exit_pwrlock(&pwrpriv->lock);
+
+//	DBG_871X("-" FUNC_ADPT_FMT ": Now PS deny for 0x%08X\n",
+//		FUNC_ADPT_ARG(padapter), pwrpriv->ps_deny);
+}
+
+/*
+ * ATTENTION:
+ *	Before calling this function pwrctrl lock should be occupied already,
+ *	otherwise it may return incorrect value.
+ */
+u32 rtw_ps_deny_get(PADAPTER padapter)
+{
+	u32 deny;
+
+
+	deny = adapter_to_pwrctl(padapter)->ps_deny;
+
+	return deny;
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_recv.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_recv.c
new file mode 100644
index 000000000..9c6802c53
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_recv.c
@@ -0,0 +1,4966 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_RECV_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+
+#error "Shall be Linux or Windows, but not both!\n"
+
+#endif
+
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+static void rtw_signal_stat_timer_hdl(struct timer_list *t);
+
+enum {
+	SIGNAL_STAT_CALC_PROFILE_0 = 0,
+	SIGNAL_STAT_CALC_PROFILE_1,
+	SIGNAL_STAT_CALC_PROFILE_MAX
+};
+
+u8 signal_stat_calc_profile[SIGNAL_STAT_CALC_PROFILE_MAX][2] = {
+	{4, 1},	/* Profile 0 => pre_stat : curr_stat = 4 : 1 */
+	{3, 7}	/* Profile 1 => pre_stat : curr_stat = 3 : 7 */
+};
+
+#ifndef RTW_SIGNAL_STATE_CALC_PROFILE	
+#define RTW_SIGNAL_STATE_CALC_PROFILE SIGNAL_STAT_CALC_PROFILE_1
+#endif
+
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+
+void _rtw_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
+{
+
+
+_func_enter_;
+
+	_rtw_memset((u8 *)psta_recvpriv, 0, sizeof (struct sta_recv_priv));
+
+	_rtw_spinlock_init(&psta_recvpriv->lock);
+
+	//for(i=0; i<MAX_RX_NUMBLKS; i++)
+	//	_rtw_init_queue(&psta_recvpriv->blk_strms[i]);
+
+	_rtw_init_queue(&psta_recvpriv->defrag_q);
+
+_func_exit_;
+
+}
+
+sint _rtw_init_recv_priv(struct recv_priv *precvpriv, _adapter *padapter)
+{
+	sint i;
+
+	union recv_frame *precvframe;
+
+	sint	res=_SUCCESS;
+
+_func_enter_;
+
+	// We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
+	//_rtw_memset((unsigned char *)precvpriv, 0, sizeof (struct  recv_priv));
+
+	_rtw_spinlock_init(&precvpriv->lock);
+
+	_rtw_init_queue(&precvpriv->free_recv_queue);
+	_rtw_init_queue(&precvpriv->recv_pending_queue);
+	_rtw_init_queue(&precvpriv->uc_swdec_pending_queue);
+
+	precvpriv->adapter = padapter;
+
+	precvpriv->free_recvframe_cnt = NR_RECVFRAME;
+
+	precvpriv->sink_udpport = 0;
+	precvpriv->pre_rtp_rxseq = 0;
+	precvpriv->cur_rtp_rxseq = 0;
+
+	rtw_os_recv_resource_init(precvpriv, padapter);
+
+	precvpriv->pallocated_frame_buf = rtw_zvmalloc(NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
+	
+	if(precvpriv->pallocated_frame_buf==NULL){
+		res= _FAIL;
+		goto exit;
+	}
+	//_rtw_memset(precvpriv->pallocated_frame_buf, 0, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
+
+	precvpriv->precv_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(precvpriv->pallocated_frame_buf), RXFRAME_ALIGN_SZ);
+	//precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf + RXFRAME_ALIGN_SZ -
+	//						((SIZE_PTR) (precvpriv->pallocated_frame_buf) &(RXFRAME_ALIGN_SZ-1));
+
+	precvframe = (union recv_frame*) precvpriv->precv_frame_buf;
+
+
+	for(i=0; i < NR_RECVFRAME ; i++)
+	{
+		_rtw_init_listhead(&(precvframe->u.list));
+
+		rtw_list_insert_tail(&(precvframe->u.list), &(precvpriv->free_recv_queue.queue));
+
+		res = rtw_os_recv_resource_alloc(padapter, precvframe);
+
+		precvframe->u.hdr.len = 0;
+
+		precvframe->u.hdr.adapter =padapter;
+		precvframe++;
+
+	}
+
+#ifdef CONFIG_USB_HCI
+
+	ATOMIC_SET(&(precvpriv->rx_pending_cnt), 1);
+
+	_rtw_init_sema(&precvpriv->allrxreturnevt, 0);
+
+#endif
+
+	res = rtw_hal_init_recv_priv(padapter);
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	timer_setup(&precvpriv->signal_stat_timer, rtw_signal_stat_timer_hdl,
+		    0);
+
+	precvpriv->signal_stat_sampling_interval = 2000; //ms
+	//precvpriv->signal_stat_converging_constant = 5000; //ms
+
+	rtw_set_signal_stat_timer(precvpriv);
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+
+exit:
+
+_func_exit_;
+
+	return res;
+
+}
+
+void rtw_mfree_recv_priv_lock(struct recv_priv *precvpriv);
+void rtw_mfree_recv_priv_lock(struct recv_priv *precvpriv)
+{
+	_rtw_spinlock_free(&precvpriv->lock);
+#ifdef CONFIG_RECV_THREAD_MODE	
+	_rtw_free_sema(&precvpriv->recv_sema);
+	_rtw_free_sema(&precvpriv->terminate_recvthread_sema);
+#endif
+
+	_rtw_spinlock_free(&precvpriv->free_recv_queue.lock);
+	_rtw_spinlock_free(&precvpriv->recv_pending_queue.lock);
+
+	_rtw_spinlock_free(&precvpriv->free_recv_buf_queue.lock);
+
+#ifdef CONFIG_USE_USB_BUFFER_ALLOC_RX
+	_rtw_spinlock_free(&precvpriv->recv_buf_pending_queue.lock);
+#endif	// CONFIG_USE_USB_BUFFER_ALLOC_RX
+}
+
+void _rtw_free_recv_priv (struct recv_priv *precvpriv)
+{
+	_adapter	*padapter = precvpriv->adapter;
+
+_func_enter_;
+
+	rtw_free_uc_swdec_pending_queue(padapter);
+
+	rtw_mfree_recv_priv_lock(precvpriv);
+
+	rtw_os_recv_resource_free(precvpriv);
+
+	if(precvpriv->pallocated_frame_buf) {
+		rtw_vmfree(precvpriv->pallocated_frame_buf, NR_RECVFRAME * sizeof(union recv_frame) + RXFRAME_ALIGN_SZ);
+	}
+
+	rtw_hal_free_recv_priv(padapter);
+
+_func_exit_;
+
+}
+
+bool rtw_rframe_del_wfd_ie(union recv_frame *rframe, u8 ies_offset)
+{
+#define DBG_RFRAME_DEL_WFD_IE 0
+	u8 *ies = rframe->u.hdr.rx_data + sizeof(struct rtw_ieee80211_hdr_3addr) + ies_offset;
+	uint ies_len_ori = rframe->u.hdr.len - (ies - rframe->u.hdr.rx_data);
+	uint ies_len;
+
+	ies_len = rtw_del_wfd_ie(ies, ies_len_ori, DBG_RFRAME_DEL_WFD_IE ? __func__ : NULL);
+	rframe->u.hdr.len -= ies_len_ori - ies_len;
+
+	return ies_len_ori != ies_len;
+}
+
+union recv_frame *_rtw_alloc_recvframe (_queue *pfree_recv_queue)
+{
+
+	union recv_frame  *precvframe;
+	_list	*plist, *phead;
+	_adapter *padapter;
+	struct recv_priv *precvpriv;
+_func_enter_;
+
+	if(_rtw_queue_empty(pfree_recv_queue) == _TRUE)
+	{
+		precvframe = NULL;
+	}
+	else
+	{
+		phead = get_list_head(pfree_recv_queue);
+
+		plist = get_next(phead);
+
+		precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+
+		rtw_list_delete(&precvframe->u.hdr.list);
+		padapter=precvframe->u.hdr.adapter;
+		if(padapter !=NULL){
+			precvpriv=&padapter->recvpriv;
+			if(pfree_recv_queue == &precvpriv->free_recv_queue)
+				precvpriv->free_recvframe_cnt--;
+		}
+	}
+
+_func_exit_;
+
+	return precvframe;
+
+}
+
+union recv_frame *rtw_alloc_recvframe (_queue *pfree_recv_queue)
+{
+	_irqL irqL;
+	union recv_frame  *precvframe;
+	
+	_enter_critical_bh(&pfree_recv_queue->lock, &irqL);
+
+	precvframe = _rtw_alloc_recvframe(pfree_recv_queue);
+
+	_exit_critical_bh(&pfree_recv_queue->lock, &irqL);
+
+	return precvframe;
+}
+
+void rtw_init_recvframe(union recv_frame *precvframe, struct recv_priv *precvpriv)
+{
+	/* Perry: This can be removed */
+	_rtw_init_listhead(&precvframe->u.hdr.list);
+
+	precvframe->u.hdr.len=0;
+}
+
+int rtw_free_recvframe(union recv_frame *precvframe, _queue *pfree_recv_queue)
+{
+	_irqL irqL;
+	_adapter *padapter=precvframe->u.hdr.adapter;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+
+_func_enter_;
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if(padapter->adapter_type > PRIMARY_ADAPTER)
+	{
+		padapter = padapter->pbuddy_adapter;//get primary_padapter
+		precvpriv = &padapter->recvpriv;
+		pfree_recv_queue = &precvpriv->free_recv_queue;
+		precvframe->u.hdr.adapter = padapter;		
+	}	
+#endif
+
+	rtw_os_free_recvframe(precvframe);
+
+
+	_enter_critical_bh(&pfree_recv_queue->lock, &irqL);
+
+	rtw_list_delete(&(precvframe->u.hdr.list));
+
+	precvframe->u.hdr.len = 0;
+
+	rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(pfree_recv_queue));
+
+	if(padapter !=NULL){
+		if(pfree_recv_queue == &precvpriv->free_recv_queue)
+				precvpriv->free_recvframe_cnt++;
+	}
+
+      _exit_critical_bh(&pfree_recv_queue->lock, &irqL);
+
+_func_exit_;
+
+	return _SUCCESS;
+
+}
+
+
+
+
+sint _rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue)
+{
+
+	_adapter *padapter=precvframe->u.hdr.adapter;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+
+_func_enter_;
+
+	//_rtw_init_listhead(&(precvframe->u.hdr.list));
+	rtw_list_delete(&(precvframe->u.hdr.list));
+
+
+	rtw_list_insert_tail(&(precvframe->u.hdr.list), get_list_head(queue));
+
+	if (padapter != NULL) {
+		if (queue == &precvpriv->free_recv_queue)
+			precvpriv->free_recvframe_cnt++;
+	}
+
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+sint rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue)
+{
+	sint ret;
+	_irqL irqL;
+	
+	//_spinlock(&pfree_recv_queue->lock);
+	_enter_critical_bh(&queue->lock, &irqL);
+	ret = _rtw_enqueue_recvframe(precvframe, queue);
+	//_rtw_spinunlock(&pfree_recv_queue->lock);
+	_exit_critical_bh(&queue->lock, &irqL);
+
+	return ret;
+}
+
+/*
+sint	rtw_enqueue_recvframe(union recv_frame *precvframe, _queue *queue)
+{
+	return rtw_free_recvframe(precvframe, queue);
+}
+*/
+
+
+
+
+/*
+caller : defrag ; recvframe_chk_defrag in recv_thread  (passive)
+pframequeue: defrag_queue : will be accessed in recv_thread  (passive)
+
+using spinlock to protect
+
+*/
+
+void rtw_free_recvframe_queue(_queue *pframequeue,  _queue *pfree_recv_queue)
+{
+	union	recv_frame 	*precvframe;
+	_list	*plist, *phead;
+
+_func_enter_;
+	_rtw_spinlock(&pframequeue->lock);
+
+	phead = get_list_head(pframequeue);
+	plist = get_next(phead);
+
+	while(rtw_end_of_queue_search(phead, plist) == _FALSE)
+	{
+		precvframe = LIST_CONTAINOR(plist, union recv_frame, u);
+
+		plist = get_next(plist);
+
+		//rtw_list_delete(&precvframe->u.hdr.list); // will do this in rtw_free_recvframe()
+
+		rtw_free_recvframe(precvframe, pfree_recv_queue);
+	}
+
+	_rtw_spinunlock(&pframequeue->lock);
+
+_func_exit_;
+
+}
+
+u32 rtw_free_uc_swdec_pending_queue(_adapter *adapter)
+{
+	u32 cnt = 0;
+	union recv_frame *pending_frame;
+	while((pending_frame=rtw_alloc_recvframe(&adapter->recvpriv.uc_swdec_pending_queue))) {
+		rtw_free_recvframe(pending_frame, &adapter->recvpriv.free_recv_queue);
+		cnt++;
+	}
+
+	if (cnt)
+		DBG_871X(FUNC_ADPT_FMT" dequeue %d\n", FUNC_ADPT_ARG(adapter), cnt);
+
+	return cnt;
+}
+
+
+sint rtw_enqueue_recvbuf_to_head(struct recv_buf *precvbuf, _queue *queue)
+{
+	_irqL irqL;
+
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	rtw_list_delete(&precvbuf->list);
+	rtw_list_insert_head(&precvbuf->list, get_list_head(queue));
+
+	_exit_critical_bh(&queue->lock, &irqL);
+
+	return _SUCCESS;
+}
+
+sint rtw_enqueue_recvbuf(struct recv_buf *precvbuf, _queue *queue)
+{
+	_irqL irqL;	
+#ifdef CONFIG_SDIO_HCI
+	_enter_critical_bh(&queue->lock, &irqL);
+#else
+	_enter_critical_ex(&queue->lock, &irqL);
+#endif/*#ifdef  CONFIG_SDIO_HCI*/
+
+	rtw_list_delete(&precvbuf->list);
+
+	rtw_list_insert_tail(&precvbuf->list, get_list_head(queue));
+#ifdef CONFIG_SDIO_HCI	
+	_exit_critical_bh(&queue->lock, &irqL);
+#else
+	_exit_critical_ex(&queue->lock, &irqL);
+#endif/*#ifdef  CONFIG_SDIO_HCI*/
+	return _SUCCESS;
+	
+}
+
+struct recv_buf *rtw_dequeue_recvbuf (_queue *queue)
+{
+	_irqL irqL;
+	struct recv_buf *precvbuf;
+	_list	*plist, *phead;	
+
+#ifdef CONFIG_SDIO_HCI
+	_enter_critical_bh(&queue->lock, &irqL);
+#else
+	_enter_critical_ex(&queue->lock, &irqL);
+#endif/*#ifdef  CONFIG_SDIO_HCI*/
+	
+	if(_rtw_queue_empty(queue) == _TRUE)
+	{
+		precvbuf = NULL;
+	}
+	else
+	{
+		phead = get_list_head(queue);
+
+		plist = get_next(phead);
+
+		precvbuf = LIST_CONTAINOR(plist, struct recv_buf, list);
+
+		rtw_list_delete(&precvbuf->list);
+		
+	}
+
+#ifdef CONFIG_SDIO_HCI
+	_exit_critical_bh(&queue->lock, &irqL);
+#else
+	_exit_critical_ex(&queue->lock, &irqL);
+#endif/*#ifdef  CONFIG_SDIO_HCI*/
+
+	return precvbuf;
+
+}
+
+sint recvframe_chkmic(_adapter *adapter,  union recv_frame *precvframe);
+sint recvframe_chkmic(_adapter *adapter,  union recv_frame *precvframe){
+
+	sint	i,res=_SUCCESS;
+	u32	datalen;
+	u8	miccode[8];
+	u8	bmic_err=_FALSE,brpt_micerror = _TRUE;
+	u8	*pframe, *payload,*pframemic;
+	u8	*mickey;
+	//u8	*iv,rxdata_key_idx=0;
+	struct	sta_info		*stainfo;
+	struct	rx_pkt_attrib	*prxattrib=&precvframe->u.hdr.attrib;
+	struct 	security_priv	*psecuritypriv=&adapter->securitypriv;
+
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+_func_enter_;
+
+	stainfo=rtw_get_stainfo(&adapter->stapriv ,&prxattrib->ta[0]);
+
+	if(prxattrib->encrypt ==_TKIP_)
+	{
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic:prxattrib->encrypt ==_TKIP_\n"));
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic:da=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+			prxattrib->ra[0],prxattrib->ra[1],prxattrib->ra[2],prxattrib->ra[3],prxattrib->ra[4],prxattrib->ra[5]));
+
+		//calculate mic code
+		if(stainfo!= NULL)
+		{
+			if(IS_MCAST(prxattrib->ra))
+			{
+				//mickey=&psecuritypriv->dot118021XGrprxmickey.skey[0];
+				//iv = precvframe->u.hdr.rx_data+prxattrib->hdrlen;
+				//rxdata_key_idx =( ((iv[3])>>6)&0x3) ;
+				mickey=&psecuritypriv->dot118021XGrprxmickey[prxattrib->key_index].skey[0];
+				
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n recvframe_chkmic: bcmc key \n"));
+				//DBG_871X("\n recvframe_chkmic: bcmc key psecuritypriv->dot118021XGrpKeyid(%d),pmlmeinfo->key_index(%d) ,recv key_id(%d)\n",
+				//								psecuritypriv->dot118021XGrpKeyid,pmlmeinfo->key_index,rxdata_key_idx);
+				
+				if(psecuritypriv->binstallGrpkey==_FALSE)
+				{
+					res=_FAIL;
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n"));
+					DBG_871X("\n recvframe_chkmic:didn't install group key!!!!!!!!!!\n");
+					goto exit;
+				}
+			}
+			else{
+				mickey=&stainfo->dot11tkiprxmickey.skey[0];
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n recvframe_chkmic: unicast key \n"));
+			}
+
+			datalen=precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;//icv_len included the mic code
+			pframe=precvframe->u.hdr.rx_data;
+			payload=pframe+prxattrib->hdrlen+prxattrib->iv_len;
+
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n prxattrib->iv_len=%d prxattrib->icv_len=%d\n",prxattrib->iv_len,prxattrib->icv_len));
+
+			//rtw_seccalctkipmic(&stainfo->dot11tkiprxmickey.skey[0],pframe,payload, datalen ,&miccode[0],(unsigned char)prxattrib->priority); //care the length of the data
+
+			rtw_seccalctkipmic(mickey,pframe,payload, datalen ,&miccode[0],(unsigned char)prxattrib->priority); //care the length of the data
+
+			pframemic=payload+datalen;
+
+			bmic_err=_FALSE;
+
+			for(i=0;i<8;i++){
+				if(miccode[i] != *(pframemic+i)){
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chkmic:miccode[%d](%02x) != *(pframemic+%d)(%02x) ",i,miccode[i],i,*(pframemic+i)));
+					bmic_err=_TRUE;
+				}
+			}
+
+
+			if(bmic_err==_TRUE){
+
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n *(pframemic-8)-*(pframemic-1)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+					*(pframemic-8),*(pframemic-7),*(pframemic-6),*(pframemic-5),*(pframemic-4),*(pframemic-3),*(pframemic-2),*(pframemic-1)));
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n *(pframemic-16)-*(pframemic-9)=0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
+					*(pframemic-16),*(pframemic-15),*(pframemic-14),*(pframemic-13),*(pframemic-12),*(pframemic-11),*(pframemic-10),*(pframemic-9)));
+
+				{
+					uint i;
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n ======demp packet (len=%d)======\n",precvframe->u.hdr.len));
+					for(i=0;i<precvframe->u.hdr.len;i=i+8){
+						RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x",
+							*(precvframe->u.hdr.rx_data+i),*(precvframe->u.hdr.rx_data+i+1),
+							*(precvframe->u.hdr.rx_data+i+2),*(precvframe->u.hdr.rx_data+i+3),
+							*(precvframe->u.hdr.rx_data+i+4),*(precvframe->u.hdr.rx_data+i+5),
+							*(precvframe->u.hdr.rx_data+i+6),*(precvframe->u.hdr.rx_data+i+7)));
+					}
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n ======demp packet end [len=%d]======\n",precvframe->u.hdr.len));
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("\n hrdlen=%d, \n",prxattrib->hdrlen));
+				}
+
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("ra=0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x psecuritypriv->binstallGrpkey=%d ",
+					prxattrib->ra[0],prxattrib->ra[1],prxattrib->ra[2],
+					prxattrib->ra[3],prxattrib->ra[4],prxattrib->ra[5],psecuritypriv->binstallGrpkey));
+
+				// double check key_index for some timing issue ,
+				// cannot compare with psecuritypriv->dot118021XGrpKeyid also cause timing issue
+				if((IS_MCAST(prxattrib->ra)==_TRUE)  && (prxattrib->key_index != pmlmeinfo->key_index ))
+					brpt_micerror = _FALSE;
+				
+				if((prxattrib->bdecrypted ==_TRUE)&& (brpt_micerror == _TRUE))
+				{
+					rtw_handle_tkip_mic_err(adapter, stainfo, (u8)IS_MCAST(prxattrib->ra));			
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" mic error :prxattrib->bdecrypted=%d ",prxattrib->bdecrypted));
+					DBG_871X(" mic error :prxattrib->bdecrypted=%d\n",prxattrib->bdecrypted);
+				}
+				else
+				{
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" mic error :prxattrib->bdecrypted=%d ",prxattrib->bdecrypted));
+					DBG_871X(" mic error :prxattrib->bdecrypted=%d\n",prxattrib->bdecrypted);
+				}
+
+				res=_FAIL;
+
+			}
+			else{
+				//mic checked ok
+				if((psecuritypriv->bcheck_grpkey ==_FALSE)&&(IS_MCAST(prxattrib->ra)==_TRUE)){
+					psecuritypriv->bcheck_grpkey =_TRUE;
+					RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("psecuritypriv->bcheck_grpkey =_TRUE"));
+				}
+			}
+
+		}
+		else
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chkmic: rtw_get_stainfo==NULL!!!\n"));
+		}
+
+		recvframe_pull_tail(precvframe, 8);
+
+	}
+
+exit:
+
+_func_exit_;
+
+	return res;
+
+}
+
+//decrypt and set the ivlen,icvlen of the recv_frame
+union recv_frame * decryptor(_adapter *padapter,union recv_frame *precv_frame);
+union recv_frame * decryptor(_adapter *padapter,union recv_frame *precv_frame)
+{
+
+	struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
+	struct security_priv *psecuritypriv=&padapter->securitypriv;
+	union recv_frame *return_packet=precv_frame;
+	u32	 res=_SUCCESS;
+
+_func_enter_;
+
+	DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt);
+
+	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("prxstat->decrypted=%x prxattrib->encrypt = 0x%03x\n",prxattrib->bdecrypted,prxattrib->encrypt));
+
+	if(prxattrib->encrypt>0)
+	{
+		u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen;
+		prxattrib->key_index = ( ((iv[3])>>6)&0x3) ;
+
+		if(prxattrib->key_index > WEP_KEYS)
+		{
+			DBG_871X("prxattrib->key_index(%d) > WEP_KEYS \n", prxattrib->key_index);
+
+			switch(prxattrib->encrypt){
+				case _WEP40_:
+				case _WEP104_:
+					prxattrib->key_index = psecuritypriv->dot11PrivacyKeyIndex;
+					break;
+				case _TKIP_:			
+				case _AES_:						
+				default:
+					prxattrib->key_index = psecuritypriv->dot118021XGrpKeyid;
+					break;
+			}	
+		}			
+	}
+
+	if((prxattrib->encrypt>0) && ((prxattrib->bdecrypted==0) ||(psecuritypriv->sw_decrypt==_TRUE)))
+	{
+
+#ifdef CONFIG_CONCURRENT_MODE
+		if(!IS_MCAST(prxattrib->ra))//bc/mc packets use sw decryption for concurrent mode
+#endif			
+			psecuritypriv->hw_decrypted=_FALSE;
+
+		#ifdef DBG_RX_DECRYPTOR
+		DBG_871X("[%s] %d:prxstat->bdecrypted:%d,  prxattrib->encrypt:%d,  Setting psecuritypriv->hw_decrypted = %d\n",
+			__FUNCTION__,
+			__LINE__,
+			prxattrib->bdecrypted,
+			prxattrib->encrypt,
+			psecuritypriv->hw_decrypted);
+		#endif
+
+		switch(prxattrib->encrypt){
+		case _WEP40_:
+		case _WEP104_:
+			DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wep);
+			rtw_wep_decrypt(padapter, (u8 *)precv_frame);
+			break;
+		case _TKIP_:
+			DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_tkip);
+			res = rtw_tkip_decrypt(padapter, (u8 *)precv_frame);
+			break;
+		case _AES_:
+			DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_aes);
+			res = rtw_aes_decrypt(padapter, (u8 * )precv_frame);
+			break;
+#ifdef CONFIG_WAPI_SUPPORT
+		case _SMS4_:
+			DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_wapi);
+			rtw_sms4_decrypt(padapter, (u8 * )precv_frame);
+			break;
+#endif
+		default:
+				break;
+		}
+	}
+	else if(prxattrib->bdecrypted==1
+		&& prxattrib->encrypt >0
+		&& (psecuritypriv->busetkipkey==1 || prxattrib->encrypt !=_TKIP_ )
+		)
+	{
+#if 0
+		if((prxstat->icv==1)&&(prxattrib->encrypt!=_AES_))
+		{
+			psecuritypriv->hw_decrypted=_FALSE;
+
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("psecuritypriv->hw_decrypted=_FALSE"));
+
+			rtw_free_recvframe(precv_frame, &padapter->recvpriv.free_recv_queue);
+
+			return_packet=NULL;
+
+		}
+		else
+#endif
+		{
+			DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_hw);
+
+			psecuritypriv->hw_decrypted=_TRUE;
+			#ifdef DBG_RX_DECRYPTOR
+			DBG_871X("[%s] %d:prxstat->bdecrypted:%d,  prxattrib->encrypt:%d,  Setting psecuritypriv->hw_decrypted = %d\n",
+				__FUNCTION__,
+				__LINE__,
+				prxattrib->bdecrypted,
+				prxattrib->encrypt,
+				psecuritypriv->hw_decrypted);
+
+			#endif
+		}
+	}
+	else {
+		DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_unknown);
+		#ifdef DBG_RX_DECRYPTOR
+		DBG_871X("[%s] %d:prxstat->bdecrypted:%d,  prxattrib->encrypt:%d,  Setting psecuritypriv->hw_decrypted = %d\n",
+			__FUNCTION__,
+			__LINE__,
+			prxattrib->bdecrypted,
+			prxattrib->encrypt,
+			psecuritypriv->hw_decrypted);
+		#endif
+	}
+	
+	if(res == _FAIL)
+	{
+		rtw_free_recvframe(return_packet,&padapter->recvpriv.free_recv_queue);			
+		return_packet = NULL;
+	}
+	else
+	{
+		prxattrib->bdecrypted = _TRUE;
+	}
+	//recvframe_chkmic(adapter, precv_frame);   //move to recvframme_defrag function
+
+_func_exit_;
+
+	return return_packet;
+
+}
+//###set the security information in the recv_frame
+union recv_frame * portctrl(_adapter *adapter,union recv_frame * precv_frame);
+union recv_frame * portctrl(_adapter *adapter,union recv_frame * precv_frame)
+{
+	u8 *psta_addr = NULL;
+	u8 *ptr;
+	uint  auth_alg;
+	struct recv_frame_hdr *pfhdr;
+	struct sta_info *psta;
+	struct sta_priv *pstapriv ;
+	union recv_frame *prtnframe;
+	u16	ether_type=0;
+	u16  eapol_type = 0x888e;//for Funia BD's WPA issue  
+	struct rx_pkt_attrib *pattrib;
+
+_func_enter_;
+
+	pstapriv = &adapter->stapriv;
+
+	auth_alg = adapter->securitypriv.dot11AuthAlgrthm;
+
+	ptr = get_recvframe_data(precv_frame);
+	pfhdr = &precv_frame->u.hdr;
+	pattrib = &pfhdr->attrib;
+	psta_addr = pattrib->ta;
+
+	prtnframe = NULL;
+
+	psta = rtw_get_stainfo(pstapriv, psta_addr);
+
+	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:adapter->securitypriv.dot11AuthAlgrthm=%d\n",adapter->securitypriv.dot11AuthAlgrthm));
+
+	if(auth_alg==2)
+	{
+		if ((psta!=NULL) && (psta->ieee8021x_blocked))
+		{
+			//blocked
+			//only accept EAPOL frame
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:psta->ieee8021x_blocked==1\n"));
+
+			prtnframe=precv_frame;
+
+			//get ether_type
+			ptr=ptr+pfhdr->attrib.hdrlen+pfhdr->attrib.iv_len+LLC_HEADER_SIZE;
+			_rtw_memcpy(&ether_type,ptr, 2);
+			ether_type= ntohs((unsigned short )ether_type);
+
+		        if (ether_type == eapol_type) {
+				prtnframe=precv_frame;
+			}
+			else {
+				//free this frame
+				rtw_free_recvframe(precv_frame, &adapter->recvpriv.free_recv_queue);
+				prtnframe=NULL;
+			}
+		}
+		else
+		{
+			//allowed
+			//check decryption status, and decrypt the frame if needed
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:psta->ieee8021x_blocked==0\n"));
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("portctrl:precv_frame->hdr.attrib.privacy=%x\n",precv_frame->u.hdr.attrib.privacy));
+
+			if (pattrib->bdecrypted == 0)
+			{
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("portctrl:prxstat->decrypted=%x\n", pattrib->bdecrypted));
+			}
+
+			prtnframe=precv_frame;
+			//check is the EAPOL frame or not (Rekey)
+			//if(ether_type == eapol_type){
+			//	RT_TRACE(_module_rtl871x_recv_c_,_drv_notice_,("########portctrl:ether_type == 0x888e\n"));
+				//check Rekey
+
+			//	prtnframe=precv_frame;
+			//}
+			//else{
+			//	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("########portctrl:ether_type=0x%04x\n", ether_type));
+			//}
+		}
+	}
+	else
+	{
+		prtnframe=precv_frame;
+	}
+
+_func_exit_;
+
+		return prtnframe;
+
+}
+
+sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache);
+sint recv_decache(union recv_frame *precv_frame, u8 bretry, struct stainfo_rxcache *prxcache)
+{
+	sint tid = precv_frame->u.hdr.attrib.priority;
+
+	u16 seq_ctrl = ( (precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
+		(precv_frame->u.hdr.attrib.frag_num & 0xf);
+
+_func_enter_;
+
+	if(tid>15)
+	{
+		RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, (tid>15)! seq_ctrl=0x%x, tid=0x%x\n", seq_ctrl, tid));
+
+		return _FAIL;
+	}
+
+	if(1)//if(bretry)
+	{
+		if(seq_ctrl == prxcache->tid_rxseq[tid])
+		{
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_decache, seq_ctrl=0x%x, tid=0x%x, tid_rxseq=0x%x\n", seq_ctrl, tid, prxcache->tid_rxseq[tid]));
+
+			return _FAIL;
+		}
+	}
+
+	prxcache->tid_rxseq[tid] = seq_ctrl;
+
+_func_exit_;
+
+	return _SUCCESS;
+
+}
+
+void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame);
+void process_pwrbit_data(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_AP_MODE
+	unsigned char pwrbit;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *psta=NULL;
+
+	psta = rtw_get_stainfo(pstapriv, pattrib->src);
+
+	pwrbit = GetPwrMgt(ptr);
+
+	if(psta)
+	{
+		if(pwrbit)
+		{
+			if(!(psta->state & WIFI_SLEEP_STATE))
+			{
+				//psta->state |= WIFI_SLEEP_STATE;
+				//pstapriv->sta_dz_bitmap |= BIT(psta->aid);
+
+				stop_sta_xmit(padapter, psta);
+
+				//DBG_871X("to sleep, sta_dz_bitmap=%x\n", pstapriv->sta_dz_bitmap);
+			}
+		}
+		else
+		{
+			if(psta->state & WIFI_SLEEP_STATE)
+			{
+				//psta->state ^= WIFI_SLEEP_STATE;
+				//pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
+
+				wakeup_sta_to_xmit(padapter, psta);
+
+				//DBG_871X("to wakeup, sta_dz_bitmap=%x\n", pstapriv->sta_dz_bitmap);
+			}
+		}
+
+	}
+
+#endif
+}
+
+void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame);
+void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame)
+{
+#ifdef CONFIG_AP_MODE		
+	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *psta=NULL;
+
+	psta = rtw_get_stainfo(pstapriv, pattrib->src);
+	
+	if(!psta) return;
+
+#ifdef CONFIG_TDLS
+	if( !(psta->tdls_sta_state & TDLS_LINKED_STATE ) )
+	{
+#endif //CONFIG_TDLS
+
+	if(!psta->qos_option)
+		return;
+
+	if(!(psta->qos_info&0xf))
+		return;
+		
+#ifdef CONFIG_TDLS
+	}
+#endif //CONFIG_TDLS		
+
+	if(psta->state&WIFI_SLEEP_STATE)
+	{
+		u8 wmmps_ac=0;	
+		
+		switch(pattrib->priority)
+		{
+			case 1:
+			case 2:
+				wmmps_ac = psta->uapsd_bk&BIT(1);
+				break;
+			case 4:
+			case 5:
+				wmmps_ac = psta->uapsd_vi&BIT(1);
+				break;
+			case 6:
+			case 7:
+				wmmps_ac = psta->uapsd_vo&BIT(1);
+				break;
+			case 0:
+			case 3:
+			default:
+				wmmps_ac = psta->uapsd_be&BIT(1);
+				break;	
+		}
+
+		if(wmmps_ac)
+		{
+			if(psta->sleepq_ac_len>0)
+			{
+				//process received triggered frame
+				xmit_delivery_enabled_frames(padapter, psta);
+			}
+			else
+			{
+				//issue one qos null frame with More data bit = 0 and the EOSP bit set (=1)
+				issue_qos_nulldata(padapter, psta->hwaddr, (u16)pattrib->priority, 0, 0);
+			}
+		}
+				
+	}
+
+	
+#endif	
+
+}
+
+#ifdef CONFIG_TDLS
+sint OnTDLS(_adapter *adapter, union recv_frame *precv_frame)
+{
+	struct rx_pkt_attrib	*pattrib = & precv_frame->u.hdr.attrib;
+	sint ret = _SUCCESS;
+	u8 *paction = get_recvframe_data(precv_frame);
+	u8 category_field = 1;
+#ifdef CONFIG_WFD
+	u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a };
+#endif /* CONFIG_WFD */
+	struct tdls_info *ptdlsinfo = &(adapter->tdlsinfo);
+
+	/* point to action field */
+	paction+=pattrib->hdrlen 
+			+ pattrib->iv_len 
+			+ SNAP_SIZE 
+			+ ETH_TYPE_LEN 
+			+ PAYLOAD_TYPE_LEN 
+			+ category_field;
+
+	DBG_871X("[TDLS] Recv %s from "MAC_FMT"\n", rtw_tdls_action_txt(*paction), MAC_ARG(pattrib->src));
+
+	if (hal_chk_wl_func(adapter, WL_FUNC_TDLS) == _FALSE) {
+		DBG_871X("Ignore tdls frame since hal doesn't support tdls\n");
+		ret = _FAIL;
+		return ret;
+	}
+
+	if (ptdlsinfo->tdls_enable == _FALSE) {
+		DBG_871X("recv tdls frame, "
+				"but tdls haven't enabled\n");
+		ret = _FAIL;
+		return ret;
+	}
+	
+	switch(*paction){
+	case TDLS_SETUP_REQUEST:
+		ret=On_TDLS_Setup_Req(adapter, precv_frame);
+		break;
+	case TDLS_SETUP_RESPONSE:
+		ret=On_TDLS_Setup_Rsp(adapter, precv_frame);
+		break;
+	case TDLS_SETUP_CONFIRM:
+		ret=On_TDLS_Setup_Cfm(adapter, precv_frame);
+		break;
+	case TDLS_TEARDOWN:
+		ret=On_TDLS_Teardown(adapter, precv_frame);
+		break;
+	case TDLS_DISCOVERY_REQUEST:
+		ret=On_TDLS_Dis_Req(adapter, precv_frame);
+		break;
+	case TDLS_PEER_TRAFFIC_INDICATION:
+		ret=On_TDLS_Peer_Traffic_Indication(adapter, precv_frame);
+		break;
+	case TDLS_PEER_TRAFFIC_RESPONSE:
+		ret=On_TDLS_Peer_Traffic_Rsp(adapter, precv_frame);
+		break;
+#ifdef CONFIG_TDLS_CH_SW		
+	case TDLS_CHANNEL_SWITCH_REQUEST:
+		ret=On_TDLS_Ch_Switch_Req(adapter, precv_frame);
+		break;
+	case TDLS_CHANNEL_SWITCH_RESPONSE:
+		ret=On_TDLS_Ch_Switch_Rsp(adapter, precv_frame);
+		break;
+#endif		
+#ifdef CONFIG_WFD			
+	/* First byte of WFA OUI */
+	case 0x50:
+		if (_rtw_memcmp(WFA_OUI, paction, 3)) {
+			/* Probe request frame */
+			if (*(paction + 3) == 0x04) {
+				/* WFDTDLS: for sigma test, do not setup direct link automatically */
+				ptdlsinfo->dev_discovered = _TRUE;
+				DBG_871X("recv tunneled probe request frame\n");
+				issue_tunneled_probe_rsp(adapter, precv_frame);
+			}
+			/* Probe response frame */ 
+			if (*(paction + 3) == 0x05) {
+				/* WFDTDLS: for sigma test, do not setup direct link automatically */
+				ptdlsinfo->dev_discovered = _TRUE;
+				DBG_871X("recv tunneled probe response frame\n");
+			}
+		}
+		break;
+#endif /* CONFIG_WFD */
+	default:
+		DBG_871X("receive TDLS frame %d but not support\n", *paction);
+		ret=_FAIL;
+		break;
+	}
+
+exit:
+	return ret;
+	
+}
+#endif /* CONFIG_TDLS */
+
+void count_rx_stats(_adapter *padapter, union recv_frame *prframe, struct sta_info*sta);
+void count_rx_stats(_adapter *padapter, union recv_frame *prframe, struct sta_info*sta)
+{
+	int	sz;
+	struct sta_info		*psta = NULL;
+	struct stainfo_stats	*pstats = NULL;
+	struct rx_pkt_attrib	*pattrib = & prframe->u.hdr.attrib;
+	struct recv_priv		*precvpriv = &padapter->recvpriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	sz = get_recvframe_len(prframe);
+	precvpriv->rx_bytes += sz;
+
+	padapter->mlmepriv.LinkDetectInfo.NumRxOkInPeriod++;
+
+	if( (!MacAddr_isBcst(pattrib->dst)) && (!IS_MCAST(pattrib->dst))){
+		padapter->mlmepriv.LinkDetectInfo.NumRxUnicastOkInPeriod++;
+	}
+
+	if(sta)
+		psta = sta;
+	else
+		psta = prframe->u.hdr.psta;
+
+	if(psta)
+	{
+		pstats = &psta->sta_stats;
+
+		pstats->rx_data_pkts++;
+		pstats->rx_bytes += sz;
+		
+		/*record rx packets for every tid*/	
+		pstats->rx_data_qos_pkts[pattrib->priority]++;
+
+#ifdef CONFIG_TDLS
+		if(psta->tdls_sta_state & TDLS_LINKED_STATE)
+		{
+			struct sta_info *pap_sta = NULL;
+			pap_sta = rtw_get_stainfo(&padapter->stapriv, get_bssid(&padapter->mlmepriv));
+			if(pap_sta)
+			{
+				pstats = &pap_sta->sta_stats;
+				pstats->rx_data_pkts++;
+				pstats->rx_bytes += sz;
+			}
+		}
+#endif //CONFIG_TDLS
+	}
+
+#ifdef CONFIG_CHECK_LEAVE_LPS
+	traffic_check_for_leave_lps(padapter, _FALSE, 0);
+#endif //CONFIG_LPS
+
+}
+
+sint sta2sta_data_frame(
+	_adapter *adapter,
+	union recv_frame *precv_frame,
+	struct sta_info**psta
+);
+sint sta2sta_data_frame(
+	_adapter *adapter,
+	union recv_frame *precv_frame,
+	struct sta_info**psta
+)
+{
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	sint ret = _SUCCESS;
+	struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
+	struct	sta_priv 		*pstapriv = &adapter->stapriv;
+	struct	mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+	u8 *mybssid  = get_bssid(pmlmepriv);
+	u8 *myhwaddr = adapter_mac_addr(adapter);
+	u8 * sta_addr = NULL;
+	sint bmcast = IS_MCAST(pattrib->dst);
+
+#ifdef CONFIG_TDLS	
+	struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+#ifdef CONFIG_TDLS_CH_SW
+	struct tdls_ch_switch *pchsw_info = &ptdlsinfo->chsw_info;
+#endif
+	struct sta_info *ptdls_sta=NULL;
+	u8 *psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+	//frame body located after [+2]: ether-type, [+1]: payload type
+	u8 *pframe_body = psnap_type+2+1;
+#endif
+
+_func_enter_;
+
+	//DBG_871X("[%s] %d, seqnum:%d\n", __FUNCTION__, __LINE__, pattrib->seq_num);
+
+	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ||
+		(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE))
+	{
+
+		// filter packets that SA is myself or multicast or broadcast
+		if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)){
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" SA==myself \n"));
+			ret= _FAIL;
+			goto exit;
+		}
+
+		if( (!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN))	&& (!bmcast) ){
+			ret= _FAIL;
+			goto exit;
+		}
+
+		if( _rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		   _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		   (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) ) {
+			ret= _FAIL;
+			goto exit;
+		}
+
+		sta_addr = pattrib->src;
+
+	}
+	else if(check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+	{
+#ifdef CONFIG_TDLS
+
+		/* direct link data transfer */
+		if (ptdlsinfo->link_established == _TRUE) {
+			ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);
+			if (ptdls_sta == NULL) {
+				ret=_FAIL;
+				goto exit;
+			} else if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
+				/* filter packets that SA is myself or multicast or broadcast */
+				if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)) {
+					ret= _FAIL;
+					goto exit;
+				}
+				/* da should be for me */
+				if ((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast)) {
+					ret= _FAIL;
+					goto exit;
+				}
+				/* check BSSID */
+				if (_rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+				     _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+				     (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN))) {
+					ret= _FAIL;
+					goto exit;
+				}
+
+#ifdef CONFIG_TDLS_CH_SW
+				pchsw_info->ch_sw_state |= TDLS_PEER_AT_OFF_STATE;
+
+				if(ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) {
+					if (!(pchsw_info->ch_sw_state & TDLS_PEER_AT_OFF_STATE)) {
+						DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
+						issue_nulldata_to_TDLS_peer_STA(adapter, ptdls_sta->hwaddr, 0, 0, 0);
+						pchsw_info->ch_sw_state |= TDLS_PEER_AT_OFF_STATE;
+						/* On_TDLS_Peer_Traffic_Rsp(adapter, precv_frame); */
+					}
+				}
+#endif
+
+				/* process UAPSD tdls sta */
+				process_pwrbit_data(adapter, precv_frame);
+
+				/* if NULL-frame, check pwrbit */
+				if ((GetFrameSubType(ptr) & WIFI_DATA_NULL) == WIFI_DATA_NULL) {
+					/* NULL-frame with pwrbit=1, buffer_STA should buffer frames for sleep_STA */
+					if (GetPwrMgt(ptr)) {
+						/* it would be triggered when we are off channel and receiving NULL DATA */
+						/* we can confirm that peer STA is at off channel */
+						DBG_871X("TDLS: recv peer null frame with pwr bit 1\n");
+						//ptdls_sta->tdls_sta_state|=TDLS_PEER_SLEEP_STATE;
+					}
+
+					/* TODO: Updated BSSID's seq. */
+					//DBG_871X("drop Null Data\n");
+					ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);
+					ret= _FAIL;
+					goto exit;
+				}
+
+				/* receive some of all TDLS management frames, process it at ON_TDLS */
+				if (_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_TDLS, 2)) {
+					ret= OnTDLS(adapter, precv_frame);
+					goto exit;
+				}
+
+				if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
+					process_wmmps_data(adapter, precv_frame);
+				}
+
+				ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);
+
+			}
+
+			sta_addr = pattrib->src;
+			
+		}		
+		else
+#endif /* CONFIG_TDLS */
+		{
+			// For Station mode, sa and bssid should always be BSSID, and DA is my mac-address
+			if(!_rtw_memcmp(pattrib->bssid, pattrib->src, ETH_ALEN) )
+			{
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("bssid != TA under STATION_MODE; drop pkt\n"));
+				ret= _FAIL;
+				goto exit;
+		}
+
+		sta_addr = pattrib->bssid;
+		}
+
+	}
+	else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{
+		if (bmcast)
+		{
+			// For AP mode, if DA == MCAST, then BSSID should be also MCAST
+			if (!IS_MCAST(pattrib->bssid)){
+					ret= _FAIL;
+					goto exit;
+			}
+		}
+		else // not mc-frame
+		{
+			// For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID
+			if(!_rtw_memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN)) {
+				ret= _FAIL;
+				goto exit;
+			}
+
+			sta_addr = pattrib->src;
+		}
+
+	}
+	else if(check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+	{
+		_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+		_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+		sta_addr = mybssid;
+	}
+	else
+	{
+		ret  = _FAIL;
+	}
+
+
+
+	if(bmcast)
+		*psta = rtw_get_bcmc_stainfo(adapter);
+	else
+		*psta = rtw_get_stainfo(pstapriv, sta_addr); // get ap_info
+
+#ifdef CONFIG_TDLS
+	if(ptdls_sta != NULL)
+	{
+		*psta = ptdls_sta;
+	}
+#endif //CONFIG_TDLS
+
+	if (*psta == NULL) {
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under sta2sta_data_frame ; drop pkt\n"));
+#ifdef CONFIG_MP_INCLUDED
+		if (adapter->registrypriv.mp_mode == 1)
+		{
+			if(check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+				adapter->mppriv.rx_pktloss++;
+		}
+#endif
+		ret= _FAIL;
+		goto exit;
+	}
+
+exit:
+_func_exit_;
+	return ret;
+
+}
+
+sint ap2sta_data_frame(
+	_adapter *adapter,
+	union recv_frame *precv_frame,
+	struct sta_info**psta );
+sint ap2sta_data_frame(
+	_adapter *adapter,
+	union recv_frame *precv_frame,
+	struct sta_info**psta )
+{
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
+	sint ret = _SUCCESS;
+	struct	sta_priv 		*pstapriv = &adapter->stapriv;
+	struct	mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+	u8 *mybssid  = get_bssid(pmlmepriv);
+	u8 *myhwaddr = adapter_mac_addr(adapter);
+	sint bmcast = IS_MCAST(pattrib->dst);
+
+_func_enter_;
+
+	if ((check_fwstate(pmlmepriv, WIFI_STATION_STATE) == _TRUE)
+		&& (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE 
+			|| check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == _TRUE	)
+		)
+	{
+
+		// filter packets that SA is myself or multicast or broadcast
+		if (_rtw_memcmp(myhwaddr, pattrib->src, ETH_ALEN)){
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" SA==myself \n"));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s SA="MAC_FMT", myhwaddr="MAC_FMT"\n",
+				__FUNCTION__, MAC_ARG(pattrib->src), MAC_ARG(myhwaddr));
+			#endif			
+			ret= _FAIL;
+			goto exit;
+		}
+
+		// da should be for me
+		if((!_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN))&& (!bmcast))
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,
+				(" ap2sta_data_frame:  compare DA fail; DA="MAC_FMT"\n", MAC_ARG(pattrib->dst)));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s DA="MAC_FMT"\n", __func__, MAC_ARG(pattrib->dst));
+			#endif
+			ret= _FAIL;
+			goto exit;
+		}
+
+
+		// check BSSID
+		if( _rtw_memcmp(pattrib->bssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		     _rtw_memcmp(mybssid, "\x0\x0\x0\x0\x0\x0", ETH_ALEN) ||
+		     (!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN)) )
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,
+				(" ap2sta_data_frame:  compare BSSID fail ; BSSID="MAC_FMT"\n", MAC_ARG(pattrib->bssid)));
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("mybssid="MAC_FMT"\n", MAC_ARG(mybssid)));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s BSSID="MAC_FMT", mybssid="MAC_FMT"\n",
+				__FUNCTION__, MAC_ARG(pattrib->bssid), MAC_ARG(mybssid));
+			DBG_871X( "this adapter = %d, buddy adapter = %d\n", adapter->adapter_type, adapter->pbuddy_adapter->adapter_type );
+			#endif
+
+			if(!bmcast)
+			{
+				DBG_871X("issue_deauth to the nonassociated ap=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));
+				issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+			}
+
+			ret= _FAIL;
+			goto exit;
+		}
+
+		if(bmcast)
+			*psta = rtw_get_bcmc_stainfo(adapter);
+		else
+			*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get ap_info
+
+		if (*psta == NULL) {
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("ap2sta: can't get psta under STATION_MODE ; drop pkt\n"));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under STATION_MODE ; drop pkt\n", __FUNCTION__);
+			#endif
+			ret= _FAIL;
+			goto exit;
+		}
+
+		if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
+		}
+
+		if (GetFrameSubType(ptr) & BIT(6)) {
+			/* No data, will not indicate to upper layer, temporily count it here */
+			count_rx_stats(adapter, precv_frame, *psta);
+			ret = RTW_RX_HANDLED;
+			goto exit;
+		}
+
+	}
+	else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) &&
+		     (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) )
+	{
+		_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+		_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+		//
+		if(adapter->mppriv.bRTWSmbCfg==_FALSE)
+			_rtw_memcpy(pattrib->bssid,  mybssid, ETH_ALEN);
+
+
+		*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get sta_info
+		if (*psta == NULL) {
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under MP_MODE ; drop pkt\n"));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt\n", __FUNCTION__);
+			#endif
+			ret= _FAIL;
+			goto exit;
+		}
+
+
+	}
+	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{
+		/* Special case */
+		ret = RTW_RX_HANDLED;
+		goto exit;
+	}
+	else
+	{
+		if(_rtw_memcmp(myhwaddr, pattrib->dst, ETH_ALEN)&& (!bmcast))
+		{
+			*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get sta_info
+			if (*psta == NULL)
+			{
+	
+				//for AP multicast issue , modify by yiwei 
+				static u32 send_issue_deauth_time=0;
+			
+				//DBG_871X("After send deauth , %u ms has elapsed.\n", rtw_get_passing_time_ms(send_issue_deauth_time));
+				
+				if(rtw_get_passing_time_ms(send_issue_deauth_time) > 10000 || send_issue_deauth_time == 0 )
+				{
+					send_issue_deauth_time = rtw_get_current_time(); 
+					
+					DBG_871X("issue_deauth to the ap=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->bssid));
+					
+					issue_deauth(adapter, pattrib->bssid, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+				}
+			}
+		}	
+	
+		ret = _FAIL;
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s fw_state:0x%x\n", __FUNCTION__, get_fwstate(pmlmepriv));
+		#endif
+	}
+
+exit:
+
+_func_exit_;
+
+	return ret;
+
+}
+
+sint sta2ap_data_frame(
+	_adapter *adapter,
+	union recv_frame *precv_frame,
+	struct sta_info**psta );
+sint sta2ap_data_frame(
+	_adapter *adapter,
+	union recv_frame *precv_frame,
+	struct sta_info**psta )
+{
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
+	struct	sta_priv 		*pstapriv = &adapter->stapriv;
+	struct	mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+	unsigned char *mybssid  = get_bssid(pmlmepriv);	
+	sint ret=_SUCCESS;
+
+_func_enter_;
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{
+		//For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR
+		if(!_rtw_memcmp(pattrib->bssid, mybssid, ETH_ALEN))
+		{
+			ret= _FAIL;
+			goto exit;
+		}
+
+		*psta = rtw_get_stainfo(pstapriv, pattrib->src);
+		if (*psta == NULL)
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under AP_MODE; drop pkt\n"));
+			DBG_871X("issue_deauth to sta=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
+
+			issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+
+			ret = RTW_RX_HANDLED;
+			goto exit;
+		}
+
+		process_pwrbit_data(adapter, precv_frame);
+
+		if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) == WIFI_QOS_DATA_TYPE) {
+			process_wmmps_data(adapter, precv_frame);
+		}
+
+		if (GetFrameSubType(ptr) & BIT(6)) {
+			/* No data, will not indicate to upper layer, temporily count it here */
+			count_rx_stats(adapter, precv_frame, *psta);
+			ret = RTW_RX_HANDLED;
+			goto exit;
+		}
+	}
+	else if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE) &&
+		     (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) )
+	{
+		//DBG_871X("%s ,in WIFI_MP_STATE \n",__func__);
+		_rtw_memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
+		_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+		_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+		//
+		if(adapter->mppriv.bRTWSmbCfg == _FALSE)
+			_rtw_memcpy(pattrib->bssid,  mybssid, ETH_ALEN);
+
+		*psta = rtw_get_stainfo(pstapriv, pattrib->bssid); // get sta_info
+		if (*psta == NULL) {
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("can't get psta under MP_MODE ; drop pkt\n"));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s can't get psta under WIFI_MP_STATE ; drop pkt\n", __FUNCTION__);
+			#endif
+			ret= _FAIL;
+			goto exit;
+		}
+
+	}
+	else {
+		u8 *myhwaddr = adapter_mac_addr(adapter);
+		if (!_rtw_memcmp(pattrib->ra, myhwaddr, ETH_ALEN)) {
+			ret = RTW_RX_HANDLED;
+			goto exit;
+		}
+		DBG_871X("issue_deauth to sta=" MAC_FMT " for the reason(7)\n", MAC_ARG(pattrib->src));
+		issue_deauth(adapter, pattrib->src, WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA);
+		ret = RTW_RX_HANDLED;
+		goto exit;
+	}
+
+exit:
+
+_func_exit_;
+
+	return ret;
+
+}
+
+sint validate_recv_ctrl_frame(_adapter *padapter, union recv_frame *precv_frame);
+sint validate_recv_ctrl_frame(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *pframe = precv_frame->u.hdr.rx_data;
+	struct sta_info *psta=NULL;
+	//uint len = precv_frame->u.hdr.len;
+		
+	//DBG_871X("+validate_recv_ctrl_frame\n");
+
+	if (GetFrameType(pframe) != WIFI_CTRL_TYPE)
+	{		
+		return _FAIL;
+	}
+
+	//receive the frames that ra(a1) is my address
+	if (!_rtw_memcmp(GetAddr1Ptr(pframe), adapter_mac_addr(padapter), ETH_ALEN))
+		return _FAIL;
+
+	psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(pframe));
+	if (psta==NULL)
+	{
+		return _FAIL;
+	}
+
+	//for rx pkt statistics
+	psta->sta_stats.rx_ctrl_pkts++;
+
+	//only handle ps-poll
+	if(GetFrameSubType(pframe) == WIFI_PSPOLL)
+	{
+#ifdef CONFIG_AP_MODE
+		u16 aid;
+		u8 wmmps_ac=0;	
+	
+		aid = GetAid(pframe);
+		if(psta->aid!=aid)
+		{
+			return _FAIL;
+		}
+
+		switch(pattrib->priority)
+		{
+			case 1:
+			case 2:
+				wmmps_ac = psta->uapsd_bk&BIT(0);
+				break;
+			case 4:
+			case 5:
+				wmmps_ac = psta->uapsd_vi&BIT(0);
+				break;
+			case 6:
+			case 7:
+				wmmps_ac = psta->uapsd_vo&BIT(0);
+				break;
+			case 0:
+			case 3:
+			default:
+				wmmps_ac = psta->uapsd_be&BIT(0);
+				break;	
+		}
+
+		if(wmmps_ac)
+			return _FAIL;
+
+		if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
+		{					
+			DBG_871X("%s alive check-rx ps-poll\n", __func__);
+			psta->expire_to = pstapriv->expire_to;
+			psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+		}	
+
+		if((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid)))
+		{
+			_irqL irqL;	 
+			_list	*xmitframe_plist, *xmitframe_phead;
+			struct xmit_frame *pxmitframe=NULL;
+			struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+		
+			//_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+			_enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+			xmitframe_phead = get_list_head(&psta->sleep_q);
+			xmitframe_plist = get_next(xmitframe_phead);
+
+			if ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+			{			
+				pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+				xmitframe_plist = get_next(xmitframe_plist);
+
+				rtw_list_delete(&pxmitframe->list);
+
+				psta->sleepq_len--;
+
+				if(psta->sleepq_len>0)
+					pxmitframe->attrib.mdata = 1;
+				else
+					pxmitframe->attrib.mdata = 0;
+
+				pxmitframe->attrib.triggered = 1;
+
+				//DBG_871X("handling ps-poll, q_len=%d, tim=%x\n", psta->sleepq_len, pstapriv->tim_bitmap);
+
+#if 0
+				_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+				if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
+				{
+					rtw_os_xmit_complete(padapter, pxmitframe);
+				}
+				_enter_critical_bh(&psta->sleep_q.lock, &irqL);	
+#endif
+				rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+
+				if(psta->sleepq_len==0)
+				{
+					pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+					//DBG_871X("after handling ps-poll, tim=%x\n", pstapriv->tim_bitmap);
+
+					//upate BCN for TIM IE
+					//update_BCNTIM(padapter);		
+					update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
+				}
+				
+				//_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+				_exit_critical_bh(&pxmitpriv->lock, &irqL);
+				
+			}
+			else
+			{
+				//_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+				_exit_critical_bh(&pxmitpriv->lock, &irqL);
+			
+				//DBG_871X("no buffered packets to xmit\n");
+				if(pstapriv->tim_bitmap&BIT(psta->aid))
+				{
+					if(psta->sleepq_len==0)
+					{
+						DBG_871X("no buffered packets to xmit\n");
+
+						//issue nulldata with More data bit = 0 to indicate we have no buffered packets
+						issue_nulldata_in_interrupt(padapter, psta->hwaddr, 0);
+					}
+					else
+					{
+						DBG_871X("error!psta->sleepq_len=%d\n", psta->sleepq_len);
+						psta->sleepq_len=0;						
+					}
+				
+					pstapriv->tim_bitmap &= ~BIT(psta->aid);					
+
+					//upate BCN for TIM IE
+					//update_BCNTIM(padapter);
+					update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
+				}
+			}				
+		}
+#endif //CONFIG_AP_MODE
+	}
+	else if(GetFrameSubType(pframe) == WIFI_NDPA) {
+#ifdef CONFIG_BEAMFORMING
+		beamforming_get_ndpa_frame(padapter, precv_frame);
+#endif/*CONFIG_BEAMFORMING*/
+	}
+
+	return _FAIL;
+
+}
+
+union recv_frame* recvframe_chk_defrag(PADAPTER padapter, union recv_frame *precv_frame);
+sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame);
+sint validate_recv_mgnt_frame(PADAPTER padapter, union recv_frame *precv_frame)
+{
+	//struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+
+	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("+validate_recv_mgnt_frame\n"));
+
+#if 0
+	if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+	{
+#ifdef CONFIG_NATIVEAP_MLME
+		mgt_dispatcher(padapter, precv_frame);
+#else
+		rtw_hostapd_mlme_rx(padapter, precv_frame);
+#endif
+	}
+	else
+	{
+		mgt_dispatcher(padapter, precv_frame);
+	}
+#endif
+
+	precv_frame = recvframe_chk_defrag(padapter, precv_frame);
+	if (precv_frame == NULL) {
+		RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,("%s: fragment packet\n",__FUNCTION__));
+		return _SUCCESS;
+	}
+
+	{
+		//for rx pkt statistics
+		struct sta_info *psta = rtw_get_stainfo(&padapter->stapriv, GetAddr2Ptr(precv_frame->u.hdr.rx_data));
+		if (psta) {
+			psta->sta_stats.rx_mgnt_pkts++;
+			if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_BEACON)
+				psta->sta_stats.rx_beacon_pkts++;
+			else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBEREQ)
+				psta->sta_stats.rx_probereq_pkts++;
+			else if (GetFrameSubType(precv_frame->u.hdr.rx_data) == WIFI_PROBERSP) {
+				if (_rtw_memcmp(adapter_mac_addr(padapter), GetAddr1Ptr(precv_frame->u.hdr.rx_data), ETH_ALEN) == _TRUE)
+					psta->sta_stats.rx_probersp_pkts++;
+				else if (is_broadcast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data))
+					|| is_multicast_mac_addr(GetAddr1Ptr(precv_frame->u.hdr.rx_data)))
+					psta->sta_stats.rx_probersp_bm_pkts++;
+				else 
+					psta->sta_stats.rx_probersp_uo_pkts++;
+			}
+		}
+	}
+
+#ifdef CONFIG_INTEL_PROXIM
+	if(padapter->proximity.proxim_on==_TRUE)
+	{
+		struct rx_pkt_attrib * pattrib=&precv_frame->u.hdr.attrib;
+		 struct recv_stat* prxstat=( struct recv_stat * )  precv_frame->u.hdr.rx_head ;
+		 u8 * pda,*psa,*pbssid,*ptr;
+		 ptr=precv_frame->u.hdr.rx_data; 
+		pda = get_da(ptr);
+		psa = get_sa(ptr);
+		pbssid = get_hdr_bssid(ptr);
+
+
+		_rtw_memcpy(pattrib->dst, pda, ETH_ALEN);
+		_rtw_memcpy(pattrib->src, psa, ETH_ALEN);
+
+		_rtw_memcpy(pattrib->bssid, pbssid, ETH_ALEN);
+
+	switch(pattrib->to_fr_ds)
+	{
+		case 0:
+			_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);
+			break;
+
+		case 1:
+			_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, pbssid, ETH_ALEN);
+			break;
+
+		case 2:
+			_rtw_memcpy(pattrib->ra, pbssid, ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);
+			break;
+
+		case 3:
+			_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" case 3\n"));
+			break;
+
+		default:
+			break;
+
+		}	
+			pattrib->priority=0;
+			pattrib->hdrlen = pattrib->to_fr_ds==3 ? 30 : 24;
+
+		 padapter->proximity.proxim_rx(padapter,precv_frame);
+	}
+#endif
+	mgt_dispatcher(padapter, precv_frame);
+
+	return _SUCCESS;
+
+}
+
+sint validate_recv_data_frame(_adapter *adapter, union recv_frame *precv_frame);
+sint validate_recv_data_frame(_adapter *adapter, union recv_frame *precv_frame)
+{
+	u8 bretry;
+	u8 *psa, *pda, *pbssid;
+	struct sta_info *psta = NULL;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib	*pattrib = & precv_frame->u.hdr.attrib;
+	struct sta_priv 	*pstapriv = &adapter->stapriv;
+	struct security_priv	*psecuritypriv = &adapter->securitypriv;	
+	sint ret = _SUCCESS;
+
+_func_enter_;
+
+	bretry = GetRetry(ptr);
+	pda = get_da(ptr);
+	psa = get_sa(ptr);
+	pbssid = get_hdr_bssid(ptr);
+
+	if(pbssid == NULL){
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s pbssid == NULL\n", __func__);
+		#endif
+		ret= _FAIL;
+		goto exit;
+	}
+
+	_rtw_memcpy(pattrib->dst, pda, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, psa, ETH_ALEN);
+
+	_rtw_memcpy(pattrib->bssid, pbssid, ETH_ALEN);
+
+	switch(pattrib->to_fr_ds)
+	{
+		case 0:
+			_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);
+			ret = sta2sta_data_frame(adapter, precv_frame, &psta);
+			break;
+
+		case 1:
+			_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, pbssid, ETH_ALEN);
+			ret = ap2sta_data_frame(adapter, precv_frame, &psta);
+			break;
+
+		case 2:
+			_rtw_memcpy(pattrib->ra, pbssid, ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);
+			ret = sta2ap_data_frame(adapter, precv_frame, &psta);
+			break;
+
+		case 3:
+			_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
+			ret =_FAIL;
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" case 3\n"));
+			break;
+
+		default:
+			ret =_FAIL;
+			break;
+
+	}
+
+	if(ret ==_FAIL){
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s case:%d, res:%d\n", __FUNCTION__, pattrib->to_fr_ds, ret);
+		#endif
+		goto exit;
+	} else if (ret == RTW_RX_HANDLED) {
+		goto exit;
+	}
+
+
+	if(psta==NULL){
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" after to_fr_ds_chk; psta==NULL \n"));
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s psta == NULL\n", __func__);
+		#endif
+		ret= _FAIL;
+		goto exit;
+	}
+	
+	//psta->rssi = prxcmd->rssi;
+	//psta->signal_quality= prxcmd->sq;
+	precv_frame->u.hdr.psta = psta;
+		
+
+	pattrib->amsdu=0;
+	pattrib->ack_policy = 0;
+	//parsing QC field
+	if(pattrib->qos == 1)
+	{
+		pattrib->priority = GetPriority((ptr + 24));
+		pattrib->ack_policy = GetAckpolicy((ptr + 24));
+		pattrib->amsdu = GetAMsdu((ptr + 24));
+		pattrib->hdrlen = pattrib->to_fr_ds==3 ? 32 : 26;
+
+		if(pattrib->priority!=0 && pattrib->priority!=3)
+			adapter->recvpriv.bIsAnyNonBEPkts = _TRUE;
+		else
+			adapter->recvpriv.bIsAnyNonBEPkts = _FALSE;
+	}
+	else
+	{
+		pattrib->priority=0;
+		pattrib->hdrlen = pattrib->to_fr_ds==3 ? 30 : 24;
+	}
+
+
+	if(pattrib->order)//HT-CTRL 11n
+	{
+		pattrib->hdrlen += 4;
+	}
+
+	precv_frame->u.hdr.preorder_ctrl = &psta->recvreorder_ctrl[pattrib->priority];
+
+	// decache, drop duplicate recv packets
+	if(recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) == _FAIL)
+	{
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("decache : drop pkt\n"));
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s recv_decache return _FAIL\n", __func__);
+		#endif
+		ret= _FAIL;
+		goto exit;
+	}
+
+	if(pattrib->privacy){
+
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("validate_recv_data_frame:pattrib->privacy=%x\n", pattrib->privacy));
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n ^^^^^^^^^^^IS_MCAST(pattrib->ra(0x%02x))=%d^^^^^^^^^^^^^^^6\n", pattrib->ra[0],IS_MCAST(pattrib->ra)));
+
+#ifdef CONFIG_TDLS
+		if((psta->tdls_sta_state & TDLS_LINKED_STATE) && (psta->dot118021XPrivacy==_AES_))
+		{
+			pattrib->encrypt=psta->dot118021XPrivacy;
+		}
+		else
+#endif //CONFIG_TDLS
+		GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, IS_MCAST(pattrib->ra));
+
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n pattrib->encrypt=%d\n",pattrib->encrypt));
+
+		SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
+	}
+	else
+	{
+		pattrib->encrypt = 0;
+		pattrib->iv_len = pattrib->icv_len = 0;
+	}
+
+exit:
+
+_func_exit_;
+
+	return ret;
+}
+
+#ifdef CONFIG_IEEE80211W
+static sint validate_80211w_mgmt(_adapter *adapter, union recv_frame *precv_frame)
+{
+	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
+	struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct sta_info	*psta;
+	struct sta_priv		*pstapriv = &adapter->stapriv;
+	u8 type;
+	u8 subtype;
+			
+	type =  GetFrameType(ptr);
+	subtype = GetFrameSubType(ptr); //bit(7)~bit(2)
+			
+	if (adapter->securitypriv.binstallBIPkey == _TRUE)
+	{
+		//unicast management frame decrypt
+		if(pattrib->privacy && !(IS_MCAST(GetAddr1Ptr(ptr))) && 
+			(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC || subtype == WIFI_ACTION))
+		{
+			u8 *ppp, *mgmt_DATA;
+			u32 data_len=0;
+			ppp = GetAddr2Ptr(ptr);
+			
+			pattrib->bdecrypted = 0;
+			pattrib->encrypt = _AES_;
+			pattrib->hdrlen = sizeof(struct rtw_ieee80211_hdr_3addr);
+			//set iv and icv length
+			SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len, pattrib->encrypt);
+			_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
+			_rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
+			//actual management data frame body
+			data_len = pattrib->pkt_len - pattrib->hdrlen - pattrib->iv_len - pattrib->icv_len;
+			mgmt_DATA = rtw_zmalloc(data_len);
+			if(mgmt_DATA == NULL)
+			{
+				DBG_871X("%s mgmt allocate fail  !!!!!!!!!\n", __FUNCTION__);
+				goto validate_80211w_fail;
+			}
+			/* //dump the packet content before decrypt
+			{
+				int pp;
+				printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
+				for(pp=0;pp< pattrib->pkt_len; pp++)
+					printk(" %02x ", ptr[pp]);
+				printk("\n");
+			}*/
+			
+			precv_frame = decryptor(adapter, precv_frame);
+			//save actual management data frame body
+			_rtw_memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len);
+			//overwrite the iv field
+			_rtw_memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len);
+			//remove the iv and icv length
+			pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;
+			rtw_mfree(mgmt_DATA, data_len);
+			/* //print packet content after decryption
+			{
+				int pp;
+				printk("after decryption pattrib->pktlen = %d @@=>", pattrib->pkt_len);
+				for(pp=0;pp< pattrib->pkt_len; pp++)
+					printk(" %02x ", ptr[pp]);
+				printk("\n");
+			}*/
+			if(!precv_frame)
+			{
+				DBG_871X("%s mgmt descrypt fail  !!!!!!!!!\n", __FUNCTION__);
+				goto validate_80211w_fail;
+			}
+		}
+		else if(IS_MCAST(GetAddr1Ptr(ptr)) &&
+			(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC))
+		{
+			sint BIP_ret = _SUCCESS;
+			//verify BIP MME IE of broadcast/multicast de-auth/disassoc packet
+			BIP_ret = rtw_BIP_verify(adapter, (u8 * )precv_frame);
+			if(BIP_ret == _FAIL)
+			{
+				//DBG_871X("802.11w BIP verify fail\n");
+				goto validate_80211w_fail;
+			}
+			else if(BIP_ret == RTW_RX_HANDLED)
+			{
+				DBG_871X("802.11w recv none protected packet\n");
+				//drop pkt, don't issue sa query request
+				/* issue_action_SA_Query(adapter, NULL, 0, 0, 0); */
+				goto validate_80211w_fail;
+			}
+		}//802.11w protect
+		else
+		{
+			psta = rtw_get_stainfo(pstapriv, GetAddr2Ptr(ptr));
+			
+			if (subtype == WIFI_ACTION && psta && psta->bpairwise_key_installed == _TRUE) {
+				//according 802.11-2012 standard, these five types are not robust types
+				if( ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_PUBLIC          &&
+					ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_HT              &&
+					ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_UNPROTECTED_WNM &&
+					ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_SELF_PROTECTED  &&
+					ptr[WLAN_HDR_A3_LEN] != RTW_WLAN_CATEGORY_P2P)
+				{
+					DBG_871X("action frame category=%d should robust\n", ptr[WLAN_HDR_A3_LEN]);
+					goto validate_80211w_fail;
+				}
+			}
+			else if(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)
+			{
+				unsigned short	reason;
+				reason = le16_to_cpu(*(unsigned short *)(ptr + WLAN_HDR_A3_LEN));
+				DBG_871X("802.11w recv none protected packet, reason=%d\n", reason);
+				if(reason == 6 || reason == 7)
+				{
+					//issue sa query request
+					issue_action_SA_Query(adapter, NULL, 0, 0, IEEE80211W_RIGHT_KEY);
+				}
+				goto validate_80211w_fail;
+			}
+		}
+	}
+	return _SUCCESS;
+			
+validate_80211w_fail:
+	return _FAIL;
+	
+}
+#endif //CONFIG_IEEE80211W
+
+static inline void dump_rx_packet(u8 *ptr)
+{
+	int i;
+
+	DBG_871X("############################# \n");
+	for(i=0; i<64;i=i+8)
+		DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
+		*(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
+	DBG_871X("############################# \n");
+}
+
+sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame);
+sint validate_recv_frame(_adapter *adapter, union recv_frame *precv_frame)
+{
+	//shall check frame subtype, to / from ds, da, bssid
+
+	//then call check if rx seq/frag. duplicated.
+
+	u8 type;
+	u8 subtype;
+	sint retval = _SUCCESS;
+
+	struct rx_pkt_attrib *pattrib = & precv_frame->u.hdr.attrib;
+
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	u8  ver =(unsigned char) (*ptr)&0x3 ;
+#ifdef CONFIG_FIND_BEST_CHANNEL
+	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
+#endif
+
+#ifdef CONFIG_TDLS
+	struct tdls_info *ptdlsinfo = &adapter->tdlsinfo;
+#endif //CONFIG_TDLS
+#ifdef CONFIG_WAPI_SUPPORT
+	PRT_WAPI_T	pWapiInfo = &adapter->wapiInfo;
+	struct recv_frame_hdr *phdr = &precv_frame->u.hdr;
+	u8 wai_pkt = 0;
+	u16 sc;
+	u8	external_len = 0;
+#endif
+
+_func_enter_;
+
+#ifdef CONFIG_FIND_BEST_CHANNEL
+	if (pmlmeext->sitesurvey_res.state == SCAN_PROCESS) {
+		int ch_set_idx = rtw_ch_set_search_ch(pmlmeext->channel_set, rtw_get_oper_ch(adapter));
+		if (ch_set_idx >= 0)
+			pmlmeext->channel_set[ch_set_idx].rx_count++;
+	}
+#endif
+
+#ifdef CONFIG_TDLS
+	if(ptdlsinfo->ch_sensing==1 && ptdlsinfo->cur_channel !=0){
+		ptdlsinfo->collect_pkt_num[ptdlsinfo->cur_channel-1]++;
+	}
+#endif //CONFIG_TDLS
+
+#ifdef RTK_DMP_PLATFORM
+	if ( 0 )
+	{
+		DBG_871X("++\n");
+		{
+			int i;
+			for(i=0; i<64;i=i+8)
+				DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:", *(ptr+i),
+				*(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
+
+		}
+		DBG_871X("--\n");
+	}
+#endif //RTK_DMP_PLATFORM
+
+	//add version chk
+	if(ver!=0){
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail! (ver!=0)\n"));
+		retval= _FAIL;
+		DBG_COUNTER(adapter->rx_logs.core_rx_pre_ver_err);
+		goto exit;
+	}
+
+	type =  GetFrameType(ptr);
+	subtype = GetFrameSubType(ptr); //bit(7)~bit(2)
+
+	pattrib->to_fr_ds = get_tofr_ds(ptr);
+
+	pattrib->frag_num = GetFragNum(ptr);
+	pattrib->seq_num = GetSequence(ptr);
+
+	pattrib->pw_save = GetPwrMgt(ptr);
+	pattrib->mfrag = GetMFrag(ptr);
+	pattrib->mdata = GetMData(ptr);
+	pattrib->privacy = GetPrivacy(ptr);
+	pattrib->order = GetOrder(ptr);
+#ifdef CONFIG_WAPI_SUPPORT
+	sc = (pattrib->seq_num<<4) | pattrib->frag_num;
+#endif
+
+#if 1 //Dump rx packets
+{
+	u8 bDumpRxPkt;
+	rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
+	if (bDumpRxPkt == 1) //dump all rx packets
+		dump_rx_packet(ptr);
+	else if ((bDumpRxPkt == 2) && (type == WIFI_MGT_TYPE))
+		dump_rx_packet(ptr);
+	else if ((bDumpRxPkt == 3) && (type == WIFI_DATA_TYPE))
+		dump_rx_packet(ptr);
+}
+#endif
+	switch (type)
+	{
+		case WIFI_MGT_TYPE: //mgnt
+			DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt);
+#ifdef CONFIG_IEEE80211W
+			if(validate_80211w_mgmt(adapter, precv_frame) == _FAIL)
+			{
+				retval = _FAIL;
+				DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt_err_80211w);
+				break;
+			}
+#endif //CONFIG_IEEE80211W
+			
+			retval = validate_recv_mgnt_frame(adapter, precv_frame);
+			if (retval == _FAIL)
+			{
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_mgnt_frame fail\n"));
+				DBG_COUNTER(adapter->rx_logs.core_rx_pre_mgmt_err);
+			}
+			retval = _FAIL; // only data frame return _SUCCESS
+			break;
+		case WIFI_CTRL_TYPE: //ctrl
+			DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl);
+			retval = validate_recv_ctrl_frame(adapter, precv_frame);
+			if (retval == _FAIL)
+			{
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_ctrl_frame fail\n"));
+				DBG_COUNTER(adapter->rx_logs.core_rx_pre_ctrl_err);
+			}
+			retval = _FAIL; // only data frame return _SUCCESS
+			break;
+		case WIFI_DATA_TYPE: //data
+			DBG_COUNTER(adapter->rx_logs.core_rx_pre_data);
+#ifdef CONFIG_WAPI_SUPPORT
+			if(pattrib->qos)
+				external_len = 2;
+			else
+				external_len= 0;
+			
+			wai_pkt = rtw_wapi_is_wai_packet(adapter,ptr);
+
+			phdr->bIsWaiPacket = wai_pkt;
+
+			if(wai_pkt !=0){
+				if(sc != adapter->wapiInfo.wapiSeqnumAndFragNum)
+				{
+					adapter->wapiInfo.wapiSeqnumAndFragNum = sc;
+				}
+				else
+				{
+					retval = _FAIL;
+					DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_wapi_seq_err);
+					break;
+				}
+			}
+			else{
+
+					if(rtw_wapi_drop_for_key_absent(adapter,GetAddr2Ptr(ptr))){
+						retval=_FAIL;
+						WAPI_TRACE(WAPI_RX,"drop for key absent for rx \n");
+						DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_wapi_key_err);
+						break;
+					}
+			}
+
+#endif
+
+			pattrib->qos = (subtype & BIT(7))? 1:0;
+			retval = validate_recv_data_frame(adapter, precv_frame);
+			if (retval == _FAIL)
+			{
+				struct recv_priv *precvpriv = &adapter->recvpriv;
+				//RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail\n"));
+				precvpriv->rx_drop++;
+				DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_err);
+			}
+			else if (retval == _SUCCESS)
+			{
+#ifdef DBG_RX_DUMP_EAP
+				u8 bDumpRxPkt;
+				u16 eth_type;
+
+				// dump eapol
+				rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
+				// get ether_type
+				_rtw_memcpy(&eth_type, ptr + pattrib->hdrlen + pattrib->iv_len + LLC_HEADER_SIZE, 2);
+				eth_type = ntohs((unsigned short) eth_type);
+				if ((bDumpRxPkt == 4) && (eth_type == 0x888e))
+					dump_rx_packet(ptr);
+#endif
+			}
+			else
+			{
+				DBG_COUNTER(adapter->rx_logs.core_rx_pre_data_handled);
+			}
+			break;
+		default:
+			DBG_COUNTER(adapter->rx_logs.core_rx_pre_unknown);
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("validate_recv_data_frame fail! type=0x%x\n", type));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME validate_recv_data_frame fail! type=0x%x\n", type);
+			#endif
+			retval = _FAIL;
+			break;
+	}
+
+exit:
+
+_func_exit_;
+
+	return retval;
+}
+
+
+//remove the wlanhdr and add the eth_hdr
+#if 1
+
+sint wlanhdr_to_ethhdr ( union recv_frame *precvframe);
+sint wlanhdr_to_ethhdr ( union recv_frame *precvframe)
+{
+	sint	rmv_len;
+	u16	eth_type, len;
+	u8	bsnaphdr;
+	u8	*psnap_type;
+	struct ieee80211_snap_hdr	*psnap;
+	
+	sint ret=_SUCCESS;
+	_adapter			*adapter =precvframe->u.hdr.adapter;
+	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+
+	u8	*ptr = get_recvframe_data(precvframe) ; // point to frame_ctrl field
+	struct rx_pkt_attrib *pattrib = & precvframe->u.hdr.attrib;
+
+_func_enter_;
+
+	if(pattrib->encrypt){
+		recvframe_pull_tail(precvframe, pattrib->icv_len);	
+	}
+
+	psnap=(struct ieee80211_snap_hdr	*)(ptr+pattrib->hdrlen + pattrib->iv_len);
+	psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+	/* convert hdr + possible LLC headers into Ethernet header */
+	//eth_type = (psnap_type[0] << 8) | psnap_type[1];
+	if((_rtw_memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
+		(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == _FALSE) && 
+		(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)==_FALSE) )||
+		//eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
+		 _rtw_memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)){
+		/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
+		bsnaphdr = _TRUE;
+	}
+	else {
+		/* Leave Ethernet header part of hdr and full payload */
+		bsnaphdr = _FALSE;
+	}
+
+	rmv_len = pattrib->hdrlen + pattrib->iv_len +(bsnaphdr?SNAP_SIZE:0);
+	len = precvframe->u.hdr.len - rmv_len;
+
+	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n===pattrib->hdrlen: %x,  pattrib->iv_len:%x ===\n\n", pattrib->hdrlen,  pattrib->iv_len));
+
+	_rtw_memcpy(&eth_type, ptr+rmv_len, 2);
+	eth_type= ntohs((unsigned short )eth_type); //pattrib->ether_type
+	pattrib->eth_type = eth_type;
+
+#ifdef CONFIG_AUTO_AP_MODE
+	if (0x8899 == pattrib->eth_type)
+	{
+		struct sta_info *psta = precvframe->u.hdr.psta;
+		
+		DBG_871X("wlan rx: got eth_type=0x%x\n", pattrib->eth_type);					
+		
+		if (psta && psta->isrc && psta->pid>0)
+		{
+			u16 rx_pid;
+
+			rx_pid = *(u16*)(ptr+rmv_len+2);
+			
+			DBG_871X("wlan rx(pid=0x%x): sta("MAC_FMT") pid=0x%x\n", 
+				rx_pid, MAC_ARG(psta->hwaddr), psta->pid);
+
+			if(rx_pid == psta->pid)
+			{
+				int i;
+				u16 len = *(u16*)(ptr+rmv_len+4);
+				//u16 ctrl_type = *(u16*)(ptr+rmv_len+6);
+
+				//DBG_871X("RC: len=0x%x, ctrl_type=0x%x\n", len, ctrl_type); 
+				DBG_871X("RC: len=0x%x\n", len); 
+
+				for(i=0;i<len;i++)
+					DBG_871X("0x%x\n", *(ptr+rmv_len+6+i));
+					//DBG_871X("0x%x\n", *(ptr+rmv_len+8+i));
+
+				DBG_871X("RC-end\n"); 
+			}			
+		}		
+	}
+#endif //CONFIG_AUTO_AP_MODE
+
+	if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE))	   	
+	{
+		ptr += rmv_len ;	
+		*ptr = 0x87;
+		*(ptr+1) = 0x12;
+
+		eth_type = 0x8712;
+		// append rx status for mp test packets
+		ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24);
+		if (!ptr) {
+			ret = _FAIL;
+			goto exiting;
+		}
+		_rtw_memcpy(ptr, get_rxmem(precvframe), 24);
+		ptr+=24;
+	}
+	else {
+		ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+ (bsnaphdr?2:0)));
+		if (!ptr) {
+			ret = _FAIL;
+			goto exiting;
+		}
+	}
+
+	if (ptr) {
+		_rtw_memcpy(ptr, pattrib->dst, ETH_ALEN);
+		_rtw_memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
+
+		if(!bsnaphdr) {
+			len = htons(len);
+			_rtw_memcpy(ptr+12, &len, 2);
+		}
+	}
+
+exiting:
+_func_exit_;	
+	return ret;
+
+}
+
+#else
+
+sint wlanhdr_to_ethhdr ( union recv_frame *precvframe)
+{
+	sint rmv_len;
+	u16 eth_type;
+	u8	bsnaphdr;
+	u8	*psnap_type;
+	struct ieee80211_snap_hdr	*psnap;
+
+	sint ret=_SUCCESS;
+	_adapter	*adapter =precvframe->u.hdr.adapter;
+	struct	mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+
+	u8* ptr = get_recvframe_data(precvframe) ; // point to frame_ctrl field
+	struct rx_pkt_attrib *pattrib = & precvframe->u.hdr.attrib;
+	struct _vlan *pvlan = NULL;
+
+_func_enter_;
+
+	psnap=(struct ieee80211_snap_hdr	*)(ptr+pattrib->hdrlen + pattrib->iv_len);
+	psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+	if (psnap->dsap==0xaa && psnap->ssap==0xaa && psnap->ctrl==0x03)
+	{
+		if (_rtw_memcmp(psnap->oui, oui_rfc1042, WLAN_IEEE_OUI_LEN))
+			bsnaphdr=_TRUE;//wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_RFC1042;	
+		else if (_rtw_memcmp(psnap->oui, SNAP_HDR_APPLETALK_DDP, WLAN_IEEE_OUI_LEN) &&
+			_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_DDP, 2) )
+			bsnaphdr=_TRUE;	//wlan_pkt_format = WLAN_PKT_FORMAT_APPLETALK;
+		else if (_rtw_memcmp( psnap->oui, oui_8021h, WLAN_IEEE_OUI_LEN))
+			bsnaphdr=_TRUE;	//wlan_pkt_format = WLAN_PKT_FORMAT_SNAP_TUNNEL;
+		else {
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("drop pkt due to invalid frame format!\n"));
+			ret= _FAIL;
+			goto exit;
+		}
+
+	} else
+		bsnaphdr=_FALSE;//wlan_pkt_format = WLAN_PKT_FORMAT_OTHERS;
+
+	rmv_len = pattrib->hdrlen + pattrib->iv_len +(bsnaphdr?SNAP_SIZE:0);
+	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("===pattrib->hdrlen: %x,  pattrib->iv_len:%x ===\n", pattrib->hdrlen,  pattrib->iv_len));
+
+	if (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _TRUE)
+	{
+		ptr += rmv_len ;
+		*ptr = 0x87;
+		*(ptr+1) = 0x12;
+
+		//back to original pointer
+		ptr -= rmv_len;
+	}
+
+	ptr += rmv_len ;
+
+	_rtw_memcpy(&eth_type, ptr, 2);
+	eth_type= ntohs((unsigned short )eth_type); //pattrib->ether_type
+	ptr +=2;
+
+	if(pattrib->encrypt){
+		recvframe_pull_tail(precvframe, pattrib->icv_len);
+	}
+
+	if(eth_type == 0x8100) //vlan
+	{
+		pvlan = (struct _vlan *) ptr;
+
+		//eth_type = get_vlan_encap_proto(pvlan);
+		//eth_type = pvlan->h_vlan_encapsulated_proto;//?
+		rmv_len += 4;
+		ptr+=4;
+	}
+
+	if(eth_type==0x0800)//ip
+	{
+		//struct iphdr*  piphdr = (struct iphdr*) ptr;
+		//__u8 tos = (unsigned char)(pattrib->priority & 0xff);
+
+		//piphdr->tos = tos;
+
+		//if (piphdr->protocol == 0x06)
+		//{
+		//	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("@@@===recv tcp len:%d @@@===\n", precvframe->u.hdr.len));
+		//}
+	}
+	else if(eth_type==0x8712)// append rx status for mp test packets
+	{
+		//ptr -= 16;
+		//_rtw_memcpy(ptr, get_rxmem(precvframe), 16);
+	}
+	else
+	{
+#ifdef PLATFORM_OS_XP
+		NDIS_PACKET_8021Q_INFO VlanPriInfo;
+		UINT32 UserPriority = precvframe->u.hdr.attrib.priority;
+		UINT32 VlanID = (pvlan!=NULL ? get_vlan_id(pvlan) : 0 );
+
+		VlanPriInfo.Value =          // Get current value.
+				NDIS_PER_PACKET_INFO_FROM_PACKET(precvframe->u.hdr.pkt, Ieee8021QInfo);
+
+		VlanPriInfo.TagHeader.UserPriority = UserPriority;
+		VlanPriInfo.TagHeader.VlanId =  VlanID ;
+
+		VlanPriInfo.TagHeader.CanonicalFormatId = 0; // Should be zero.
+		VlanPriInfo.TagHeader.Reserved = 0; // Should be zero.
+		NDIS_PER_PACKET_INFO_FROM_PACKET(precvframe->u.hdr.pkt, Ieee8021QInfo) = VlanPriInfo.Value;
+#endif
+	}
+
+	if(eth_type==0x8712)// append rx status for mp test packets
+	{
+		ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24);
+		_rtw_memcpy(ptr, get_rxmem(precvframe), 24);
+		ptr+=24;
+	}
+	else
+		ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2));
+
+	_rtw_memcpy(ptr, pattrib->dst, ETH_ALEN);
+	_rtw_memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
+
+	eth_type = htons((unsigned short)eth_type) ;
+	_rtw_memcpy(ptr+12, &eth_type, 2);
+
+exit:
+
+_func_exit_;
+
+	return ret;
+}
+#endif
+
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+#ifdef PLATFORM_LINUX
+static void recvframe_expand_pkt(
+	PADAPTER padapter,
+	union recv_frame *prframe)
+{
+	struct recv_frame_hdr *pfhdr;
+	_pkt *ppkt;
+	u8 shift_sz;
+	u32 alloc_sz;
+	u8 *ptr;
+
+
+	pfhdr = &prframe->u.hdr;
+
+	//	6 is for IP header 8 bytes alignment in QoS packet case.
+	if (pfhdr->attrib.qos)
+		shift_sz = 6;
+	else
+		shift_sz = 0;
+
+	// for first fragment packet, need to allocate
+	// (1536 + RXDESC_SIZE + drvinfo_sz) to reassemble packet
+	//	8 is for skb->data 8 bytes alignment.
+//	alloc_sz = _RND(1536 + RXDESC_SIZE + pfhdr->attrib.drvinfosize + shift_sz + 8, 128);
+	alloc_sz = 1664; // round (1536 + 24 + 32 + shift_sz + 8) to 128 bytes alignment
+
+	//3 1. alloc new skb
+	// prepare extra space for 4 bytes alignment
+	ppkt = rtw_skb_alloc(alloc_sz);
+
+	if (!ppkt) return; // no way to expand
+
+	//3 2. Prepare new skb to replace & release old skb
+	// force ppkt->data at 8-byte alignment address
+	skb_reserve(ppkt, 8 - ((SIZE_PTR)ppkt->data & 7));
+	// force ip_hdr at 8-byte alignment address according to shift_sz
+	skb_reserve(ppkt, shift_sz);
+
+	// copy data to new pkt
+	ptr = skb_put(ppkt, pfhdr->len);
+	if (ptr)
+		_rtw_memcpy(ptr, pfhdr->rx_data, pfhdr->len);
+
+	rtw_skb_free(pfhdr->pkt);
+
+	// attach new pkt to recvframe
+	pfhdr->pkt = ppkt;
+	pfhdr->rx_head = ppkt->head;
+	pfhdr->rx_data = ppkt->data;
+	pfhdr->rx_tail = skb_tail_pointer(ppkt);
+	pfhdr->rx_end = skb_end_pointer(ppkt);
+}
+#else
+#warning "recvframe_expand_pkt not implement, defrag may crash system"
+#endif
+#endif
+
+//perform defrag
+union recv_frame * recvframe_defrag(_adapter *adapter,_queue *defrag_q);
+union recv_frame * recvframe_defrag(_adapter *adapter,_queue *defrag_q)
+{
+	_list	 *plist, *phead;
+	u8	*data,wlanhdr_offset;
+	u8	curfragnum;
+	struct recv_frame_hdr *pfhdr,*pnfhdr;
+	union recv_frame* prframe, *pnextrframe;
+	_queue	*pfree_recv_queue;
+
+_func_enter_;
+
+	curfragnum=0;
+	pfree_recv_queue=&adapter->recvpriv.free_recv_queue;
+
+	phead = get_list_head(defrag_q);
+	plist = get_next(phead);
+	prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+	pfhdr=&prframe->u.hdr;
+	rtw_list_delete(&(prframe->u.list));
+
+	if(curfragnum!=pfhdr->attrib.frag_num)
+	{
+		//the first fragment number must be 0
+		//free the whole queue
+		rtw_free_recvframe(prframe, pfree_recv_queue);
+		rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
+
+		return NULL;
+	}
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+#ifndef CONFIG_SDIO_RX_COPY
+	recvframe_expand_pkt(adapter, prframe);
+#endif
+#endif
+
+	curfragnum++;
+
+	plist= get_list_head(defrag_q);
+
+	plist = get_next(plist);
+
+	data=get_recvframe_data(prframe);
+
+	while(rtw_end_of_queue_search(phead, plist) == _FALSE)
+	{
+		pnextrframe = LIST_CONTAINOR(plist, union recv_frame , u);
+		pnfhdr=&pnextrframe->u.hdr;
+
+
+		//check the fragment sequence  (2nd ~n fragment frame)
+
+		if(curfragnum!=pnfhdr->attrib.frag_num)
+		{
+			//the fragment number must be increasing  (after decache)
+			//release the defrag_q & prframe
+			rtw_free_recvframe(prframe, pfree_recv_queue);
+			rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
+			return NULL;
+		}
+
+		curfragnum++;
+
+		//copy the 2nd~n fragment frame's payload to the first fragment
+		//get the 2nd~last fragment frame's payload
+
+		wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
+
+		recvframe_pull(pnextrframe, wlanhdr_offset);
+
+		//append  to first fragment frame's tail (if privacy frame, pull the ICV)
+		recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
+
+		//memcpy
+		_rtw_memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
+
+		recvframe_put(prframe, pnfhdr->len);
+
+		pfhdr->attrib.icv_len=pnfhdr->attrib.icv_len;
+		plist = get_next(plist);
+
+	};
+
+	//free the defrag_q queue and return the prframe
+	rtw_free_recvframe_queue(defrag_q, pfree_recv_queue);
+
+	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Performance defrag!!!!!\n"));
+
+_func_exit_;
+
+	return prframe;
+}
+
+//check if need to defrag, if needed queue the frame to defrag_q
+union recv_frame* recvframe_chk_defrag(PADAPTER padapter, union recv_frame *precv_frame)
+{
+	u8	ismfrag;
+	u8	fragnum;
+	u8	*psta_addr;
+	struct recv_frame_hdr *pfhdr;
+	struct sta_info *psta;
+	struct sta_priv *pstapriv;
+	_list *phead;
+	union recv_frame *prtnframe = NULL;
+	_queue *pfree_recv_queue, *pdefrag_q;
+
+_func_enter_;
+
+	pstapriv = &padapter->stapriv;
+
+	pfhdr = &precv_frame->u.hdr;
+
+	pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+	//need to define struct of wlan header frame ctrl
+	ismfrag = pfhdr->attrib.mfrag;
+	fragnum = pfhdr->attrib.frag_num;
+
+	psta_addr = pfhdr->attrib.ta;
+	psta = rtw_get_stainfo(pstapriv, psta_addr);
+	if (psta == NULL)
+	{
+		u8 type = GetFrameType(pfhdr->rx_data);
+		if (type != WIFI_DATA_TYPE) {
+			psta = rtw_get_bcmc_stainfo(padapter);
+			pdefrag_q = &psta->sta_recvpriv.defrag_q;
+		} else
+			pdefrag_q = NULL;
+	}
+	else
+		pdefrag_q = &psta->sta_recvpriv.defrag_q;
+
+	if ((ismfrag==0) && (fragnum==0))
+	{
+		prtnframe = precv_frame;//isn't a fragment frame
+	}
+
+	if (ismfrag==1)
+	{
+		//0~(n-1) fragment frame
+		//enqueue to defraf_g
+		if(pdefrag_q != NULL)
+		{
+			if(fragnum==0)
+			{
+				//the first fragment
+				if(_rtw_queue_empty(pdefrag_q) == _FALSE)
+				{
+					//free current defrag_q
+					rtw_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
+				}
+			}
+
+
+			//Then enqueue the 0~(n-1) fragment into the defrag_q
+
+			//_rtw_spinlock(&pdefrag_q->lock);
+			phead = get_list_head(pdefrag_q);
+			rtw_list_insert_tail(&pfhdr->list, phead);
+			//_rtw_spinunlock(&pdefrag_q->lock);
+
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Enqueuq: ismfrag = %d, fragnum= %d\n", ismfrag,fragnum));
+
+			prtnframe=NULL;
+
+		}
+		else
+		{
+			//can't find this ta's defrag_queue, so free this recv_frame
+			rtw_free_recvframe(precv_frame, pfree_recv_queue);
+			prtnframe=NULL;
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("Free because pdefrag_q ==NULL: ismfrag = %d, fragnum= %d\n", ismfrag, fragnum));
+		}
+
+	}
+
+	if((ismfrag==0)&&(fragnum!=0))
+	{
+		//the last fragment frame
+		//enqueue the last fragment
+		if(pdefrag_q != NULL)
+		{
+			//_rtw_spinlock(&pdefrag_q->lock);
+			phead = get_list_head(pdefrag_q);
+			rtw_list_insert_tail(&pfhdr->list,phead);
+			//_rtw_spinunlock(&pdefrag_q->lock);
+
+			//call recvframe_defrag to defrag
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("defrag: ismfrag = %d, fragnum= %d\n", ismfrag, fragnum));
+			precv_frame = recvframe_defrag(padapter, pdefrag_q);
+			prtnframe=precv_frame;
+
+		}
+		else
+		{
+			//can't find this ta's defrag_queue, so free this recv_frame
+			rtw_free_recvframe(precv_frame, pfree_recv_queue);
+			prtnframe=NULL;
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("Free because pdefrag_q ==NULL: ismfrag = %d, fragnum= %d\n", ismfrag,fragnum));
+		}
+
+	}
+
+
+	if((prtnframe!=NULL)&&(prtnframe->u.hdr.attrib.privacy))
+	{
+		//after defrag we must check tkip mic code
+		if(recvframe_chkmic(padapter,  prtnframe)==_FAIL)
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chkmic(padapter,  prtnframe)==_FAIL\n"));
+			rtw_free_recvframe(prtnframe,pfree_recv_queue);
+			prtnframe=NULL;
+		}
+	}
+
+_func_exit_;
+
+	return prtnframe;
+
+}
+
+int amsdu_to_msdu(_adapter *padapter, union recv_frame *prframe)
+{
+	int	a_len, padding_len;
+	u16	nSubframe_Length;	
+	u8	nr_subframes, i;
+	u8	*pdata;
+	_pkt *sub_pkt,*subframes[MAX_SUBFRAME_COUNT];
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	_queue *pfree_recv_queue = &(precvpriv->free_recv_queue);
+	int	ret = _SUCCESS;
+
+	nr_subframes = 0;
+
+	recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
+	
+	if(prframe->u.hdr.attrib.iv_len >0)
+	{
+		recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
+	}
+
+	a_len = prframe->u.hdr.len;
+
+	pdata = prframe->u.hdr.rx_data;
+
+	while(a_len > ETH_HLEN) {
+
+		/* Offset 12 denote 2 mac address */
+		nSubframe_Length = RTW_GET_BE16(pdata + 12);
+
+		if( a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length) ) {
+			DBG_871X("nRemain_Length is %d and nSubframe_Length is : %d\n",a_len,nSubframe_Length);
+			break;
+		}
+
+		sub_pkt = rtw_os_alloc_msdu_pkt(prframe, nSubframe_Length, pdata);
+		if (sub_pkt == NULL) {
+			DBG_871X("%s(): allocate sub packet fail !!!\n",__FUNCTION__);
+			break;
+		}
+
+		/* move the data point to data content */
+		pdata += ETH_HLEN;
+		a_len -= ETH_HLEN;
+
+		subframes[nr_subframes++] = sub_pkt;
+
+		if(nr_subframes >= MAX_SUBFRAME_COUNT) {
+			DBG_871X("ParseSubframe(): Too many Subframes! Packets dropped!\n");
+			break;
+		}
+
+		pdata += nSubframe_Length;
+		a_len -= nSubframe_Length;
+		if(a_len != 0) {
+			padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1));
+			if(padding_len == 4) {
+				padding_len = 0;
+			}
+
+			if(a_len < padding_len) {
+				DBG_871X("ParseSubframe(): a_len < padding_len !\n");
+				break;
+			}
+			pdata += padding_len;
+			a_len -= padding_len;
+		}
+	}
+
+	for(i=0; i<nr_subframes; i++){
+		sub_pkt = subframes[i];
+
+		/* Indicat the packets to upper layer */
+		if (sub_pkt) {
+			rtw_os_recv_indicate_pkt(padapter, sub_pkt, &prframe->u.hdr.attrib);
+		}
+	}
+
+	prframe->u.hdr.len = 0;
+	rtw_free_recvframe(prframe, pfree_recv_queue);//free this recv_frame
+	
+	return ret;
+}
+
+int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num);
+int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl, u16 seq_num)
+{
+	PADAPTER padapter = preorder_ctrl->padapter;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	u8	wsize = preorder_ctrl->wsize_b;
+	u16	wend = (preorder_ctrl->indicate_seq + wsize -1) & 0xFFF;//% 4096;
+
+	// Rx Reorder initialize condition.
+	if (preorder_ctrl->indicate_seq == 0xFFFF)
+	{
+		preorder_ctrl->indicate_seq = seq_num;
+		#ifdef DBG_RX_SEQ
+		DBG_871X("DBG_RX_SEQ %s:%d init IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+			preorder_ctrl->indicate_seq, seq_num);
+		#endif
+
+		//DbgPrint("check_indicate_seq, 1st->indicate_seq=%d\n", precvpriv->indicate_seq);
+	}
+
+	//DbgPrint("enter->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
+
+	// Drop out the packet which SeqNum is smaller than WinStart
+	if( SN_LESS(seq_num, preorder_ctrl->indicate_seq) )
+	{
+		//RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
+		//DbgPrint("CheckRxTsIndicateSeq(): Packet Drop! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
+
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("%s IndicateSeq: %d > NewSeq: %d\n", __FUNCTION__, 
+			preorder_ctrl->indicate_seq, seq_num);
+		#endif
+
+
+		return _FALSE;
+	}
+
+	//
+	// Sliding window manipulation. Conditions includes:
+	// 1. Incoming SeqNum is equal to WinStart =>Window shift 1
+	// 2. Incoming SeqNum is larger than the WinEnd => Window shift N
+	//
+	if( SN_EQUAL(seq_num, preorder_ctrl->indicate_seq) )
+	{
+		preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
+
+		#ifdef DBG_RX_SEQ
+		DBG_871X("DBG_RX_SEQ %s:%d SN_EQUAL IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+			preorder_ctrl->indicate_seq, seq_num);
+		#endif
+	}
+	else if(SN_LESS(wend, seq_num))
+	{
+		//RT_TRACE(COMP_RX_REORDER, DBG_LOUD, ("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, NewSeqNum));
+		//DbgPrint("CheckRxTsIndicateSeq(): Window Shift! IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
+
+		// boundary situation, when seq_num cross 0xFFF
+		if(seq_num >= (wsize - 1))
+			preorder_ctrl->indicate_seq = seq_num + 1 -wsize;
+		else
+			preorder_ctrl->indicate_seq = 0xFFF - (wsize - (seq_num + 1)) + 1;
+		pdbgpriv->dbg_rx_ampdu_window_shift_cnt++;
+		#ifdef DBG_RX_SEQ
+		DBG_871X("DBG_RX_SEQ %s:%d SN_LESS(wend, seq_num) IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+			preorder_ctrl->indicate_seq, seq_num);
+		#endif
+	}
+
+	//DbgPrint("exit->check_indicate_seq(): IndicateSeq: %d, NewSeq: %d\n", precvpriv->indicate_seq, seq_num);
+
+	return _TRUE;
+}
+
+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe);
+int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl, union recv_frame *prframe)
+{
+	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+	_queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+	_list	*phead, *plist;
+	union recv_frame *pnextrframe;
+	struct rx_pkt_attrib *pnextattrib;
+
+	//DbgPrint("+enqueue_reorder_recvframe()\n");
+
+	//_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
+	//_rtw_spinlock_ex(&ppending_recvframe_queue->lock);
+
+
+	phead = get_list_head(ppending_recvframe_queue);
+	plist = get_next(phead);
+
+	while(rtw_end_of_queue_search(phead, plist) == _FALSE)
+	{
+		pnextrframe = LIST_CONTAINOR(plist, union recv_frame, u);
+		pnextattrib = &pnextrframe->u.hdr.attrib;
+
+		if(SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
+		{
+			plist = get_next(plist);
+		}
+		else if( SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
+		{
+			//Duplicate entry is found!! Do not insert current entry.
+			//RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Duplicate packet is dropped!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum));
+
+			//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+
+			return _FALSE;
+		}
+		else
+		{
+			break;
+		}
+
+		//DbgPrint("enqueue_reorder_recvframe():while\n");
+
+	}
+
+
+	//_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
+	//_rtw_spinlock_ex(&ppending_recvframe_queue->lock);
+
+	rtw_list_delete(&(prframe->u.hdr.list));
+
+	rtw_list_insert_tail(&(prframe->u.hdr.list), plist);
+
+	//_rtw_spinunlock_ex(&ppending_recvframe_queue->lock);
+	//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+
+
+	//RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("InsertRxReorderList(): Pkt insert into buffer!! IndicateSeq: %d, NewSeq: %d\n", pTS->RxIndicateSeq, SeqNum));
+	return _TRUE;
+
+}
+
+void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq);
+void recv_indicatepkts_pkt_loss_cnt(struct debug_priv *pdbgpriv, u64 prev_seq, u64 current_seq)
+{
+	if(current_seq < prev_seq)
+	{
+		pdbgpriv->dbg_rx_ampdu_loss_count+= (4096 + current_seq - prev_seq);
+
+	}
+	else
+	{
+		pdbgpriv->dbg_rx_ampdu_loss_count+= (current_seq - prev_seq);
+	}
+}
+int recv_indicatepkts_in_order(_adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced);
+int recv_indicatepkts_in_order(_adapter *padapter, struct recv_reorder_ctrl *preorder_ctrl, int bforced)
+{
+	//_irqL irql;
+	//u8 bcancelled;
+	_list	*phead, *plist;
+	union recv_frame *prframe;
+	struct rx_pkt_attrib *pattrib;
+	//u8 index = 0;
+	int bPktInBuf = _FALSE;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	_queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+
+	DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_in_oder);
+
+	//DbgPrint("+recv_indicatepkts_in_order\n");
+
+	//_enter_critical_ex(&ppending_recvframe_queue->lock, &irql);
+	//_rtw_spinlock_ex(&ppending_recvframe_queue->lock);
+
+	phead = 	get_list_head(ppending_recvframe_queue);
+	plist = get_next(phead);
+
+#if 0
+	// Check if there is any other indication thread running.
+	if(pTS->RxIndicateState == RXTS_INDICATE_PROCESSING)
+		return;
+#endif
+
+	// Handling some condition for forced indicate case.
+	if(bforced==_TRUE)
+	{
+		pdbgpriv->dbg_rx_ampdu_forced_indicate_count++;
+		if(rtw_is_list_empty(phead))
+		{
+			// _exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+			//_rtw_spinunlock_ex(&ppending_recvframe_queue->lock);
+			return _TRUE;
+		}
+	
+		prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+		pattrib = &prframe->u.hdr.attrib;	
+
+		#ifdef DBG_RX_SEQ
+		DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+			preorder_ctrl->indicate_seq, pattrib->seq_num);
+		#endif
+		recv_indicatepkts_pkt_loss_cnt(pdbgpriv,preorder_ctrl->indicate_seq,pattrib->seq_num);
+		preorder_ctrl->indicate_seq = pattrib->seq_num;		
+		
+	}
+
+	// Prepare indication list and indication.
+	// Check if there is any packet need indicate.
+	while(!rtw_is_list_empty(phead))
+	{
+	
+		prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+		pattrib = &prframe->u.hdr.attrib;
+
+		if(!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num))
+		{
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
+				 ("recv_indicatepkts_in_order: indicate=%d seq=%d amsdu=%d\n",
+				  preorder_ctrl->indicate_seq, pattrib->seq_num, pattrib->amsdu));
+
+#if 0
+			// This protect buffer from overflow.
+			if(index >= REORDER_WIN_SIZE)
+			{
+				RT_ASSERT(FALSE, ("IndicateRxReorderList(): Buffer overflow!! \n"));
+				bPktInBuf = TRUE;
+				break;
+			}
+#endif
+
+			plist = get_next(plist);
+			rtw_list_delete(&(prframe->u.hdr.list));
+
+			if(SN_EQUAL(preorder_ctrl->indicate_seq, pattrib->seq_num))
+			{
+				preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) & 0xFFF;
+				#ifdef DBG_RX_SEQ
+				DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+					preorder_ctrl->indicate_seq, pattrib->seq_num);
+				#endif
+			}
+
+#if 0
+			index++;
+			if(index==1)
+			{
+				//Cancel previous pending timer.
+				//PlatformCancelTimer(Adapter, &pTS->RxPktPendingTimer);
+				if(bforced!=_TRUE)
+				{
+					//DBG_871X("_cancel_timer(&preorder_ctrl->reordering_ctrl_timer, &bcancelled);\n");
+					_cancel_timer(&preorder_ctrl->reordering_ctrl_timer, &bcancelled);
+				}
+			}
+#endif
+
+			//Set this as a lock to make sure that only one thread is indicating packet.
+			//pTS->RxIndicateState = RXTS_INDICATE_PROCESSING;
+
+			// Indicate packets
+			//RT_ASSERT((index<=REORDER_WIN_SIZE), ("RxReorderIndicatePacket(): Rx Reorder buffer full!! \n"));
+
+
+			//indicate this recv_frame
+			//DbgPrint("recv_indicatepkts_in_order, indicate_seq=%d, seq_num=%d\n", precvpriv->indicate_seq, pattrib->seq_num);
+			if(!pattrib->amsdu)
+			{
+				//DBG_871X("recv_indicatepkts_in_order, amsdu!=1, indicate_seq=%d, seq_num=%d\n", preorder_ctrl->indicate_seq, pattrib->seq_num);
+
+				if (!RTW_CANNOT_RUN(padapter))
+					rtw_recv_indicatepkt(padapter, prframe);/*indicate this recv_frame*/
+
+			}
+			else if(pattrib->amsdu==1)
+			{
+				if(amsdu_to_msdu(padapter, prframe)!=_SUCCESS)
+				{
+					rtw_free_recvframe(prframe, &precvpriv->free_recv_queue);
+				}
+			}
+			else
+			{
+				//error condition;
+			}
+
+
+			//Update local variables.
+			bPktInBuf = _FALSE;
+
+		}
+		else
+		{
+			bPktInBuf = _TRUE;
+			break;
+		}
+
+		//DbgPrint("recv_indicatepkts_in_order():while\n");
+
+	}
+
+	//_rtw_spinunlock_ex(&ppending_recvframe_queue->lock);
+	//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+
+/*
+	//Release the indication lock and set to new indication step.
+	if(bPktInBuf)
+	{
+		// Set new pending timer.
+		//pTS->RxIndicateState = RXTS_INDICATE_REORDER;
+		//PlatformSetTimer(Adapter, &pTS->RxPktPendingTimer, pHTInfo->RxReorderPendingTime);
+		//DBG_871X("_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME)\n");
+		_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
+	}
+	else
+	{
+		//pTS->RxIndicateState = RXTS_INDICATE_IDLE;
+	}
+*/
+	//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+
+	//return _TRUE;
+	return bPktInBuf;
+
+}
+
+int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe);
+int recv_indicatepkt_reorder(_adapter *padapter, union recv_frame *prframe)
+{
+	_irqL irql;
+	int retval = _SUCCESS;
+	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+	struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
+	_queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+
+	DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_reoder);
+
+	if(!pattrib->amsdu)
+	{
+		//s1.
+                retval = wlanhdr_to_ethhdr(prframe);
+                if (retval != _SUCCESS)
+                {
+                        RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("wlanhdr_to_ethhdr: drop pkt \n"));
+                        #ifdef DBG_RX_DROP_FRAME
+                        DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr error!\n", __FUNCTION__);
+                        #endif
+                        return retval;
+                }
+
+		//if ((pattrib->qos!=1) /*|| pattrib->priority!=0 || IS_MCAST(pattrib->ra)*/
+		//	|| (pattrib->eth_type==0x0806) || (pattrib->ack_policy!=0))
+		if (pattrib->qos!=1)
+		{
+			if (!RTW_CANNOT_RUN(padapter)) {
+				RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@  recv_indicatepkt_reorder -recv_func recv_indicatepkt\n" ));
+
+				rtw_recv_indicatepkt(padapter, prframe);
+				return _SUCCESS;
+
+			}
+			
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s pattrib->qos !=1\n", __FUNCTION__);
+			#endif
+			
+			return _FAIL;
+		
+		}
+
+		if (preorder_ctrl->enable == _FALSE)
+		{
+			//indicate this recv_frame			
+			preorder_ctrl->indicate_seq = pattrib->seq_num;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq, pattrib->seq_num);
+			#endif
+			
+			rtw_recv_indicatepkt(padapter, prframe);		
+			
+			preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq, pattrib->seq_num);
+			#endif
+			
+			return _SUCCESS;	
+		}			
+
+#ifndef CONFIG_RECV_REORDERING_CTRL
+		//indicate this recv_frame
+		rtw_recv_indicatepkt(padapter, prframe);
+		return _SUCCESS;
+#endif
+
+	}
+	else if(pattrib->amsdu==1) //temp filter -> means didn't support A-MSDUs in a A-MPDU
+	{
+		if (preorder_ctrl->enable == _FALSE)
+		{
+			preorder_ctrl->indicate_seq = pattrib->seq_num;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq, pattrib->seq_num);
+			#endif
+
+			retval = amsdu_to_msdu(padapter, prframe);
+
+			preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, NewSeq: %d\n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq, pattrib->seq_num);
+			#endif
+
+			if(retval != _SUCCESS){
+				#ifdef DBG_RX_DROP_FRAME
+				DBG_871X("DBG_RX_DROP_FRAME %s amsdu_to_msdu fail\n", __FUNCTION__);
+				#endif
+			}
+
+			return retval;
+		}
+	}
+	else
+	{
+
+	}
+
+	_enter_critical_bh(&ppending_recvframe_queue->lock, &irql);
+
+	RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_,
+		 ("recv_indicatepkt_reorder: indicate=%d seq=%d\n",
+		  preorder_ctrl->indicate_seq, pattrib->seq_num));
+
+	//s2. check if winstart_b(indicate_seq) needs to been updated
+	if(!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
+	{
+		pdbgpriv->dbg_rx_ampdu_drop_count++;
+		//pHTInfo->RxReorderDropCounter++;
+		//ReturnRFDList(Adapter, pRfd);
+		//RT_TRACE(COMP_RX_REORDER, DBG_TRACE, ("RxReorderIndicatePacket() ==> Packet Drop!!\n"));
+		//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+		//return _FAIL;
+
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s check_indicate_seq fail\n", __FUNCTION__);
+		#endif
+#if 0		
+		rtw_recv_indicatepkt(padapter, prframe);
+
+		_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
+		
+		goto _success_exit;
+#else
+		goto _err_exit;
+#endif
+	}
+
+
+	//s3. Insert all packet into Reorder Queue to maintain its ordering.
+	if(!enqueue_reorder_recvframe(preorder_ctrl, prframe))
+	{
+		//DbgPrint("recv_indicatepkt_reorder, enqueue_reorder_recvframe fail!\n");
+		//_exit_critical_ex(&ppending_recvframe_queue->lock, &irql);
+		//return _FAIL;
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s enqueue_reorder_recvframe fail\n", __FUNCTION__);
+		#endif
+		goto _err_exit;
+	}
+
+
+	//s4.
+	// Indication process.
+	// After Packet dropping and Sliding Window shifting as above, we can now just indicate the packets
+	// with the SeqNum smaller than latest WinStart and buffer other packets.
+	//
+	// For Rx Reorder condition:
+	// 1. All packets with SeqNum smaller than WinStart => Indicate
+	// 2. All packets with SeqNum larger than or equal to WinStart => Buffer it.
+	//
+
+	//recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE);
+	if(recv_indicatepkts_in_order(padapter, preorder_ctrl, _FALSE)==_TRUE)
+	{
+		_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);
+		_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
+	}
+	else
+	{
+		_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
+		_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);
+	}
+
+
+_success_exit:
+
+	return _SUCCESS;
+
+_err_exit:
+
+        _exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
+
+	return _FAIL;
+}
+
+
+void rtw_reordering_ctrl_timeout_handler(struct timer_list *t)
+{
+	_irqL irql;
+	struct recv_reorder_ctrl *preorder_ctrl =
+		from_timer(preorder_ctrl, t, reordering_ctrl_timer);
+	_adapter *padapter = preorder_ctrl->padapter;
+	_queue *ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+
+	if (RTW_CANNOT_RUN(padapter))
+		return;
+
+	//DBG_871X("+rtw_reordering_ctrl_timeout_handler()=>\n");
+
+	_enter_critical_bh(&ppending_recvframe_queue->lock, &irql);
+
+	if(recv_indicatepkts_in_order(padapter, preorder_ctrl, _TRUE)==_TRUE)
+	{
+		_set_timer(&preorder_ctrl->reordering_ctrl_timer, REORDER_WAIT_TIME);		
+	}
+
+	_exit_critical_bh(&ppending_recvframe_queue->lock, &irql);
+
+}
+
+int process_recv_indicatepkts(_adapter *padapter, union recv_frame *prframe);
+int process_recv_indicatepkts(_adapter *padapter, union recv_frame *prframe)
+{
+	int retval = _SUCCESS;
+	//struct recv_priv *precvpriv = &padapter->recvpriv;
+	//struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+#ifdef CONFIG_TDLS
+	struct sta_info *psta = prframe->u.hdr.psta;
+#endif //CONFIG_TDLS
+
+#ifdef CONFIG_80211N_HT
+
+	struct ht_priv	*phtpriv = &pmlmepriv->htpriv;
+	
+	DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate);
+
+#ifdef CONFIG_TDLS
+	if( (phtpriv->ht_option==_TRUE) ||
+		((psta->tdls_sta_state & TDLS_LINKED_STATE) && 
+		 (psta->htpriv.ht_option==_TRUE) &&
+		 (psta->htpriv.ampdu_enable==_TRUE))) //B/G/N Mode
+#else
+	if(phtpriv->ht_option==_TRUE)  //B/G/N Mode
+#endif //CONFIG_TDLS
+	{
+		//prframe->u.hdr.preorder_ctrl = &precvpriv->recvreorder_ctrl[pattrib->priority];
+
+		if(recv_indicatepkt_reorder(padapter, prframe)!=_SUCCESS)// including perform A-MPDU Rx Ordering Buffer Control
+		{
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s recv_indicatepkt_reorder error!\n", __FUNCTION__);
+			#endif
+		
+			if (!RTW_CANNOT_RUN(padapter))	{
+				retval = _FAIL;
+				return retval;
+			}
+		}
+	}
+	else //B/G mode
+#endif
+	{
+		retval=wlanhdr_to_ethhdr (prframe);
+		if(retval != _SUCCESS)
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("wlanhdr_to_ethhdr: drop pkt \n"));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr error!\n", __FUNCTION__);
+			#endif
+			return retval;
+		}
+
+		if (!RTW_CANNOT_RUN(padapter)) {
+			//indicate this recv_frame
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func recv_indicatepkt\n" ));
+			rtw_recv_indicatepkt(padapter, prframe);
+		}
+		else
+		{
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("@@@@ process_recv_indicatepkts- recv_func free_indicatepkt\n" ));
+
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_notice_, ("recv_func:bDriverStopped(%s) OR bSurpriseRemoved(%s)"
+				, rtw_is_drv_stopped(padapter)?"True":"False"
+				, rtw_is_surprise_removed(padapter)?"True":"False"));
+			retval = _FAIL;
+			return retval;
+		}
+
+	}
+
+	return retval;
+
+}
+
+#ifdef CONFIG_MP_INCLUDED
+int validate_mp_recv_frame(_adapter *adapter, union recv_frame *precv_frame)
+{
+	int ret = _SUCCESS;
+	u8 *ptr = precv_frame->u.hdr.rx_data;	
+	u8 type,subtype;
+
+	if(!adapter->mppriv.bmac_filter)	
+		return ret;
+#if 0	
+	if (1){
+		u8 bDumpRxPkt;
+		type =  GetFrameType(ptr);
+		subtype = GetFrameSubType(ptr); //bit(7)~bit(2)	
+		
+		rtw_hal_get_def_var(adapter, HAL_DEF_DBG_DUMP_RXPKT, &(bDumpRxPkt));
+		if(bDumpRxPkt ==1){//dump all rx packets
+			int i;
+			DBG_871X("############ type:0x%02x subtype:0x%02x ################# \n",type,subtype);
+			
+			for(i=0; i<64;i=i+8)
+				DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:\n", *(ptr+i),
+				*(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
+			DBG_871X("############################# \n");
+		}
+	}
+#endif		
+
+	if(_rtw_memcmp( GetAddr2Ptr(ptr), adapter->mppriv.mac_filter, ETH_ALEN) == _FALSE )
+		ret = _FAIL;
+
+	return ret;
+}
+#endif
+
+static sint MPwlanhdr_to_ethhdr ( union recv_frame *precvframe)
+{
+	sint	rmv_len;
+	u16 eth_type, len;
+	u8	bsnaphdr;
+	u8	*psnap_type;
+	u8 mcastheadermac[]={0x01,0x00,0x5e};
+	
+	struct ieee80211_snap_hdr	*psnap;
+	
+	sint ret=_SUCCESS;
+	_adapter			*adapter =precvframe->u.hdr.adapter;
+	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+
+	u8	*ptr = get_recvframe_data(precvframe) ; // point to frame_ctrl field
+	struct rx_pkt_attrib *pattrib = & precvframe->u.hdr.attrib;
+
+_func_enter_;
+
+	if(pattrib->encrypt){
+		recvframe_pull_tail(precvframe, pattrib->icv_len);	
+	}
+
+	psnap=(struct ieee80211_snap_hdr	*)(ptr+pattrib->hdrlen + pattrib->iv_len);
+	psnap_type=ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+	/* convert hdr + possible LLC headers into Ethernet header */
+	//eth_type = (psnap_type[0] << 8) | psnap_type[1];
+	if((_rtw_memcmp(psnap, rtw_rfc1042_header, SNAP_SIZE) &&
+		(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_IPX, 2) == _FALSE) && 
+		(_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_APPLETALK_AARP, 2)==_FALSE) )||
+		//eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
+		 _rtw_memcmp(psnap, rtw_bridge_tunnel_header, SNAP_SIZE)){
+		/* remove RFC1042 or Bridge-Tunnel encapsulation and replace EtherType */
+		bsnaphdr = _TRUE;
+	}
+	else {
+		/* Leave Ethernet header part of hdr and full payload */
+		bsnaphdr = _FALSE;
+	}
+
+	rmv_len = pattrib->hdrlen + pattrib->iv_len +(bsnaphdr?SNAP_SIZE:0);
+	len = precvframe->u.hdr.len - rmv_len;
+
+	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("\n===pattrib->hdrlen: %x,  pattrib->iv_len:%x ===\n\n", pattrib->hdrlen,	pattrib->iv_len));
+
+	_rtw_memcpy(&eth_type, ptr+rmv_len, 2);
+	eth_type= ntohs((unsigned short )eth_type); //pattrib->ether_type
+	pattrib->eth_type = eth_type;
+
+	{
+		ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+ (bsnaphdr?2:0)));
+	}
+
+	_rtw_memcpy(ptr, pattrib->dst, ETH_ALEN);
+	_rtw_memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
+
+	if(!bsnaphdr) {
+		len = htons(len);
+		_rtw_memcpy(ptr+12, &len, 2);
+	}
+	
+
+		len = htons(pattrib->seq_num);
+		//DBG_871X("wlan seq = %d ,seq_num =%x\n",len,pattrib->seq_num);
+		_rtw_memcpy(ptr+12,&len, 2);
+	if(adapter->mppriv.bRTWSmbCfg==_TRUE)
+	{
+//		if(_rtw_memcmp(mcastheadermac, pattrib->dst, 3) == _TRUE)//SimpleConfig Dest.
+//			_rtw_memcpy(ptr+ETH_ALEN, pattrib->bssid, ETH_ALEN);
+
+		if(_rtw_memcmp(mcastheadermac, pattrib->bssid, 3) == _TRUE) //SimpleConfig Dest.
+			_rtw_memcpy(ptr, pattrib->bssid, ETH_ALEN);
+
+	}
+
+	
+_func_exit_;	
+	return ret;
+
+}
+
+
+int mp_recv_frame(_adapter *padapter, union recv_frame *rframe)
+{
+	int ret = _SUCCESS;
+	struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+#ifdef CONFIG_MP_INCLUDED
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct mp_priv *pmppriv = &padapter->mppriv;
+#endif //CONFIG_MP_INCLUDED
+	u8 type;
+	u8 *ptr = rframe->u.hdr.rx_data;
+	u8 *psa, *pda, *pbssid;
+	struct sta_info *psta = NULL;
+    	DBG_COUNTER(padapter->rx_logs.core_rx_pre);
+    	
+	if ( (check_fwstate(pmlmepriv, _FW_LINKED) == _TRUE) )//&&(padapter->mppriv.check_mp_pkt == 0))
+	{
+		if (pattrib->crc_err == 1){
+			padapter->mppriv.rx_crcerrpktcount++;
+		}
+		else{
+			if(_SUCCESS == validate_mp_recv_frame(padapter, rframe))
+				padapter->mppriv.rx_pktcount++;
+			else
+				padapter->mppriv.rx_pktcount_filter_out++;
+		}
+
+		if(pmppriv->rx_bindicatePkt == _FALSE)
+		{
+			//RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("MP - Not in loopback mode , drop pkt \n"));
+			ret = _FAIL;
+			rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame
+			goto exit;
+		}
+		else 
+		{				
+			type =	GetFrameType(ptr);
+			pattrib->to_fr_ds = get_tofr_ds(ptr);
+			pattrib->frag_num = GetFragNum(ptr);
+			pattrib->seq_num = GetSequence(ptr);
+			pattrib->pw_save = GetPwrMgt(ptr);
+			pattrib->mfrag = GetMFrag(ptr);
+			pattrib->mdata = GetMData(ptr);
+			pattrib->privacy = GetPrivacy(ptr);
+			pattrib->order = GetOrder(ptr);
+	
+			if(type ==WIFI_DATA_TYPE)
+			{
+				pda = get_da(ptr);
+				psa = get_sa(ptr);
+				pbssid = get_hdr_bssid(ptr);
+				
+				_rtw_memcpy(pattrib->dst, pda, ETH_ALEN);
+				_rtw_memcpy(pattrib->src, psa, ETH_ALEN);
+				_rtw_memcpy(pattrib->bssid, pbssid, ETH_ALEN);
+			
+			switch(pattrib->to_fr_ds)
+			{
+			case 0:
+				_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);
+				_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);
+				ret = sta2sta_data_frame(padapter, rframe, &psta);
+				break;
+
+			case 1:
+		
+				_rtw_memcpy(pattrib->ra, pda, ETH_ALEN);
+				_rtw_memcpy(pattrib->ta, pbssid, ETH_ALEN);
+				ret = ap2sta_data_frame(padapter, rframe, &psta);
+		
+				break;
+
+			case 2:
+				_rtw_memcpy(pattrib->ra, pbssid, ETH_ALEN);
+				_rtw_memcpy(pattrib->ta, psa, ETH_ALEN);
+				ret = sta2ap_data_frame(padapter, rframe, &psta);
+				break;
+
+			case 3:
+				_rtw_memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
+				_rtw_memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
+				ret =_FAIL;
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" case 3\n"));
+				break;
+
+			default:
+				ret =_FAIL;
+				break;
+			}
+		
+			ret = MPwlanhdr_to_ethhdr (rframe);
+				
+			if (ret != _SUCCESS)
+			{
+				RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("wlanhdr_to_ethhdr: drop pkt \n"));
+				#ifdef DBG_RX_DROP_FRAME
+					DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr: drop pkt\n", __FUNCTION__);
+				#endif
+					rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame
+					ret = _FAIL;
+					goto exit;
+				}
+				if (!RTW_CANNOT_RUN(padapter)) {
+					RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@ recv_func: recv_func rtw_recv_indicatepkt\n" ));
+							//indicate this recv_frame
+					ret = rtw_recv_indicatepkt(padapter, rframe);
+					if (ret != _SUCCESS)
+					{	
+					#ifdef DBG_RX_DROP_FRAME
+								DBG_871X("DBG_RX_DROP_FRAME %s rtw_recv_indicatepkt fail!\n", __FUNCTION__);
+					#endif
+								rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame
+								ret = _FAIL;
+
+								goto exit;
+					}
+				}
+				else
+				{
+					RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@  recv_func: rtw_free_recvframe\n" ));
+					RT_TRACE(_module_rtl871x_recv_c_, _drv_debug_, ("recv_func:bDriverStopped(%s) OR bSurpriseRemoved(%s)"
+						, rtw_is_drv_stopped(padapter)?"True":"False"
+						, rtw_is_surprise_removed(padapter)?"True":"False"));
+					#ifdef DBG_RX_DROP_FRAME
+						DBG_871X("DBG_RX_DROP_FRAME %s ecv_func:bDriverStopped(%s) OR bSurpriseRemoved(%s)\n", __func__,
+									rtw_is_drv_stopped(padapter)?"True":"False",
+									rtw_is_surprise_removed(padapter)?"True":"False");
+					#endif
+					ret = _FAIL;
+					rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame
+						goto exit;
+				}
+
+			}
+		}
+				
+	}
+
+	RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
+	rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame
+	ret = _FAIL;
+
+exit:
+		return ret;
+
+}
+
+static sint fill_radiotap_hdr(_adapter *padapter, union recv_frame *precvframe, u8 *buf)
+{
+#define CHAN2FREQ(a) ((a < 14)?(2407+5*a):(5000+5*a))
+
+#if 0
+#define RTW_RX_RADIOTAP_PRESENT (                 \
+		(1 << IEEE80211_RADIOTAP_TSFT)              | \
+		(1 << IEEE80211_RADIOTAP_FLAGS)             | \
+		(1 << IEEE80211_RADIOTAP_RATE)              | \
+		(1 << IEEE80211_RADIOTAP_CHANNEL)           | \
+		(0 << IEEE80211_RADIOTAP_FHSS)              | \
+		(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL)     | \
+		(1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)      | \
+		(0 << IEEE80211_RADIOTAP_LOCK_QUALITY)      | \
+		(0 << IEEE80211_RADIOTAP_TX_ATTENUATION)    | \
+		(0 << IEEE80211_RADIOTAP_DB_TX_ATTENUATION) | \
+		(0 << IEEE80211_RADIOTAP_DBM_TX_POWER)      | \
+		(1 << IEEE80211_RADIOTAP_ANTENNA)           | \
+		(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL)      | \
+		(0 << IEEE80211_RADIOTAP_DB_ANTNOISE)       | \
+		(0 << IEEE80211_RADIOTAP_RX_FLAGS)          | \
+		(0 << IEEE80211_RADIOTAP_TX_FLAGS)          | \
+		(0 << IEEE80211_RADIOTAP_RTS_RETRIES)       | \
+		(0 << IEEE80211_RADIOTAP_DATA_RETRIES)      | \
+		(0 << IEEE80211_RADIOTAP_MCS)               | \
+		(0 << IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE)| \
+		(0 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE)  | \
+		(0 << IEEE80211_RADIOTAP_EXT)               | \
+		0)
+
+	/* (0 << IEEE80211_RADIOTAP_AMPDU_STATUS)      | \ */
+	/* (0 << IEEE80211_RADIOTAP_VHT)               | \ */
+#endif
+#ifndef IEEE80211_RADIOTAP_MCS
+#define IEEE80211_RADIOTAP_MCS 19
+#endif
+#ifndef IEEE80211_RADIOTAP_VHT
+#define IEEE80211_RADIOTAP_VHT 21
+#endif
+
+#ifndef IEEE80211_RADIOTAP_F_BADFCS
+#define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* bad FCS */
+#endif
+
+	sint ret = _SUCCESS;
+	_adapter			*adapter = precvframe->u.hdr.adapter;
+	struct mlme_priv	*pmlmepriv = &adapter->mlmepriv;
+	struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
+
+	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
+
+	u16 tmp_16bit = 0;
+
+	u8 data_rate[] = {
+		2, 4, 11, 22, /* CCK */
+		12, 18, 24, 36, 48, 72, 93, 108, /* OFDM */
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* HT MCS index */
+		16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 1 */
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 2 */
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 3 */
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, /* VHT Nss 4 */
+	};
+
+	_pkt *pskb = NULL;
+
+	struct ieee80211_radiotap_header *rtap_hdr = NULL;
+	u8 *ptr = NULL;
+
+	u8 hdr_buf[64] = {0};
+	u16 rt_len = 8;
+
+	/* create header */
+	rtap_hdr = (struct ieee80211_radiotap_header *)&hdr_buf[0];
+	rtap_hdr->it_version = PKTHDR_RADIOTAP_VERSION;
+
+	/* tsft */
+	if (pattrib->tsfl) {
+		u64 tmp_64bit;
+
+		rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_TSFT);
+		tmp_64bit = cpu_to_le64(pattrib->tsfl);
+		memcpy(&hdr_buf[rt_len], &tmp_64bit, 8);
+		rt_len += 8;
+	}
+
+	/* flags */
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_FLAGS);
+	if (0)
+		hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_CFP;
+
+	if (0)
+		hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_SHORTPRE;
+
+	if ((pattrib->encrypt == 1) || (pattrib->encrypt == 5))
+		hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_WEP;
+
+	if (pattrib->mfrag)
+		hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_FRAG;
+
+	/* always append FCS */
+	hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_FCS;
+
+	if (0)
+		hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_DATAPAD;
+
+	if (pattrib->crc_err)
+		hdr_buf[rt_len] |= IEEE80211_RADIOTAP_F_BADFCS;
+
+	if (pattrib->sgi) {
+		/* Currently unspecified but used */
+		hdr_buf[rt_len] |= 0x80;
+	}
+	rt_len += 1;
+
+	/* rate */
+	if (pattrib->data_rate < 12) {
+		rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE);
+		if (pattrib->data_rate < 4) {
+			/* CCK */
+			hdr_buf[rt_len] = data_rate[pattrib->data_rate];
+		} else {
+			/* OFDM */
+			hdr_buf[rt_len] = data_rate[pattrib->data_rate];
+		}
+	}
+	rt_len += 1; /* force padding 1 byte for aligned */
+
+	/* channel */
+	tmp_16bit = 0;
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_CHANNEL);
+	tmp_16bit = CHAN2FREQ(rtw_get_oper_ch(padapter));
+	/*tmp_16bit = CHAN2FREQ(pHalData->CurrentChannel);*/
+	memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
+	rt_len += 2;
+
+	/* channel flags */
+	tmp_16bit = 0;
+	if (pHalData->CurrentBandType == 0) 
+		tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_2GHZ);
+	else 
+		tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_5GHZ);
+
+	if (pattrib->data_rate < 12) {
+		if (pattrib->data_rate < 4) {
+			/* CCK */
+			tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_CCK);
+		} else {
+			/* OFDM */
+			tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_OFDM);
+		}
+	} else {
+		tmp_16bit |= cpu_to_le16(IEEE80211_CHAN_DYN);
+	}
+	memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
+	rt_len += 2;
+
+	/* dBm Antenna Signal */
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
+	hdr_buf[rt_len] = pattrib->phy_info.RecvSignalPower;
+	rt_len += 1;
+
+#if 0
+	/* dBm Antenna Noise */
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
+	hdr_buf[rt_len] = 0;
+	rt_len += 1;
+
+	/* Signal Quality */
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_LOCK_QUALITY);
+	hdr_buf[rt_len] = pattrib->phy_info.SignalQuality;
+	rt_len += 1;
+#endif
+
+	/* Antenna */
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_ANTENNA);
+	hdr_buf[rt_len] = 0; /* pHalData->rf_type; */
+	rt_len += 1;
+
+	/* RX flags */
+	rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_RX_FLAGS);
+#if 0
+	tmp_16bit = cpu_to_le16(0);
+	memcpy(ptr, &tmp_16bit, 1);
+#endif
+	rt_len += 2;
+
+	/* MCS information */
+	if (pattrib->data_rate >= 12 && pattrib->data_rate < 44) {
+		rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_MCS);
+		/* known, flag */
+		hdr_buf[rt_len] |= BIT1; /* MCS index known */
+
+		/* bandwidth */
+		hdr_buf[rt_len] |= BIT0;
+		hdr_buf[rt_len+1] |= (pattrib->bw & 0x03);
+
+		/* guard interval */
+		hdr_buf[rt_len] |= BIT2;
+		hdr_buf[rt_len+1] |= (pattrib->sgi & 0x01) << 2;
+
+		/* STBC */
+		hdr_buf[rt_len] |= BIT5;
+		hdr_buf[rt_len+1] |= (pattrib->stbc & 0x03) << 5;
+
+		rt_len += 2;
+
+		/* MCS rate index */
+		hdr_buf[rt_len] = data_rate[pattrib->data_rate];
+		rt_len += 1;
+	}
+
+	/* VHT */
+	if (pattrib->data_rate >= 44 && pattrib->data_rate < 84) {
+		rtap_hdr->it_present |= (1 << IEEE80211_RADIOTAP_VHT);
+
+		/* known 16 bit, flag 8 bit */
+		tmp_16bit = 0;
+
+		/* Bandwidth */
+		tmp_16bit |= BIT6;
+
+		/* Group ID */
+		tmp_16bit |= BIT7;
+
+		/* Partial AID */
+		tmp_16bit |= BIT8;
+
+		/* STBC */
+		tmp_16bit |= BIT0;
+		hdr_buf[rt_len+2] |= (pattrib->stbc & 0x01);
+
+		/* Guard interval */
+		tmp_16bit |= BIT2;
+		hdr_buf[rt_len+2] |= (pattrib->sgi & 0x01) << 2;
+
+		/* LDPC extra OFDM symbol */
+		tmp_16bit |= BIT4;
+		hdr_buf[rt_len+2] |= (pattrib->ldpc & 0x01) << 4;
+
+		memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
+		rt_len += 3;
+
+		/* bandwidth */
+		if (pattrib->bw == 0) 
+			hdr_buf[rt_len] |= 0;
+		else if (pattrib->bw == 1) 
+			hdr_buf[rt_len] |= 1;
+		else if (pattrib->bw == 2) 
+			hdr_buf[rt_len] |= 4;
+		else if (pattrib->bw == 3) 
+			hdr_buf[rt_len] |= 11;
+		rt_len += 1;
+
+		/* mcs_nss */
+		if (pattrib->data_rate >= 44 && pattrib->data_rate < 54) {
+			hdr_buf[rt_len] |= 1;
+			hdr_buf[rt_len] |= data_rate[pattrib->data_rate] << 4;
+		} else if (pattrib->data_rate >= 54 && pattrib->data_rate < 64) {
+			hdr_buf[rt_len + 1] |= 2;
+			hdr_buf[rt_len + 1] |= data_rate[pattrib->data_rate] << 4;
+		} else if (pattrib->data_rate >= 64 && pattrib->data_rate < 74) {
+			hdr_buf[rt_len + 2] |= 3;
+			hdr_buf[rt_len + 2] |= data_rate[pattrib->data_rate] << 4;
+		} else if (pattrib->data_rate >= 74 && pattrib->data_rate < 84) {
+			hdr_buf[rt_len + 3] |= 4;
+			hdr_buf[rt_len + 3] |= data_rate[pattrib->data_rate] << 4;
+		}
+		rt_len += 4;
+
+		/* coding */
+		hdr_buf[rt_len] = 0;
+		rt_len += 1;
+
+		/* group_id */
+		hdr_buf[rt_len] = 0;
+		rt_len += 1;
+
+		/* partial_aid */
+		tmp_16bit = 0;
+		memcpy(&hdr_buf[rt_len], &tmp_16bit, 2);
+		rt_len += 2;
+	}
+
+	/* push to skb */
+	pskb = (_pkt *)buf;
+	if (skb_headroom(pskb) < rt_len) {
+		DBG_871X("%s:%d %s headroom is too small.\n", __FILE__, __LINE__, __func__);
+		ret = _FAIL;
+		return ret;
+	}
+
+	ptr = skb_push(pskb, rt_len);
+	if (ptr) {
+		rtap_hdr->it_len = cpu_to_le16(rt_len);
+		memcpy(ptr, rtap_hdr, rt_len);
+	} else {
+		ret = _FAIL;
+	}
+
+	return ret;
+
+}
+
+int recv_frame_monitor(_adapter *padapter, union recv_frame *rframe)
+{
+	int ret = _SUCCESS;
+	struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+	_pkt *pskb = NULL;
+
+	/* read skb information from recv frame */
+	pskb = rframe->u.hdr.pkt;
+	pskb->len = rframe->u.hdr.len;
+	pskb->data = rframe->u.hdr.rx_data;
+	skb_set_tail_pointer(pskb, rframe->u.hdr.len);
+
+	/* fill radiotap header */
+	if (fill_radiotap_hdr(padapter, rframe, (u8 *)pskb) == _FAIL) {
+		ret = _FAIL;
+		rtw_free_recvframe(rframe, pfree_recv_queue); /* free this recv_frame */
+		goto exit;
+	}
+
+	/* write skb information to recv frame */
+	skb_reset_mac_header(pskb);
+	rframe->u.hdr.len = pskb->len;
+	rframe->u.hdr.rx_data = pskb->data;
+	rframe->u.hdr.rx_head = pskb->head;
+	rframe->u.hdr.rx_tail = skb_tail_pointer(pskb);
+	rframe->u.hdr.rx_end = skb_end_pointer(pskb);
+
+	if (!RTW_CANNOT_RUN(padapter)) {
+		/* indicate this recv_frame */
+		ret = rtw_recv_monitor(padapter, rframe);
+		if (ret != _SUCCESS) {
+			ret = _FAIL;
+			rtw_free_recvframe(rframe, pfree_recv_queue); /* free this recv_frame */
+			goto exit;
+		}
+	} else {
+		ret = _FAIL;
+		rtw_free_recvframe(rframe, pfree_recv_queue); /* free this recv_frame */
+		goto exit;
+	}
+
+exit:
+	return ret;
+}
+
+int recv_func_prehandle(_adapter *padapter, union recv_frame *rframe)
+{
+	int ret = _SUCCESS;
+	struct rx_pkt_attrib *pattrib = &rframe->u.hdr.attrib;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+
+#ifdef DBG_RX_COUNTER_DUMP
+	if( padapter->dump_rx_cnt_mode & DUMP_DRV_RX_COUNTER )
+	{
+		if (pattrib->crc_err == 1)
+			padapter->drv_rx_cnt_crcerror++;
+		else
+			padapter->drv_rx_cnt_ok++;
+	}
+#endif
+
+#ifdef CONFIG_MP_INCLUDED
+	if (padapter->registrypriv.mp_mode == 1 || padapter->mppriv.bRTWSmbCfg ==_TRUE)
+	{
+		mp_recv_frame(padapter,rframe);
+		ret = _FAIL;
+		goto exit;
+        }
+	else
+#endif
+	{
+	//check the frame crtl field and decache
+	ret = validate_recv_frame(padapter, rframe);
+	if (ret != _SUCCESS)
+	{
+		RT_TRACE(_module_rtl871x_recv_c_, _drv_info_, ("recv_func: validate_recv_frame fail! drop pkt\n"));
+		rtw_free_recvframe(rframe, pfree_recv_queue);//free this recv_frame
+		goto exit;
+	}
+	}
+exit:
+	return ret;
+}
+
+int recv_func_posthandle(_adapter *padapter, union recv_frame *prframe)
+{
+	int ret = _SUCCESS;
+	union recv_frame *orig_prframe = prframe;
+	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+	struct recv_priv *precvpriv = &padapter->recvpriv;
+	_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+#ifdef CONFIG_TDLS
+	u8 *psnap_type, *pcategory;
+#endif //CONFIG_TDLS
+
+	DBG_COUNTER(padapter->rx_logs.core_rx_post);
+
+	// DATA FRAME
+	rtw_led_control(padapter, LED_CTL_RX);
+
+	prframe = decryptor(padapter, prframe);
+	if (prframe == NULL) {
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("decryptor: drop pkt\n"));
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s decryptor: drop pkt\n", __FUNCTION__);
+		#endif
+		ret = _FAIL;
+		DBG_COUNTER(padapter->rx_logs.core_rx_post_decrypt_err);
+		goto _recv_data_drop;
+	}
+
+#if 0
+	if ( padapter->adapter_type == PRIMARY_ADAPTER )
+	{
+		DBG_871X("+++\n");
+		{
+			int i;
+			u8	*ptr = get_recvframe_data(prframe);
+			for(i=0; i<140;i=i+8)
+				DBG_871X("%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:", *(ptr+i),
+				*(ptr+i+1), *(ptr+i+2) ,*(ptr+i+3) ,*(ptr+i+4),*(ptr+i+5), *(ptr+i+6), *(ptr+i+7));
+
+		}
+		DBG_871X("---\n");
+	}
+#endif
+
+#ifdef CONFIG_TDLS
+	//check TDLS frame
+	psnap_type = get_recvframe_data(orig_prframe) + pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+	pcategory = psnap_type + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN;
+
+	if((_rtw_memcmp(psnap_type, SNAP_ETH_TYPE_TDLS, ETH_TYPE_LEN)) &&
+		((*pcategory==RTW_WLAN_CATEGORY_TDLS) || (*pcategory==RTW_WLAN_CATEGORY_P2P))){
+		ret = OnTDLS(padapter, prframe);
+		if(ret == _FAIL)
+			goto _exit_recv_func;
+	}
+#endif //CONFIG_TDLS
+
+	prframe = recvframe_chk_defrag(padapter, prframe);
+	if(prframe==NULL)	{
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recvframe_chk_defrag: drop pkt\n"));
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s recvframe_chk_defrag: drop pkt\n", __FUNCTION__);
+		#endif
+		DBG_COUNTER(padapter->rx_logs.core_rx_post_defrag_err);
+		goto _recv_data_drop;		
+	}
+
+	prframe=portctrl(padapter, prframe);
+	if (prframe == NULL) {
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("portctrl: drop pkt \n"));
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s portctrl: drop pkt\n", __FUNCTION__);
+		#endif
+		ret = _FAIL;
+		DBG_COUNTER(padapter->rx_logs.core_rx_post_portctrl_err);
+		goto _recv_data_drop;
+	}
+
+	count_rx_stats(padapter, prframe, NULL);
+
+#ifdef CONFIG_WAPI_SUPPORT
+	rtw_wapi_update_info(padapter, prframe);
+#endif
+
+#ifdef CONFIG_80211N_HT
+	ret = process_recv_indicatepkts(padapter, prframe);
+	if (ret != _SUCCESS)
+	{
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("recv_func: process_recv_indicatepkts fail! \n"));
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s process_recv_indicatepkts fail!\n", __FUNCTION__);
+		#endif
+		rtw_free_recvframe(orig_prframe, pfree_recv_queue);//free this recv_frame
+		DBG_COUNTER(padapter->rx_logs.core_rx_post_indicate_err);
+		goto _recv_data_drop;
+	}
+#else // CONFIG_80211N_HT
+	if (!pattrib->amsdu)
+	{
+		ret = wlanhdr_to_ethhdr (prframe);
+		if (ret != _SUCCESS)
+		{
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("wlanhdr_to_ethhdr: drop pkt \n"));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s wlanhdr_to_ethhdr: drop pkt\n", __FUNCTION__);
+			#endif
+			rtw_free_recvframe(orig_prframe, pfree_recv_queue);//free this recv_frame
+			goto _recv_data_drop;
+		}
+
+		if (!RTW_CANNOT_RUN(padapter)) {
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@ recv_func: recv_func rtw_recv_indicatepkt\n" ));
+			//indicate this recv_frame
+			ret = rtw_recv_indicatepkt(padapter, prframe);
+			if (ret != _SUCCESS)
+			{	
+				#ifdef DBG_RX_DROP_FRAME
+				DBG_871X("DBG_RX_DROP_FRAME %s rtw_recv_indicatepkt fail!\n", __FUNCTION__);
+				#endif
+				goto _recv_data_drop;
+			}
+		}
+		else
+		{
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_alert_, ("@@@@  recv_func: rtw_free_recvframe\n" ));
+			RT_TRACE(_module_rtl871x_recv_c_, _drv_debug_, ("recv_func:bDriverStopped(%d) OR bSurpriseRemoved(%d)", padapter->bDriverStopped, padapter->bSurpriseRemoved));
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s ecv_func:bDriverStopped(%s) OR bSurpriseRemoved(%s)\n", __func__
+				, rtw_is_drv_stopped(padapter)?"True":"False"
+				, rtw_is_surprise_removed(padapter)?"True":"False");
+			#endif
+			ret = _FAIL;
+			rtw_free_recvframe(orig_prframe, pfree_recv_queue); //free this recv_frame
+		}
+
+	}
+	else if(pattrib->amsdu==1)
+	{
+
+		ret = amsdu_to_msdu(padapter, prframe);
+		if(ret != _SUCCESS)
+		{
+			#ifdef DBG_RX_DROP_FRAME
+			DBG_871X("DBG_RX_DROP_FRAME %s amsdu_to_msdu fail\n", __FUNCTION__);
+			#endif
+			rtw_free_recvframe(orig_prframe, pfree_recv_queue);
+			goto _recv_data_drop;
+		}
+	}
+	else
+	{
+		#ifdef DBG_RX_DROP_FRAME
+		DBG_871X("DBG_RX_DROP_FRAME %s what is this condition??\n", __FUNCTION__);
+		#endif
+		goto _recv_data_drop;
+	}
+#endif // CONFIG_80211N_HT
+
+_exit_recv_func:
+	return ret;
+
+_recv_data_drop:
+	precvpriv->rx_drop++;
+	return ret;
+}
+
+
+int recv_func(_adapter *padapter, union recv_frame *rframe);
+int recv_func(_adapter *padapter, union recv_frame *rframe)
+{
+	int ret;
+	struct rx_pkt_attrib *prxattrib = &rframe->u.hdr.attrib;
+	struct recv_priv *recvpriv = &padapter->recvpriv;
+	struct security_priv *psecuritypriv=&padapter->securitypriv;
+	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+
+	if (check_fwstate(mlmepriv, WIFI_MONITOR_STATE)) {
+		/* monitor mode */
+		recv_frame_monitor(padapter, rframe);
+		ret = _SUCCESS;
+		goto exit;
+	} else
+
+	/* check if need to handle uc_swdec_pending_queue*/
+	if (check_fwstate(mlmepriv, WIFI_STATION_STATE) && psecuritypriv->busetkipkey)
+	{
+		union recv_frame *pending_frame;
+		int cnt = 0;
+
+		while((pending_frame=rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue))) {
+			cnt++;
+			DBG_COUNTER(padapter->rx_logs.core_rx_dequeue);
+			recv_func_posthandle(padapter, pending_frame);
+		}
+
+		if (cnt)
+			DBG_871X(FUNC_ADPT_FMT" dequeue %d from uc_swdec_pending_queue\n",
+				FUNC_ADPT_ARG(padapter), cnt);
+	}
+
+	DBG_COUNTER(padapter->rx_logs.core_rx);
+	ret = recv_func_prehandle(padapter, rframe);
+
+	if(ret == _SUCCESS) {
+		
+		/* check if need to enqueue into uc_swdec_pending_queue*/
+		if (check_fwstate(mlmepriv, WIFI_STATION_STATE) &&
+			!IS_MCAST(prxattrib->ra) && prxattrib->encrypt>0 &&
+			(prxattrib->bdecrypted == 0 ||psecuritypriv->sw_decrypt == _TRUE) &&
+			psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPAPSK &&
+			!psecuritypriv->busetkipkey)
+		{
+			DBG_COUNTER(padapter->rx_logs.core_rx_enqueue);
+			rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
+			//DBG_871X("%s: no key, enqueue uc_swdec_pending_queue\n", __func__);
+
+			if (recvpriv->free_recvframe_cnt < NR_RECVFRAME/4) {
+				/* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt  */
+				rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
+				if (rframe)
+					goto do_posthandle;
+			}
+			goto exit;
+		}
+
+do_posthandle:
+		ret = recv_func_posthandle(padapter, rframe);
+	}
+
+exit:
+	return ret;
+}
+
+
+s32 rtw_recv_entry(union recv_frame *precvframe)
+{
+	_adapter *padapter;
+	struct recv_priv *precvpriv;
+	s32 ret=_SUCCESS;
+
+_func_enter_;
+
+//	RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("+rtw_recv_entry\n"));
+
+	padapter = precvframe->u.hdr.adapter;
+
+	precvpriv = &padapter->recvpriv;
+
+
+	if ((ret = recv_func(padapter, precvframe)) == _FAIL)
+	{
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("rtw_recv_entry: recv_func return fail!!!\n"));
+		goto _recv_entry_drop;
+	}
+
+
+	precvpriv->rx_pkts++;
+
+_func_exit_;
+
+	return ret;
+
+_recv_entry_drop:
+
+#ifdef CONFIG_MP_INCLUDED
+	if (padapter->registrypriv.mp_mode == 1)
+		padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
+#endif
+
+	//RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,("_recv_entry_drop\n"));
+
+_func_exit_;
+
+	return ret;
+}
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+static void rtw_signal_stat_timer_hdl(struct timer_list *t)
+{
+	_adapter *adapter =
+		from_timer(adapter, t, recvpriv.signal_stat_timer);
+	struct recv_priv *recvpriv = &adapter->recvpriv;
+	
+	u32 tmp_s, tmp_q;
+	u8 avg_signal_strength = 0;
+	u8 avg_signal_qual = 0;
+	u32 num_signal_strength = 0;
+	u32 num_signal_qual = 0;
+	u8 ratio_pre_stat = 0, ratio_curr_stat = 0, ratio_total = 0, ratio_profile = SIGNAL_STAT_CALC_PROFILE_0;
+
+	if(adapter->recvpriv.is_signal_dbg) {
+		//update the user specific value, signal_strength_dbg, to signal_strength, rssi
+		adapter->recvpriv.signal_strength= adapter->recvpriv.signal_strength_dbg;
+		adapter->recvpriv.rssi=(s8)translate_percentage_to_dbm((u8)adapter->recvpriv.signal_strength_dbg);
+	} else {
+
+		if(recvpriv->signal_strength_data.update_req == 0) {// update_req is clear, means we got rx
+			avg_signal_strength = recvpriv->signal_strength_data.avg_val;
+			num_signal_strength = recvpriv->signal_strength_data.total_num;
+			// after avg_vals are accquired, we can re-stat the signal values
+			recvpriv->signal_strength_data.update_req = 1;
+		}
+		
+		if(recvpriv->signal_qual_data.update_req == 0) {// update_req is clear, means we got rx
+			avg_signal_qual = recvpriv->signal_qual_data.avg_val;
+			num_signal_qual = recvpriv->signal_qual_data.total_num;
+			// after avg_vals are accquired, we can re-stat the signal values
+			recvpriv->signal_qual_data.update_req = 1;
+		}
+
+		if (num_signal_strength == 0) {
+			if (rtw_get_on_cur_ch_time(adapter) == 0
+				|| rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) < 2 * adapter->mlmeextpriv.mlmext_info.bcn_interval
+			) {
+				goto set_timer;
+			}
+		}
+
+		if(check_fwstate(&adapter->mlmepriv, _FW_UNDER_SURVEY) == _TRUE
+			|| check_fwstate(&adapter->mlmepriv, _FW_LINKED) == _FALSE
+		) { 
+			goto set_timer;
+		}
+
+		#ifdef CONFIG_CONCURRENT_MODE
+		if (check_buddy_fwstate(adapter, _FW_UNDER_SURVEY) == _TRUE)
+			goto set_timer;
+		#endif
+
+		if (RTW_SIGNAL_STATE_CALC_PROFILE < SIGNAL_STAT_CALC_PROFILE_MAX)
+			ratio_profile = RTW_SIGNAL_STATE_CALC_PROFILE;
+
+		ratio_pre_stat = signal_stat_calc_profile[ratio_profile][0];
+		ratio_curr_stat = signal_stat_calc_profile[ratio_profile][1];
+		ratio_total = ratio_pre_stat + ratio_curr_stat;
+
+		//update value of signal_strength, rssi, signal_qual
+		tmp_s = (ratio_curr_stat * avg_signal_strength + ratio_pre_stat * recvpriv->signal_strength);
+		if (tmp_s % ratio_total)
+			tmp_s = tmp_s / ratio_total + 1;
+		else
+			tmp_s = tmp_s / ratio_total;
+		if (tmp_s > 100)
+			tmp_s = 100;
+
+		tmp_q = (ratio_curr_stat * avg_signal_qual + ratio_pre_stat * recvpriv->signal_qual);
+		if (tmp_q % ratio_total)
+			tmp_q = tmp_q / ratio_total + 1;
+		else
+			tmp_q = tmp_q / ratio_total;
+		if (tmp_q > 100)
+			tmp_q = 100;
+
+		recvpriv->signal_strength = tmp_s;
+		recvpriv->rssi = (s8)translate_percentage_to_dbm(tmp_s);
+		recvpriv->signal_qual = tmp_q;
+
+		#if defined(DBG_RX_SIGNAL_DISPLAY_PROCESSING) && 1
+		DBG_871X(FUNC_ADPT_FMT" signal_strength:%3u, rssi:%3d, signal_qual:%3u"
+			", num_signal_strength:%u, num_signal_qual:%u"
+			", on_cur_ch_ms:%d"
+			"\n"
+			, FUNC_ADPT_ARG(adapter)
+			, recvpriv->signal_strength
+			, recvpriv->rssi
+			, recvpriv->signal_qual
+			, num_signal_strength, num_signal_qual
+			, rtw_get_on_cur_ch_time(adapter) ? rtw_get_passing_time_ms(rtw_get_on_cur_ch_time(adapter)) : 0
+		);
+		#endif
+	}
+
+set_timer:
+	rtw_set_signal_stat_timer(recvpriv);
+	
+}
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+
+static void rx_process_rssi(_adapter *padapter,union recv_frame *prframe)
+{
+	u32	last_rssi, tmp_val;
+	struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	struct signal_stat * signal_stat = &padapter->recvpriv.signal_strength_data;
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+
+	//DBG_8192C("process_rssi=> pattrib->rssil(%d) signal_strength(%d)\n ",pattrib->RecvSignalPower,pattrib->signal_strength);
+	//if(pRfd->Status.bPacketToSelf || pRfd->Status.bPacketBeacon)
+	{
+	#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+		if(signal_stat->update_req) {
+			signal_stat->total_num = 0;
+			signal_stat->total_val = 0;
+			signal_stat->update_req = 0;
+		}
+
+		signal_stat->total_num++;
+		signal_stat->total_val  += pattrib->phy_info.SignalStrength;
+		signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;		
+	#else //CONFIG_NEW_SIGNAL_STAT_PROCESS
+	
+		//Adapter->RxStats.RssiCalculateCnt++;	//For antenna Test
+		if(padapter->recvpriv.signal_strength_data.total_num++ >= PHY_RSSI_SLID_WIN_MAX)
+		{
+			padapter->recvpriv.signal_strength_data.total_num = PHY_RSSI_SLID_WIN_MAX;
+			last_rssi = padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index];
+			padapter->recvpriv.signal_strength_data.total_val -= last_rssi;
+		}
+		padapter->recvpriv.signal_strength_data.total_val  +=pattrib->phy_info.SignalStrength;
+
+		padapter->recvpriv.signal_strength_data.elements[padapter->recvpriv.signal_strength_data.index++] = pattrib->phy_info.SignalStrength;
+		if(padapter->recvpriv.signal_strength_data.index >= PHY_RSSI_SLID_WIN_MAX)
+			padapter->recvpriv.signal_strength_data.index = 0;
+
+
+		tmp_val = padapter->recvpriv.signal_strength_data.total_val/padapter->recvpriv.signal_strength_data.total_num;
+		
+		if(padapter->recvpriv.is_signal_dbg) {
+			padapter->recvpriv.signal_strength= padapter->recvpriv.signal_strength_dbg;
+			padapter->recvpriv.rssi=(s8)translate_percentage_to_dbm(padapter->recvpriv.signal_strength_dbg);
+		} else {
+			padapter->recvpriv.signal_strength= tmp_val;
+			padapter->recvpriv.rssi=(s8)translate_percentage_to_dbm(tmp_val);
+		}
+
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("UI RSSI = %d, ui_rssi.TotalVal = %d, ui_rssi.TotalNum = %d\n", tmp_val, padapter->recvpriv.signal_strength_data.total_val,padapter->recvpriv.signal_strength_data.total_num));
+	#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+	}
+}
+
+static void rx_process_link_qual(_adapter *padapter,union recv_frame *prframe)
+{
+	u32	last_evm=0, tmpVal;
+ 	struct rx_pkt_attrib *pattrib;
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	struct signal_stat * signal_stat;
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+
+	if(prframe == NULL || padapter==NULL){
+		return;
+	}
+
+	pattrib = &prframe->u.hdr.attrib;
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	signal_stat = &padapter->recvpriv.signal_qual_data;
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+
+	//DBG_8192C("process_link_qual=> pattrib->signal_qual(%d)\n ",pattrib->signal_qual);
+
+#ifdef CONFIG_NEW_SIGNAL_STAT_PROCESS
+	if(signal_stat->update_req) {
+		signal_stat->total_num = 0;
+		signal_stat->total_val = 0;
+		signal_stat->update_req = 0;
+	}
+
+	signal_stat->total_num++;
+	signal_stat->total_val  += pattrib->phy_info.SignalQuality;
+	signal_stat->avg_val = signal_stat->total_val / signal_stat->total_num;
+	
+#else //CONFIG_NEW_SIGNAL_STAT_PROCESS
+	if(pattrib->phy_info.SignalQuality != 0)
+	{
+			//
+			// 1. Record the general EVM to the sliding window.
+			//
+			if(padapter->recvpriv.signal_qual_data.total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX)
+			{
+				padapter->recvpriv.signal_qual_data.total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
+				last_evm = padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index];
+				padapter->recvpriv.signal_qual_data.total_val -= last_evm;
+			}
+			padapter->recvpriv.signal_qual_data.total_val += pattrib->phy_info.SignalQuality;
+
+			padapter->recvpriv.signal_qual_data.elements[padapter->recvpriv.signal_qual_data.index++] = pattrib->phy_info.SignalQuality;
+			if(padapter->recvpriv.signal_qual_data.index >= PHY_LINKQUALITY_SLID_WIN_MAX)
+				padapter->recvpriv.signal_qual_data.index = 0;
+
+			RT_TRACE(_module_rtl871x_recv_c_,_drv_info_,("Total SQ=%d  pattrib->signal_qual= %d\n", padapter->recvpriv.signal_qual_data.total_val, pattrib->phy_info.SignalQuality));
+
+			// <1> Showed on UI for user, in percentage.
+			tmpVal = padapter->recvpriv.signal_qual_data.total_val/padapter->recvpriv.signal_qual_data.total_num;
+			padapter->recvpriv.signal_qual=(u8)tmpVal;
+
+	}
+	else
+	{
+		RT_TRACE(_module_rtl871x_recv_c_,_drv_err_,(" pattrib->signal_qual =%d\n", pattrib->phy_info.SignalQuality));
+	}
+#endif //CONFIG_NEW_SIGNAL_STAT_PROCESS
+}
+
+void rx_process_phy_info(_adapter *padapter, union recv_frame *rframe)
+{
+	/* Check RSSI */
+	rx_process_rssi(padapter, rframe);
+
+	/* Check PWDB */
+	//process_PWDB(padapter, rframe); 
+
+	//UpdateRxSignalStatistics8192C(Adapter, pRfd);
+	
+	/* Check EVM */
+	rx_process_link_qual(padapter, rframe);
+	#ifdef DBG_RX_SIGNAL_DISPLAY_RAW_DATA
+	rtw_store_phy_info( padapter, rframe);
+	#endif
+}
+
+void rx_query_phy_status(
+	union recv_frame	*precvframe,
+	u8 *pphy_status)
+{
+	PADAPTER 			padapter = precvframe->u.hdr.adapter;
+	struct rx_pkt_attrib	*pattrib = &precvframe->u.hdr.attrib;
+	HAL_DATA_TYPE		*pHalData = GET_HAL_DATA(padapter);	
+	PODM_PHY_INFO_T 	pPHYInfo  = (PODM_PHY_INFO_T)(&pattrib->phy_info);
+	u8					*wlanhdr;
+	ODM_PACKET_INFO_T	pkt_info;
+	u8 *sa;
+	struct sta_priv *pstapriv;
+	struct sta_info *psta = NULL;
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+	//_irqL		irqL;
+	
+	pkt_info.bPacketMatchBSSID =_FALSE;
+	pkt_info.bPacketToSelf = _FALSE;
+	pkt_info.bPacketBeacon = _FALSE;
+
+	wlanhdr = get_recvframe_data(precvframe);
+
+	pkt_info.bPacketMatchBSSID = (!IsFrameTypeCtrl(wlanhdr))
+		&& (!pattrib->icv_err) && (!pattrib->crc_err)
+		&& _rtw_memcmp(get_hdr_bssid(wlanhdr), get_bssid(&padapter->mlmepriv), ETH_ALEN);
+
+	pkt_info.bToSelf = (!pattrib->icv_err) && (!pattrib->crc_err)
+		&& _rtw_memcmp(get_ra(wlanhdr), adapter_mac_addr(padapter), ETH_ALEN);
+
+	pkt_info.bPacketToSelf = pkt_info.bPacketMatchBSSID
+		&& _rtw_memcmp(get_ra(wlanhdr), adapter_mac_addr(padapter), ETH_ALEN);
+
+	pkt_info.bPacketBeacon = pkt_info.bPacketMatchBSSID
+		&& (GetFrameSubType(wlanhdr) == WIFI_BEACON);
+
+	sa = get_ta(wlanhdr);
+
+	pkt_info.StationID = 0xFF;
+
+	if (_rtw_memcmp(adapter_mac_addr(padapter), sa, ETH_ALEN) == _TRUE) {
+		static u32 start_time = 0;
+
+#if 0 /*For debug */
+		if (IsFrameTypeCtrl(wlanhdr)) {
+				DBG_871X("-->Control frame: Y\n");
+				DBG_871X("-->pkt_len: %d\n", pattrib->pkt_len);
+				DBG_871X("-->Sub Type = 0x%X\n", GetFrameSubType(wlanhdr));
+		}
+
+		/* Dump first 40 bytes of header */
+		int i = 0;
+
+		for (i = 0; i < 40; i++)
+			DBG_871X("%d: %X\n", i, *((u8 *)wlanhdr + i));
+
+		DBG_871X("\n");
+#endif
+
+		if ((start_time == 0) || (rtw_get_passing_time_ms(start_time) > 5000)) {
+			DBG_871X_LEVEL(_drv_always_, "Warning!!! %s: Confilc mac addr!!\n", __func__);
+			start_time = rtw_get_current_time();
+		}
+		pdbgpriv->dbg_rx_conflic_mac_addr_cnt++;
+	} else{
+		pstapriv = &padapter->stapriv;
+		psta = rtw_get_stainfo(pstapriv, sa);
+		if (psta)
+			pkt_info.StationID = psta->mac_id;
+	}
+
+	pkt_info.DataRate = pattrib->data_rate;
+
+	//_enter_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
+	ODM_PhyStatusQuery(&pHalData->odmpriv, pPHYInfo, pphy_status, &pkt_info);
+	if (psta)
+		psta->rssi = pattrib->phy_info.RecvSignalPower;
+	//_exit_critical_bh(&pHalData->odm_stainfo_lock, &irqL);
+
+	{
+		precvframe->u.hdr.psta = NULL;
+		if (pkt_info.bPacketMatchBSSID
+			&& (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
+		) {
+			if (psta) {
+				precvframe->u.hdr.psta = psta;
+				rx_process_phy_info(padapter, precvframe);
+			}
+		} else if (pkt_info.bPacketToSelf || pkt_info.bPacketBeacon) {
+			if (check_fwstate(&padapter->mlmepriv, WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE) == _TRUE) {
+				if (psta)
+					precvframe->u.hdr.psta = psta;
+			}
+			rx_process_phy_info(padapter, precvframe);
+		}
+	}
+}
+/*
+* Increase and check if the continual_no_rx_packet of this @param pmlmepriv is larger than MAX_CONTINUAL_NORXPACKET_COUNT
+* @return _TRUE:
+* @return _FALSE:
+*/
+int rtw_inc_and_chk_continual_no_rx_packet(struct sta_info *sta, int tid_index)
+{
+	
+	int ret = _FALSE;
+	int value = ATOMIC_INC_RETURN(&sta->continual_no_rx_packet[tid_index]);
+
+	if (value >= MAX_CONTINUAL_NORXPACKET_COUNT) 
+		ret = _TRUE;
+	
+	return ret;
+}
+
+/*
+* Set the continual_no_rx_packet of this @param pmlmepriv to 0
+*/
+void rtw_reset_continual_no_rx_packet(struct sta_info *sta, int tid_index)
+{	
+	ATOMIC_SET(&sta->continual_no_rx_packet[tid_index], 0);	
+}
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_rf.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_rf.c
new file mode 100644
index 000000000..a682cf3ab
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_rf.c
@@ -0,0 +1,477 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_RF_C_
+
+#include <drv_types.h>
+#include <hal_data.h>
+
+u8 center_ch_5g_all[CENTER_CH_5G_ALL_NUM] = {
+		36, 38, 40, 42, 44, 46, 48,			/* Band 1 */
+		52, 54, 56, 58, 60, 62, 64,			/* Band 2 */
+		100, 102, 104, 106, 108, 110, 112,	/* Band 3 */
+		116, 118, 120, 122, 124, 126, 128,	/* Band 3 */
+		132, 134, 136, 138, 140, 142, 144,	/* Band 3 */
+		149, 151, 153, 155, 157, 159, 161,	/* Band 4 */
+		165, 167, 169, 171, 173, 175, 177};	/* Band 4 */
+
+u8 center_ch_5g_20m[CENTER_CH_5G_20M_NUM] = {
+	36, 40, 44, 48,
+	52, 56, 60, 64,
+	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
+	149, 153, 157, 161, 165, 169, 173, 177
+};
+
+u8 center_ch_5g_40m[CENTER_CH_5G_40M_NUM] = {38, 46, 54, 62, 102, 110, 118, 126, 134, 142, 151, 159, 167, 175};
+
+u8 center_ch_5g_80m[CENTER_CH_5G_80M_NUM] = {42, 58, 106, 122, 138, 155, 171};
+
+struct center_chs_ent {
+	u8 ch_num;
+	u8 *chs;
+};
+
+struct center_chs_ent center_chs_5g_by_bw[] = {
+	{CENTER_CH_5G_20M_NUM, center_ch_5g_20m},
+	{CENTER_CH_5G_40M_NUM, center_ch_5g_40m},
+	{CENTER_CH_5G_80M_NUM, center_ch_5g_80m},
+};
+
+inline u8 center_chs_5g_num(u8 bw)
+{
+	if (bw >= CHANNEL_WIDTH_160)
+		return 0;
+	
+	return center_chs_5g_by_bw[bw].ch_num;
+}
+
+inline u8 center_chs_5g(u8 bw, u8 id)
+{
+	if (bw >= CHANNEL_WIDTH_160)
+		return 0;
+
+	if (id >= center_chs_5g_num(bw))
+		return 0;
+		
+	return center_chs_5g_by_bw[bw].chs[id];
+}
+
+int rtw_ch2freq(int chan)
+{
+	/* see 802.11 17.3.8.3.2 and Annex J
+	* there are overlapping channel numbers in 5GHz and 2GHz bands */
+
+	/*
+	* RTK: don't consider the overlapping channel numbers: 5G channel <= 14,
+	* because we don't support it. simply judge from channel number
+	*/
+
+	if (chan >= 1 && chan <= 14) {
+		if (chan == 14)
+			return 2484;
+		else if (chan < 14)
+			return 2407 + chan * 5;
+	} else if (chan >= 36 && chan <= 177) {
+		return 5000 + chan * 5;
+	}
+
+	return 0; /* not supported */
+}
+
+int rtw_freq2ch(int freq)
+{
+	/* see 802.11 17.3.8.3.2 and Annex J */
+	if (freq == 2484)
+		return 14;
+	else if (freq < 2484)
+		return (freq - 2407) / 5;
+	else if (freq >= 4910 && freq <= 4980)
+		return (freq - 4000) / 5;
+	else if (freq <= 45000) /* DMG band lower limit */
+		return (freq - 5000) / 5;
+	else if (freq >= 58320 && freq <= 64800)
+		return (freq - 56160) / 2160;
+	else
+		return 0;
+}
+
+bool rtw_chbw_to_freq_range(u8 ch, u8 bw, u8 offset, u32 *hi, u32 *lo)
+{
+	u8 c_ch;
+	u32 freq;
+	u32 hi_ret = 0, lo_ret = 0;
+	int i;
+	bool valid = _FALSE;
+
+	if (hi)
+		*hi = 0;
+	if (lo)
+		*lo = 0;
+
+	c_ch = rtw_get_center_ch(ch, bw, offset);
+	freq = rtw_ch2freq(c_ch);
+
+	if (!freq) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (bw == CHANNEL_WIDTH_80) {
+		hi_ret = freq + 40;
+		lo_ret = freq - 40;
+	} else if (bw == CHANNEL_WIDTH_40) {
+		hi_ret = freq + 20;
+		lo_ret = freq - 20;
+	} else if (bw == CHANNEL_WIDTH_20) {
+		hi_ret = freq + 10;
+		lo_ret = freq - 10;
+	} else {
+		rtw_warn_on(1);
+	}
+
+	if (hi)
+		*hi = hi_ret;
+	if (lo)
+		*lo = lo_ret;
+
+	valid = _TRUE;
+
+exit:
+	return valid;
+}
+
+const char * const _ch_width_str[] = {
+	"20MHz",
+	"40MHz",
+	"80MHz",
+	"160MHz",
+	"80_80MHz",
+	"CHANNEL_WIDTH_MAX",
+};
+
+const u8 _ch_width_to_bw_cap[] = {
+	BW_CAP_20M,
+	BW_CAP_40M,
+	BW_CAP_80M,
+	BW_CAP_160M,
+	BW_CAP_80_80M,
+	0,
+};
+
+const char * const _band_str[] = {
+	"2.4G",
+	"5G",
+	"BOTH",
+	"BAND_MAX",
+};
+
+const u8 _band_to_band_cap[] = {
+	BAND_CAP_2G,
+	BAND_CAP_5G,
+	0,
+	0,
+};
+
+struct country_chplan {
+	char alpha2[2];
+	u8 chplan;
+};
+
+static const struct country_chplan country_chplan_map[] = {
+	{"AD", 0x26}, /* Andorra */
+	{"AE", 0x26}, /* United Arab Emirates */
+	{"AG", 0x30}, /* Antigua & Barbuda */
+	{"AI", 0x26}, /* Anguilla(UK) */
+	{"AL", 0x26}, /* Albania */
+	{"AM", 0x34}, /* Armenia */
+	{"AO", 0x26}, /* Angola */
+	{"AQ", 0x26}, /* Antarctica */
+	{"AR", 0x57}, /* Argentina */
+	{"AS", 0x34}, /* American Samoa */
+	{"AT", 0x26}, /* Austria */
+	{"AU", 0x45}, /* Australia */
+	{"AW", 0x34}, /* Aruba */
+	{"AZ", 0x26}, /* Azerbaijan */
+	{"BA", 0x26}, /* Bosnia & Herzegovina */
+	{"BD", 0x26}, /* Bangladesh */
+	{"BE", 0x26}, /* Belgium */
+	{"BG", 0x26}, /* Bulgaria */
+	{"BH", 0x47}, /* Bahrain */
+	{"BO", 0x30}, /* Bolivia */
+	{"BR", 0x34}, /* Brazil */
+	{"CA", 0x34}, /* Canada */
+	{"CH", 0x26}, /* Switzerland */
+	{"CL", 0x30}, /* Chile */
+	{"CN", 0x48}, /* China */
+	{"CO", 0x34}, /* Colombia */
+	{"CR", 0x34}, /* Costa Rica */
+	{"CY", 0x26}, /* Cyprus */
+	{"CZ", 0x26}, /* Czech Republic */
+	{"DE", 0x26}, /* Germany */
+	{"DK", 0x26}, /* Denmark */
+	{"DO", 0x34}, /* Dominican Republic */
+	{"EC", 0x34}, /* Ecuador */
+	{"EE", 0x26}, /* Estonia */
+	{"EG", 0x47}, /* Egypt */
+	{"ES", 0x26}, /* Spain */
+	{"FI", 0x26}, /* Finland */
+	{"FR", 0x26}, /* France */
+	{"GB", 0x26}, /* Great Britain (United Kingdom; England) */
+	{"GH", 0x26}, /* Ghana */
+	{"GR", 0x26}, /* Greece */
+	{"GT", 0x34}, /* Guatemala */
+	{"HK", 0x26}, /* Hong Kong */
+	{"HN", 0x32}, /* Honduras */
+	{"HR", 0x26}, /* Croatia */
+	{"HU", 0x26}, /* Hungary */
+	{"ID", 0x54}, /* Indonesia */
+	{"IE", 0x26}, /* Ireland */
+	{"IL", 0x47}, /* Israel */
+	{"IN", 0x47}, /* India */
+	{"IQ", 0x26}, /* Iraq */
+	{"IS", 0x26}, /* Iceland */
+	{"IT", 0x26}, /* Italy */
+	{"JM", 0x51}, /* Jamaica */
+	{"JO", 0x49}, /* Jordan */
+	{"JP", 0x27}, /* Japan- Telec */
+	{"KE", 0x47}, /* Kenya */
+	{"KG", 0x26}, /* Kyrgyzstan */
+	{"KH", 0x26}, /* Cambodia */
+	{"KR", 0x28}, /* South Korea */
+	{"KW", 0x47}, /* Kuwait */
+	{"KZ", 0x26}, /* Kazakhstan */
+	{"LB", 0x26}, /* Lebanon */
+	{"LI", 0x26}, /* Liechtenstein */
+	{"LK", 0x26}, /* Sri Lanka */
+	{"LS", 0x26}, /* Lesotho */
+	{"LT", 0x26}, /* Lithuania */
+	{"LU", 0x26}, /* Luxembourg */
+	{"LV", 0x26}, /* Latvia */
+	{"MA", 0x47}, /* Morocco */
+	{"MC", 0x26}, /* Monaco */
+	{"ME", 0x26}, /* Montenegro */
+	{"MK", 0x26}, /* Republic of Macedonia (FYROM) */
+	{"MT", 0x26}, /* Malta */
+	{"MX", 0x34}, /* Mexico */
+	{"MY", 0x47}, /* Malaysia */
+	{"MZ", 0x26}, /* Mozambique */
+	{"NA", 0x26}, /* Namibia */
+	{"NG", 0x50}, /* Nigeria */
+	{"NI", 0x34}, /* Nicaragua */
+	{"NL", 0x26}, /* Netherlands */
+	{"NO", 0x26}, /* Norway */
+	{"NZ", 0x45}, /* New Zealand */
+	{"OM", 0x26}, /* Oman */
+	{"PA", 0x34}, /* Panama */
+	{"PE", 0x34}, /* Peru */
+	{"PG", 0x26}, /* Papua New Guinea */
+	{"PH", 0x26}, /* Philippines */
+	{"PK", 0x51}, /* Pakistan */
+	{"PL", 0x26}, /* Poland */
+	{"PR", 0x34}, /* Puerto Rico */
+	{"PT", 0x26}, /* Portugal */
+	{"PY", 0x34}, /* Paraguay */
+	{"QA", 0x51}, /* Qatar */
+	{"RO", 0x26}, /* Romania */
+	{"RS", 0x26}, /* Serbia */
+	{"RU", 0x59}, /* Russia, fac/gost */
+	{"SA", 0x26}, /* Saudi Arabia */
+	{"SE", 0x26}, /* Sweden */
+	{"SG", 0x47}, /* Singapore */
+	{"SI", 0x26}, /* Slovenia */
+	{"SK", 0x26}, /* Slovakia */
+	{"SN", 0x26}, /* Senegal */
+	{"SV", 0x30}, /* El Salvador */
+	{"TH", 0x26}, /* Thailand */
+	{"TN", 0x47}, /* Tunisia */
+	{"TR", 0x26}, /* Turkey */
+	{"TT", 0x42}, /* Trinidad & Tobago */
+	{"TW", 0x39}, /* Taiwan */
+	{"UA", 0x26}, /* Ukraine */
+	{"US", 0x34}, /* United States of America (USA) */
+	{"UY", 0x34}, /* Uruguay */
+	{"VE", 0x30}, /* Venezuela */
+	{"VN", 0x26}, /* Vietnam */
+	{"YE", 0x26}, /* Yemen */
+	{"ZA", 0x26}, /* South Africa */
+	{"ZW", 0x26}, /* Zimbabwe */
+};
+
+u16 country_chplan_map_sz = sizeof(country_chplan_map)/sizeof(struct country_chplan);
+
+/*
+* rtw_get_chplan_from_country -
+* @country_code: string of country code
+*
+* Return channel_plan index or -1 when unsupported country_code is given
+*/
+int rtw_get_chplan_from_country(const char *country_code)
+{
+	int channel_plan = -1;
+	int i;
+
+	/* TODO: should consider 3-character country code? */
+
+	for (i = 0; i < country_chplan_map_sz; i++) {
+		if (strncmp(country_code, country_chplan_map[i].alpha2, 2) == 0) {
+			channel_plan = country_chplan_map[i].chplan;
+			break;
+		}
+	}
+
+	return channel_plan;
+}
+
+int rtw_ch_to_bb_gain_sel(int ch)
+{
+	int sel = -1;
+
+	if (ch >= 1 && ch <= 14)
+		sel = BB_GAIN_2G;
+#ifdef CONFIG_IEEE80211_BAND_5GHZ
+	else if (ch >= 36 && ch < 48)
+		sel = BB_GAIN_5GLB1;
+	else if (ch >= 52 && ch <= 64)
+		sel = BB_GAIN_5GLB2;
+	else if (ch >= 100 && ch <= 120)
+		sel = BB_GAIN_5GMB1;
+	else if (ch >= 124 && ch <= 144)
+		sel = BB_GAIN_5GMB2;
+	else if (ch >= 149 && ch <= 177)
+		sel = BB_GAIN_5GHB;
+#endif
+
+	return sel;
+}
+
+s8 rtw_rf_get_kfree_tx_gain_offset(_adapter *padapter, u8 path, u8 ch)
+{
+	s8 kfree_offset = 0;
+
+#ifdef CONFIG_RF_GAIN_OFFSET
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(padapter);
+	struct kfree_data_t *kfree_data = GET_KFREE_DATA(padapter);
+	s8 bb_gain_sel = rtw_ch_to_bb_gain_sel(ch);
+
+	if (bb_gain_sel < BB_GAIN_2G || bb_gain_sel >= BB_GAIN_NUM) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (kfree_data->flag & KFREE_FLAG_ON) {
+		kfree_offset = kfree_data->bb_gain[bb_gain_sel][path];
+		if (1)
+			DBG_871X("%s path:%u, ch:%u, bb_gain_sel:%d, kfree_offset:%d\n"
+				, __func__, path, ch, bb_gain_sel, kfree_offset);
+	}
+exit:
+#endif /* CONFIG_RF_GAIN_OFFSET */
+	return kfree_offset;
+}
+
+void rtw_rf_set_tx_gain_offset(_adapter *adapter, u8 path, s8 offset)
+{
+	u8 write_value;
+
+	DBG_871X("kfree gain_offset 0x55:0x%x ", rtw_hal_read_rfreg(adapter, path, 0x55, 0xffffffff));
+	switch (rtw_get_chip_type(adapter)) {
+#ifdef CONFIG_RTL8703B
+	case RTL8703B:
+		write_value = RF_TX_GAIN_OFFSET_8703B(offset);
+		rtw_hal_write_rfreg(adapter, path, 0x55, 0x0fc000, write_value);
+		break;
+#endif /* CONFIG_RTL8703B */
+#ifdef CONFIG_RTL8188F
+	case RTL8188F:
+		write_value = RF_TX_GAIN_OFFSET_8188F(offset);
+		rtw_hal_write_rfreg(adapter, path, 0x55, 0x0fc000, write_value);
+		break;
+#endif /* CONFIG_RTL8188F */
+#ifdef CONFIG_RTL8192E
+	case RTL8192E:
+		write_value = RF_TX_GAIN_OFFSET_8192E(offset);
+		rtw_hal_write_rfreg(adapter, path, 0x55, 0x0f8000, write_value);
+		break;
+#endif /* CONFIG_RTL8188F */
+
+#ifdef CONFIG_RTL8821A
+	case RTL8821:
+		write_value = RF_TX_GAIN_OFFSET_8821A(offset);
+		rtw_hal_write_rfreg(adapter, path, 0x55, 0x0f8000, write_value);
+		break;
+#endif /* CONFIG_RTL8821A */
+#ifdef CONFIG_RTL8814A
+		case RTL8814A:
+		DBG_871X("\nkfree by PhyDM on the sw CH. path %d\n", path);
+		break;
+#endif /* CONFIG_RTL8821A */
+
+	default:
+		rtw_warn_on(1);
+		break;
+	}
+
+	DBG_871X(" after :0x%x\n", rtw_hal_read_rfreg(adapter, path, 0x55, 0xffffffff));
+}
+
+void rtw_rf_apply_tx_gain_offset(_adapter *adapter, u8 ch)
+{
+	HAL_DATA_TYPE *hal_data = GET_HAL_DATA(adapter);
+	s8 kfree_offset = 0;
+	s8 tx_pwr_track_offset = 0; /* TODO: 8814A should consider tx pwr track when setting tx gain offset */
+	s8 total_offset;
+	int i;
+
+	for (i = 0; i < hal_data->NumTotalRFPath; i++) {
+		kfree_offset = rtw_rf_get_kfree_tx_gain_offset(adapter, i, ch);
+		total_offset = kfree_offset + tx_pwr_track_offset;
+		rtw_rf_set_tx_gain_offset(adapter, i, total_offset);
+	}
+}
+
+bool rtw_is_dfs_range(u32 hi, u32 lo)
+{
+	return rtw_is_range_overlap(hi, lo, 5720 + 10, 5260 - 10)?_TRUE:_FALSE;
+}
+
+bool rtw_is_dfs_ch(u8 ch, u8 bw, u8 offset)
+{
+	u32 hi, lo;
+
+	if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
+		return _FALSE;
+
+	return rtw_is_dfs_range(hi, lo)?_TRUE:_FALSE;
+}
+
+bool rtw_is_long_cac_range(u32 hi, u32 lo)
+{
+	return rtw_is_range_overlap(hi, lo, 5660 + 10, 5600 - 10)?_TRUE:_FALSE;
+}
+
+bool rtw_is_long_cac_ch(u8 ch, u8 bw, u8 offset)
+{
+	u32 hi, lo;
+
+	if (rtw_chbw_to_freq_range(ch, bw, offset, &hi, &lo) == _FALSE)
+		return _FALSE;
+
+	return rtw_is_long_cac_range(hi, lo)?_TRUE:_FALSE;
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_security.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_security.c
new file mode 100644
index 000000000..52b4cea45
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_security.c
@@ -0,0 +1,3320 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define  _RTW_SECURITY_C_
+
+#include <drv_types.h>
+
+static const char *_security_type_str[] = {
+	"N/A",
+	"WEP40",
+	"TKIP",
+	"TKIP_WM",
+	"AES",
+	"WEP104",
+	"SMS4",
+	"WEP_WPA",
+	"BIP",
+};
+
+const char *security_type_str(u8 value)
+{
+#ifdef CONFIG_IEEE80211W
+	if (value <= _BIP_)
+#else
+	if (value <= _WEP_WPA_MIXED_)
+#endif
+		return _security_type_str[value];
+	return NULL;
+}
+
+#ifdef DBG_SW_SEC_CNT
+#define WEP_SW_ENC_CNT_INC(sec, ra) \
+	if (is_broadcast_mac_addr(ra)) \
+		sec->wep_sw_enc_cnt_bc++; \
+	else if (is_multicast_mac_addr(ra)) \
+		sec->wep_sw_enc_cnt_mc++; \
+	else \
+		sec->wep_sw_enc_cnt_uc++;
+
+#define WEP_SW_DEC_CNT_INC(sec, ra) \
+	if (is_broadcast_mac_addr(ra)) \
+		sec->wep_sw_dec_cnt_bc++; \
+	else if (is_multicast_mac_addr(ra)) \
+		sec->wep_sw_dec_cnt_mc++; \
+	else \
+		sec->wep_sw_dec_cnt_uc++;
+
+#define TKIP_SW_ENC_CNT_INC(sec, ra) \
+	if (is_broadcast_mac_addr(ra)) \
+		sec->tkip_sw_enc_cnt_bc++; \
+	else if (is_multicast_mac_addr(ra)) \
+		sec->tkip_sw_enc_cnt_mc++; \
+	else \
+		sec->tkip_sw_enc_cnt_uc++;
+
+#define TKIP_SW_DEC_CNT_INC(sec, ra) \
+	if (is_broadcast_mac_addr(ra)) \
+		sec->tkip_sw_dec_cnt_bc++; \
+	else if (is_multicast_mac_addr(ra)) \
+		sec->tkip_sw_dec_cnt_mc++; \
+	else \
+		sec->tkip_sw_dec_cnt_uc++;
+
+#define AES_SW_ENC_CNT_INC(sec, ra) \
+	if (is_broadcast_mac_addr(ra)) \
+		sec->aes_sw_enc_cnt_bc++; \
+	else if (is_multicast_mac_addr(ra)) \
+		sec->aes_sw_enc_cnt_mc++; \
+	else \
+		sec->aes_sw_enc_cnt_uc++;
+
+#define AES_SW_DEC_CNT_INC(sec, ra) \
+	if (is_broadcast_mac_addr(ra)) \
+		sec->aes_sw_dec_cnt_bc++; \
+	else if (is_multicast_mac_addr(ra)) \
+		sec->aes_sw_dec_cnt_mc++; \
+	else \
+		sec->aes_sw_dec_cnt_uc++;
+#else
+#define WEP_SW_ENC_CNT_INC(sec, ra)
+#define WEP_SW_DEC_CNT_INC(sec, ra)
+#define TKIP_SW_ENC_CNT_INC(sec, ra)
+#define TKIP_SW_DEC_CNT_INC(sec, ra)
+#define AES_SW_ENC_CNT_INC(sec, ra)
+#define AES_SW_DEC_CNT_INC(sec, ra)
+#endif /* DBG_SW_SEC_CNT */
+
+//=====WEP related===== 
+
+#define CRC32_POLY 0x04c11db7
+
+struct arc4context
+{
+	u32 x;
+	u32 y;
+	u8 state[256];
+};
+
+
+static void arcfour_init(struct arc4context 	*parc4ctx, u8 * key,u32	key_len)
+{
+	u32	t, u;
+	u32	keyindex;
+	u32	stateindex;
+	u8 * state;
+	u32	counter;
+_func_enter_;
+	state = parc4ctx->state;
+	parc4ctx->x = 0;
+	parc4ctx->y = 0;
+	for (counter = 0; counter < 256; counter++)
+		state[counter] = (u8)counter;
+	keyindex = 0;
+	stateindex = 0;
+	for (counter = 0; counter < 256; counter++)
+	{
+		t = state[counter];
+		stateindex = (stateindex + key[keyindex] + t) & 0xff;
+		u = state[stateindex];
+		state[stateindex] = (u8)t;
+		state[counter] = (u8)u;
+		if (++keyindex >= key_len)
+			keyindex = 0;
+	}
+_func_exit_;	
+}
+static u32 arcfour_byte(	struct arc4context	*parc4ctx)
+{
+	u32 x;
+	u32 y;
+	u32 sx, sy;
+	u8 * state;
+_func_enter_;
+	state = parc4ctx->state;
+	x = (parc4ctx->x + 1) & 0xff;
+	sx = state[x];
+	y = (sx + parc4ctx->y) & 0xff;
+	sy = state[y];
+	parc4ctx->x = x;
+	parc4ctx->y = y;
+	state[y] = (u8)sx;
+	state[x] = (u8)sy;
+_func_exit_;	
+	return state[(sx + sy) & 0xff];
+}
+              
+           
+static void arcfour_encrypt(	struct arc4context	*parc4ctx, 
+	u8 * dest,
+	u8 * src, 
+	u32 len)
+{
+	u32	i;
+_func_enter_;	
+	for (i = 0; i < len; i++)
+		dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
+_func_exit_;		
+}
+
+static sint bcrc32initialized = 0;
+static u32 crc32_table[256];
+
+
+static u8 crc32_reverseBit( u8 data)
+{
+	return( (u8)((data<<7)&0x80) | ((data<<5)&0x40) | ((data<<3)&0x20) | ((data<<1)&0x10) | ((data>>1)&0x08) | ((data>>3)&0x04) | ((data>>5)&0x02) | ((data>>7)&0x01) );
+}
+
+static void crc32_init(void)
+{
+_func_enter_;	
+	if (bcrc32initialized == 1) 
+		goto exit;
+	else{
+		sint i, j;
+		u32 c;
+		u8 *p=(u8 *)&c, *p1;
+		u8 k;
+
+		c = 0x12340000;
+
+		for (i = 0; i < 256; ++i) 
+		{
+			k = crc32_reverseBit((u8)i);
+			for (c = ((u32)k) << 24, j = 8; j > 0; --j){
+				c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY : (c << 1);
+			}
+			p1 = (u8 *)&crc32_table[i];
+
+			p1[0] = crc32_reverseBit(p[3]);
+			p1[1] = crc32_reverseBit(p[2]);
+			p1[2] = crc32_reverseBit(p[1]);
+			p1[3] = crc32_reverseBit(p[0]);
+		}
+		bcrc32initialized= 1;
+	}
+exit:	
+_func_exit_;			
+}
+
+static u32 getcrc32(u8 *buf, sint len)
+{
+	u8 *p;
+	u32  crc;
+_func_enter_;	
+	if (bcrc32initialized == 0) crc32_init();
+
+	crc = 0xffffffff;       /* preload shift register, per CRC-32 spec */
+
+	for (p = buf; len > 0; ++p, --len) 
+	{
+		crc = crc32_table[ (crc ^ *p) & 0xff] ^ (crc >> 8);
+	}
+_func_exit_;				
+	return ~crc;    /* transmit complement, per CRC-32 spec */
+}
+
+
+/*
+	Need to consider the fragment  situation
+*/
+void rtw_wep_encrypt(_adapter *padapter, u8 *pxmitframe)
+{																	// exclude ICV
+	
+	unsigned char	crc[4];
+	struct arc4context	 mycontext;
+
+	sint	curfragnum,length;
+	u32	keylength;
+
+	u8	*pframe, *payload,*iv;    //,*wepkey
+	u8	wepkey[16];
+	u8   hw_hdr_offset=0;
+	struct	pkt_attrib	 *pattrib = &((struct xmit_frame*)pxmitframe)->attrib;
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+	struct	xmit_priv		*pxmitpriv=&padapter->xmitpriv;
+	
+_func_enter_;	
+
+	
+	if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL)
+		return;
+
+#ifdef CONFIG_USB_TX_AGGREGATION
+	hw_hdr_offset = TXDESC_SIZE +
+		 (((struct xmit_frame*)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);	
+#else
+	#ifdef CONFIG_TX_EARLY_MODE
+	hw_hdr_offset = TXDESC_OFFSET+EARLY_MODE_INFO_SIZE;
+	#else
+	hw_hdr_offset = TXDESC_OFFSET;
+	#endif
+#endif
+
+	pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + hw_hdr_offset;
+	
+	//start to encrypt each fragment
+	if((pattrib->encrypt==_WEP40_)||(pattrib->encrypt==_WEP104_))
+	{
+		keylength=psecuritypriv->dot11DefKeylen[psecuritypriv->dot11PrivacyKeyIndex];
+
+		for(curfragnum=0;curfragnum<pattrib->nr_frags;curfragnum++)
+		{
+			iv=pframe+pattrib->hdrlen;
+			_rtw_memcpy(&wepkey[0], iv, 3);
+			_rtw_memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0],keylength);
+			payload=pframe+pattrib->iv_len+pattrib->hdrlen;
+
+			if((curfragnum+1)==pattrib->nr_frags)
+			{	//the last fragment
+			
+				length=pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
+			
+				*((u32 *)crc)=cpu_to_le32(getcrc32(payload,length));
+
+				arcfour_init(&mycontext, wepkey,3+keylength);
+				arcfour_encrypt(&mycontext, payload, payload, length);
+				arcfour_encrypt(&mycontext, payload+length, crc, 4);
+
+			}
+			else
+			{
+			length=pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
+				*((u32 *)crc)=cpu_to_le32(getcrc32(payload,length));
+				arcfour_init(&mycontext, wepkey,3+keylength);
+				arcfour_encrypt(&mycontext, payload, payload, length);
+				arcfour_encrypt(&mycontext, payload+length, crc, 4);
+	
+			pframe+=pxmitpriv->frag_len;
+			pframe=(u8 *)RND4((SIZE_PTR)(pframe));
+
+			}
+			
+		}		
+
+		WEP_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
+	}
+	
+_func_exit_;						
+
+}
+
+void rtw_wep_decrypt(_adapter  *padapter, u8 *precvframe)
+{								
+	// exclude ICV
+	u8	crc[4];
+	struct arc4context	 mycontext;
+	sint 	length;
+	u32	keylength;
+	u8	*pframe, *payload,*iv,wepkey[16];
+	u8	 keyindex;
+	struct	rx_pkt_attrib	 *prxattrib = &(((union recv_frame*)precvframe)->u.hdr.attrib);
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+
+_func_enter_;	
+
+	pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+	
+	//start to decrypt recvframe
+	if((prxattrib->encrypt==_WEP40_)||(prxattrib->encrypt==_WEP104_))
+	{
+		iv=pframe+prxattrib->hdrlen;
+		//keyindex=(iv[3]&0x3);
+		keyindex = prxattrib->key_index;
+		keylength=psecuritypriv->dot11DefKeylen[keyindex];
+		_rtw_memcpy(&wepkey[0], iv, 3);
+		//_rtw_memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[psecuritypriv->dot11PrivacyKeyIndex].skey[0],keylength);
+		_rtw_memcpy(&wepkey[3], &psecuritypriv->dot11DefKey[keyindex].skey[0],keylength);
+		length= ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+
+		payload=pframe+prxattrib->iv_len+prxattrib->hdrlen;
+		
+		//decrypt payload include icv
+		arcfour_init(&mycontext, wepkey,3+keylength);
+		arcfour_encrypt(&mycontext, payload, payload,  length);
+				
+		//calculate icv and compare the icv
+		*((u32 *)crc)=le32_to_cpu(getcrc32(payload,length-4));
+		
+		if(crc[3]!=payload[length-1] || crc[2]!=payload[length-2] || crc[1]!=payload[length-3] || crc[0]!=payload[length-4])
+		{
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
+						crc[3],payload[length-1],crc[2],payload[length-2],crc[1],payload[length-3],crc[0],payload[length-4]));
+		}
+
+		WEP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
+	}
+	
+_func_exit_;		
+
+	return;
+	
+}
+
+//3 		=====TKIP related=====
+
+static u32 secmicgetuint32( u8 * p )
+// Convert from Byte[] to Us4Byte32 in a portable way
+{
+	s32 i;
+	u32 res = 0;
+_func_enter_;		
+	for( i=0; i<4; i++ )
+	{
+		res |= ((u32)(*p++)) << (8*i);
+	}
+_func_exit_;		
+	return res;
+}
+
+static void secmicputuint32( u8 * p, u32 val )
+// Convert from Us4Byte32 to Byte[] in a portable way
+{
+	long i;
+_func_enter_;			
+	for( i=0; i<4; i++ )
+	{
+		*p++ = (u8) (val & 0xff);
+		val >>= 8;
+	}
+_func_exit_;		
+}
+
+static void secmicclear(struct mic_data *pmicdata)
+{
+// Reset the state to the empty message.
+_func_enter_;	
+	pmicdata->L = pmicdata->K0;
+	pmicdata->R = pmicdata->K1;
+	pmicdata->nBytesInM = 0;
+	pmicdata->M = 0;
+_func_exit_;	
+}
+
+void rtw_secmicsetkey(struct mic_data *pmicdata, u8 * key )
+{
+	// Set the key
+_func_enter_;		
+	pmicdata->K0 = secmicgetuint32( key );
+	pmicdata->K1 = secmicgetuint32( key + 4 );
+	// and reset the message
+	secmicclear(pmicdata);
+_func_exit_;		
+}
+
+void rtw_secmicappendbyte(struct mic_data *pmicdata, u8 b )
+{
+_func_enter_;	
+	// Append the byte to our word-sized buffer
+	pmicdata->M |= ((unsigned long)b) << (8*pmicdata->nBytesInM);
+	pmicdata->nBytesInM++;
+	// Process the word if it is full.
+	if( pmicdata->nBytesInM >= 4 )
+	{
+		pmicdata->L ^= pmicdata->M;
+		pmicdata->R ^= ROL32( pmicdata->L, 17 );
+		pmicdata->L += pmicdata->R;
+		pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) | ((pmicdata->L & 0x00ff00ff) << 8);
+		pmicdata->L += pmicdata->R;
+		pmicdata->R ^= ROL32( pmicdata->L, 3 );
+		pmicdata->L += pmicdata->R;
+		pmicdata->R ^= ROR32( pmicdata->L, 2 );
+		pmicdata->L += pmicdata->R;
+		// Clear the buffer
+		pmicdata->M = 0;
+		pmicdata->nBytesInM = 0;
+	}
+_func_exit_;			
+}
+
+void rtw_secmicappend(struct mic_data *pmicdata, u8 * src, u32 nbytes )
+{
+_func_enter_;	
+	// This is simple
+	while( nbytes > 0 )
+	{
+		rtw_secmicappendbyte(pmicdata, *src++ );
+		nbytes--;
+	}
+_func_exit_;			
+}
+
+void rtw_secgetmic(struct mic_data *pmicdata, u8 * dst )
+{
+_func_enter_;	
+	// Append the minimum padding
+	rtw_secmicappendbyte(pmicdata, 0x5a );
+	rtw_secmicappendbyte(pmicdata, 0 );
+	rtw_secmicappendbyte(pmicdata, 0 );
+	rtw_secmicappendbyte(pmicdata, 0 );
+	rtw_secmicappendbyte(pmicdata, 0 );
+	// and then zeroes until the length is a multiple of 4
+	while( pmicdata->nBytesInM != 0 )
+	{
+		rtw_secmicappendbyte(pmicdata, 0 );
+	}
+	// The appendByte function has already computed the result.
+	secmicputuint32( dst, pmicdata->L );
+	secmicputuint32( dst+4, pmicdata->R );
+	// Reset to the empty message.
+	secmicclear(pmicdata);
+_func_exit_;		
+}
+
+
+void rtw_seccalctkipmic(u8 * key,u8 *header,u8 *data,u32 data_len,u8 *mic_code, u8 pri)
+{
+
+	struct mic_data	micdata;
+	u8 priority[4]={0x0,0x0,0x0,0x0};
+_func_enter_;		
+	rtw_secmicsetkey(&micdata, key);
+	priority[0]=pri;
+	
+	/* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
+	if(header[1]&1){   //ToDS==1
+			rtw_secmicappend(&micdata, &header[16], 6);  //DA
+		if(header[1]&2)  //From Ds==1
+			rtw_secmicappend(&micdata, &header[24], 6);
+		else
+			rtw_secmicappend(&micdata, &header[10], 6);		
+	}	
+	else{	//ToDS==0
+		rtw_secmicappend(&micdata, &header[4], 6);   //DA
+		if(header[1]&2)  //From Ds==1
+			rtw_secmicappend(&micdata, &header[16], 6);
+		else
+			rtw_secmicappend(&micdata, &header[10], 6);
+
+	}
+	rtw_secmicappend(&micdata, &priority[0], 4);
+
+	
+	rtw_secmicappend(&micdata, data, data_len);
+
+	rtw_secgetmic(&micdata,mic_code);
+_func_exit_;	
+}
+
+
+
+
+/* macros for extraction/creation of unsigned char/unsigned short values  */
+#define RotR1(v16)   ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
+#define   Lo8(v16)   ((u8)( (v16)       & 0x00FF))
+#define   Hi8(v16)   ((u8)(((v16) >> 8) & 0x00FF))
+#define  Lo16(v32)   ((u16)( (v32)       & 0xFFFF))
+#define  Hi16(v32)   ((u16)(((v32) >>16) & 0xFFFF))
+#define  Mk16(hi,lo) ((lo) ^ (((u16)(hi)) << 8))
+
+/* select the Nth 16-bit word of the temporal key unsigned char array TK[]   */
+#define  TK16(N)     Mk16(tk[2*(N)+1],tk[2*(N)])
+
+/* S-box lookup: 16 bits --> 16 bits */
+#define _S_(v16)     (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
+
+/* fixed algorithm "parameters" */
+#define PHASE1_LOOP_CNT   8    /* this needs to be "big enough"     */
+#define TA_SIZE           6    /*  48-bit transmitter address       */
+#define TK_SIZE          16    /* 128-bit temporal key              */
+#define P1K_SIZE         10    /*  80-bit Phase1 key                */
+#define RC4_KEY_SIZE     16    /* 128-bit RC4KEY (104 bits unknown) */
+
+
+/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
+static const unsigned short Sbox1[2][256]=       /* Sbox for hash (can be in ROM)     */
+{ {
+   0xC6A5,0xF884,0xEE99,0xF68D,0xFF0D,0xD6BD,0xDEB1,0x9154,
+   0x6050,0x0203,0xCEA9,0x567D,0xE719,0xB562,0x4DE6,0xEC9A,
+   0x8F45,0x1F9D,0x8940,0xFA87,0xEF15,0xB2EB,0x8EC9,0xFB0B,
+   0x41EC,0xB367,0x5FFD,0x45EA,0x23BF,0x53F7,0xE496,0x9B5B,
+   0x75C2,0xE11C,0x3DAE,0x4C6A,0x6C5A,0x7E41,0xF502,0x834F,
+   0x685C,0x51F4,0xD134,0xF908,0xE293,0xAB73,0x6253,0x2A3F,
+   0x080C,0x9552,0x4665,0x9D5E,0x3028,0x37A1,0x0A0F,0x2FB5,
+   0x0E09,0x2436,0x1B9B,0xDF3D,0xCD26,0x4E69,0x7FCD,0xEA9F,
+   0x121B,0x1D9E,0x5874,0x342E,0x362D,0xDCB2,0xB4EE,0x5BFB,
+   0xA4F6,0x764D,0xB761,0x7DCE,0x527B,0xDD3E,0x5E71,0x1397,
+   0xA6F5,0xB968,0x0000,0xC12C,0x4060,0xE31F,0x79C8,0xB6ED,
+   0xD4BE,0x8D46,0x67D9,0x724B,0x94DE,0x98D4,0xB0E8,0x854A,
+   0xBB6B,0xC52A,0x4FE5,0xED16,0x86C5,0x9AD7,0x6655,0x1194,
+   0x8ACF,0xE910,0x0406,0xFE81,0xA0F0,0x7844,0x25BA,0x4BE3,
+   0xA2F3,0x5DFE,0x80C0,0x058A,0x3FAD,0x21BC,0x7048,0xF104,
+   0x63DF,0x77C1,0xAF75,0x4263,0x2030,0xE51A,0xFD0E,0xBF6D,
+   0x814C,0x1814,0x2635,0xC32F,0xBEE1,0x35A2,0x88CC,0x2E39,
+   0x9357,0x55F2,0xFC82,0x7A47,0xC8AC,0xBAE7,0x322B,0xE695,
+   0xC0A0,0x1998,0x9ED1,0xA37F,0x4466,0x547E,0x3BAB,0x0B83,
+   0x8CCA,0xC729,0x6BD3,0x283C,0xA779,0xBCE2,0x161D,0xAD76,
+   0xDB3B,0x6456,0x744E,0x141E,0x92DB,0x0C0A,0x486C,0xB8E4,
+   0x9F5D,0xBD6E,0x43EF,0xC4A6,0x39A8,0x31A4,0xD337,0xF28B,
+   0xD532,0x8B43,0x6E59,0xDAB7,0x018C,0xB164,0x9CD2,0x49E0,
+   0xD8B4,0xACFA,0xF307,0xCF25,0xCAAF,0xF48E,0x47E9,0x1018,
+   0x6FD5,0xF088,0x4A6F,0x5C72,0x3824,0x57F1,0x73C7,0x9751,
+   0xCB23,0xA17C,0xE89C,0x3E21,0x96DD,0x61DC,0x0D86,0x0F85,
+   0xE090,0x7C42,0x71C4,0xCCAA,0x90D8,0x0605,0xF701,0x1C12,
+   0xC2A3,0x6A5F,0xAEF9,0x69D0,0x1791,0x9958,0x3A27,0x27B9,
+   0xD938,0xEB13,0x2BB3,0x2233,0xD2BB,0xA970,0x0789,0x33A7,
+   0x2DB6,0x3C22,0x1592,0xC920,0x8749,0xAAFF,0x5078,0xA57A,
+   0x038F,0x59F8,0x0980,0x1A17,0x65DA,0xD731,0x84C6,0xD0B8,
+   0x82C3,0x29B0,0x5A77,0x1E11,0x7BCB,0xA8FC,0x6DD6,0x2C3A,
+  },
+ 
+
+  {  /* second half of table is unsigned char-reversed version of first! */
+   0xA5C6,0x84F8,0x99EE,0x8DF6,0x0DFF,0xBDD6,0xB1DE,0x5491,
+   0x5060,0x0302,0xA9CE,0x7D56,0x19E7,0x62B5,0xE64D,0x9AEC,
+   0x458F,0x9D1F,0x4089,0x87FA,0x15EF,0xEBB2,0xC98E,0x0BFB,
+   0xEC41,0x67B3,0xFD5F,0xEA45,0xBF23,0xF753,0x96E4,0x5B9B,
+   0xC275,0x1CE1,0xAE3D,0x6A4C,0x5A6C,0x417E,0x02F5,0x4F83,
+   0x5C68,0xF451,0x34D1,0x08F9,0x93E2,0x73AB,0x5362,0x3F2A,
+   0x0C08,0x5295,0x6546,0x5E9D,0x2830,0xA137,0x0F0A,0xB52F,
+   0x090E,0x3624,0x9B1B,0x3DDF,0x26CD,0x694E,0xCD7F,0x9FEA,
+   0x1B12,0x9E1D,0x7458,0x2E34,0x2D36,0xB2DC,0xEEB4,0xFB5B,
+   0xF6A4,0x4D76,0x61B7,0xCE7D,0x7B52,0x3EDD,0x715E,0x9713,
+   0xF5A6,0x68B9,0x0000,0x2CC1,0x6040,0x1FE3,0xC879,0xEDB6,
+   0xBED4,0x468D,0xD967,0x4B72,0xDE94,0xD498,0xE8B0,0x4A85,
+   0x6BBB,0x2AC5,0xE54F,0x16ED,0xC586,0xD79A,0x5566,0x9411,
+   0xCF8A,0x10E9,0x0604,0x81FE,0xF0A0,0x4478,0xBA25,0xE34B,
+   0xF3A2,0xFE5D,0xC080,0x8A05,0xAD3F,0xBC21,0x4870,0x04F1,
+   0xDF63,0xC177,0x75AF,0x6342,0x3020,0x1AE5,0x0EFD,0x6DBF,
+   0x4C81,0x1418,0x3526,0x2FC3,0xE1BE,0xA235,0xCC88,0x392E,
+   0x5793,0xF255,0x82FC,0x477A,0xACC8,0xE7BA,0x2B32,0x95E6,
+   0xA0C0,0x9819,0xD19E,0x7FA3,0x6644,0x7E54,0xAB3B,0x830B,
+   0xCA8C,0x29C7,0xD36B,0x3C28,0x79A7,0xE2BC,0x1D16,0x76AD,
+   0x3BDB,0x5664,0x4E74,0x1E14,0xDB92,0x0A0C,0x6C48,0xE4B8,
+   0x5D9F,0x6EBD,0xEF43,0xA6C4,0xA839,0xA431,0x37D3,0x8BF2,
+   0x32D5,0x438B,0x596E,0xB7DA,0x8C01,0x64B1,0xD29C,0xE049,
+   0xB4D8,0xFAAC,0x07F3,0x25CF,0xAFCA,0x8EF4,0xE947,0x1810,
+   0xD56F,0x88F0,0x6F4A,0x725C,0x2438,0xF157,0xC773,0x5197,
+   0x23CB,0x7CA1,0x9CE8,0x213E,0xDD96,0xDC61,0x860D,0x850F,
+   0x90E0,0x427C,0xC471,0xAACC,0xD890,0x0506,0x01F7,0x121C,
+   0xA3C2,0x5F6A,0xF9AE,0xD069,0x9117,0x5899,0x273A,0xB927,
+   0x38D9,0x13EB,0xB32B,0x3322,0xBBD2,0x70A9,0x8907,0xA733,
+   0xB62D,0x223C,0x9215,0x20C9,0x4987,0xFFAA,0x7850,0x7AA5,
+   0x8F03,0xF859,0x8009,0x171A,0xDA65,0x31D7,0xC684,0xB8D0,
+   0xC382,0xB029,0x775A,0x111E,0xCB7B,0xFCA8,0xD66D,0x3A2C,
+  }
+};
+ 
+ /*
+**********************************************************************
+* Routine: Phase 1 -- generate P1K, given TA, TK, IV32
+*
+* Inputs:
+*     tk[]      = temporal key                         [128 bits]
+*     ta[]      = transmitter's MAC address            [ 48 bits]
+*     iv32      = upper 32 bits of IV                  [ 32 bits]
+* Output:
+*     p1k[]     = Phase 1 key                          [ 80 bits]
+*
+* Note:
+*     This function only needs to be called every 2**16 packets,
+*     although in theory it could be called every packet.
+*
+**********************************************************************
+*/
+static void phase1(u16 *p1k,const u8 *tk,const u8 *ta,u32 iv32)
+{
+	sint  i;
+_func_enter_;
+	/* Initialize the 80 bits of P1K[] from IV32 and TA[0..5]     */
+	p1k[0]      = Lo16(iv32);
+	p1k[1]      = Hi16(iv32);
+	p1k[2]      = Mk16(ta[1],ta[0]); /* use TA[] as little-endian */
+	p1k[3]      = Mk16(ta[3],ta[2]);
+	p1k[4]      = Mk16(ta[5],ta[4]);
+
+	/* Now compute an unbalanced Feistel cipher with 80-bit block */
+	/* size on the 80-bit block P1K[], using the 128-bit key TK[] */
+	for (i=0; i < PHASE1_LOOP_CNT ;i++)
+	{                 /* Each add operation here is mod 2**16 */
+      		p1k[0] += _S_(p1k[4] ^ TK16((i&1)+0));
+		p1k[1] += _S_(p1k[0] ^ TK16((i&1)+2));
+		p1k[2] += _S_(p1k[1] ^ TK16((i&1)+4));
+		p1k[3] += _S_(p1k[2] ^ TK16((i&1)+6));
+		p1k[4] += _S_(p1k[3] ^ TK16((i&1)+0));
+		p1k[4] +=  (unsigned short)i;                    /* avoid "slide attacks" */
+        }
+_func_exit_;
+}
+ 
+
+/*
+**********************************************************************
+* Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
+*
+* Inputs:
+*     tk[]      = Temporal key                         [128 bits]
+*     p1k[]     = Phase 1 output key                   [ 80 bits]
+*     iv16      = low 16 bits of IV counter            [ 16 bits]
+* Output:
+*     rc4key[]  = the key used to encrypt the packet   [128 bits]
+*
+* Note:
+*     The value {TA,IV32,IV16} for Phase1/Phase2 must be unique
+*     across all packets using the same key TK value. Then, for a
+*     given value of TK[], this TKIP48 construction guarantees that
+*     the final RC4KEY value is unique across all packets.
+*
+* Suggested implementation optimization: if PPK[] is "overlaid"
+*     appropriately on RC4KEY[], there is no need for the final
+*     for loop below that copies the PPK[] result into RC4KEY[].
+*
+**********************************************************************
+*/
+static void phase2(u8 *rc4key,const u8 *tk,const u16 *p1k,u16 iv16)
+{
+	sint  i;
+	u16 PPK[6];                          /* temporary key for mixing    */
+_func_enter_;
+	/* Note: all adds in the PPK[] equations below are mod 2**16         */
+	for (i=0;i<5;i++) PPK[i]=p1k[i];      /* first, copy P1K to PPK      */
+		PPK[5]  =  p1k[4] +iv16;             /* next,  add in IV16          */
+
+	/* Bijective non-linear mixing of the 96 bits of PPK[0..5]           */
+	PPK[0] +=    _S_(PPK[5] ^ TK16(0));   /* Mix key in each "round"     */
+	PPK[1] +=    _S_(PPK[0] ^ TK16(1));
+	PPK[2] +=    _S_(PPK[1] ^ TK16(2));
+	PPK[3] +=    _S_(PPK[2] ^ TK16(3));
+	PPK[4] +=    _S_(PPK[3] ^ TK16(4));
+	PPK[5] +=    _S_(PPK[4] ^ TK16(5));   /* Total # S-box lookups == 6  */
+
+	/* Final sweep: bijective, "linear". Rotates kill LSB correlations   */
+	PPK[0] +=  RotR1(PPK[5] ^ TK16(6));
+	PPK[1] +=  RotR1(PPK[0] ^ TK16(7));   /* Use all of TK[] in Phase2   */
+	PPK[2] +=  RotR1(PPK[1]);
+	PPK[3] +=  RotR1(PPK[2]);
+	PPK[4] +=  RotR1(PPK[3]);
+	PPK[5] +=  RotR1(PPK[4]);
+	/* Note: At this point, for a given key TK[0..15], the 96-bit output */
+	/*       value PPK[0..5] is guaranteed to be unique, as a function   */
+	/*       of the 96-bit "input" value   {TA,IV32,IV16}. That is, P1K  */
+	/*       is now a keyed permutation of {TA,IV32,IV16}.               */
+
+	/* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key   */
+	rc4key[0] = Hi8(iv16);                /* RC4KEY[0..2] is the WEP IV  */
+	rc4key[1] =(Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys  */
+	rc4key[2] = Lo8(iv16);
+	rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
+	 
+
+	/* Copy 96 bits of PPK[0..5] to RC4KEY[4..15]  (little-endian)       */
+	for (i=0;i<6;i++)
+	{
+		rc4key[4+2*i] = Lo8(PPK[i]);
+		rc4key[5+2*i] = Hi8(PPK[i]);
+	}
+_func_exit_;	
+}
+
+
+//The hlen isn't include the IV
+u32	rtw_tkip_encrypt(_adapter *padapter, u8 *pxmitframe)
+{																	// exclude ICV
+	u16	pnl;
+	u32	pnh;
+	u8	rc4key[16];
+	u8   ttkey[16];
+	u8	crc[4];
+	u8   hw_hdr_offset = 0;
+	struct arc4context mycontext;
+	sint 			curfragnum,length;
+	u32	prwskeylen;
+
+	u8	*pframe, *payload,*iv,*prwskey;
+	union pn48 dot11txpn;
+	//struct	sta_info		*stainfo;
+	struct	pkt_attrib	 *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+	struct	xmit_priv		*pxmitpriv=&padapter->xmitpriv;
+	u32	res=_SUCCESS;
+_func_enter_;
+
+	if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL)
+		return _FAIL;
+
+#ifdef CONFIG_USB_TX_AGGREGATION
+	hw_hdr_offset = TXDESC_SIZE +
+		 (((struct xmit_frame*)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);	
+#else
+	#ifdef CONFIG_TX_EARLY_MODE
+	hw_hdr_offset = TXDESC_OFFSET+EARLY_MODE_INFO_SIZE;
+	#else
+	hw_hdr_offset = TXDESC_OFFSET;
+	#endif
+#endif
+
+	pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + hw_hdr_offset;
+	//4 start to encrypt each fragment
+	if(pattrib->encrypt==_TKIP_){
+
+/*
+		if(pattrib->psta)
+		{
+			stainfo = pattrib->psta;
+		}
+		else
+		{
+			DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+			stainfo=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0] );
+		}	
+*/	
+		//if (stainfo!=NULL)
+		{
+/*
+			if(!(stainfo->state &_FW_LINKED))
+			{
+				DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
+				return _FAIL;
+			}
+*/			
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_tkip_encrypt: stainfo!=NULL!!!\n"));
+
+			if(IS_MCAST(pattrib->ra))
+			{
+				prwskey=psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+			}
+			else
+			{
+				//prwskey=&stainfo->dot118021x_UncstKey.skey[0];
+				prwskey=pattrib->dot118021x_UncstKey.skey;
+			}
+
+			prwskeylen=16;
+
+			for(curfragnum=0;curfragnum<pattrib->nr_frags;curfragnum++){
+				iv=pframe+pattrib->hdrlen;
+				payload=pframe+pattrib->iv_len+pattrib->hdrlen;
+				
+				GET_TKIP_PN(iv, dot11txpn);
+
+				pnl=(u16)(dot11txpn.val);
+				pnh=(u32)(dot11txpn.val>>16);
+
+				phase1((u16 *)&ttkey[0],prwskey,&pattrib->ta[0],pnh);
+
+				phase2(&rc4key[0],prwskey,(u16 *)&ttkey[0],pnl);	
+
+				if((curfragnum+1)==pattrib->nr_frags){	//4 the last fragment
+					length=pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
+					RT_TRACE(_module_rtl871x_security_c_,_drv_info_,("pattrib->iv_len =%x, pattrib->icv_len =%x\n", pattrib->iv_len,pattrib->icv_len));
+					*((u32 *)crc)=cpu_to_le32(getcrc32(payload,length));/* modified by Amy*/
+
+					arcfour_init(&mycontext, rc4key,16);
+					arcfour_encrypt(&mycontext, payload, payload, length);
+					arcfour_encrypt(&mycontext, payload+length, crc, 4);
+
+				}
+				else{
+					length=pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
+					*((u32 *)crc)=cpu_to_le32(getcrc32(payload,length));/* modified by Amy*/
+					arcfour_init(&mycontext,rc4key,16);
+					arcfour_encrypt(&mycontext, payload, payload, length);
+					arcfour_encrypt(&mycontext, payload+length, crc, 4);
+	
+				pframe+=pxmitpriv->frag_len;
+				pframe=(u8 *)RND4((SIZE_PTR)(pframe));
+
+				}
+			}
+
+			TKIP_SW_ENC_CNT_INC(psecuritypriv,pattrib->ra);
+		}
+/*
+		else{
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_tkip_encrypt: stainfo==NULL!!!\n"));
+                        DBG_871X("%s, psta==NUL\n", __func__);
+			res=_FAIL;
+		}
+*/		
+						
+	}
+_func_exit_;	
+	return res;
+				
+}
+
+
+//The hlen isn't include the IV
+u32 rtw_tkip_decrypt(_adapter *padapter, u8 *precvframe)
+{																	// exclude ICV
+	u16 pnl;
+	u32 pnh;
+	u8   rc4key[16];
+	u8   ttkey[16];
+	u8	crc[4];
+	struct arc4context mycontext;
+	sint 			length;
+	u32	prwskeylen;
+
+	u8	*pframe, *payload,*iv,*prwskey;
+	union pn48 dot11txpn;
+	struct	sta_info		*stainfo;
+	struct	rx_pkt_attrib	 *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+//	struct	recv_priv		*precvpriv=&padapter->recvpriv;
+	u32		res=_SUCCESS;
+
+_func_enter_;
+
+	pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+	
+	//4 start to decrypt recvframe
+	if(prxattrib->encrypt==_TKIP_){
+
+		stainfo=rtw_get_stainfo(&padapter->stapriv ,&prxattrib->ta[0] );
+		if (stainfo!=NULL){
+
+			if(IS_MCAST(prxattrib->ra))
+			{
+				static u32 start = 0;
+				static u32 no_gkey_bc_cnt = 0;
+				static u32 no_gkey_mc_cnt = 0;
+
+				if(psecuritypriv->binstallGrpkey==_FALSE)
+				{
+					res=_FAIL;
+
+					if (start == 0)
+						start = rtw_get_current_time();
+
+					if (is_broadcast_mac_addr(prxattrib->ra))
+						no_gkey_bc_cnt++;
+					else
+						no_gkey_mc_cnt++;
+
+					if (rtw_get_passing_time_ms(start) > 1000) {
+						if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
+							DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
+								FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
+						}
+						start = rtw_get_current_time();
+						no_gkey_bc_cnt = 0;
+						no_gkey_mc_cnt = 0;
+					}
+					goto exit;
+				}
+
+				if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
+					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
+						FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
+				}
+				start = 0;
+				no_gkey_bc_cnt = 0;
+				no_gkey_mc_cnt = 0;
+
+				//DBG_871X("rx bc/mc packets, to perform sw rtw_tkip_decrypt\n");
+				//prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+				prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+				prwskeylen=16;
+			}
+			else
+			{
+				prwskey=&stainfo->dot118021x_UncstKey.skey[0];
+				prwskeylen=16;
+			}
+			
+			iv=pframe+prxattrib->hdrlen;
+			payload=pframe+prxattrib->iv_len+prxattrib->hdrlen;
+			length= ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+				
+			GET_TKIP_PN(iv, dot11txpn);
+
+			pnl=(u16)(dot11txpn.val);
+			pnh=(u32)(dot11txpn.val>>16);
+
+			phase1((u16 *)&ttkey[0],prwskey,&prxattrib->ta[0],pnh);
+			phase2(&rc4key[0],prwskey,(unsigned short *)&ttkey[0],pnl);	
+
+			//4 decrypt payload include icv
+					
+			arcfour_init(&mycontext, rc4key,16);
+			arcfour_encrypt(&mycontext, payload, payload, length);
+
+			*((u32 *)crc)=le32_to_cpu(getcrc32(payload,length-4));
+
+			if(crc[3]!=payload[length-1] || crc[2]!=payload[length-2] || crc[1]!=payload[length-3] || crc[0]!=payload[length-4])
+			{
+			    RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_wep_decrypt:icv error crc[3](%x)!=payload[length-1](%x) || crc[2](%x)!=payload[length-2](%x) || crc[1](%x)!=payload[length-3](%x) || crc[0](%x)!=payload[length-4](%x)\n",
+						crc[3],payload[length-1],crc[2],payload[length-2],crc[1],payload[length-3],crc[0],payload[length-4]));
+				res=_FAIL;
+			}
+
+			TKIP_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
+		}
+		else{
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_tkip_decrypt: stainfo==NULL!!!\n"));
+			res=_FAIL;
+		}
+						
+	}
+_func_exit_;	
+exit:
+	return res;
+				
+}
+
+
+//3			=====AES related=====
+
+
+
+#define MAX_MSG_SIZE	2048
+/*****************************/
+/******** SBOX Table *********/
+/*****************************/
+
+  static  u8 sbox_table[256] =
+    {
+        0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
+        0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+        0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
+        0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+        0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
+        0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+        0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
+        0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+        0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
+        0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+        0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
+        0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+        0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
+        0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+        0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
+        0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+        0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
+        0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+        0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
+        0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+        0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
+        0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+        0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
+        0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+        0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
+        0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+        0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
+        0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+        0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
+        0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+        0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
+        0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
+    };
+
+/*****************************/
+/**** Function Prototypes ****/
+/*****************************/
+
+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out);
+static void construct_mic_iv(
+                        u8 *mic_header1,
+                        sint qc_exists,
+                        sint a4_exists,
+                        u8 *mpdu,
+                        uint payload_length,
+                        u8 * pn_vector,
+                        uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use
+static void construct_mic_header1(
+                        u8 *mic_header1,
+                        sint header_length,
+                        u8 *mpdu,
+                        uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use
+static void construct_mic_header2(
+                    u8 *mic_header2,
+                    u8 *mpdu,
+                    sint a4_exists,
+                    sint qc_exists);
+static void construct_ctr_preload(
+                        u8 *ctr_preload,
+                        sint a4_exists,
+                        sint qc_exists,
+                        u8 *mpdu,
+                        u8 *pn_vector,
+                        sint c,
+                        uint frtype);// add for CONFIG_IEEE80211W, none 11w also can use
+static void xor_128(u8 *a, u8 *b, u8 *out);
+static void xor_32(u8 *a, u8 *b, u8 *out);
+static u8 sbox(u8 a);
+static void next_key(u8 *key, sint round);
+static void byte_sub(u8 *in, u8 *out);
+static void shift_row(u8 *in, u8 *out);
+static void mix_column(u8 *in, u8 *out);
+#ifndef PLATFORM_FREEBSD 
+static void add_round_key( u8 *shiftrow_in,
+                    u8 *mcol_in,
+                    u8 *block_in,
+                    sint round,
+                    u8 *out);
+#endif //PLATFORM_FREEBSD
+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext);
+
+
+/****************************************/
+/* aes128k128d()                        */
+/* Performs a 128 bit AES encrypt with  */
+/* 128 bit data.                        */
+/****************************************/
+static void xor_128(u8 *a, u8 *b, u8 *out)
+{
+    sint i;
+_func_enter_;	
+    for (i=0;i<16; i++)
+    {
+        out[i] = a[i] ^ b[i];
+    }
+_func_exit_;		
+}
+
+
+static void xor_32(u8 *a, u8 *b, u8 *out)
+{
+    sint i;
+_func_enter_;		
+    for (i=0;i<4; i++)
+    {
+        out[i] = a[i] ^ b[i];
+    }
+_func_exit_;		
+}
+
+
+static u8 sbox(u8 a)
+{
+    return sbox_table[(sint)a];
+}
+
+
+static void next_key(u8 *key, sint round)
+{
+    u8 rcon;
+    u8 sbox_key[4];
+    u8 rcon_table[12] =
+    {
+        0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
+        0x1b, 0x36, 0x36, 0x36
+    };
+_func_enter_;		
+    sbox_key[0] = sbox(key[13]);
+    sbox_key[1] = sbox(key[14]);
+    sbox_key[2] = sbox(key[15]);
+    sbox_key[3] = sbox(key[12]);
+
+    rcon = rcon_table[round];
+
+    xor_32(&key[0], sbox_key, &key[0]);
+    key[0] = key[0] ^ rcon;
+
+    xor_32(&key[4], &key[0], &key[4]);
+    xor_32(&key[8], &key[4], &key[8]);
+    xor_32(&key[12], &key[8], &key[12]);
+_func_exit_;		
+}
+
+
+static void byte_sub(u8 *in, u8 *out)
+{
+    sint i;
+_func_enter_;			
+    for (i=0; i< 16; i++)
+    {
+        out[i] = sbox(in[i]);
+    }
+_func_exit_;	
+}
+
+
+static void shift_row(u8 *in, u8 *out)
+{
+_func_enter_;	
+    out[0] =  in[0];
+    out[1] =  in[5];
+    out[2] =  in[10];
+    out[3] =  in[15];
+    out[4] =  in[4];
+    out[5] =  in[9];
+    out[6] =  in[14];
+    out[7] =  in[3];
+    out[8] =  in[8];
+    out[9] =  in[13];
+    out[10] = in[2];
+    out[11] = in[7];
+    out[12] = in[12];
+    out[13] = in[1];
+    out[14] = in[6];
+    out[15] = in[11];
+_func_exit_;		
+}
+
+
+static void mix_column(u8 *in, u8 *out)
+{
+    sint i;
+    u8 add1b[4];
+    u8 add1bf7[4];
+    u8 rotl[4];
+    u8 swap_halfs[4];
+    u8 andf7[4];
+    u8 rotr[4];
+    u8 temp[4];
+    u8 tempb[4];
+_func_enter_;	
+    for (i=0 ; i<4; i++)
+    {
+        if ((in[i] & 0x80)== 0x80)
+            add1b[i] = 0x1b;
+        else
+            add1b[i] = 0x00;
+    }
+
+    swap_halfs[0] = in[2];    /* Swap halfs */
+    swap_halfs[1] = in[3];
+    swap_halfs[2] = in[0];
+    swap_halfs[3] = in[1];
+
+    rotl[0] = in[3];        /* Rotate left 8 bits */
+    rotl[1] = in[0];
+    rotl[2] = in[1];
+    rotl[3] = in[2];
+
+    andf7[0] = in[0] & 0x7f;
+    andf7[1] = in[1] & 0x7f;
+    andf7[2] = in[2] & 0x7f;
+    andf7[3] = in[3] & 0x7f;
+
+    for (i = 3; i>0; i--)    /* logical shift left 1 bit */
+    {
+        andf7[i] = andf7[i] << 1;
+        if ((andf7[i-1] & 0x80) == 0x80)
+        {
+            andf7[i] = (andf7[i] | 0x01);
+        }
+    }
+    andf7[0] = andf7[0] << 1;
+    andf7[0] = andf7[0] & 0xfe;
+
+    xor_32(add1b, andf7, add1bf7);
+
+    xor_32(in, add1bf7, rotr);
+
+    temp[0] = rotr[0];         /* Rotate right 8 bits */
+    rotr[0] = rotr[1];
+    rotr[1] = rotr[2];
+    rotr[2] = rotr[3];
+    rotr[3] = temp[0];
+
+    xor_32(add1bf7, rotr, temp);
+    xor_32(swap_halfs, rotl,tempb);
+    xor_32(temp, tempb, out);
+_func_exit_;		
+}
+
+
+static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
+{
+    sint round;
+    sint i;
+    u8 intermediatea[16];
+    u8 intermediateb[16];
+    u8 round_key[16];
+_func_enter_;	
+    for(i=0; i<16; i++) round_key[i] = key[i];
+
+    for (round = 0; round < 11; round++)
+    {
+        if (round == 0)
+        {
+            xor_128(round_key, data, ciphertext);
+            next_key(round_key, round);
+        }
+        else if (round == 10)
+        {
+            byte_sub(ciphertext, intermediatea);
+            shift_row(intermediatea, intermediateb);
+            xor_128(intermediateb, round_key, ciphertext);
+        }
+        else    /* 1 - 9 */
+        {
+            byte_sub(ciphertext, intermediatea);
+            shift_row(intermediatea, intermediateb);
+            mix_column(&intermediateb[0], &intermediatea[0]);
+            mix_column(&intermediateb[4], &intermediatea[4]);
+            mix_column(&intermediateb[8], &intermediatea[8]);
+            mix_column(&intermediateb[12], &intermediatea[12]);
+            xor_128(intermediatea, round_key, ciphertext);
+            next_key(round_key, round);
+        }
+    }
+_func_exit_;	
+}
+
+
+/************************************************/
+/* construct_mic_iv()                           */
+/* Builds the MIC IV from header fields and PN  */
+/* Baron think the function is construct CCM    */
+/* nonce                                        */
+/************************************************/
+static void construct_mic_iv(
+                        u8 *mic_iv,
+                        sint qc_exists,
+                        sint a4_exists,
+                        u8 *mpdu,
+                        uint payload_length,
+                        u8 *pn_vector,
+                        uint frtype// add for CONFIG_IEEE80211W, none 11w also can use
+                        )
+{
+    sint i;
+_func_enter_;	
+    mic_iv[0] = 0x59;
+    if (qc_exists && a4_exists) mic_iv[1] = mpdu[30] & 0x0f;    /* QoS_TC           */
+    if (qc_exists && !a4_exists) mic_iv[1] = mpdu[24] & 0x0f;   /* mute bits 7-4    */
+    if (!qc_exists) mic_iv[1] = 0x00;
+#ifdef CONFIG_IEEE80211W
+	//802.11w management frame should set management bit(4)
+    if(frtype == WIFI_MGT_TYPE)
+		mic_iv[1] |= BIT(4);
+#endif //CONFIG_IEEE80211W
+    for (i = 2; i < 8; i++)
+        mic_iv[i] = mpdu[i + 8];                    /* mic_iv[2:7] = A2[0:5] = mpdu[10:15] */
+    #ifdef CONSISTENT_PN_ORDER
+        for (i = 8; i < 14; i++)
+            mic_iv[i] = pn_vector[i - 8];           /* mic_iv[8:13] = PN[0:5] */
+    #else
+        for (i = 8; i < 14; i++)
+            mic_iv[i] = pn_vector[13 - i];          /* mic_iv[8:13] = PN[5:0] */
+    #endif
+    mic_iv[14] = (unsigned char) (payload_length / 256);
+    mic_iv[15] = (unsigned char) (payload_length % 256);
+_func_exit_;		
+}
+
+
+/************************************************/
+/* construct_mic_header1()                      */
+/* Builds the first MIC header block from       */
+/* header fields.                               */
+/* Build AAD SC,A1,A2                           */
+/************************************************/
+static void construct_mic_header1(
+                        u8 *mic_header1,
+                        sint header_length,
+                        u8 *mpdu,
+                        uint frtype// add for CONFIG_IEEE80211W, none 11w also can use
+                        )
+{
+_func_enter_;	
+    mic_header1[0] = (u8)((header_length - 2) / 256);
+    mic_header1[1] = (u8)((header_length - 2) % 256);
+#ifdef CONFIG_IEEE80211W
+    //802.11w management frame don't AND subtype bits 4,5,6 of frame control field
+    if(frtype == WIFI_MGT_TYPE)
+		mic_header1[2] = mpdu[0];
+	else
+#endif //CONFIG_IEEE80211W
+		mic_header1[2] = mpdu[0] & 0xcf;    /* Mute CF poll & CF ack bits */
+    
+    mic_header1[3] = mpdu[1] & 0xc7;    /* Mute retry, more data and pwr mgt bits */
+    mic_header1[4] = mpdu[4];       /* A1 */
+    mic_header1[5] = mpdu[5];
+    mic_header1[6] = mpdu[6];
+    mic_header1[7] = mpdu[7];
+    mic_header1[8] = mpdu[8];
+    mic_header1[9] = mpdu[9];
+    mic_header1[10] = mpdu[10];     /* A2 */
+    mic_header1[11] = mpdu[11];
+    mic_header1[12] = mpdu[12];
+    mic_header1[13] = mpdu[13];
+    mic_header1[14] = mpdu[14];
+    mic_header1[15] = mpdu[15];
+_func_exit_;	
+}
+
+
+/************************************************/
+/* construct_mic_header2()                      */
+/* Builds the last MIC header block from        */
+/* header fields.                               */
+/************************************************/
+static void construct_mic_header2(
+                u8 *mic_header2,
+                u8 *mpdu,
+                sint a4_exists,
+                sint qc_exists
+                )
+{
+    sint i;
+_func_enter_;	
+    for (i = 0; i<16; i++) mic_header2[i]=0x00;
+
+    mic_header2[0] = mpdu[16];    /* A3 */
+    mic_header2[1] = mpdu[17];
+    mic_header2[2] = mpdu[18];
+    mic_header2[3] = mpdu[19];
+    mic_header2[4] = mpdu[20];
+    mic_header2[5] = mpdu[21];
+
+    //mic_header2[6] = mpdu[22] & 0xf0;   /* SC */
+    mic_header2[6] = 0x00;
+    mic_header2[7] = 0x00; /* mpdu[23]; */
+
+
+    if (!qc_exists && a4_exists)
+    {
+        for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i];   /* A4 */
+
+    }
+
+    if (qc_exists && !a4_exists)
+    {
+        mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
+        mic_header2[9] = mpdu[25] & 0x00;
+    }
+
+    if (qc_exists && a4_exists)
+    {
+        for (i=0;i<6;i++) mic_header2[8+i] = mpdu[24+i];   /* A4 */
+
+        mic_header2[14] = mpdu[30] & 0x0f;
+        mic_header2[15] = mpdu[31] & 0x00;
+    }
+
+_func_exit_;	
+}
+
+
+/************************************************/
+/* construct_mic_header2()                      */
+/* Builds the last MIC header block from        */
+/* header fields.                               */
+/* Baron think the function is construct CCM    */
+/* nonce                                        */
+/************************************************/
+static void construct_ctr_preload(
+                        u8 *ctr_preload,
+                        sint a4_exists,
+                        sint qc_exists,
+                        u8 *mpdu,
+                        u8 *pn_vector,
+                        sint c,
+                        uint frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                        )
+{
+    sint i = 0;
+_func_enter_;		
+    for (i=0; i<16; i++) ctr_preload[i] = 0x00;
+    i = 0;
+	
+    ctr_preload[0] = 0x01;                                  /* flag */
+    if (qc_exists && a4_exists) 
+		ctr_preload[1] = mpdu[30] & 0x0f;   /* QoC_Control */
+    if (qc_exists && !a4_exists) 
+		ctr_preload[1] = mpdu[24] & 0x0f;
+#ifdef CONFIG_IEEE80211W
+	//802.11w management frame should set management bit(4)
+	if(frtype == WIFI_MGT_TYPE)
+		ctr_preload[1] |= BIT(4);
+#endif //CONFIG_IEEE80211W
+    for (i = 2; i < 8; i++)
+        ctr_preload[i] = mpdu[i + 8];                       /* ctr_preload[2:7] = A2[0:5] = mpdu[10:15] */
+    #ifdef CONSISTENT_PN_ORDER
+      for (i = 8; i < 14; i++)
+            ctr_preload[i] =    pn_vector[i - 8];           /* ctr_preload[8:13] = PN[0:5] */
+    #else
+      for (i = 8; i < 14; i++)
+            ctr_preload[i] =    pn_vector[13 - i];          /* ctr_preload[8:13] = PN[5:0] */
+    #endif
+    ctr_preload[14] =  (unsigned char) (c / 256); /* Ctr */
+    ctr_preload[15] =  (unsigned char) (c % 256);
+_func_exit_;		
+}
+
+
+/************************************/
+/* bitwise_xor()                    */
+/* A 128 bit, bitwise exclusive or  */
+/************************************/
+static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
+{
+    sint i;
+_func_enter_;		
+    for (i=0; i<16; i++)
+    {
+        out[i] = ina[i] ^ inb[i];
+    }
+_func_exit_;		
+}
+
+
+static sint aes_cipher(u8 *key, uint	hdrlen,
+			u8 *pframe, uint plen)
+{
+//	/*static*/ unsigned char	message[MAX_MSG_SIZE];
+	uint	qc_exists, a4_exists, i, j, payload_remainder,
+		num_blocks, payload_index;
+
+	u8 pn_vector[6];
+	u8 mic_iv[16];
+	u8 mic_header1[16];
+	u8 mic_header2[16];
+	u8 ctr_preload[16];
+
+	/* Intermediate Buffers */
+	u8 chain_buffer[16];
+	u8 aes_out[16];
+	u8 padded_buffer[16];
+	u8 mic[8];
+//	uint	offset = 0;
+	uint	frtype  = GetFrameType(pframe);
+	uint	frsubtype  = GetFrameSubType(pframe);
+	
+_func_enter_;		
+	frsubtype=frsubtype>>4;
+
+
+	_rtw_memset((void *)mic_iv, 0, 16);
+	_rtw_memset((void *)mic_header1, 0, 16);
+	_rtw_memset((void *)mic_header2, 0, 16);
+	_rtw_memset((void *)ctr_preload, 0, 16);
+	_rtw_memset((void *)chain_buffer, 0, 16);
+	_rtw_memset((void *)aes_out, 0, 16);
+	_rtw_memset((void *)padded_buffer, 0, 16);
+
+	if ((hdrlen == WLAN_HDR_A3_LEN )||(hdrlen ==  WLAN_HDR_A3_QOS_LEN))
+		a4_exists = 0;
+	else
+		a4_exists = 1;
+
+	if (
+		((frtype|frsubtype) == WIFI_DATA_CFACK) ||
+		((frtype|frsubtype) == WIFI_DATA_CFPOLL)||
+		((frtype|frsubtype) == WIFI_DATA_CFACKPOLL))
+		{
+			qc_exists = 1;
+					if(hdrlen !=  WLAN_HDR_A3_QOS_LEN){
+				 
+					hdrlen += 2;
+			}
+		}
+	// add for CONFIG_IEEE80211W, none 11w also can use
+	else if ((frtype == WIFI_DATA) &&
+		((frsubtype == 0x08) ||
+		(frsubtype == 0x09)||
+		(frsubtype == 0x0a)||
+		(frsubtype == 0x0b)))
+		{
+			if(hdrlen !=  WLAN_HDR_A3_QOS_LEN){
+				 
+					hdrlen += 2;
+			}
+			qc_exists = 1;
+		}
+	else
+		qc_exists = 0;
+
+	pn_vector[0]=pframe[hdrlen];
+	pn_vector[1]=pframe[hdrlen+1];
+	pn_vector[2]=pframe[hdrlen+4];
+	pn_vector[3]=pframe[hdrlen+5];
+	pn_vector[4]=pframe[hdrlen+6];
+	pn_vector[5]=pframe[hdrlen+7];
+	
+	construct_mic_iv(
+                        mic_iv,
+                        qc_exists,
+                        a4_exists,
+                        pframe,	 //message,
+                        plen,
+                        pn_vector,
+                        frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                        );
+
+    construct_mic_header1(
+                            mic_header1,
+                            hdrlen,
+                            pframe,	//message
+                            frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                            );
+    construct_mic_header2(
+                            mic_header2,
+                            pframe,	//message,
+                            a4_exists,
+                            qc_exists
+                            );
+
+
+	payload_remainder = plen % 16;
+    num_blocks = plen / 16;
+
+    /* Find start of payload */
+    payload_index = (hdrlen + 8);
+
+    /* Calculate MIC */
+    aes128k128d(key, mic_iv, aes_out);
+    bitwise_xor(aes_out, mic_header1, chain_buffer);
+    aes128k128d(key, chain_buffer, aes_out);
+    bitwise_xor(aes_out, mic_header2, chain_buffer);
+    aes128k128d(key, chain_buffer, aes_out);
+
+	for (i = 0; i < num_blocks; i++)
+    {
+        bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);//bitwise_xor(aes_out, &message[payload_index], chain_buffer);
+
+        payload_index += 16;
+        aes128k128d(key, chain_buffer, aes_out);
+    }
+
+    /* Add on the final payload block if it needs padding */
+    if (payload_remainder > 0)
+    {
+        for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+        for (j = 0; j < payload_remainder; j++)
+        {
+            padded_buffer[j] = pframe[payload_index++];//padded_buffer[j] = message[payload_index++];
+        }
+        bitwise_xor(aes_out, padded_buffer, chain_buffer);
+        aes128k128d(key, chain_buffer, aes_out);
+
+    }
+
+    for (j = 0 ; j < 8; j++) mic[j] = aes_out[j];
+
+    /* Insert MIC into payload */
+    for (j = 0; j < 8; j++)
+    	pframe[payload_index+j] = mic[j];	//message[payload_index+j] = mic[j];
+
+	payload_index = hdrlen + 8;
+	for (i=0; i< num_blocks; i++)
+    {
+        construct_ctr_preload(
+                                ctr_preload,
+                                a4_exists,
+                                qc_exists,
+                                pframe,	//message,
+                                pn_vector,
+                                i+1,
+                                frtype); // add for CONFIG_IEEE80211W, none 11w also can use
+        aes128k128d(key, ctr_preload, aes_out);
+        bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);//bitwise_xor(aes_out, &message[payload_index], chain_buffer);
+        for (j=0; j<16;j++) pframe[payload_index++] = chain_buffer[j];//for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j];
+    }
+
+    if (payload_remainder > 0)          /* If there is a short final block, then pad it,*/
+    {                                   /* encrypt it and copy the unpadded part back   */
+        construct_ctr_preload(
+                                ctr_preload,
+                                a4_exists,
+                                qc_exists,
+                                pframe,	//message,
+                                pn_vector,
+                                num_blocks+1,
+                                frtype); // add for CONFIG_IEEE80211W, none 11w also can use
+
+        for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+        for (j = 0; j < payload_remainder; j++)
+        {
+            padded_buffer[j] = pframe[payload_index+j];//padded_buffer[j] = message[payload_index+j];
+        }
+        aes128k128d(key, ctr_preload, aes_out);
+        bitwise_xor(aes_out, padded_buffer, chain_buffer);
+        for (j=0; j<payload_remainder;j++) pframe[payload_index++] = chain_buffer[j];//for (j=0; j<payload_remainder;j++) message[payload_index++] = chain_buffer[j];
+    }
+
+    /* Encrypt the MIC */
+    construct_ctr_preload(
+                        ctr_preload,
+                        a4_exists,
+                        qc_exists,
+                        pframe,	//message,
+                        pn_vector,
+                        0,
+                        frtype); // add for CONFIG_IEEE80211W, none 11w also can use
+
+    for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+    for (j = 0; j < 8; j++)
+    {
+        padded_buffer[j] = pframe[j+hdrlen+8+plen];//padded_buffer[j] = message[j+hdrlen+8+plen];
+    }
+
+    aes128k128d(key, ctr_preload, aes_out);
+    bitwise_xor(aes_out, padded_buffer, chain_buffer);
+    for (j=0; j<8;j++) pframe[payload_index++] = chain_buffer[j];//for (j=0; j<8;j++) message[payload_index++] = chain_buffer[j];
+_func_exit_;		
+	return _SUCCESS;
+}
+
+
+
+
+
+u32	rtw_aes_encrypt(_adapter *padapter, u8 *pxmitframe)
+{	// exclude ICV
+
+
+	/*static*/ 
+//	unsigned char	message[MAX_MSG_SIZE];
+
+    	/* Intermediate Buffers */
+	sint 	curfragnum,length;
+	u32	prwskeylen;
+	u8	*pframe,*prwskey;	//, *payload,*iv
+	u8   hw_hdr_offset = 0;
+	//struct	sta_info		*stainfo=NULL;
+	struct	pkt_attrib	 *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+	struct	xmit_priv		*pxmitpriv=&padapter->xmitpriv;
+
+//	uint	offset = 0;
+	u32 res=_SUCCESS;
+_func_enter_;		
+
+	if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL)
+		return _FAIL;
+
+#ifdef CONFIG_USB_TX_AGGREGATION
+	hw_hdr_offset = TXDESC_SIZE +
+		 (((struct xmit_frame*)pxmitframe)->pkt_offset * PACKET_OFFSET_SZ);
+#else
+	#ifdef CONFIG_TX_EARLY_MODE
+	hw_hdr_offset = TXDESC_OFFSET+EARLY_MODE_INFO_SIZE;
+	#else
+	hw_hdr_offset = TXDESC_OFFSET;
+	#endif	
+#endif
+
+	pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + hw_hdr_offset;
+
+	//4 start to encrypt each fragment
+	if((pattrib->encrypt==_AES_)){
+/*
+		if(pattrib->psta)
+		{
+			stainfo = pattrib->psta;
+		}
+		else
+		{
+			DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+			stainfo=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0] );
+		}
+*/		
+		//if (stainfo!=NULL)
+		{
+/*
+			if(!(stainfo->state &_FW_LINKED))
+			{
+				DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
+				return _FAIL;
+			}
+*/
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_aes_encrypt: stainfo!=NULL!!!\n"));
+
+			if(IS_MCAST(pattrib->ra))
+			{
+				prwskey=psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+			}
+			else
+			{
+				//prwskey=&stainfo->dot118021x_UncstKey.skey[0];
+				prwskey=pattrib->dot118021x_UncstKey.skey;
+			}
+
+#ifdef CONFIG_TDLS
+			{
+				/* Swencryption */
+				struct	sta_info		*ptdls_sta;
+				ptdls_sta=rtw_get_stainfo(&padapter->stapriv ,&pattrib->dst[0] );
+				if((ptdls_sta != NULL) && (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) )
+				{
+					DBG_871X("[%s] for tdls link\n", __FUNCTION__);
+					prwskey=&ptdls_sta->tpk.tk[0];
+				}
+			}
+#endif //CONFIG_TDLS
+
+			prwskeylen=16;
+	
+			for(curfragnum=0;curfragnum<pattrib->nr_frags;curfragnum++){
+			
+				if((curfragnum+1)==pattrib->nr_frags){	//4 the last fragment
+					length=pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len- pattrib->icv_len;
+				
+					aes_cipher(prwskey,pattrib->hdrlen,pframe, length);
+				}
+				else{
+					length=pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-pattrib->icv_len ;
+				
+					aes_cipher(prwskey,pattrib->hdrlen,pframe, length);
+				pframe+=pxmitpriv->frag_len;
+				pframe=(u8*)RND4((SIZE_PTR)(pframe));
+
+				}
+			}
+
+			AES_SW_ENC_CNT_INC(psecuritypriv, pattrib->ra);
+		}
+/*
+		else{
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_aes_encrypt: stainfo==NULL!!!\n"));
+			DBG_871X("%s, psta==NUL\n", __func__);
+			res=_FAIL;
+		}
+*/
+	}
+
+
+
+_func_exit_;
+		return res;
+}
+
+static sint aes_decipher(u8 *key, uint	hdrlen,
+			u8 *pframe, uint plen)
+{
+	static u8	message[MAX_MSG_SIZE];
+	uint	qc_exists, a4_exists, i, j, payload_remainder,
+			num_blocks, payload_index;
+	sint res = _SUCCESS;
+	u8 pn_vector[6];
+	u8 mic_iv[16];
+	u8 mic_header1[16];
+	u8 mic_header2[16];
+	u8 ctr_preload[16];
+
+    /* Intermediate Buffers */
+	u8 chain_buffer[16];
+	u8 aes_out[16];
+	u8 padded_buffer[16];
+	u8 mic[8];
+
+
+//	uint	offset = 0;
+	uint	frtype  = GetFrameType(pframe);
+	uint	frsubtype  = GetFrameSubType(pframe);
+_func_enter_;			
+	frsubtype=frsubtype>>4;
+
+
+	_rtw_memset((void *)mic_iv, 0, 16);
+	_rtw_memset((void *)mic_header1, 0, 16);
+	_rtw_memset((void *)mic_header2, 0, 16);
+	_rtw_memset((void *)ctr_preload, 0, 16);
+	_rtw_memset((void *)chain_buffer, 0, 16);
+	_rtw_memset((void *)aes_out, 0, 16);
+	_rtw_memset((void *)padded_buffer, 0, 16);
+
+	//start to decrypt the payload
+
+	num_blocks = (plen-8) / 16; //(plen including LLC, payload_length and mic )
+
+	payload_remainder = (plen-8) % 16;
+
+	pn_vector[0]  = pframe[hdrlen];
+	pn_vector[1]  = pframe[hdrlen+1];
+	pn_vector[2]  = pframe[hdrlen+4];
+	pn_vector[3]  = pframe[hdrlen+5];
+	pn_vector[4]  = pframe[hdrlen+6];
+	pn_vector[5]  = pframe[hdrlen+7];
+
+	if ((hdrlen == WLAN_HDR_A3_LEN )||(hdrlen ==  WLAN_HDR_A3_QOS_LEN))
+		a4_exists = 0;
+	else
+		a4_exists = 1;
+
+	if (
+		((frtype|frsubtype) == WIFI_DATA_CFACK) ||
+		((frtype|frsubtype) == WIFI_DATA_CFPOLL)||
+		((frtype|frsubtype) == WIFI_DATA_CFACKPOLL))
+		{
+			qc_exists = 1;
+					if(hdrlen !=  WLAN_HDR_A3_QOS_LEN){
+				 
+					hdrlen += 2;
+			}
+		}//only for data packet . add for CONFIG_IEEE80211W, none 11w also can use
+	else if ((frtype == WIFI_DATA) &&
+		((frsubtype == 0x08) ||
+		(frsubtype == 0x09)||
+		(frsubtype == 0x0a)||
+		(frsubtype == 0x0b)))
+		{
+			if(hdrlen !=  WLAN_HDR_A3_QOS_LEN){
+				 
+					hdrlen += 2;
+			}
+			qc_exists = 1;
+		}
+	else
+		qc_exists = 0;
+
+
+	// now, decrypt pframe with hdrlen offset and plen long
+
+	payload_index = hdrlen + 8; // 8 is for extiv
+	
+	for (i=0; i< num_blocks; i++)
+    {
+        construct_ctr_preload(
+                                ctr_preload,
+                                a4_exists,
+                                qc_exists,
+                                pframe,
+                                pn_vector,
+                                i+1,
+                                frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                            );
+
+        aes128k128d(key, ctr_preload, aes_out);
+        bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
+
+        for (j=0; j<16;j++) pframe[payload_index++] = chain_buffer[j];
+    }
+
+    if (payload_remainder > 0)          /* If there is a short final block, then pad it,*/
+    {                                   /* encrypt it and copy the unpadded part back   */
+        construct_ctr_preload(
+                                ctr_preload,
+                                a4_exists,
+                                qc_exists,
+                                pframe,
+                                pn_vector,
+                                num_blocks+1,
+                                frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                            );
+
+        for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+        for (j = 0; j < payload_remainder; j++)
+        {
+            padded_buffer[j] = pframe[payload_index+j];
+        }
+        aes128k128d(key, ctr_preload, aes_out);
+        bitwise_xor(aes_out, padded_buffer, chain_buffer);
+        for (j=0; j<payload_remainder;j++) pframe[payload_index++] = chain_buffer[j];
+    }
+
+	//start to calculate the mic	
+	if((hdrlen +plen+8) <= MAX_MSG_SIZE)
+		_rtw_memcpy((void *)message, pframe, (hdrlen +plen+8)); //8 is for ext iv len
+
+
+	pn_vector[0]=pframe[hdrlen];
+	pn_vector[1]=pframe[hdrlen+1];
+	pn_vector[2]=pframe[hdrlen+4];
+	pn_vector[3]=pframe[hdrlen+5];
+	pn_vector[4]=pframe[hdrlen+6];
+	pn_vector[5]=pframe[hdrlen+7];
+
+
+	
+	construct_mic_iv(
+                        mic_iv,
+                        qc_exists,
+                        a4_exists,
+                        message,
+                        plen-8,
+                        pn_vector,
+                        frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                        );
+
+    construct_mic_header1(
+                            mic_header1,
+                            hdrlen,
+                            message,
+                            frtype // add for CONFIG_IEEE80211W, none 11w also can use
+                            );
+    construct_mic_header2(
+                            mic_header2,
+                            message,
+                            a4_exists,
+                            qc_exists
+                            );
+
+
+	payload_remainder = (plen-8) % 16;
+    num_blocks = (plen-8) / 16;
+
+    /* Find start of payload */
+    payload_index = (hdrlen + 8);
+
+    /* Calculate MIC */
+    aes128k128d(key, mic_iv, aes_out);
+    bitwise_xor(aes_out, mic_header1, chain_buffer);
+    aes128k128d(key, chain_buffer, aes_out);
+    bitwise_xor(aes_out, mic_header2, chain_buffer);
+    aes128k128d(key, chain_buffer, aes_out);
+
+	for (i = 0; i < num_blocks; i++)
+    {
+        bitwise_xor(aes_out, &message[payload_index], chain_buffer);
+
+        payload_index += 16;
+        aes128k128d(key, chain_buffer, aes_out);
+    }
+
+    /* Add on the final payload block if it needs padding */
+    if (payload_remainder > 0)
+    {
+        for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+        for (j = 0; j < payload_remainder; j++)
+        {
+            padded_buffer[j] = message[payload_index++];
+        }
+        bitwise_xor(aes_out, padded_buffer, chain_buffer);
+        aes128k128d(key, chain_buffer, aes_out);
+
+    }
+
+    for (j = 0 ; j < 8; j++) mic[j] = aes_out[j];
+
+    /* Insert MIC into payload */
+    for (j = 0; j < 8; j++)
+    	message[payload_index+j] = mic[j];
+
+	payload_index = hdrlen + 8;
+	for (i=0; i< num_blocks; i++)
+    {
+        construct_ctr_preload(
+                                ctr_preload,
+                                a4_exists,
+                                qc_exists,
+                                message,
+                                pn_vector,
+                                i+1,
+                                frtype); // add for CONFIG_IEEE80211W, none 11w also can use
+        aes128k128d(key, ctr_preload, aes_out);
+        bitwise_xor(aes_out, &message[payload_index], chain_buffer);
+        for (j=0; j<16;j++) message[payload_index++] = chain_buffer[j];
+    }
+
+    if (payload_remainder > 0)          /* If there is a short final block, then pad it,*/
+    {                                   /* encrypt it and copy the unpadded part back   */
+        construct_ctr_preload(
+                                ctr_preload,
+                                a4_exists,
+                                qc_exists,
+                                message,
+                                pn_vector,
+                                num_blocks+1,
+                                frtype); // add for CONFIG_IEEE80211W, none 11w also can use
+
+        for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+        for (j = 0; j < payload_remainder; j++)
+        {
+            padded_buffer[j] = message[payload_index+j];
+        }
+        aes128k128d(key, ctr_preload, aes_out);
+        bitwise_xor(aes_out, padded_buffer, chain_buffer);
+        for (j=0; j<payload_remainder;j++) message[payload_index++] = chain_buffer[j];
+    }
+
+    /* Encrypt the MIC */
+    construct_ctr_preload(
+                        ctr_preload,
+                        a4_exists,
+                        qc_exists,
+                        message,
+                        pn_vector,
+                        0,
+                        frtype); // add for CONFIG_IEEE80211W, none 11w also can use
+
+    for (j = 0; j < 16; j++) padded_buffer[j] = 0x00;
+    for (j = 0; j < 8; j++)
+    {
+        padded_buffer[j] = message[j+hdrlen+8+plen-8];
+    }
+
+    aes128k128d(key, ctr_preload, aes_out);
+    bitwise_xor(aes_out, padded_buffer, chain_buffer);
+    for (j=0; j<8;j++) message[payload_index++] = chain_buffer[j];
+
+	//compare the mic
+	for(i=0;i<8;i++){
+		if(pframe[hdrlen+8+plen-8+i] != message[hdrlen+8+plen-8+i])
+		{
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x) \n",
+						i,pframe[hdrlen+8+plen-8+i],message[hdrlen+8+plen-8+i]));
+			DBG_871X("aes_decipher:mic check error mic[%d]: pframe(%x) != message(%x) \n",
+						i,pframe[hdrlen+8+plen-8+i],message[hdrlen+8+plen-8+i]);
+			res = _FAIL;
+		}
+	}
+_func_exit_;	
+	return res;
+}
+
+u32	rtw_aes_decrypt(_adapter *padapter, u8 *precvframe)
+{	// exclude ICV
+
+
+	/*static*/ 
+//	unsigned char	message[MAX_MSG_SIZE];
+
+
+    	/* Intermediate Buffers */
+
+
+	sint 		length;
+	u32	prwskeylen;
+	u8	*pframe,*prwskey;	//, *payload,*iv
+	struct	sta_info		*stainfo;
+	struct	rx_pkt_attrib	 *prxattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+//	struct	recv_priv		*precvpriv=&padapter->recvpriv;
+	u32	res=_SUCCESS;
+_func_enter_;	 
+	pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+	//4 start to encrypt each fragment
+	if((prxattrib->encrypt==_AES_)){
+
+		stainfo=rtw_get_stainfo(&padapter->stapriv ,&prxattrib->ta[0] );
+		if (stainfo!=NULL){
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_aes_decrypt: stainfo!=NULL!!!\n"));
+
+			if(IS_MCAST(prxattrib->ra))
+			{
+				static u32 start = 0;
+				static u32 no_gkey_bc_cnt = 0;
+				static u32 no_gkey_mc_cnt = 0;
+
+				//DBG_871X("rx bc/mc packets, to perform sw rtw_aes_decrypt\n");
+				//prwskey = psecuritypriv->dot118021XGrpKey[psecuritypriv->dot118021XGrpKeyid].skey;
+				if(psecuritypriv->binstallGrpkey==_FALSE)
+				{
+					res=_FAIL;
+
+					if (start == 0)
+						start = rtw_get_current_time();
+
+					if (is_broadcast_mac_addr(prxattrib->ra))
+						no_gkey_bc_cnt++;
+					else
+						no_gkey_mc_cnt++;
+
+					if (rtw_get_passing_time_ms(start) > 1000) {
+						if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
+							DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
+								FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
+						}
+						start = rtw_get_current_time();
+						no_gkey_bc_cnt = 0;
+						no_gkey_mc_cnt = 0;
+					}
+
+					goto exit;
+				}
+
+				if (no_gkey_bc_cnt || no_gkey_mc_cnt) {
+					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" gkey installed. no_gkey_bc_cnt:%u, no_gkey_mc_cnt:%u\n",
+						FUNC_ADPT_ARG(padapter), no_gkey_bc_cnt, no_gkey_mc_cnt);
+				}
+				start = 0;
+				no_gkey_bc_cnt = 0;
+				no_gkey_mc_cnt = 0;
+
+				prwskey = psecuritypriv->dot118021XGrpKey[prxattrib->key_index].skey;
+				if(psecuritypriv->dot118021XGrpKeyid != prxattrib->key_index)
+				{
+					DBG_871X("not match packet_index=%d, install_index=%d \n"
+					, prxattrib->key_index, psecuritypriv->dot118021XGrpKeyid);
+					res=_FAIL;
+					goto exit;
+				}
+			}
+			else
+			{
+				prwskey=&stainfo->dot118021x_UncstKey.skey[0];
+			}
+			
+			length= ((union recv_frame *)precvframe)->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len;
+			/*// add for CONFIG_IEEE80211W, debug
+			if(0)
+			printk("@@@@@@@@@@@@@@@@@@ length=%d, prxattrib->hdrlen=%d, prxattrib->pkt_len=%d \n"
+			, length, prxattrib->hdrlen, prxattrib->pkt_len);
+			if(0)
+			{
+				int no;
+				//test print PSK
+				printk("PSK key below:\n");
+				for(no=0;no<16;no++)
+					printk(" %02x ", prwskey[no]);
+				printk("\n");
+			}
+			if(0)
+			{
+				int no;
+				//test print PSK
+				printk("frame:\n");
+				for(no=0;no<prxattrib->pkt_len;no++)
+					printk(" %02x ", pframe[no]);
+				printk("\n");
+			}*/
+
+			res= aes_decipher(prwskey,prxattrib->hdrlen,pframe, length);
+
+			AES_SW_DEC_CNT_INC(psecuritypriv, prxattrib->ra);
+		}
+		else{
+			RT_TRACE(_module_rtl871x_security_c_,_drv_err_,("rtw_aes_decrypt: stainfo==NULL!!!\n"));
+			res=_FAIL;
+		}
+						
+	}
+_func_exit_;	
+exit:
+	return res;
+}
+
+#ifdef CONFIG_IEEE80211W
+u32	rtw_BIP_verify(_adapter *padapter, u8 *precvframe)
+{
+	struct rx_pkt_attrib *pattrib = &((union recv_frame *)precvframe)->u.hdr.attrib;
+	u8 *pframe;
+	u8 *BIP_AAD, *p;
+	u32	res=_FAIL;
+	uint len, ori_len;
+	struct rtw_ieee80211_hdr *pwlanhdr;
+	u8 mic[16];
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	ori_len = pattrib->pkt_len-WLAN_HDR_A3_LEN+BIP_AAD_SIZE;
+	BIP_AAD = rtw_zmalloc(ori_len);
+	
+	if(BIP_AAD == NULL)
+	{
+		DBG_871X("BIP AAD allocate fail\n");
+		return _FAIL;
+	}
+	//PKT start
+	pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+	//mapping to wlan header
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+	//save the frame body + MME
+	_rtw_memcpy(BIP_AAD+BIP_AAD_SIZE, pframe+WLAN_HDR_A3_LEN, pattrib->pkt_len-WLAN_HDR_A3_LEN);
+	//find MME IE pointer
+	p = rtw_get_ie(BIP_AAD+BIP_AAD_SIZE, _MME_IE_, &len, pattrib->pkt_len-WLAN_HDR_A3_LEN);
+	//Baron
+	if(p)
+	{
+		u16 keyid=0;
+		u64 temp_ipn=0;
+		//save packet number
+		_rtw_memcpy(&temp_ipn, p+4, 6);
+		temp_ipn = le64_to_cpu(temp_ipn);
+		//BIP packet number should bigger than previous BIP packet
+		if (temp_ipn < pmlmeext->mgnt_80211w_IPN_rx) {
+			DBG_871X("replay BIP packet\n");
+			goto BIP_exit;
+		}
+		//copy key index
+		_rtw_memcpy(&keyid, p+2, 2);
+		keyid = le16_to_cpu(keyid);
+		if(keyid != padapter->securitypriv.dot11wBIPKeyid)
+		{
+			DBG_871X("BIP key index error!\n");
+			goto BIP_exit;
+		}
+		//clear the MIC field of MME to zero
+		_rtw_memset(p+2+len-8, 0, 8);
+		
+		//conscruct AAD, copy frame control field
+		_rtw_memcpy(BIP_AAD, &pwlanhdr->frame_ctl, 2);
+		ClearRetry(BIP_AAD);
+		ClearPwrMgt(BIP_AAD);
+		ClearMData(BIP_AAD);
+		//conscruct AAD, copy address 1 to address 3
+		_rtw_memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
+		
+		if(omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
+			, BIP_AAD, ori_len, mic))
+			goto BIP_exit;
+		
+		/*//management packet content
+		{
+			int pp;
+			DBG_871X("pkt: ");
+			for(pp=0;pp< pattrib->pkt_len; pp++)
+				printk(" %02x ", pframe[pp]);
+			DBG_871X("\n");
+			//BIP AAD + management frame body + MME(MIC is zero)
+			DBG_871X("AAD+PKT: ");
+			for(pp=0;pp< ori_len; pp++)
+				DBG_871X(" %02x ", BIP_AAD[pp]);
+			DBG_871X("\n");
+			//show the MIC result
+			DBG_871X("mic: ");
+			for(pp=0;pp<16; pp++)
+				DBG_871X(" %02x ", mic[pp]);
+			DBG_871X("\n");
+		}
+		*/
+		//MIC field should be last 8 bytes of packet (packet without FCS)
+		if(_rtw_memcmp(mic, pframe+pattrib->pkt_len-8, 8))
+		{
+			pmlmeext->mgnt_80211w_IPN_rx = temp_ipn;
+			res=_SUCCESS;
+		}
+		else
+			DBG_871X("BIP MIC error!\n");
+		
+	}
+	else
+		res = RTW_RX_HANDLED;
+BIP_exit:
+
+	rtw_mfree(BIP_AAD, ori_len);
+	return res;
+}
+#endif //CONFIG_IEEE80211W
+
+#ifndef PLATFORM_FREEBSD
+/* compress 512-bits */
+static int sha256_compress(struct rtl_sha256_state *md, unsigned char *buf)
+{
+	u32 S[8], W[64], t0, t1;
+	u32 t;
+	int i;
+
+	/* copy state into S */
+	for (i = 0; i < 8; i++) {
+		S[i] = md->state[i];
+	}
+
+	/* copy the state into 512-bits into W[0..15] */
+	for (i = 0; i < 16; i++)
+		W[i] = WPA_GET_BE32(buf + (4 * i));
+
+	/* fill W[16..63] */
+	for (i = 16; i < 64; i++) {
+		W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
+			W[i - 16];
+	}        
+
+	/* Compress */
+#define RND(a,b,c,d,e,f,g,h,i)                          \
+	t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];	\
+	t1 = Sigma0(a) + Maj(a, b, c);			\
+	d += t0;					\
+	h  = t0 + t1;
+
+	for (i = 0; i < 64; ++i) {
+		RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
+		t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; 
+		S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+	}
+
+	/* feedback */
+	for (i = 0; i < 8; i++) {
+		md->state[i] = md->state[i] + S[i];
+	}
+	return 0;
+}
+
+/* Initialize the hash state */
+static void sha256_init(struct rtl_sha256_state *md)
+{
+	md->curlen = 0;
+	md->length = 0;
+	md->state[0] = 0x6A09E667UL;
+	md->state[1] = 0xBB67AE85UL;
+	md->state[2] = 0x3C6EF372UL;
+	md->state[3] = 0xA54FF53AUL;
+	md->state[4] = 0x510E527FUL;
+	md->state[5] = 0x9B05688CUL;
+	md->state[6] = 0x1F83D9ABUL;
+	md->state[7] = 0x5BE0CD19UL;
+}
+
+/**
+   Process a block of memory though the hash
+   @param md     The hash state
+   @param in     The data to hash
+   @param inlen  The length of the data (octets)
+   @return CRYPT_OK if successful
+*/
+static int sha256_process(struct rtl_sha256_state *md, unsigned char *in,
+			  unsigned long inlen)
+{
+	unsigned long n;
+#define block_size 64
+
+	if (md->curlen > sizeof(md->buf))
+		return -1;
+
+	while (inlen > 0) {
+		if (md->curlen == 0 && inlen >= block_size) {
+			if (sha256_compress(md, (unsigned char *) in) < 0)
+				return -1;
+			md->length += block_size * 8;
+			in += block_size;
+			inlen -= block_size;
+		} else {
+			n = MIN(inlen, (block_size - md->curlen));
+			_rtw_memcpy(md->buf + md->curlen, in, n);
+			md->curlen += n;
+			in += n;
+			inlen -= n;
+			if (md->curlen == block_size) {
+				if (sha256_compress(md, md->buf) < 0)
+					return -1;
+				md->length += 8 * block_size;
+				md->curlen = 0;
+			}
+		}
+	}
+
+	return 0;
+}
+
+
+/**
+   Terminate the hash to get the digest
+   @param md  The hash state
+   @param out [out] The destination of the hash (32 bytes)
+   @return CRYPT_OK if successful
+*/
+static int sha256_done(struct rtl_sha256_state *md, unsigned char *out)
+{
+	int i;
+
+	if (md->curlen >= sizeof(md->buf))
+		return -1;
+
+	/* increase the length of the message */
+	md->length += md->curlen * 8;
+
+	/* append the '1' bit */
+	md->buf[md->curlen++] = (unsigned char) 0x80;
+
+	/* if the length is currently above 56 bytes we append zeros
+	 * then compress.  Then we can fall back to padding zeros and length
+	 * encoding like normal.
+	 */
+	if (md->curlen > 56) {
+		while (md->curlen < 64) {
+			md->buf[md->curlen++] = (unsigned char) 0;
+		}
+		sha256_compress(md, md->buf);
+		md->curlen = 0;
+	}
+
+	/* pad upto 56 bytes of zeroes */
+	while (md->curlen < 56) {
+		md->buf[md->curlen++] = (unsigned char) 0;
+	}
+
+	/* store length */
+	WPA_PUT_BE64(md->buf + 56, md->length);
+	sha256_compress(md, md->buf);
+
+	/* copy output */
+	for (i = 0; i < 8; i++)
+		WPA_PUT_BE32(out + (4 * i), md->state[i]);
+
+	return 0;
+}
+
+/**
+ * sha256_vector - SHA256 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+static int sha256_vector(size_t num_elem, u8 *addr[], size_t *len,
+		  u8 *mac)
+{
+	struct rtl_sha256_state ctx;
+	size_t i;
+
+	sha256_init(&ctx);
+	for (i = 0; i < num_elem; i++)
+		if (sha256_process(&ctx, addr[i], len[i]))
+			return -1;
+	if (sha256_done(&ctx, mac))
+		return -1;
+	return 0;
+}
+
+static u8 os_strlen(const char *s)
+{
+	const char *p = s;
+	while (*p)
+		p++;
+	return p - s;
+}
+
+static int os_memcmp(void *s1, void *s2, u8 n)
+{
+	unsigned char *p1 = s1, *p2 = s2;
+
+	if (n == 0)
+		return 0;
+
+	while (*p1 == *p2) {
+		p1++;
+		p2++;
+		n--;
+		if (n == 0)
+			return 0;
+	}
+
+	return *p1 - *p2;
+}
+
+/**
+ * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (32 bytes)
+ */
+static void hmac_sha256_vector(u8 *key, size_t key_len, size_t num_elem,
+			u8 *addr[], size_t *len, u8 *mac)
+{
+	unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
+	unsigned char tk[32];
+	u8 *_addr[6];
+	size_t _len[6], i;
+
+	if (num_elem > 5) {
+		/*
+		 * Fixed limit on the number of fragments to avoid having to
+		 * allocate memory (which could fail).
+		 */
+		return;
+	}
+
+        /* if key is longer than 64 bytes reset it to key = SHA256(key) */
+        if (key_len > 64) {
+		sha256_vector(1, &key, &key_len, tk);
+		key = tk;
+		key_len = 32;
+        }
+
+	/* the HMAC_SHA256 transform looks like:
+	 *
+	 * SHA256(K XOR opad, SHA256(K XOR ipad, text))
+	 *
+	 * where K is an n byte key
+	 * ipad is the byte 0x36 repeated 64 times
+	 * opad is the byte 0x5c repeated 64 times
+	 * and text is the data being protected */
+
+	/* start out by storing key in ipad */
+	_rtw_memset(k_pad, 0, sizeof(k_pad));
+	_rtw_memcpy(k_pad, key, key_len);
+	/* XOR key with ipad values */
+	for (i = 0; i < 64; i++)
+		k_pad[i] ^= 0x36;
+
+	/* perform inner SHA256 */
+	_addr[0] = k_pad;
+	_len[0] = 64;
+	for (i = 0; i < num_elem; i++) {
+		_addr[i + 1] = addr[i];
+		_len[i + 1] = len[i];
+	}
+	sha256_vector(1 + num_elem, _addr, _len, mac);
+
+	_rtw_memset(k_pad, 0, sizeof(k_pad));
+	_rtw_memcpy(k_pad, key, key_len);
+	/* XOR key with opad values */
+	for (i = 0; i < 64; i++)
+		k_pad[i] ^= 0x5c;
+
+	/* perform outer SHA256 */
+	_addr[0] = k_pad;
+	_len[0] = 64;
+	_addr[1] = mac;
+	_len[1] = 32;
+	sha256_vector(2, _addr, _len, mac);
+}
+#endif //PLATFORM_FREEBSD
+/**
+ * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
+ * @key: Key for PRF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bytes of key to generate
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key.
+ */
+#ifndef PLATFORM_FREEBSD //Baron
+static void sha256_prf(u8 *key, size_t key_len, char *label,
+		u8 *data, size_t data_len, u8 *buf, size_t buf_len)
+{
+	u16 counter = 1;
+	size_t pos, plen;
+	u8 hash[SHA256_MAC_LEN];
+	u8 *addr[4];
+	size_t len[4];
+	u8 counter_le[2], length_le[2];
+
+	addr[0] = counter_le;
+	len[0] = 2;
+	addr[1] = (u8 *) label;
+	len[1] = os_strlen(label);
+	addr[2] = data;
+	len[2] = data_len;
+	addr[3] = length_le;
+	len[3] = sizeof(length_le);
+
+	WPA_PUT_LE16(length_le, buf_len * 8);
+	pos = 0;
+	while (pos < buf_len) {
+		plen = buf_len - pos;
+		WPA_PUT_LE16(counter_le, counter);
+		if (plen >= SHA256_MAC_LEN) {
+			hmac_sha256_vector(key, key_len, 4, addr, len,
+					   &buf[pos]);
+			pos += SHA256_MAC_LEN;
+		} else {
+			hmac_sha256_vector(key, key_len, 4, addr, len, hash);
+			_rtw_memcpy(&buf[pos], hash, plen);
+			break;
+		}
+		counter++;
+	}
+}
+#endif //PLATFORM_FREEBSD Baron
+
+/* AES tables*/
+const u32 Te0[256] = {
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+const u32 Td0[256] = {
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+const u8 Td4s[256] = {
+    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+const u8 rcons[] = {
+	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+	/* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return	the number of rounds for the given cipher key size.
+ */
+#ifndef PLATFORM_FREEBSD //Baron
+static void rijndaelKeySetupEnc(u32 rk[/*44*/], const u8 cipherKey[])
+{
+	int i;
+	u32 temp;
+
+	rk[0] = GETU32(cipherKey     );
+	rk[1] = GETU32(cipherKey +  4);
+	rk[2] = GETU32(cipherKey +  8);
+	rk[3] = GETU32(cipherKey + 12);
+	for (i = 0; i < 10; i++) {
+		temp  = rk[3];
+		rk[4] = rk[0] ^
+			TE421(temp) ^ TE432(temp) ^ TE443(temp) ^ TE414(temp) ^
+			RCON(i);
+		rk[5] = rk[1] ^ rk[4];
+		rk[6] = rk[2] ^ rk[5];
+		rk[7] = rk[3] ^ rk[6];
+		rk += 4;
+	}
+}
+
+static void rijndaelEncrypt(u32 rk[/*44*/], u8 pt[16], u8 ct[16])
+{
+	u32 s0, s1, s2, s3, t0, t1, t2, t3;
+	int Nr = 10;
+#ifndef FULL_UNROLL
+	int r;
+#endif /* ?FULL_UNROLL */
+
+	/*
+	 * map byte array block to cipher state
+	 * and add initial round key:
+	 */
+	s0 = GETU32(pt     ) ^ rk[0];
+	s1 = GETU32(pt +  4) ^ rk[1];
+	s2 = GETU32(pt +  8) ^ rk[2];
+	s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+	ROUND(1,t,s);
+	ROUND(2,s,t);
+	ROUND(3,t,s);
+	ROUND(4,s,t);
+	ROUND(5,t,s);
+	ROUND(6,s,t);
+	ROUND(7,t,s);
+	ROUND(8,s,t);
+	ROUND(9,t,s);
+
+	rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+	/* Nr - 1 full rounds: */
+	r = Nr >> 1;
+	for (;;) {
+		ROUND(1,t,s);
+		rk += 8;
+		if (--r == 0)
+			break;
+		ROUND(0,s,t);
+	}
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+	/*
+	 * apply last round and
+	 * map cipher state to byte array block:
+	 */
+	s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
+	PUTU32(ct     , s0);
+	s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
+	PUTU32(ct +  4, s1);
+	s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
+	PUTU32(ct +  8, s2);
+	s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
+	PUTU32(ct + 12, s3);
+}
+
+static void * aes_encrypt_init(u8 *key, size_t len)
+{
+	u32 *rk;
+	if (len != 16)
+		return NULL;
+	rk = (u32*)rtw_malloc(AES_PRIV_SIZE);
+	if (rk == NULL)
+		return NULL;
+	rijndaelKeySetupEnc(rk, key);
+	return rk;
+}
+
+static void aes_128_encrypt(void *ctx, u8 *plain, u8 *crypt)
+{
+	rijndaelEncrypt(ctx, plain, crypt);
+}
+
+
+static void gf_mulx(u8 *pad)
+{
+	int i, carry;
+
+	carry = pad[0] & 0x80;
+	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
+		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
+	pad[AES_BLOCK_SIZE - 1] <<= 1;
+	if (carry)
+		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
+}
+
+static void aes_encrypt_deinit(void *ctx)
+{
+	_rtw_memset(ctx, 0, AES_PRIV_SIZE);
+	rtw_mfree(ctx, AES_PRIV_SIZE);
+}
+
+
+/**
+ * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
+ * @key: 128-bit key for the hash operation
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */
+static int omac1_aes_128_vector(u8 *key, size_t num_elem,
+							 u8 *addr[], size_t *len, u8 *mac)
+{
+	void *ctx;
+	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
+	u8 *pos, *end;
+	size_t i, e, left, total_len;
+
+	ctx = aes_encrypt_init(key, 16);
+	if (ctx == NULL)
+		return -1;
+	_rtw_memset(cbc, 0, AES_BLOCK_SIZE);
+
+	total_len = 0;
+	for (e = 0; e < num_elem; e++)
+		total_len += len[e];
+	left = total_len;
+
+	e = 0;
+	pos = addr[0];
+	end = pos + len[0];
+
+	while (left >= AES_BLOCK_SIZE) {
+		for (i = 0; i < AES_BLOCK_SIZE; i++) {
+			cbc[i] ^= *pos++;
+			if (pos >= end) {
+				e++;
+				pos = addr[e];
+				end = pos + len[e];
+			}
+		}
+		if (left > AES_BLOCK_SIZE)
+			aes_128_encrypt(ctx, cbc, cbc);
+		left -= AES_BLOCK_SIZE;
+	}
+
+	_rtw_memset(pad, 0, AES_BLOCK_SIZE);
+	aes_128_encrypt(ctx, pad, pad);
+	gf_mulx(pad);
+
+	if (left || total_len == 0) {
+		for (i = 0; i < left; i++) {
+			cbc[i] ^= *pos++;
+			if (pos >= end) {
+				e++;
+				pos = addr[e];
+				end = pos + len[e];
+			}
+		}
+		cbc[left] ^= 0x80;
+		gf_mulx(pad);
+	}
+
+	for (i = 0; i < AES_BLOCK_SIZE; i++)
+		pad[i] ^= cbc[i];
+	aes_128_encrypt(ctx, pad, mac);
+	aes_encrypt_deinit(ctx);
+	return 0;
+}
+
+
+/**
+ * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
+ * @key: 128-bit key for the hash operation
+ * @data: Data buffer for which a MAC is determined
+ * @data_len: Length of data buffer in bytes
+ * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This is a mode for using block cipher (AES in this case) for authentication.
+ * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
+ * (SP) 800-38B.
+ */ //modify for CONFIG_IEEE80211W
+int omac1_aes_128(u8 *key, u8 *data, size_t data_len, u8 *mac)
+{
+	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
+}
+#endif //PLATFORM_FREEBSD Baron
+
+#ifdef CONFIG_TDLS
+void wpa_tdls_generate_tpk(_adapter *padapter, PVOID sta)
+{
+	struct sta_info *psta = (struct sta_info *)sta;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	u8 *SNonce = psta->SNonce;
+	u8 *ANonce = psta->ANonce;
+
+	u8 key_input[SHA256_MAC_LEN];
+	u8 *nonce[2];
+	size_t len[2];
+	u8 data[3 * ETH_ALEN];
+
+	/* IEEE Std 802.11z-2010 8.5.9.1:
+	 * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
+	 */
+	len[0] = 32;
+	len[1] = 32;
+	if (os_memcmp(SNonce, ANonce, 32) < 0) {
+		nonce[0] = SNonce;
+		nonce[1] = ANonce;
+	} else {
+		nonce[0] = ANonce;
+		nonce[1] = SNonce;
+	}
+
+	sha256_vector(2, nonce, len, key_input);
+
+	/*
+	 * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
+	 *	min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
+	 * TODO: is N_KEY really included in KDF Context and if so, in which
+	 * presentation format (little endian 16-bit?) is it used? It gets
+	 * added by the KDF anyway..
+	 */
+
+	if (os_memcmp(adapter_mac_addr(padapter), psta->hwaddr, ETH_ALEN) < 0) {
+		_rtw_memcpy(data, adapter_mac_addr(padapter), ETH_ALEN);
+		_rtw_memcpy(data + ETH_ALEN, psta->hwaddr, ETH_ALEN);
+	} else {
+		_rtw_memcpy(data, psta->hwaddr, ETH_ALEN);
+		_rtw_memcpy(data + ETH_ALEN, adapter_mac_addr(padapter), ETH_ALEN);
+	}
+	_rtw_memcpy(data + 2 * ETH_ALEN, get_bssid(pmlmepriv), ETH_ALEN);
+
+	sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), (u8 *) &psta->tpk, sizeof(psta->tpk));	
+
+
+}
+
+/**
+ * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
+ * @kck: TPK-KCK
+ * @lnkid: Pointer to the beginning of Link Identifier IE
+ * @rsnie: Pointer to the beginning of RSN IE used for handshake
+ * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
+ * @ftie: Pointer to the beginning of FT IE
+ * @mic: Pointer for writing MIC
+ *
+ * Calculate MIC for TDLS frame.
+ */
+int wpa_tdls_ftie_mic(u8 *kck, u8 trans_seq, 
+							u8 *lnkid, u8 *rsnie, u8 *timeoutie, u8 *ftie,
+							u8 *mic)
+{
+	u8 *buf, *pos;
+	struct wpa_tdls_ftie *_ftie;
+	struct wpa_tdls_lnkid *_lnkid;
+	int ret;
+	int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] +
+		2 + timeoutie[1] + 2 + ftie[1];
+	buf = rtw_zmalloc(len);
+	if (!buf) {
+		DBG_871X("TDLS: No memory for MIC calculation\n");
+		return -1;
+	}
+
+	pos = buf;
+	_lnkid = (struct wpa_tdls_lnkid *) lnkid;
+	/* 1) TDLS initiator STA MAC address */
+	_rtw_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
+	pos += ETH_ALEN;
+	/* 2) TDLS responder STA MAC address */
+	_rtw_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
+	pos += ETH_ALEN;
+	/* 3) Transaction Sequence number */
+	*pos++ = trans_seq;
+	/* 4) Link Identifier IE */
+	_rtw_memcpy(pos, lnkid, 2 + lnkid[1]);
+	pos += 2 + lnkid[1];
+	/* 5) RSN IE */
+	_rtw_memcpy(pos, rsnie, 2 + rsnie[1]);
+	pos += 2 + rsnie[1];
+	/* 6) Timeout Interval IE */
+	_rtw_memcpy(pos, timeoutie, 2 + timeoutie[1]);
+	pos += 2 + timeoutie[1];
+	/* 7) FTIE, with the MIC field of the FTIE set to 0 */
+	_rtw_memcpy(pos, ftie, 2 + ftie[1]);
+	_ftie = (struct wpa_tdls_ftie *) pos;
+	_rtw_memset(_ftie->mic, 0, TDLS_MIC_LEN);
+	pos += 2 + ftie[1];
+ 
+	ret = omac1_aes_128(kck, buf, pos - buf, mic);
+	rtw_mfree(buf, len);
+	return ret;
+
+}
+
+/**
+ * wpa_tdls_teardown_ftie_mic - Calculate TDLS TEARDOWN FTIE MIC
+ * @kck: TPK-KCK
+ * @lnkid: Pointer to the beginning of Link Identifier IE
+ * @reason: Reason code of TDLS Teardown
+ * @dialog_token: Dialog token that was used in the MIC calculation for TPK Handshake Message 3
+ * @trans_seq: Transaction Sequence number (1 octet) which shall be set to the value 4
+ * @ftie: Pointer to the beginning of FT IE
+ * @mic: Pointer for writing MIC
+ *
+ * Calculate MIC for TDLS TEARDOWN frame according to Section 10.22.5 in IEEE 802.11 - 2012.
+ */
+int wpa_tdls_teardown_ftie_mic(u8 *kck, u8 *lnkid, u16 reason, 
+	u8 dialog_token, u8 trans_seq, u8 *ftie, u8 *mic)
+{
+	u8 *buf, *pos;
+	struct wpa_tdls_ftie *_ftie;
+	int ret;
+	int len = 2 + lnkid[1] + 2 + 1 + 1 + 2 + ftie[1];
+	
+	buf = rtw_zmalloc(len);
+	if (!buf) {
+		DBG_871X("TDLS: No memory for MIC calculation\n");
+		return -1;
+	}
+
+	pos = buf;
+	/* 1) Link Identifier IE */
+	_rtw_memcpy(pos, lnkid, 2 + lnkid[1]);
+	pos += 2 + lnkid[1];
+	/* 2) Reason Code */
+	_rtw_memcpy(pos, (u8 *)&reason, 2);
+	pos += 2;
+	/* 3) Dialog Token */
+	*pos++ = dialog_token;
+	/* 4) Transaction Sequence number */
+	*pos++ = trans_seq;
+	/* 5) FTIE, with the MIC field of the FTIE set to 0 */
+	_rtw_memcpy(pos, ftie, 2 + ftie[1]);
+	_ftie = (struct wpa_tdls_ftie *) pos;
+	_rtw_memset(_ftie->mic, 0, TDLS_MIC_LEN);
+	pos += 2 + ftie[1];
+
+	ret = omac1_aes_128(kck, buf, pos - buf, mic);
+	rtw_mfree(buf, len);
+	return ret;
+
+}
+
+int tdls_verify_mic(u8 *kck, u8 trans_seq,
+							u8 *lnkid, u8 *rsnie, u8 *timeoutie, u8 *ftie)
+{
+	u8 *buf, *pos;
+	int len;
+	u8 mic[16];
+	int ret;
+	u8 *rx_ftie, *tmp_ftie;
+
+	if (lnkid == NULL || rsnie == NULL ||
+	    timeoutie == NULL || ftie == NULL){
+		return _FAIL;
+	}
+	
+	len = 2 * ETH_ALEN + 1 + 2 + 18 + 2 + *(rsnie+1) + 2 + *(timeoutie+1) + 2 + *(ftie+1);
+
+	buf = rtw_zmalloc(len);
+	if (buf == NULL)
+		return _FAIL;
+
+	pos = buf;
+	/* 1) TDLS initiator STA MAC address */
+	_rtw_memcpy(pos, lnkid + ETH_ALEN + 2, ETH_ALEN);
+	pos += ETH_ALEN;
+	/* 2) TDLS responder STA MAC address */
+	_rtw_memcpy(pos, lnkid + 2 * ETH_ALEN + 2, ETH_ALEN);
+	pos += ETH_ALEN;
+	/* 3) Transaction Sequence number */
+	*pos++ = trans_seq;
+	/* 4) Link Identifier IE */
+	_rtw_memcpy(pos, lnkid, 2 + 18);
+	pos += 2 + 18;
+	/* 5) RSN IE */
+	_rtw_memcpy(pos, rsnie, 2 + *(rsnie+1));
+	pos += 2 + *(rsnie+1);
+	/* 6) Timeout Interval IE */
+	_rtw_memcpy(pos, timeoutie, 2 + *(timeoutie+1));
+	pos += 2 + *(timeoutie+1);
+	/* 7) FTIE, with the MIC field of the FTIE set to 0 */
+	_rtw_memcpy(pos, ftie, 2 + *(ftie+1));
+	pos += 2;
+	tmp_ftie = (u8 *) (pos+2);
+	_rtw_memset(tmp_ftie, 0, 16);
+	pos += *(ftie+1);
+
+	ret = omac1_aes_128(kck, buf, pos - buf, mic);
+	rtw_mfree(buf, len);
+	if (ret)
+		return _FAIL;
+	rx_ftie = ftie+4;
+
+	if (os_memcmp(mic, rx_ftie, 16) == 0) {
+		//Valid MIC
+		return _SUCCESS;
+	}
+
+	//Invalid MIC
+	DBG_871X( "[%s] Invalid MIC\n", __FUNCTION__);
+	return _FAIL;
+
+}
+#endif //CONFIG_TDLS
+
+/* Restore HW wep key setting according to key_mask */
+void rtw_sec_restore_wep_key(_adapter *adapter)
+{
+	struct security_priv* securitypriv=&(adapter->securitypriv);
+	sint keyid;
+
+	if((_WEP40_ == securitypriv->dot11PrivacyAlgrthm) ||(_WEP104_ == securitypriv->dot11PrivacyAlgrthm)) {
+		for(keyid=0;keyid<4;keyid++){
+			if(securitypriv->key_mask & BIT(keyid)){
+				if(keyid == securitypriv->dot11PrivacyKeyIndex)
+					rtw_set_key(adapter,securitypriv, keyid, 1, _FALSE);
+				else
+					rtw_set_key(adapter,securitypriv, keyid, 0, _FALSE);
+			}
+		}
+	}
+}
+
+u8 rtw_handle_tkip_countermeasure(_adapter* adapter, const char *caller)
+{
+	struct security_priv* securitypriv=&(adapter->securitypriv);
+	u8 status = _SUCCESS;
+
+	if (securitypriv->btkip_countermeasure == _TRUE) {
+		u32 passing_ms = rtw_get_passing_time_ms(securitypriv->btkip_countermeasure_time);
+		if (passing_ms > 60*1000) {
+			DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%ds > 60s \n",
+				caller, ADPT_ARG(adapter), passing_ms/1000);
+			securitypriv->btkip_countermeasure = _FALSE;
+			securitypriv->btkip_countermeasure_time = 0;
+		} else {
+			DBG_871X_LEVEL(_drv_always_, "%s("ADPT_FMT") countermeasure time:%ds < 60s \n",
+				caller, ADPT_ARG(adapter), passing_ms/1000);
+			status = _FAIL;
+		}
+	}
+
+	return status;
+}
+
+#ifdef CONFIG_WOWLAN
+u16 rtw_cal_crc16(u8 data, u16 crc)
+{
+	u8 shift_in, data_bit;
+	u8 crc_bit4, crc_bit11, crc_bit15;
+	u16 crc_result;
+	int index;
+
+	for (index = 0; index < 8; index++) {
+		crc_bit15 = ((crc & BIT15) ? 1 : 0);
+		data_bit = (data & (BIT0 << index) ? 1 : 0);
+		shift_in = crc_bit15 ^ data_bit;
+		/*printf("crc_bit15=%d, DataBit=%d, shift_in=%d\n",
+		 * crc_bit15, data_bit, shift_in);*/
+
+		crc_result = crc << 1;
+
+		if (shift_in == 0)
+			crc_result &= (~BIT0);
+		else
+			crc_result |= BIT0;
+		/*printf("CRC =%x\n",CRC_Result);*/
+
+		crc_bit11 = ((crc & BIT11) ? 1 : 0) ^ shift_in;
+
+		if (crc_bit11 == 0)
+			crc_result &= (~BIT12); 
+		else
+			crc_result |= BIT12;
+
+		/*printf("bit12 CRC =%x\n",CRC_Result);*/
+
+		crc_bit4 = ((crc & BIT4) ? 1 : 0) ^ shift_in;
+
+		if (crc_bit4 == 0)
+			crc_result &= (~BIT5);
+		else
+			crc_result |= BIT5;
+
+		/* printf("bit5 CRC =%x\n",CRC_Result); */
+		/* repeat using the last result*/
+		crc = crc_result;
+	}
+	return crc;
+}
+
+/*
+ * function name :rtw_calc_crc
+ *
+ * input: char* pattern , pattern size
+ *
+ */
+u16 rtw_calc_crc(u8  *pdata, int length)
+{
+	u16 crc = 0xffff;
+	int i;
+	
+	for (i = 0; i < length; i++)
+		crc = rtw_cal_crc16(pdata[i], crc);
+	/* get 1' complement */
+	crc = ~crc;
+
+	return crc;
+}
+#endif /*CONFIG_WOWLAN*/
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_sreset.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_sreset.c
new file mode 100644
index 000000000..f49b0994e
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_sreset.c
@@ -0,0 +1,370 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+
+#include <drv_types.h>
+#include <hal_data.h>
+#include <rtw_sreset.h>
+
+void sreset_init_value(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+	_rtw_mutex_init(&psrtpriv->silentreset_mutex);
+	psrtpriv->silent_reset_inprogress = _FALSE;
+	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+	psrtpriv->last_tx_time =0;
+	psrtpriv->last_tx_complete_time =0;
+#endif
+}
+void sreset_reset_value(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+	psrtpriv->last_tx_time =0;
+	psrtpriv->last_tx_complete_time =0;
+#endif
+}
+
+u8 sreset_get_wifi_status(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+
+	u8 status = WIFI_STATUS_SUCCESS;
+	u32 val32 = 0;
+	_irqL irqL;
+	if(psrtpriv->silent_reset_inprogress == _TRUE)
+        {
+		return status;
+	}
+	val32 =rtw_read32(padapter,REG_TXDMA_STATUS);
+	if(val32==0xeaeaeaea){
+		psrtpriv->Wifi_Error_Status = WIFI_IF_NOT_EXIST;
+	}
+	else if(val32!=0){
+		DBG_8192C("txdmastatu(%x)\n",val32);
+		psrtpriv->Wifi_Error_Status = WIFI_MAC_TXDMA_ERROR;
+	}
+
+	if(WIFI_STATUS_SUCCESS !=psrtpriv->Wifi_Error_Status)
+	{
+		DBG_8192C("==>%s error_status(0x%x) \n",__FUNCTION__,psrtpriv->Wifi_Error_Status);
+		status = (psrtpriv->Wifi_Error_Status &( ~(USB_READ_PORT_FAIL|USB_WRITE_PORT_FAIL)));
+	}
+	DBG_8192C("==> %s wifi_status(0x%x)\n",__FUNCTION__,status);
+
+	//status restore
+	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+
+	return status;
+#else
+	return WIFI_STATUS_SUCCESS;
+#endif
+}
+
+void sreset_set_wifi_error_status(_adapter *padapter, u32 status)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	pHalData->srestpriv.Wifi_Error_Status = status;
+#endif
+}
+
+void sreset_set_trigger_point(_adapter *padapter, s32 tgp)
+{
+#if defined(DBG_CONFIG_ERROR_DETECT)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	pHalData->srestpriv.dbg_trigger_point = tgp;
+#endif
+}
+
+bool sreset_inprogress(_adapter *padapter)
+{
+#if defined(DBG_CONFIG_ERROR_RESET)
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	return pHalData->srestpriv.silent_reset_inprogress;
+#else
+	return _FALSE;
+#endif
+}
+
+void sreset_restore_security_station(_adapter *padapter)
+{
+	u8 EntryId = 0;
+	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+	struct sta_priv * pstapriv = &padapter->stapriv;
+	struct sta_info *psta;
+	struct security_priv* psecuritypriv=&(padapter->securitypriv);
+	struct mlme_ext_info	*pmlmeinfo = &padapter->mlmeextpriv.mlmext_info;
+
+	{
+		u8 val8;
+
+		if (pmlmeinfo->auth_algo == dot11AuthAlgrthm_8021X) {
+			val8 = 0xcc;
+		#ifdef CONFIG_WAPI_SUPPORT
+		} else if (padapter->wapiInfo.bWapiEnable && pmlmeinfo->auth_algo == dot11AuthAlgrthm_WAPI) {
+			//Disable TxUseDefaultKey, RxUseDefaultKey, RxBroadcastUseDefaultKey.
+			val8 = 0x4c;
+		#endif
+		} else {
+			val8 = 0xcf;
+		}
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_CFG, (u8 *)(&val8));
+	}
+
+	#if 0
+	if (	( padapter->securitypriv.dot11PrivacyAlgrthm == _WEP40_ ) ||
+		( padapter->securitypriv.dot11PrivacyAlgrthm == _WEP104_ ))
+	{
+
+		for(EntryId=0; EntryId<4; EntryId++)
+		{
+			if(EntryId == psecuritypriv->dot11PrivacyKeyIndex)
+				rtw_set_key(padapter,&padapter->securitypriv, EntryId, 1,_FALSE);
+			else
+				rtw_set_key(padapter,&padapter->securitypriv, EntryId, 0,_FALSE);
+		}
+
+	}
+	else
+	#endif
+	if((padapter->securitypriv.dot11PrivacyAlgrthm == _TKIP_) ||
+		(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_))
+	{
+		psta = rtw_get_stainfo(pstapriv, get_bssid(mlmepriv));
+		if (psta == NULL) {
+			//DEBUG_ERR( ("Set wpa_set_encryption: Obtain Sta_info fail \n"));
+		}
+		else
+		{
+			//pairwise key
+			rtw_setstakey_cmd(padapter, psta, UNICAST_KEY,_FALSE);
+			//group key
+			rtw_set_key(padapter,&padapter->securitypriv,padapter->securitypriv.dot118021XGrpKeyid, 0,_FALSE);
+		}
+	}
+}
+
+void sreset_restore_network_station(_adapter *padapter)
+{
+	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 doiqk = _FALSE;
+
+	#if 0
+	{
+	//=======================================================
+	// reset related register of Beacon control
+
+	//set MSR to nolink
+	Set_MSR(padapter, _HW_STATE_NOLINK_);		
+	// reject all data frame
+	rtw_write16(padapter, REG_RXFLTMAP2,0x00);
+	//reset TSF
+	rtw_write8(padapter, REG_DUAL_TSF_RST, (BIT(0)|BIT(1)));
+
+	// disable update TSF
+	SetBcnCtrlReg(padapter, BIT(4), 0);
+
+	//=======================================================
+	}
+	#endif
+	
+	rtw_setopmode_cmd(padapter, Ndis802_11Infrastructure,_FALSE);
+
+	{
+		u8 threshold;
+		#ifdef CONFIG_USB_HCI
+		// TH=1 => means that invalidate usb rx aggregation
+		// TH=0 => means that validate usb rx aggregation, use init value.
+		if(mlmepriv->htpriv.ht_option) {
+			if(padapter->registrypriv.wifi_spec==1)		
+				threshold = 1;
+			else
+				threshold = 0;
+			rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+		} else {
+			threshold = 1;
+			rtw_hal_set_hwreg(padapter, HW_VAR_RXDMA_AGG_PG_TH, (u8 *)(&threshold));
+		}
+		#endif
+	}
+
+	doiqk = _TRUE;
+	rtw_hal_set_hwreg(padapter, HW_VAR_DO_IQK , &doiqk);
+
+	set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+	doiqk = _FALSE;
+	rtw_hal_set_hwreg(padapter , HW_VAR_DO_IQK , &doiqk);
+	//disable dynamic functions, such as high power, DIG
+	/*rtw_phydm_func_disable_all(padapter);*/
+	
+	rtw_hal_set_hwreg(padapter, HW_VAR_BSSID, pmlmeinfo->network.MacAddress);
+
+	{
+		u8	join_type = 0;
+		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_JOIN, (u8 *)(&join_type));
+	}
+
+	Set_MSR(padapter, (pmlmeinfo->state & 0x3));
+
+	mlmeext_joinbss_event_callback(padapter, 1);
+	//restore Sequence No.
+	rtw_hal_set_hwreg(padapter, HW_VAR_RESTORE_HW_SEQ, 0);
+
+	sreset_restore_security_station(padapter);
+}
+
+
+void sreset_restore_network_status(_adapter *padapter)
+{
+	struct mlme_priv *mlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if (check_fwstate(mlmepriv, WIFI_STATION_STATE)) {
+		DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_STATION_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+		sreset_restore_network_station(padapter);
+	} else if (check_fwstate(mlmepriv, WIFI_AP_STATE)) {
+		DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_AP_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+		rtw_ap_restore_network(padapter);
+	} else if (check_fwstate(mlmepriv, WIFI_ADHOC_STATE)) {
+		DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - WIFI_ADHOC_STATE\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+	} else {
+		DBG_871X(FUNC_ADPT_FMT" fwstate:0x%08x - ???\n", FUNC_ADPT_ARG(padapter), get_fwstate(mlmepriv));
+	}
+}
+
+void sreset_stop_adapter(_adapter *padapter)
+{
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+
+	if (padapter == NULL)
+		return;
+
+	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+	rtw_netif_stop_queue(padapter->pnetdev);
+
+	rtw_cancel_all_timer(padapter);
+
+	/* TODO: OS and HCI independent */
+	#if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI)
+	tasklet_kill(&pxmitpriv->xmit_tasklet);
+	#endif
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
+		rtw_scan_abort(padapter);
+
+	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
+	{
+		rtw_set_to_roam(padapter, 0);
+		printk("%s %d\n", __func__, __LINE__);
+		//_rtw_join_timeout_handler(padapter);
+	}
+
+}
+
+void sreset_start_adapter(_adapter *padapter)
+{
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+
+	if (padapter == NULL)
+		return;
+
+	DBG_871X(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
+
+	if (check_fwstate(pmlmepriv, _FW_LINKED)) {
+		sreset_restore_network_status(padapter);
+	}
+
+	/* TODO: OS and HCI independent */
+	#if defined(PLATFORM_LINUX) && defined(CONFIG_USB_HCI)
+	tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
+	#endif
+
+	if (is_primary_adapter(padapter))
+		_set_timer(&padapter->mlmepriv.dynamic_chk_timer, 2000);
+
+	rtw_netif_wake_queue(padapter->pnetdev);
+}
+
+void sreset_reset(_adapter *padapter)
+{
+#ifdef DBG_CONFIG_ERROR_RESET
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(padapter);
+	struct sreset_priv *psrtpriv = &pHalData->srestpriv;
+	struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	_irqL irqL;
+	u32 start = rtw_get_current_time();
+	struct dvobj_priv *psdpriv = padapter->dvobj;
+	struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
+
+	DBG_871X("%s\n", __FUNCTION__);
+
+	psrtpriv->Wifi_Error_Status = WIFI_STATUS_SUCCESS;
+
+
+#ifdef CONFIG_LPS
+	rtw_set_ps_mode(padapter, PS_MODE_ACTIVE, 0, 0, "SRESET");
+#endif//#ifdef CONFIG_LPS
+	
+	_enter_pwrlock(&pwrpriv->lock);
+
+	psrtpriv->silent_reset_inprogress = _TRUE;
+	pwrpriv->change_rfpwrstate = rf_off;
+
+	sreset_stop_adapter(padapter);
+	#ifdef CONFIG_CONCURRENT_MODE
+	sreset_stop_adapter(padapter->pbuddy_adapter);
+	#endif
+
+	#ifdef CONFIG_IPS
+	_ips_enter(padapter);
+	_ips_leave(padapter);
+	#endif
+
+	sreset_start_adapter(padapter);
+	#ifdef CONFIG_CONCURRENT_MODE
+	sreset_start_adapter(padapter->pbuddy_adapter);
+	#endif
+
+	psrtpriv->silent_reset_inprogress = _FALSE;
+
+	_exit_pwrlock(&pwrpriv->lock);
+
+	DBG_871X("%s done in %d ms\n", __FUNCTION__, rtw_get_passing_time_ms(start));
+	pdbgpriv->dbg_sreset_cnt++;
+#endif
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_sta_mgt.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_sta_mgt.c
new file mode 100644
index 000000000..730b425d4
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_sta_mgt.c
@@ -0,0 +1,1021 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_STA_MGT_C_
+
+#include <drv_types.h>
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+
+#error "Shall be Linux or Windows, but not both!\n"
+
+#endif
+
+
+bool test_st_match_rule(_adapter *adapter, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
+{
+	if (ntohs(*((u16 *)local_port)) == 5001 || ntohs(*((u16 *)remote_port)) == 5001)
+		return _TRUE;
+	return _FALSE;
+}
+
+struct st_register test_st_reg = {
+	.s_proto = 0x06,
+	.rule = test_st_match_rule,
+};
+
+inline void rtw_st_ctl_init(struct st_ctl_t *st_ctl)
+{
+	_rtw_memset(st_ctl->reg, 0 , sizeof(struct st_register) * SESSION_TRACKER_REG_ID_NUM);
+	_rtw_init_queue(&st_ctl->tracker_q);
+}
+
+inline void rtw_st_ctl_clear_tracker_q(struct st_ctl_t *st_ctl)
+{
+	_irqL irqL;
+	_list *plist, *phead;
+	struct session_tracker *st;
+
+	_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+	phead = &st_ctl->tracker_q.queue;
+	plist = get_next(phead);
+	while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+		st = LIST_CONTAINOR(plist, struct session_tracker, list);
+		plist = get_next(plist);
+		rtw_list_delete(&st->list);
+		rtw_mfree((u8 *)st, sizeof(struct session_tracker));
+	}
+	_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+}
+
+inline void rtw_st_ctl_deinit(struct st_ctl_t *st_ctl)
+{
+	rtw_st_ctl_clear_tracker_q(st_ctl);
+	_rtw_deinit_queue(&st_ctl->tracker_q);
+}
+
+inline void rtw_st_ctl_register(struct st_ctl_t *st_ctl, u8 st_reg_id, struct st_register *reg)
+{
+	if (st_reg_id >= SESSION_TRACKER_REG_ID_NUM) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	st_ctl->reg[st_reg_id].s_proto = reg->s_proto;
+	st_ctl->reg[st_reg_id].rule = reg->rule;
+}
+
+inline void rtw_st_ctl_unregister(struct st_ctl_t *st_ctl, u8 st_reg_id)
+{
+	int i;
+
+	if (st_reg_id >= SESSION_TRACKER_REG_ID_NUM) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	st_ctl->reg[st_reg_id].s_proto = 0;
+	st_ctl->reg[st_reg_id].rule = NULL;
+
+	/* clear tracker queue if no session trecker registered */
+	for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++)
+		if (st_ctl->reg[i].s_proto != 0)
+			break;
+	if (i >= SESSION_TRACKER_REG_ID_NUM)
+		rtw_st_ctl_clear_tracker_q(st_ctl);
+}
+
+inline bool rtw_st_ctl_chk_reg_s_proto(struct st_ctl_t *st_ctl, u8 s_proto)
+{
+	bool ret = _FALSE;
+	int i;
+
+	for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
+		if (st_ctl->reg[i].s_proto == s_proto) {
+			ret = _TRUE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+inline bool rtw_st_ctl_chk_reg_rule(struct st_ctl_t *st_ctl, _adapter *adapter, u8 *local_naddr, u8 *local_port, u8 *remote_naddr, u8 *remote_port)
+{
+	bool ret = _FALSE;
+	int i;
+	st_match_rule rule;
+
+	for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++) {
+		rule = st_ctl->reg[i].rule;
+		if (rule && rule(adapter, local_naddr, local_port, remote_naddr, remote_port) == _TRUE) {
+			ret = _TRUE;
+			break;
+		}
+	}
+
+	return ret;
+}
+
+#define SESSION_TRACKER_FMT IP_FMT":"PORT_FMT" "IP_FMT":"PORT_FMT" %u %d"
+#define SESSION_TRACKER_ARG(st) IP_ARG(&(st)->local_naddr), PORT_ARG(&(st)->local_port), IP_ARG(&(st)->remote_naddr), PORT_ARG(&(st)->remote_port), (st)->status, rtw_get_passing_time_ms((st)->set_time)
+
+void dump_st_ctl(void *sel, struct st_ctl_t *st_ctl)
+{
+	int i;
+	_irqL irqL;
+	_list *plist, *phead;
+	struct session_tracker *st;
+
+	if (!DBG_SESSION_TRACKER)
+		return;
+
+	for (i = 0; i < SESSION_TRACKER_REG_ID_NUM; i++)
+		DBG_871X_SEL_NL(sel, "reg%d: %u %p\n", i, st_ctl->reg[i].s_proto, st_ctl->reg[i].rule);
+
+	_enter_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+	phead = &st_ctl->tracker_q.queue;
+	plist = get_next(phead);
+	while (rtw_end_of_queue_search(phead, plist) == _FALSE) {
+		st = LIST_CONTAINOR(plist, struct session_tracker, list);
+		plist = get_next(plist);
+
+		DBG_871X_SEL_NL(sel, SESSION_TRACKER_FMT"\n", SESSION_TRACKER_ARG(st));
+	}
+	_exit_critical_bh(&st_ctl->tracker_q.lock, &irqL);
+
+}
+
+void _rtw_init_stainfo(struct sta_info *psta);
+void _rtw_init_stainfo(struct sta_info *psta)
+{
+
+_func_enter_;
+
+	_rtw_memset((u8 *)psta, 0, sizeof (struct sta_info));
+
+	 _rtw_spinlock_init(&psta->lock);
+	_rtw_init_listhead(&psta->list);
+	_rtw_init_listhead(&psta->hash_list);
+	//_rtw_init_listhead(&psta->asoc_list);
+	//_rtw_init_listhead(&psta->sleep_list);
+	//_rtw_init_listhead(&psta->wakeup_list);	
+
+	_rtw_init_queue(&psta->sleep_q);
+	psta->sleepq_len = 0;
+
+	_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
+	_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
+	
+#ifdef CONFIG_AP_MODE
+
+	_rtw_init_listhead(&psta->asoc_list);
+
+	_rtw_init_listhead(&psta->auth_list);
+	
+	psta->expire_to = 0;
+	
+	psta->flags = 0;
+	
+	psta->capability = 0;
+
+	psta->bpairwise_key_installed = _FALSE;
+
+
+#ifdef CONFIG_NATIVEAP_MLME
+	psta->nonerp_set = 0;
+	psta->no_short_slot_time_set = 0;
+	psta->no_short_preamble_set = 0;
+	psta->no_ht_gf_set = 0;
+	psta->no_ht_set = 0;
+	psta->ht_20mhz_set = 0;
+	psta->ht_40mhz_intolerant = 0;
+#endif	
+
+#ifdef CONFIG_TX_MCAST2UNI
+	psta->under_exist_checking = 0;
+#endif	// CONFIG_TX_MCAST2UNI
+	
+	psta->keep_alive_trycnt = 0;
+
+#endif	// CONFIG_AP_MODE	
+
+	rtw_st_ctl_init(&psta->st_ctl);
+
+_func_exit_;	
+
+}
+
+u32	_rtw_init_sta_priv(struct	sta_priv *pstapriv)
+{
+	struct sta_info *psta;
+	s32 i;
+
+_func_enter_;	
+
+	pstapriv->pallocated_stainfo_buf = rtw_zvmalloc (sizeof(struct sta_info) * NUM_STA+ 4);
+	
+	if(!pstapriv->pallocated_stainfo_buf)
+		return _FAIL;
+
+	pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 - 
+		((SIZE_PTR)(pstapriv->pallocated_stainfo_buf ) & 3);
+
+	_rtw_init_queue(&pstapriv->free_sta_queue);
+
+	_rtw_spinlock_init(&pstapriv->sta_hash_lock);
+	
+	//_rtw_init_queue(&pstapriv->asoc_q);
+	pstapriv->asoc_sta_count = 0;
+	_rtw_init_queue(&pstapriv->sleep_q);
+	_rtw_init_queue(&pstapriv->wakeup_q);
+
+	psta = (struct sta_info *)(pstapriv->pstainfo_buf);
+
+		
+	for(i = 0; i < NUM_STA; i++)
+	{
+		_rtw_init_stainfo(psta);
+
+		_rtw_init_listhead(&(pstapriv->sta_hash[i]));
+
+		rtw_list_insert_tail(&psta->list, get_list_head(&pstapriv->free_sta_queue));
+
+		psta++;
+	}
+
+	
+
+#ifdef CONFIG_AP_MODE
+
+	pstapriv->sta_dz_bitmap = 0;
+	pstapriv->tim_bitmap = 0;
+
+	_rtw_init_listhead(&pstapriv->asoc_list);
+	_rtw_init_listhead(&pstapriv->auth_list);
+	_rtw_spinlock_init(&pstapriv->asoc_list_lock);
+	_rtw_spinlock_init(&pstapriv->auth_list_lock);
+	pstapriv->asoc_list_cnt = 0;
+	pstapriv->auth_list_cnt = 0;
+
+	pstapriv->auth_to = 3; // 3*2 = 6 sec 
+	pstapriv->assoc_to = 3;
+	//pstapriv->expire_to = 900;// 900*2 = 1800 sec = 30 min, expire after no any traffic.
+	//pstapriv->expire_to = 30;// 30*2 = 60 sec = 1 min, expire after no any traffic.
+#ifdef CONFIG_ACTIVE_KEEP_ALIVE_CHECK
+	pstapriv->expire_to = 3; // 3*2 = 6 sec
+#else
+	pstapriv->expire_to = 60;// 60*2 = 120 sec = 2 min, expire after no any traffic.
+#endif	
+#ifdef CONFIG_ATMEL_RC_PATCH
+	_rtw_memset(  pstapriv->atmel_rc_pattern, 0, ETH_ALEN);
+#endif	
+	pstapriv->max_num_sta = NUM_STA;
+		
+#endif
+	
+_func_exit_;		
+
+	return _SUCCESS;
+	
+}
+
+inline int rtw_stainfo_offset(struct sta_priv *stapriv, struct sta_info *sta)
+{
+	int offset = (((u8 *)sta) - stapriv->pstainfo_buf)/sizeof(struct sta_info);
+
+	if (!stainfo_offset_valid(offset))
+		DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
+
+	return offset;
+}
+
+inline struct sta_info *rtw_get_stainfo_by_offset(struct sta_priv *stapriv, int offset)
+{
+	if (!stainfo_offset_valid(offset))
+		DBG_871X("%s invalid offset(%d), out of range!!!", __func__, offset);
+
+	return (struct sta_info *)(stapriv->pstainfo_buf + offset * sizeof(struct sta_info));
+}
+
+void	_rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv);
+void	_rtw_free_sta_xmit_priv_lock(struct sta_xmit_priv *psta_xmitpriv)
+{
+_func_enter_;
+
+	_rtw_spinlock_free(&psta_xmitpriv->lock);
+
+	_rtw_spinlock_free(&(psta_xmitpriv->be_q.sta_pending.lock));
+	_rtw_spinlock_free(&(psta_xmitpriv->bk_q.sta_pending.lock));
+	_rtw_spinlock_free(&(psta_xmitpriv->vi_q.sta_pending.lock));
+	_rtw_spinlock_free(&(psta_xmitpriv->vo_q.sta_pending.lock));
+_func_exit_;	
+}
+
+static void	_rtw_free_sta_recv_priv_lock(struct sta_recv_priv *psta_recvpriv)
+{
+_func_enter_;	
+
+	_rtw_spinlock_free(&psta_recvpriv->lock);
+
+	_rtw_spinlock_free(&(psta_recvpriv->defrag_q.lock));
+
+_func_exit_;
+
+}
+
+void rtw_mfree_stainfo(struct sta_info *psta);
+void rtw_mfree_stainfo(struct sta_info *psta)
+{
+_func_enter_;
+
+	if(&psta->lock != NULL)
+		 _rtw_spinlock_free(&psta->lock);
+
+	_rtw_free_sta_xmit_priv_lock(&psta->sta_xmitpriv);
+	_rtw_free_sta_recv_priv_lock(&psta->sta_recvpriv);
+	
+_func_exit_;	
+}
+
+
+// this function is used to free the memory of lock || sema for all stainfos
+void rtw_mfree_all_stainfo(struct sta_priv *pstapriv );
+void rtw_mfree_all_stainfo(struct sta_priv *pstapriv )
+{
+	_irqL	 irqL;
+	_list	*plist, *phead;
+	struct sta_info *psta = NULL;
+	
+_func_enter_;	
+
+	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+	phead = get_list_head(&pstapriv->free_sta_queue);
+	plist = get_next(phead);
+		
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+		psta = LIST_CONTAINOR(plist, struct sta_info ,list);
+		plist = get_next(plist);
+
+		rtw_mfree_stainfo(psta);
+	}
+	
+	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+_func_exit_;	
+
+}
+
+void rtw_mfree_sta_priv_lock(struct	sta_priv *pstapriv);
+void rtw_mfree_sta_priv_lock(struct	sta_priv *pstapriv)
+{
+#ifdef CONFIG_AP_MODE
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+#endif
+
+	 rtw_mfree_all_stainfo(pstapriv); //be done before free sta_hash_lock
+
+	_rtw_spinlock_free(&pstapriv->free_sta_queue.lock);
+
+	_rtw_spinlock_free(&pstapriv->sta_hash_lock);
+	_rtw_spinlock_free(&pstapriv->wakeup_q.lock);
+	_rtw_spinlock_free(&pstapriv->sleep_q.lock);
+
+#ifdef CONFIG_AP_MODE
+	_rtw_spinlock_free(&pstapriv->asoc_list_lock);
+	_rtw_spinlock_free(&pstapriv->auth_list_lock);
+	_rtw_spinlock_free(&pacl_list->acl_node_q.lock);
+#endif
+
+}
+
+u32	_rtw_free_sta_priv(struct	sta_priv *pstapriv)
+{
+	_irqL 	irqL;
+	_list	*phead, *plist;
+	struct sta_info *psta = NULL;
+	struct recv_reorder_ctrl *preorder_ctrl;
+	int 	index;
+
+_func_enter_;
+	if(pstapriv){
+
+		/*	delete all reordering_ctrl_timer		*/ 
+		_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		for(index = 0; index < NUM_STA; index++)
+		{
+			phead = &(pstapriv->sta_hash[index]);
+			plist = get_next(phead);
+			
+			while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+			{
+				int i;	
+				psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
+				plist = get_next(plist);
+
+				for(i=0; i < 16 ; i++)
+				{
+					preorder_ctrl = &psta->recvreorder_ctrl[i];
+					_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);	
+				}
+			}
+		}
+		_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+		/*===============================*/
+		
+		rtw_mfree_sta_priv_lock(pstapriv);
+
+		if(pstapriv->pallocated_stainfo_buf) {
+			rtw_vmfree(pstapriv->pallocated_stainfo_buf, sizeof(struct sta_info)*NUM_STA+4);
+		}
+	}
+	
+_func_exit_;
+	return _SUCCESS;
+}
+
+
+//struct	sta_info *rtw_alloc_stainfo(_queue *pfree_sta_queue, unsigned char *hwaddr)
+struct	sta_info *rtw_alloc_stainfo(struct	sta_priv *pstapriv, u8 *hwaddr) 
+{	
+	_irqL irqL, irqL2;
+	uint tmp_aid;
+	s32	index;
+	_list	*phash_list;
+	struct sta_info	*psta;
+	_queue *pfree_sta_queue;
+	struct recv_reorder_ctrl *preorder_ctrl;
+	int i = 0;
+	u16  wRxSeqInitialValue = 0xffff;
+	
+_func_enter_;	
+
+	pfree_sta_queue = &pstapriv->free_sta_queue;
+
+	//_enter_critical_bh(&(pfree_sta_queue->lock), &irqL);
+	_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+	if (_rtw_queue_empty(pfree_sta_queue) == _TRUE)
+	{
+		//_exit_critical_bh(&(pfree_sta_queue->lock), &irqL);
+		_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+		psta = NULL;
+	}
+	else
+	{
+		psta = LIST_CONTAINOR(get_next(&pfree_sta_queue->queue), struct sta_info, list);
+		
+		rtw_list_delete(&(psta->list));
+
+		//_exit_critical_bh(&(pfree_sta_queue->lock), &irqL);
+		
+		tmp_aid = psta->aid;	
+	
+		_rtw_init_stainfo(psta);
+
+		psta->padapter = pstapriv->padapter;
+
+		_rtw_memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
+
+		index = wifi_mac_hash(hwaddr);
+
+		RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("rtw_alloc_stainfo: index  = %x", index));
+
+		if(index >= NUM_STA){
+			RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("ERROR=> rtw_alloc_stainfo: index >= NUM_STA"));
+			psta= NULL;	
+			goto exit;
+		}
+		phash_list = &(pstapriv->sta_hash[index]);
+
+		//_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+
+		rtw_list_insert_tail(&psta->hash_list, phash_list);
+
+		pstapriv->asoc_sta_count ++ ;
+
+		//_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+
+// Commented by Albert 2009/08/13
+// For the SMC router, the sequence number of first packet of WPS handshake will be 0.
+// In this case, this packet will be dropped by recv_decache function if we use the 0x00 as the default value for tid_rxseq variable.
+// So, we initialize the tid_rxseq variable as the 0xffff.
+
+		for( i = 0; i < 16; i++ )
+		{
+                     _rtw_memcpy( &psta->sta_recvpriv.rxcache.tid_rxseq[ i ], &wRxSeqInitialValue, 2 );
+		}
+
+		RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_info_,("alloc number_%d stainfo  with hwaddr = %x %x %x %x %x %x  \n", 
+		pstapriv->asoc_sta_count , hwaddr[0], hwaddr[1], hwaddr[2],hwaddr[3],hwaddr[4],hwaddr[5]));
+
+		init_addba_retry_timer(pstapriv->padapter, psta);
+#ifdef CONFIG_IEEE80211W
+		init_dot11w_expire_timer(pstapriv->padapter, psta);
+#endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_TDLS
+		rtw_init_tdls_timer(pstapriv->padapter, psta);
+#endif //CONFIG_TDLS
+
+		//for A-MPDU Rx reordering buffer control
+		for(i=0; i < 16 ; i++)
+		{
+			preorder_ctrl = &psta->recvreorder_ctrl[i];
+
+			preorder_ctrl->padapter = pstapriv->padapter;
+		
+			preorder_ctrl->enable = _FALSE;
+		
+			preorder_ctrl->indicate_seq = 0xffff;
+			#ifdef DBG_RX_SEQ
+			DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d\n", __FUNCTION__, __LINE__,
+				preorder_ctrl->indicate_seq);
+			#endif
+			preorder_ctrl->wend_b= 0xffff;       
+			//preorder_ctrl->wsize_b = (NR_RECVBUFF-2);
+			preorder_ctrl->wsize_b = 64;//64;
+			preorder_ctrl->ampdu_size = RX_AMPDU_SIZE_INVALID;
+
+			_rtw_init_queue(&preorder_ctrl->pending_recvframe_queue);
+
+			rtw_init_recv_timer(preorder_ctrl);
+		}
+
+
+		//init for DM
+		psta->rssi_stat.UndecoratedSmoothedPWDB = (-1);
+		psta->rssi_stat.UndecoratedSmoothedCCK = (-1);
+#ifdef CONFIG_ATMEL_RC_PATCH
+		psta->flag_atmel_rc = 0;
+#endif
+		/* init for the sequence number of received management frame */
+		psta->RxMgmtFrameSeqNum = 0xffff;
+		psta->ra_rpt_linked = _FALSE;
+
+		//alloc mac id for non-bc/mc station,
+		rtw_alloc_macid(pstapriv->padapter, psta);
+
+	}
+	
+exit:
+
+	_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL2);
+
+_func_exit_;
+
+	return psta;
+
+
+}
+
+
+// using pstapriv->sta_hash_lock to protect
+u32	rtw_free_stainfo(_adapter *padapter , struct sta_info *psta)
+{	
+	int i;
+	_irqL irqL0;
+	_queue *pfree_sta_queue;
+	struct recv_reorder_ctrl *preorder_ctrl;
+	struct	sta_xmit_priv	*pstaxmitpriv;
+	struct	xmit_priv	*pxmitpriv= &padapter->xmitpriv;
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct hw_xmit *phwxmit;
+	int pending_qcnt[4];
+
+_func_enter_;	
+	
+	if (psta == NULL)
+		goto exit;
+
+	_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
+	rtw_list_delete(&psta->hash_list);
+	RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("\n free number_%d stainfo  with hwaddr = 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x 0x%.2x  \n",pstapriv->asoc_sta_count , psta->hwaddr[0], psta->hwaddr[1], psta->hwaddr[2],psta->hwaddr[3],psta->hwaddr[4],psta->hwaddr[5]));
+	pstapriv->asoc_sta_count --;
+	_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
+
+
+	_enter_critical_bh(&psta->lock, &irqL0);
+	psta->state &= ~_FW_LINKED;
+	_exit_critical_bh(&psta->lock, &irqL0);
+
+	pfree_sta_queue = &pstapriv->free_sta_queue;
+
+
+	pstaxmitpriv = &psta->sta_xmitpriv;
+	
+	//rtw_list_delete(&psta->sleep_list);
+	
+	//rtw_list_delete(&psta->wakeup_list);
+	
+	_enter_critical_bh(&pxmitpriv->lock, &irqL0);
+	
+	rtw_free_xmitframe_queue(pxmitpriv, &psta->sleep_q);
+	psta->sleepq_len = 0;
+	
+	//vo
+	//_enter_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0);
+	rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
+	phwxmit = pxmitpriv->hwxmits;
+	phwxmit->accnt -= pstaxmitpriv->vo_q.qcnt;
+	pending_qcnt[0] = pstaxmitpriv->vo_q.qcnt;
+	pstaxmitpriv->vo_q.qcnt = 0;
+	//_exit_critical_bh(&(pxmitpriv->vo_pending.lock), &irqL0);
+
+	//vi
+	//_enter_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0);
+	rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
+	phwxmit = pxmitpriv->hwxmits+1;
+	phwxmit->accnt -= pstaxmitpriv->vi_q.qcnt;
+	pending_qcnt[1] = pstaxmitpriv->vi_q.qcnt;
+	pstaxmitpriv->vi_q.qcnt = 0;
+	//_exit_critical_bh(&(pxmitpriv->vi_pending.lock), &irqL0);
+
+	//be
+	//_enter_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0);
+	rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	phwxmit = pxmitpriv->hwxmits+2;
+	phwxmit->accnt -= pstaxmitpriv->be_q.qcnt;
+	pending_qcnt[2] = pstaxmitpriv->be_q.qcnt;
+	pstaxmitpriv->be_q.qcnt = 0;
+	//_exit_critical_bh(&(pxmitpriv->be_pending.lock), &irqL0);
+	
+	//bk
+	//_enter_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0);
+	rtw_free_xmitframe_queue( pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
+	phwxmit = pxmitpriv->hwxmits+3;
+	phwxmit->accnt -= pstaxmitpriv->bk_q.qcnt;
+	pending_qcnt[3] = pstaxmitpriv->bk_q.qcnt;
+	pstaxmitpriv->bk_q.qcnt = 0;
+	//_exit_critical_bh(&(pxmitpriv->bk_pending.lock), &irqL0);
+
+	rtw_os_wake_queue_at_free_stainfo(padapter, pending_qcnt);
+
+	_exit_critical_bh(&pxmitpriv->lock, &irqL0);
+	
+	
+	// re-init sta_info; 20061114 // will be init in alloc_stainfo
+	//_rtw_init_sta_xmit_priv(&psta->sta_xmitpriv);
+	//_rtw_init_sta_recv_priv(&psta->sta_recvpriv);
+#ifdef CONFIG_IEEE80211W
+	_cancel_timer_ex(&psta->dot11w_expire_timer);
+#endif /* CONFIG_IEEE80211W */
+	_cancel_timer_ex(&psta->addba_retry_timer);
+
+#ifdef CONFIG_TDLS
+	psta->tdls_sta_state = TDLS_STATE_NONE;
+	rtw_free_tdls_timer(psta);
+#endif //CONFIG_TDLS
+
+	//for A-MPDU Rx reordering buffer control, cancel reordering_ctrl_timer
+	for(i=0; i < 16 ; i++)
+	{
+		_irqL irqL;
+		_list	*phead, *plist;
+		union recv_frame *prframe;
+		_queue *ppending_recvframe_queue;
+		_queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
+	
+		preorder_ctrl = &psta->recvreorder_ctrl[i];
+		
+		_cancel_timer_ex(&preorder_ctrl->reordering_ctrl_timer);		
+
+		
+		ppending_recvframe_queue = &preorder_ctrl->pending_recvframe_queue;
+
+		_enter_critical_bh(&ppending_recvframe_queue->lock, &irqL);
+
+		phead = 	get_list_head(ppending_recvframe_queue);
+		plist = get_next(phead);
+		
+		while(!rtw_is_list_empty(phead))
+		{	
+			prframe = LIST_CONTAINOR(plist, union recv_frame, u);
+			
+			plist = get_next(plist);
+			
+			rtw_list_delete(&(prframe->u.hdr.list));
+
+			rtw_free_recvframe(prframe, pfree_recv_queue);
+		}
+
+		_exit_critical_bh(&ppending_recvframe_queue->lock, &irqL);
+		
+	}
+
+	if (!(psta->state & WIFI_AP_STATE))
+		rtw_hal_set_odm_var(padapter, HAL_ODM_STA_INFO, psta, _FALSE);
+			
+
+	//release mac id for non-bc/mc station,
+	rtw_release_macid(pstapriv->padapter, psta);
+
+#ifdef CONFIG_AP_MODE
+
+/*
+	_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
+	rtw_list_delete(&psta->asoc_list);	
+	_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL0);
+*/
+	_enter_critical_bh(&pstapriv->auth_list_lock, &irqL0);
+	if (!rtw_is_list_empty(&psta->auth_list)) {
+		rtw_list_delete(&psta->auth_list);
+		pstapriv->auth_list_cnt--;
+	}
+	_exit_critical_bh(&pstapriv->auth_list_lock, &irqL0);
+	
+	psta->expire_to = 0;
+#ifdef CONFIG_ATMEL_RC_PATCH
+	psta->flag_atmel_rc = 0;
+#endif
+	psta->sleepq_ac_len = 0;
+	psta->qos_info = 0;
+
+	psta->max_sp_len = 0;
+	psta->uapsd_bk = 0;
+	psta->uapsd_be = 0;
+	psta->uapsd_vi = 0;
+	psta->uapsd_vo = 0;
+
+	psta->has_legacy_ac = 0;
+
+#ifdef CONFIG_NATIVEAP_MLME
+	
+	pstapriv->sta_dz_bitmap &=~BIT(psta->aid);
+	pstapriv->tim_bitmap &=~BIT(psta->aid);	
+
+	//rtw_indicate_sta_disassoc_event(padapter, psta);
+
+	if ((psta->aid >0)&&(pstapriv->sta_aid[psta->aid - 1] == psta))
+	{
+		pstapriv->sta_aid[psta->aid - 1] = NULL;
+		psta->aid = 0;
+	}	
+	
+#endif	// CONFIG_NATIVEAP_MLME	
+
+#ifdef CONFIG_TX_MCAST2UNI
+	psta->under_exist_checking = 0;
+#endif	// CONFIG_TX_MCAST2UNI
+
+#endif	// CONFIG_AP_MODE	
+
+	rtw_st_ctl_deinit(&psta->st_ctl);
+
+	 _rtw_spinlock_free(&psta->lock);
+
+	//_enter_critical_bh(&(pfree_sta_queue->lock), &irqL0);
+	_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);	
+	rtw_list_insert_tail(&psta->list, get_list_head(pfree_sta_queue));
+	_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL0);
+	//_exit_critical_bh(&(pfree_sta_queue->lock), &irqL0);
+
+exit:
+	
+_func_exit_;	
+
+	return _SUCCESS;
+	
+}
+
+// free all stainfo which in sta_hash[all]
+void rtw_free_all_stainfo(_adapter *padapter)
+{
+	_irqL	 irqL;
+	_list	*plist, *phead;
+	s32	index;
+	struct sta_info *psta = NULL;
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info* pbcmc_stainfo =rtw_get_bcmc_stainfo( padapter);
+	u8 free_sta_num = 0;
+	char free_sta_list[NUM_STA];
+	int stainfo_offset;
+	
+_func_enter_;	
+
+	if(pstapriv->asoc_sta_count==1)
+		goto exit;
+
+	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+	for(index=0; index< NUM_STA; index++)
+	{
+		phead = &(pstapriv->sta_hash[index]);
+		plist = get_next(phead);
+		
+		while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+		{
+			psta = LIST_CONTAINOR(plist, struct sta_info ,hash_list);
+
+			plist = get_next(plist);
+
+			if(pbcmc_stainfo!=psta)
+			{
+				rtw_list_delete(&psta->hash_list);
+				//rtw_free_stainfo(padapter , psta);
+				stainfo_offset = rtw_stainfo_offset(pstapriv, psta);
+				if (stainfo_offset_valid(stainfo_offset)) {
+					free_sta_list[free_sta_num++] = stainfo_offset;
+				}
+			}	
+			
+		}
+	}
+	
+	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+
+
+	for (index = 0; index < free_sta_num; index++) 
+	{
+		psta = rtw_get_stainfo_by_offset(pstapriv, free_sta_list[index]);
+		rtw_free_stainfo(padapter , psta);
+	}
+	
+exit:	
+	
+_func_exit_;	
+
+}
+
+/* any station allocated can be searched by hash list */
+struct sta_info *rtw_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
+{
+
+	_irqL	 irqL;
+
+	_list	*plist, *phead;
+
+	struct sta_info *psta = NULL;
+	
+	u32	index;
+
+	u8 *addr;
+
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+
+_func_enter_;
+
+	if(hwaddr==NULL)
+		return NULL;
+		
+	if(IS_MCAST(hwaddr))
+	{
+		addr = bc_addr;
+	}
+	else
+	{
+		addr = hwaddr;
+	}
+
+	index = wifi_mac_hash(addr);
+
+	_enter_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+	
+	phead = &(pstapriv->sta_hash[index]);
+	plist = get_next(phead);
+
+
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+	
+		psta = LIST_CONTAINOR(plist, struct sta_info, hash_list);
+		
+		if ((_rtw_memcmp(psta->hwaddr, addr, ETH_ALEN))== _TRUE) 
+		{ // if found the matched address
+			break;
+		}
+		psta=NULL;
+		plist = get_next(plist);
+	}
+
+	_exit_critical_bh(&pstapriv->sta_hash_lock, &irqL);
+_func_exit_;	
+	return psta;
+	
+}
+
+u32 rtw_init_bcmc_stainfo(_adapter* padapter)
+{
+
+	struct sta_info 	*psta;
+	struct tx_servq	*ptxservq;
+	u32 res=_SUCCESS;
+	NDIS_802_11_MAC_ADDRESS	bcast_addr= {0xff,0xff,0xff,0xff,0xff,0xff};
+	
+	struct	sta_priv *pstapriv = &padapter->stapriv;
+	//_queue	*pstapending = &padapter->xmitpriv.bm_pending; 
+	
+_func_enter_;
+
+	psta = rtw_alloc_stainfo(pstapriv, bcast_addr);
+	
+	if(psta==NULL){
+		res=_FAIL;
+		RT_TRACE(_module_rtl871x_sta_mgt_c_,_drv_err_,("rtw_alloc_stainfo fail"));
+		goto exit;
+	}
+#ifdef CONFIG_BEAMFORMING
+	psta->txbf_gid = 63;
+	psta->txbf_paid = 0;
+#endif
+	ptxservq= &(psta->sta_xmitpriv.be_q);
+
+/*
+	_enter_critical(&pstapending->lock, &irqL0);
+
+	if (rtw_is_list_empty(&ptxservq->tx_pending))
+		rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(pstapending));
+
+	_exit_critical(&pstapending->lock, &irqL0);
+*/
+	
+exit:
+_func_exit_;		
+	return _SUCCESS;
+
+}
+
+
+struct sta_info* rtw_get_bcmc_stainfo(_adapter* padapter)
+{
+	struct sta_info 	*psta;
+	struct sta_priv 	*pstapriv = &padapter->stapriv;
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+_func_enter_;
+	 psta = rtw_get_stainfo(pstapriv, bc_addr);
+_func_exit_;		 
+	return psta;
+
+}
+
+u8 rtw_access_ctrl(_adapter *padapter, u8 *mac_addr)
+{
+	u8 res = _TRUE;
+#ifdef  CONFIG_AP_MODE
+	_irqL irqL;
+	_list	*plist, *phead;
+	struct rtw_wlan_acl_node *paclnode;
+	u8 match = _FALSE;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct wlan_acl_pool *pacl_list = &pstapriv->acl_list;
+	_queue	*pacl_node_q =&pacl_list->acl_node_q;
+	
+	_enter_critical_bh(&(pacl_node_q->lock), &irqL);
+	phead = get_list_head(pacl_node_q);
+	plist = get_next(phead);		
+	while ((rtw_end_of_queue_search(phead, plist)) == _FALSE)
+	{
+		paclnode = LIST_CONTAINOR(plist, struct rtw_wlan_acl_node, list);
+		plist = get_next(plist);
+
+		if(_rtw_memcmp(paclnode->addr, mac_addr, ETH_ALEN))
+		{
+			if(paclnode->valid == _TRUE)
+			{
+				match = _TRUE;
+				break;
+			}
+		}		
+	}	
+	_exit_critical_bh(&(pacl_node_q->lock), &irqL);
+	
+
+	if(pacl_list->mode == 1)//accept unless in deny list
+	{
+		res = (match == _TRUE) ?  _FALSE:_TRUE;
+	}	
+	else if(pacl_list->mode == 2)//deny unless in accept list
+	{
+		res = (match == _TRUE) ?  _TRUE:_FALSE;
+	}
+	else
+	{
+		 res = _TRUE;
+	}		
+	
+#endif
+
+	return res;
+
+}
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_tdls.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_tdls.c
new file mode 100644
index 000000000..72bc94b89
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_tdls.c
@@ -0,0 +1,3162 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_TDLS_C_
+
+#include <drv_types.h>
+
+#ifdef CONFIG_TDLS
+#define ONE_SEC 	1000 /* 1000 ms */
+
+extern unsigned char MCS_rate_2R[16];
+extern unsigned char MCS_rate_1R[16];
+extern void process_wmmps_data(_adapter *padapter, union recv_frame *precv_frame);
+
+void rtw_reset_tdls_info(_adapter* padapter)
+{
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	ptdlsinfo->ap_prohibited = _FALSE;
+	
+	/* For TDLS channel switch, currently we only allow it to work in wifi logo test mode */
+	if (padapter->registrypriv.wifi_spec == 1)
+	{
+		ptdlsinfo->ch_switch_prohibited = _FALSE;
+	}
+	else
+	{
+		ptdlsinfo->ch_switch_prohibited = _TRUE;
+	}
+
+	ptdlsinfo->link_established = _FALSE;
+	ptdlsinfo->sta_cnt = 0;
+	ptdlsinfo->sta_maximum = _FALSE;
+
+#ifdef CONFIG_TDLS_CH_SW
+	ptdlsinfo->chsw_info.ch_sw_state = TDLS_STATE_NONE;
+	ATOMIC_SET(&ptdlsinfo->chsw_info.chsw_on, _FALSE);
+	ptdlsinfo->chsw_info.off_ch_num = 0;
+	ptdlsinfo->chsw_info.ch_offset = 0;
+	ptdlsinfo->chsw_info.cur_time = 0;
+	ptdlsinfo->chsw_info.delay_switch_back = _FALSE;
+	ptdlsinfo->chsw_info.dump_stack = _FALSE;
+#endif
+	
+	ptdlsinfo->ch_sensing = 0;
+	ptdlsinfo->watchdog_count = 0;
+	ptdlsinfo->dev_discovered = _FALSE;
+
+#ifdef CONFIG_WFD
+	ptdlsinfo->wfd_info = &padapter->wfd_info;
+#endif
+}
+
+int rtw_init_tdls_info(_adapter* padapter)
+{
+	int	res = _SUCCESS;
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+
+	rtw_reset_tdls_info(padapter);
+
+	ptdlsinfo->tdls_enable = _TRUE;
+#ifdef CONFIG_TDLS_DRIVER_SETUP
+	ptdlsinfo->driver_setup = _TRUE;
+#else
+	ptdlsinfo->driver_setup = _FALSE;
+#endif /* CONFIG_TDLS_DRIVER_SETUP */
+
+	_rtw_spinlock_init(&ptdlsinfo->cmd_lock);
+	_rtw_spinlock_init(&ptdlsinfo->hdl_lock);
+
+	return res;
+
+}
+
+void rtw_free_tdls_info(struct tdls_info *ptdlsinfo)
+{
+	_rtw_spinlock_free(&ptdlsinfo->cmd_lock);
+	_rtw_spinlock_free(&ptdlsinfo->hdl_lock);
+
+	_rtw_memset(ptdlsinfo, 0, sizeof(struct tdls_info) );
+
+}
+
+int check_ap_tdls_prohibited(u8 *pframe, u8 pkt_len)
+{
+	u8 tdls_prohibited_bit = 0x40; /* bit(38); TDLS_prohibited */
+
+	if (pkt_len < 5) {
+		return _FALSE;
+	}
+
+	pframe += 4;
+	if ((*pframe) & tdls_prohibited_bit)
+		return _TRUE;
+
+	return _FALSE;
+}
+
+int check_ap_tdls_ch_switching_prohibited(u8 *pframe, u8 pkt_len)
+{
+	u8 tdls_ch_swithcing_prohibited_bit = 0x80; /* bit(39); TDLS_channel_switching prohibited */
+
+	if (pkt_len < 5) {
+		return _FALSE;
+	}
+
+	pframe += 4;
+	if ((*pframe) & tdls_ch_swithcing_prohibited_bit)
+		return _TRUE;
+
+	return _FALSE;
+}
+
+int _issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int wait_ack)
+{
+	int ret = _FAIL;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	unsigned char					*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short				*fctrl, *qc;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	pattrib->hdrlen +=2;
+	pattrib->qos_en = _TRUE;
+	pattrib->eosp = 1;
+	pattrib->ack_policy = 0;
+	pattrib->mdata = 0;	
+	pattrib->retry_ctrl = _FALSE;
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	if (power_mode)
+		SetPwrMgt(fctrl);
+
+	qc = (unsigned short *)(pframe + pattrib->hdrlen - 2);
+	
+	SetPriority(qc, 7);	/* Set priority to VO */
+
+	SetEOSP(qc, pattrib->eosp);
+
+	SetAckpolicy(qc, pattrib->ack_policy);
+
+	_rtw_memcpy(pwlanhdr->addr1, da, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(&(pmlmeinfo->network)), ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_QOS_DATA_NULL);
+
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr_qos);
+	pattrib->pktlen = sizeof(struct rtw_ieee80211_hdr_3addr_qos);
+
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	if (wait_ack)
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+	return ret;
+
+}
+
+/*
+ *wait_ms == 0 means that there is no need to wait ack through C2H_CCX_TX_RPT
+ *wait_ms > 0 means you want to wait ack through C2H_CCX_TX_RPT, and the value of wait_ms means the interval between each TX
+ *try_cnt means the maximal TX count to try
+ */
+int issue_nulldata_to_TDLS_peer_STA(_adapter *padapter, unsigned char *da, unsigned int power_mode, int try_cnt, int wait_ms)
+{
+	int ret;
+	int i = 0;
+	u32 start = rtw_get_current_time();
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	#if 0
+	psta = rtw_get_stainfo(&padapter->stapriv, da);
+	if (psta) {
+		if (power_mode)
+			rtw_hal_macid_sleep(padapter, psta->mac_id);
+		else
+			rtw_hal_macid_wakeup(padapter, psta->mac_id);
+	} else {
+		DBG_871X(FUNC_ADPT_FMT ": Can't find sta info for " MAC_FMT ", skip macid %s!!\n",
+			FUNC_ADPT_ARG(padapter), MAC_ARG(da), power_mode?"sleep":"wakeup");
+		rtw_warn_on(1);
+	}
+	#endif
+
+	do {
+		ret = _issue_nulldata_to_TDLS_peer_STA(padapter, da, power_mode, wait_ms>0 ? _TRUE : _FALSE);
+
+		i++;
+
+		if (RTW_CANNOT_RUN(padapter))
+			break;
+
+		if (i < try_cnt && wait_ms > 0 && ret == _FAIL)
+			rtw_msleep_os(wait_ms);
+
+	} while ((i < try_cnt) && (ret==_FAIL || wait_ms==0));
+
+	if (ret != _FAIL) {
+		ret = _SUCCESS;
+		#ifndef DBG_XMIT_ACK
+		goto exit;
+		#endif
+	}
+
+	if (try_cnt && wait_ms) {
+		if (da)
+			DBG_871X(FUNC_ADPT_FMT" to "MAC_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), MAC_ARG(da), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+		else
+			DBG_871X(FUNC_ADPT_FMT", ch:%u%s, %d/%d in %u ms\n",
+				FUNC_ADPT_ARG(padapter), rtw_get_oper_ch(padapter),
+				ret==_SUCCESS?", acked":"", i, try_cnt, rtw_get_passing_time_ms(start));
+	}
+exit:
+	return ret;
+}
+
+void free_tdls_sta(_adapter *padapter, struct sta_info *ptdls_sta)
+{
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	_irqL irqL;
+	
+	/* free peer sta_info */
+	_enter_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+	if (ptdlsinfo->sta_cnt != 0)
+		ptdlsinfo->sta_cnt--;
+	_exit_critical_bh(&(pstapriv->sta_hash_lock), &irqL);
+	/* -2: AP + BC/MC sta, -4: default key */
+	if (ptdlsinfo->sta_cnt < MAX_ALLOWED_TDLS_STA_NUM) {
+		ptdlsinfo->sta_maximum = _FALSE;
+		_rtw_memset( &ptdlsinfo->ss_record, 0x00, sizeof(struct tdls_ss_record) );
+	}
+
+	/* clear cam */
+	rtw_clearstakey_cmd(padapter, ptdls_sta, _TRUE);
+
+	if (ptdlsinfo->sta_cnt == 0) {
+		rtw_tdls_cmd(padapter, NULL, TDLS_RS_RCR);
+		ptdlsinfo->link_established = _FALSE;
+	}
+	else
+		DBG_871X("Remain tdls sta:%02x\n", ptdlsinfo->sta_cnt);
+
+	rtw_free_stainfo(padapter,  ptdls_sta);
+	
+}
+
+
+/* TDLS encryption(if needed) will always be CCMP */
+void rtw_tdls_set_key(_adapter *padapter, struct sta_info *ptdls_sta)
+{
+	ptdls_sta->dot118021XPrivacy=_AES_;
+	rtw_setstakey_cmd(padapter, ptdls_sta, TDLS_KEY, _TRUE);
+}
+
+#ifdef CONFIG_80211N_HT
+void rtw_tdls_process_ht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct ht_priv			*phtpriv = &pmlmepriv->htpriv;
+	u8	max_AMPDU_len, min_MPDU_spacing;
+	u8	cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0;
+	
+	/* Save HT capabilities in the sta object */
+	_rtw_memset(&ptdls_sta->htpriv.ht_cap, 0, sizeof(struct rtw_ieee80211_ht_cap));
+	if (data && Length >= sizeof(struct rtw_ieee80211_ht_cap)) {
+		ptdls_sta->flags |= WLAN_STA_HT;
+		ptdls_sta->flags |= WLAN_STA_WME;
+
+		_rtw_memcpy(&ptdls_sta->htpriv.ht_cap, data, sizeof(struct rtw_ieee80211_ht_cap));			
+	} else
+		ptdls_sta->flags &= ~WLAN_STA_HT;
+
+	if (ptdls_sta->flags & WLAN_STA_HT) {
+		if (padapter->registrypriv.ht_enable == _TRUE) {
+			ptdls_sta->htpriv.ht_option = _TRUE;
+			ptdls_sta->qos_option = _TRUE;
+		} else {
+			ptdls_sta->htpriv.ht_option = _FALSE;
+			ptdls_sta->qos_option = _FALSE;
+		}
+	}
+
+	/* HT related cap */
+	if (ptdls_sta->htpriv.ht_option) {
+		/* Check if sta supports rx ampdu */
+		if (padapter->registrypriv.ampdu_enable == 1)
+			ptdls_sta->htpriv.ampdu_enable = _TRUE;
+
+		/* AMPDU Parameters field */
+		/* Get MIN of MAX AMPDU Length Exp */
+		if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (data[2] & 0x3))
+			max_AMPDU_len = (data[2] & 0x3);
+		else
+			max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
+		/* Get MAX of MIN MPDU Start Spacing */
+		if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (data[2] & 0x1c))
+			min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
+		else
+			min_MPDU_spacing = (data[2] & 0x1c);
+		ptdls_sta->htpriv.rx_ampdu_min_spacing = max_AMPDU_len | min_MPDU_spacing;
+
+		/* Check if sta support s Short GI 20M */
+		if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_20))
+			ptdls_sta->htpriv.sgi_20m = _TRUE;
+
+		/* Check if sta support s Short GI 40M */
+		if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SGI_40))
+			ptdls_sta->htpriv.sgi_40m = _TRUE;
+
+		/* Bwmode would still followed AP's setting */
+		if (ptdls_sta->htpriv.ht_cap.cap_info & cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH)) {
+			if (padapter->mlmeextpriv.cur_bwmode >= CHANNEL_WIDTH_40)
+				ptdls_sta->bw_mode = CHANNEL_WIDTH_40;
+			ptdls_sta->htpriv.ch_offset = padapter->mlmeextpriv.cur_ch_offset;
+		}
+
+		/* Config LDPC Coding Capability */
+		if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX) && GET_HT_CAP_ELE_LDPC_CAP(data)) {
+			SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
+			DBG_871X("Enable HT Tx LDPC!\n");
+		}
+		ptdls_sta->htpriv.ldpc_cap = cur_ldpc_cap;
+
+		/* Config STBC setting */
+		if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAP_ELE_RX_STBC(data)) {
+			SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX));
+			DBG_871X("Enable HT Tx STBC!\n");
+		}
+		ptdls_sta->htpriv.stbc_cap = cur_stbc_cap;
+
+#ifdef CONFIG_BEAMFORMING
+		/* Config Tx beamforming setting */
+		if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && 
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(data)) {
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
+		}
+
+		if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(data)) {
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
+		}
+		ptdls_sta->htpriv.beamform_cap = cur_beamform_cap;
+		if (cur_beamform_cap)
+			DBG_871X("Client HT Beamforming Cap = 0x%02X\n", cur_beamform_cap);
+#endif /* CONFIG_BEAMFORMING */
+	}
+
+}
+
+u8 *rtw_tdls_set_ht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	rtw_ht_use_default_setting(padapter);
+
+	rtw_restructure_ht_ie(padapter, NULL, pframe, 0, &(pattrib->pktlen), padapter->mlmeextpriv.cur_channel);
+
+	return pframe + pattrib->pktlen;
+}
+#endif
+
+#ifdef CONFIG_80211AC_VHT
+void rtw_tdls_process_vht_cap(_adapter *padapter, struct sta_info *ptdls_sta, u8 *data, u8 Length)
+{
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv			*pvhtpriv = &pmlmepriv->vhtpriv;
+	u8	cur_ldpc_cap = 0, cur_stbc_cap = 0, cur_beamform_cap = 0, rf_type = RF_1T1R;
+	u8	*pcap_mcs;
+	u8	vht_mcs[2];
+	
+	_rtw_memset(&ptdls_sta->vhtpriv, 0, sizeof(struct vht_priv));
+	if (data && Length == 12) {
+		ptdls_sta->flags |= WLAN_STA_VHT;
+
+		_rtw_memcpy(ptdls_sta->vhtpriv.vht_cap, data, 12);
+
+#if 0
+		if (elems.vht_op_mode_notify && elems.vht_op_mode_notify_len == 1) {
+			_rtw_memcpy(&pstat->vhtpriv.vht_op_mode_notify, elems.vht_op_mode_notify, 1);
+		} else /* for Frame without Operating Mode notify ie; default: 80M */ {
+			pstat->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;
+		}
+#else
+		ptdls_sta->vhtpriv.vht_op_mode_notify = CHANNEL_WIDTH_80;
+#endif
+	} else
+		ptdls_sta->flags &= ~WLAN_STA_VHT;
+
+	if (ptdls_sta->flags & WLAN_STA_VHT) {
+		if (REGSTY_IS_11AC_ENABLE(&padapter->registrypriv)
+			&& hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
+			&& (!pmlmepriv->country_ent || COUNTRY_CHPLAN_EN_11AC(pmlmepriv->country_ent)))
+			ptdls_sta->vhtpriv.vht_option = _TRUE;
+		else 
+			ptdls_sta->vhtpriv.vht_option = _FALSE;
+	}
+
+	/* B4 Rx LDPC */
+	if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) && 
+		GET_VHT_CAPABILITY_ELE_RX_LDPC(data)) {
+		SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
+		DBG_871X("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
+	}
+	ptdls_sta->vhtpriv.ldpc_cap = cur_ldpc_cap;
+
+	/* B5 Short GI for 80 MHz */
+	ptdls_sta->vhtpriv.sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
+
+	/* B8 B9 B10 Rx STBC */
+	if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) && 
+		GET_VHT_CAPABILITY_ELE_RX_STBC(data)) {
+		SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));	
+		DBG_871X("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
+	}
+	ptdls_sta->vhtpriv.stbc_cap = cur_stbc_cap;
+
+	/* B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee */
+	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) && 
+		GET_VHT_CAPABILITY_ELE_SU_BFEE(data)) {
+		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
+	}
+
+	/* B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer */
+	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
+		GET_VHT_CAPABILITY_ELE_SU_BFER(data)) {
+		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+	}
+	ptdls_sta->vhtpriv.beamform_cap = cur_beamform_cap;
+	if (cur_beamform_cap)
+		DBG_871X("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
+
+	/* B23 B24 B25 Maximum A-MPDU Length Exponent */
+	ptdls_sta->vhtpriv.ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(data);
+
+	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(data);
+	_rtw_memcpy(vht_mcs, pcap_mcs, 2);
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
+		vht_mcs[0] |= 0xfc;
+	else if (rf_type == RF_2T2R)
+		vht_mcs[0] |= 0xf0;
+	else if (rf_type == RF_3T3R)
+		vht_mcs[0] |= 0xc0;
+
+	_rtw_memcpy(ptdls_sta->vhtpriv.vht_mcs_map, vht_mcs, 2);
+
+	ptdls_sta->vhtpriv.vht_highest_rate = rtw_get_vht_highest_rate(ptdls_sta->vhtpriv.vht_mcs_map);
+}
+
+u8 *rtw_tdls_set_aid(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	return rtw_set_ie(pframe, EID_AID, 2, (u8 *)&(padapter->mlmepriv.cur_network.aid), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_vht_cap(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	u32 ie_len = 0;
+	
+	rtw_vht_use_default_setting(padapter);
+
+	ie_len = rtw_build_vht_cap_ie(padapter, pframe);
+	pattrib->pktlen += ie_len;
+	
+	return pframe + ie_len;
+}
+
+u8 *rtw_tdls_set_vht_operation(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 channel)
+{
+	u32 ie_len = 0;
+
+	ie_len = rtw_build_vht_operation_ie(padapter, pframe, channel);
+	pattrib->pktlen += ie_len;
+	
+	return pframe + ie_len;
+}
+
+u8 *rtw_tdls_set_vht_op_mode_notify(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib, u8 bw)
+{
+	u32 ie_len = 0;
+	
+	ie_len = rtw_build_vht_op_mode_notify_ie(padapter, pframe, bw);
+	pattrib->pktlen += ie_len;
+
+	return pframe + ie_len;
+}
+#endif
+
+
+u8 *rtw_tdls_set_sup_ch(struct mlme_ext_priv *pmlmeext, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	u8 sup_ch[30 * 2] = {0x00}, ch_set_idx = 0, sup_ch_idx = 2;	
+
+	do {
+		if (pmlmeext->channel_set[ch_set_idx].ChannelNum <= 14) {
+			sup_ch[0] = 1;	/* First channel number */
+			sup_ch[1] = pmlmeext->channel_set[ch_set_idx].ChannelNum;	/* Number of channel */
+		} else {
+			sup_ch[sup_ch_idx++] = pmlmeext->channel_set[ch_set_idx].ChannelNum;
+			sup_ch[sup_ch_idx++] = 1;
+		}
+		ch_set_idx++;
+	} while (pmlmeext->channel_set[ch_set_idx].ChannelNum != 0 && ch_set_idx < MAX_CHANNEL_NUM);
+
+	return rtw_set_ie(pframe, _SUPPORTED_CH_IE_, sup_ch_idx, sup_ch, &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_rsnie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib,  int init, struct sta_info *ptdls_sta)
+{
+	u8 *p = NULL;
+	int len = 0;
+
+	if (ptxmgmt->len > 0)
+		p = rtw_get_ie(ptxmgmt->buf, _RSN_IE_2_, &len, ptxmgmt->len);
+
+	if (p != NULL)
+		return rtw_set_ie(pframe, _RSN_IE_2_, len, p+2, &(pattrib->pktlen));
+	else
+		if (init == _TRUE)
+			return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(TDLS_RSNIE), TDLS_RSNIE, &(pattrib->pktlen));
+		else
+			return rtw_set_ie(pframe, _RSN_IE_2_, sizeof(ptdls_sta->TDLS_RSNIE), ptdls_sta->TDLS_RSNIE, &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_ext_cap(u8 *pframe, struct pkt_attrib *pattrib)
+{
+	return rtw_set_ie(pframe, _EXT_CAP_IE_ , sizeof(TDLS_EXT_CAPIE), TDLS_EXT_CAPIE, &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_qos_cap(u8 *pframe, struct pkt_attrib *pattrib)
+{
+	return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, sizeof(TDLS_WMMIE), TDLS_WMMIE,  &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_ftie(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, u8 *ANonce, u8 *SNonce)
+{
+	struct wpa_tdls_ftie FTIE = {0};
+	u8 *p = NULL;
+	int len = 0;
+
+	if (ptxmgmt->len > 0)
+		p = rtw_get_ie(ptxmgmt->buf, _FTIE_, &len, ptxmgmt->len);
+
+	if (p != NULL)
+		return rtw_set_ie(pframe, _FTIE_, len, p+2, &(pattrib->pktlen));
+	else {
+		if (ANonce != NULL)
+			_rtw_memcpy(FTIE.Anonce, ANonce, WPA_NONCE_LEN);
+		if (SNonce != NULL)
+			_rtw_memcpy(FTIE.Snonce, SNonce, WPA_NONCE_LEN);
+		return rtw_set_ie(pframe, _FTIE_ , 82, (u8 *)FTIE.mic_ctrl, &(pattrib->pktlen));
+	}
+}
+
+u8 *rtw_tdls_set_timeout_interval(struct tdls_txmgmt *ptxmgmt, u8 *pframe, struct pkt_attrib *pattrib, int init, struct sta_info *ptdls_sta)
+{
+	u8 timeout_itvl[5];	/* set timeout interval to maximum value */
+	u32 timeout_interval= TPK_RESEND_COUNT;
+	u8 *p = NULL;
+	int len = 0;
+
+	if (ptxmgmt->len > 0)
+		p = rtw_get_ie(ptxmgmt->buf, _TIMEOUT_ITVL_IE_, &len, ptxmgmt->len);
+
+	if (p != NULL)
+		return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, len, p+2, &(pattrib->pktlen));
+	else {
+		/* Timeout interval */
+		timeout_itvl[0]=0x02;
+		if (init == _TRUE)
+			_rtw_memcpy(timeout_itvl+1, &timeout_interval, 4);
+		else
+			_rtw_memcpy(timeout_itvl+1, (u8 *)(&ptdls_sta->TDLS_PeerKey_Lifetime), 4);
+
+		return rtw_set_ie(pframe, _TIMEOUT_ITVL_IE_, 5, timeout_itvl, &(pattrib->pktlen));
+	}
+}
+
+u8 *rtw_tdls_set_bss_coexist(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	u8 iedata=0;
+
+	if (padapter->mlmepriv.num_FortyMHzIntolerant > 0)
+		iedata |= BIT(2);	/* 20 MHz BSS Width Request */
+
+	/* Information Bit should be set by TDLS test plan 5.9 */
+	iedata |= BIT(0);
+	return rtw_set_ie(pframe, EID_BSSCoexistence, 1, &iedata, &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_payload_type(u8 *pframe, struct pkt_attrib *pattrib)
+{
+	u8 payload_type = 0x02;
+	return rtw_set_fixed_ie(pframe, 1, &(payload_type), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_category(u8 *pframe, struct pkt_attrib *pattrib, u8 category)
+{
+	return rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_action(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
+{
+	return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->action_code), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_status_code(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
+{
+	return rtw_set_fixed_ie(pframe, 2, (u8 *)&(ptxmgmt->status_code), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_dialog(u8 *pframe, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
+{
+	u8 dialogtoken = 1;
+	if (ptxmgmt->dialog_token)
+		return rtw_set_fixed_ie(pframe, 1, &(ptxmgmt->dialog_token), &(pattrib->pktlen));
+	else
+		return rtw_set_fixed_ie(pframe, 1, &(dialogtoken), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_reg_class(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)
+{
+	u8 reg_class = 1;
+	return rtw_set_fixed_ie(pframe, 1, &(reg_class), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_capability(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
+	u8 cap_from_ie[2] = {0};
+
+	_rtw_memcpy(cap_from_ie, rtw_get_capability_from_ie(pmlmeinfo->network.IEs), 2);
+
+	return rtw_set_fixed_ie(pframe, 2, cap_from_ie, &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_supported_rate(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	u8 bssrate[NDIS_802_11_LENGTH_RATES_EX];
+ 	int bssrate_len = 0;
+	u8 more_supportedrates = 0;
+
+	rtw_set_supported_rate(bssrate, (padapter->registrypriv.wireless_mode == WIRELESS_MODE_MAX) ? padapter->mlmeextpriv.cur_wireless_mode : padapter->registrypriv.wireless_mode); 
+	bssrate_len = rtw_get_rateset_len(bssrate);
+
+	if (bssrate_len > 8) {
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , 8, bssrate, &(pattrib->pktlen));
+		more_supportedrates = 1;
+	} else {
+		pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_ , bssrate_len , bssrate, &(pattrib->pktlen));
+	}
+
+	/* extended supported rates */
+	if (more_supportedrates == 1) {
+		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_ , (bssrate_len - 8), (bssrate + 8), &(pattrib->pktlen));
+	}
+
+	return pframe;
+}
+
+u8 *rtw_tdls_set_sup_reg_class(u8 *pframe, struct pkt_attrib *pattrib)
+{
+	return rtw_set_ie(pframe, _SRC_IE_ , sizeof(TDLS_SRC), TDLS_SRC, &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_linkid(u8 *pframe, struct pkt_attrib *pattrib, u8 init)
+{
+	u8 link_id_addr[18] = {0};
+	if (init == _TRUE) {
+		_rtw_memcpy(link_id_addr, pattrib->ra, 6);
+		_rtw_memcpy((link_id_addr+6), pattrib->src, 6);
+		_rtw_memcpy((link_id_addr+12), pattrib->dst, 6);
+	} else {
+		_rtw_memcpy(link_id_addr, pattrib->ra, 6);
+		_rtw_memcpy((link_id_addr+6), pattrib->dst, 6);
+		_rtw_memcpy((link_id_addr+12), pattrib->src, 6);
+	}
+	return rtw_set_ie(pframe, _LINK_ID_IE_, 18, link_id_addr, &(pattrib->pktlen));
+}
+
+#ifdef CONFIG_TDLS_CH_SW
+u8 *rtw_tdls_set_target_ch(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	u8 target_ch = 1;
+	if (padapter->tdlsinfo.chsw_info.off_ch_num)
+		return rtw_set_fixed_ie(pframe, 1, &(padapter->tdlsinfo.chsw_info.off_ch_num), &(pattrib->pktlen));
+	else
+		return rtw_set_fixed_ie(pframe, 1, &(target_ch), &(pattrib->pktlen));
+}
+
+u8 *rtw_tdls_set_ch_sw(u8 *pframe, struct pkt_attrib *pattrib, struct sta_info *ptdls_sta)
+{
+	u8 ch_switch_timing[4] = {0};
+	u16 switch_time = (ptdls_sta->ch_switch_time >= CH_SWITCH_TIME * 1000) ? 
+		ptdls_sta->ch_switch_time : CH_SWITCH_TIME;
+	u16 switch_timeout = (ptdls_sta->ch_switch_timeout >= CH_SWITCH_TIMEOUT * 1000) ? 
+		ptdls_sta->ch_switch_timeout : CH_SWITCH_TIMEOUT;
+
+	_rtw_memcpy(ch_switch_timing, &switch_time, 2);
+	_rtw_memcpy(ch_switch_timing + 2, &switch_timeout, 2);
+
+	return rtw_set_ie(pframe, _CH_SWITCH_TIMING_,  4, ch_switch_timing, &(pattrib->pktlen));
+}
+#endif
+
+u8 *rtw_tdls_set_wmm_params(_adapter *padapter, u8 *pframe, struct pkt_attrib *pattrib)
+{
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);	
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 wmm_param_ele[24] = {0};
+
+	if (&pmlmeinfo->WMM_param) {
+		_rtw_memcpy(wmm_param_ele, WMM_PARA_OUI, 6);
+		if (_rtw_memcmp(&pmlmeinfo->WMM_param, &wmm_param_ele[6], 18) == _TRUE)
+			/* Use default WMM Param */
+			_rtw_memcpy(wmm_param_ele + 6, (u8 *)&TDLS_WMM_PARAM_IE, sizeof(TDLS_WMM_PARAM_IE));
+		else	
+			_rtw_memcpy(wmm_param_ele + 6, (u8 *)&pmlmeinfo->WMM_param, sizeof(pmlmeinfo->WMM_param));
+		return rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_,  24, wmm_param_ele, &(pattrib->pktlen));		
+	}
+	else
+		return pframe;
+}
+
+#ifdef CONFIG_WFD
+void rtw_tdls_process_wfd_ie(struct tdls_info *ptdlsinfo, u8 *ptr, u8 length)
+{
+	u8 *wfd_ie;
+	u32	wfd_ielen = 0;
+
+	if (!hal_chk_wl_func(tdls_info_to_adapter(ptdlsinfo), WL_FUNC_MIRACAST))
+		return;
+
+	/* Try to get the TCP port information when receiving the negotiation response. */
+
+	wfd_ie = rtw_get_wfd_ie(ptr, length, NULL, &wfd_ielen);
+	while (wfd_ie) {
+		u8 *attr_content;
+		u32	attr_contentlen = 0;
+		int	i;
+
+		DBG_871X( "[%s] WFD IE Found!!\n", __FUNCTION__ );
+		attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &attr_contentlen);
+		if (attr_content && attr_contentlen) {
+			ptdlsinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16( attr_content + 2 );
+			DBG_871X( "[%s] Peer PORT NUM = %d\n", __FUNCTION__, ptdlsinfo->wfd_info->peer_rtsp_ctrlport );
+		}
+
+		attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_LOCAL_IP_ADDR, NULL, &attr_contentlen);
+		if (attr_content && attr_contentlen) {
+			_rtw_memcpy(ptdlsinfo->wfd_info->peer_ip_address, ( attr_content + 1 ), 4);
+			DBG_871X("[%s] Peer IP = %02u.%02u.%02u.%02u\n", __FUNCTION__, 
+				ptdlsinfo->wfd_info->peer_ip_address[0], ptdlsinfo->wfd_info->peer_ip_address[1],
+				ptdlsinfo->wfd_info->peer_ip_address[2], ptdlsinfo->wfd_info->peer_ip_address[3]);
+		}
+
+		wfd_ie = rtw_get_wfd_ie(wfd_ie + wfd_ielen, (ptr + length) - (wfd_ie + wfd_ielen), NULL, &wfd_ielen);
+	}
+}
+
+int issue_tunneled_probe_req(_adapter *padapter)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	u8 baddr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 
+	struct tdls_txmgmt txmgmt;
+	int ret = _FAIL;
+
+	DBG_871X("[%s]\n", __FUNCTION__);
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	txmgmt.action_code = TUNNELED_PROBE_REQ;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, baddr, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+	dump_mgntframe(padapter, pmgntframe);
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+}
+
+int issue_tunneled_probe_rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct tdls_txmgmt txmgmt;
+	int ret = _FAIL;
+
+	DBG_871X("[%s]\n", __FUNCTION__);
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	txmgmt.action_code = TUNNELED_PROBE_RSP;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, precv_frame->u.hdr.attrib.src, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+	dump_mgntframe(padapter, pmgntframe);
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+}
+#endif /* CONFIG_WFD */
+
+int issue_tdls_setup_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)
+{
+	struct tdls_info	*ptdlsinfo = &padapter->tdlsinfo;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *ptdls_sta= NULL;
+	_irqL irqL;
+	int ret = _FAIL;
+	/* Retry timer should be set at least 301 sec, using TPK_count counting 301 times. */
+	u32 timeout_interval= TPK_RESEND_COUNT;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	ptxmgmt->action_code = TDLS_SETUP_REQUEST;
+	if (ptdlsinfo->ap_prohibited == _TRUE)
+		goto exit;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+
+	/* init peer sta_info */
+	ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);
+	if (ptdls_sta == NULL) {
+		ptdls_sta = rtw_alloc_stainfo(pstapriv, ptxmgmt->peer);
+		if (ptdls_sta == NULL) {
+			DBG_871X("[%s] rtw_alloc_stainfo fail\n", __FUNCTION__);	
+			rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+			rtw_free_xmitframe(pxmitpriv, pmgntframe);
+			goto exit;
+		}
+	}
+	
+	if(!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
+		ptdlsinfo->sta_cnt++;
+
+	if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)
+		ptdlsinfo->sta_maximum  = _TRUE;
+
+	ptdls_sta->tdls_sta_state |= TDLS_RESPONDER_STATE;
+
+	if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
+		ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
+		_set_timer(&ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
+	}
+
+	pattrib->qsel = pattrib->priority;
+
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+
+	if (wait_ack) {
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+exit:
+
+	return ret;
+}
+
+int _issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info	*ptdls_sta=NULL;
+	_irqL irqL;
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	ptxmgmt->action_code = TDLS_TEARDOWN;
+	ptdls_sta = rtw_get_stainfo(pstapriv, ptxmgmt->peer);
+	if (ptdls_sta == NULL) {
+		DBG_871X("Np tdls_sta for tearing down\n");
+		goto exit;
+	}
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	rtw_set_scan_deny(padapter, 550);
+
+	rtw_scan_abort(padapter);
+#ifdef CONFIG_CONCURRENT_MODE		
+	if (rtw_buddy_adapter_up(padapter))	
+		rtw_scan_abort(padapter->pbuddy_adapter);
+#endif /* CONFIG_CONCURRENT_MODE */
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+
+	if (rtw_tdls_is_driver_setup(padapter) == _TRUE) 
+		if(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)
+			if (pattrib->encrypt) 
+				_cancel_timer_ex(&ptdls_sta->TPK_timer);
+
+	if (wait_ack) {
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+
+	if (ret == _SUCCESS && rtw_tdls_is_driver_setup(padapter))
+		rtw_tdls_cmd(padapter, ptxmgmt->peer, TDLS_TEAR_STA);
+
+exit:
+
+	return ret;
+}
+
+int issue_tdls_teardown(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 wait_ack)
+{
+	int ret = _FAIL;
+	
+	ret = _issue_tdls_teardown(padapter, ptxmgmt, wait_ack);
+	if ((ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_) && (ret == _FAIL)) {
+		/* Change status code and send teardown again via AP */
+		ptxmgmt->status_code = _RSON_TDLS_TEAR_TOOFAR_;
+		ret = _issue_tdls_teardown(padapter, ptxmgmt, wait_ack);
+	}
+
+	return ret;
+}
+
+int issue_tdls_dis_req(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	int ret = _FAIL;
+	
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+	
+	ptxmgmt->action_code = TDLS_DISCOVERY_REQUEST;
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+	dump_mgntframe(padapter, pmgntframe);
+	DBG_871X("issue tdls dis req\n");
+
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+}
+
+int issue_tdls_setup_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	ptxmgmt->action_code = TDLS_SETUP_RESPONSE;		
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(&(padapter->mlmepriv)), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+
+}
+
+int issue_tdls_setup_cfm(_adapter *padapter, struct tdls_txmgmt *ptxmgmt)
+{
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	int ret = _FAIL;
+	
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+	
+	ptxmgmt->action_code = TDLS_SETUP_CONFIRM;
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(&padapter->mlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;		
+	}
+
+	dump_mgntframe(padapter, pmgntframe);
+
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+
+}
+
+/* TDLS Discovery Response frame is a management action frame */
+int issue_tdls_dis_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, u8 privacy)
+{
+	struct xmit_frame		*pmgntframe;
+	struct pkt_attrib		*pattrib;
+	unsigned char			*pframe;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	unsigned short		*fctrl;
+	struct xmit_priv		*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+	update_mgntframe_attrib(padapter, pattrib);
+
+	_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+	pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+
+	/* unicast probe request frame */
+	_rtw_memcpy(pwlanhdr->addr1, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->dst, pwlanhdr->addr1, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->src, pwlanhdr->addr2, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_bssid(&padapter->mlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, pwlanhdr->addr3, ETH_ALEN);
+
+	SetSeqNum(pwlanhdr, pmlmeext->mgnt_seq);
+	pmlmeext->mgnt_seq++;
+	SetFrameSubType(pframe, WIFI_ACTION);
+
+	pframe += sizeof (struct rtw_ieee80211_hdr_3addr);
+	pattrib->pktlen = sizeof (struct rtw_ieee80211_hdr_3addr);
+
+	rtw_build_tdls_dis_rsp_ies(padapter, pmgntframe, pframe, ptxmgmt, privacy);
+
+	pattrib->nr_frags = 1;
+	pattrib->last_txcmdsz = pattrib->pktlen;
+
+	dump_mgntframe(padapter, pmgntframe);
+	ret = _SUCCESS;
+
+exit:
+	return ret;
+}
+
+int issue_tdls_peer_traffic_rsp(_adapter *padapter, struct sta_info *ptdls_sta, struct tdls_txmgmt *ptxmgmt)
+{
+	struct xmit_frame	*pmgntframe;
+	struct pkt_attrib	*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	ptxmgmt->action_code = TDLS_PEER_TRAFFIC_RESPONSE;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;	
+	}
+
+	dump_mgntframe(padapter, pmgntframe);
+	ret = _SUCCESS;
+
+exit:
+
+	return ret;
+}
+
+int issue_tdls_peer_traffic_indication(_adapter *padapter, struct sta_info *ptdls_sta)
+{
+	struct xmit_frame			*pmgntframe;
+	struct pkt_attrib			*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct tdls_txmgmt txmgmt;
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	txmgmt.action_code = TDLS_PEER_TRAFFIC_INDICATION;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	/* PTI frame's priority should be AC_VO */
+	pattrib->priority = 7; 
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) != _SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv, pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+
+	dump_mgntframe(padapter, pmgntframe);
+	ret = _SUCCESS;
+	
+exit:
+
+	return ret;
+}
+
+int issue_tdls_ch_switch_req(_adapter *padapter, struct sta_info *ptdls_sta)
+{
+	struct xmit_frame	*pmgntframe;
+	struct pkt_attrib	*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+	struct tdls_txmgmt txmgmt;
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
+	{	DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
+		goto exit;
+	}
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	txmgmt.action_code = TDLS_CHANNEL_SWITCH_REQUEST;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptdls_sta->hwaddr, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, &txmgmt) !=_SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+
+	dump_mgntframe(padapter, pmgntframe);
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+}
+
+int issue_tdls_ch_switch_rsp(_adapter *padapter, struct tdls_txmgmt *ptxmgmt, int wait_ack)
+{
+	struct xmit_frame	*pmgntframe;
+	struct pkt_attrib	*pattrib;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+	int ret = _FAIL;
+
+	DBG_871X("[TDLS] %s\n", __FUNCTION__);
+
+	if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
+	{	DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
+		goto exit;
+	}
+
+	ptxmgmt->action_code = TDLS_CHANNEL_SWITCH_RESPONSE;
+
+	if ((pmgntframe = alloc_mgtxmitframe(pxmitpriv)) == NULL)
+		goto exit;
+
+	pattrib = &pmgntframe->attrib;
+
+	pmgntframe->frame_tag = DATA_FRAMETAG;
+	pattrib->ether_type = 0x890d;
+
+	_rtw_memcpy(pattrib->dst, ptxmgmt->peer, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+	_rtw_memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
+
+	update_tdls_attrib(padapter, pattrib);
+	pattrib->qsel = pattrib->priority;
+/*
+	_enter_critical_bh(&pxmitpriv->lock, &irqL);
+	if(xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pmgntframe)==_TRUE){
+		_exit_critical_bh(&pxmitpriv->lock, &irqL);
+		return _FALSE;
+	}
+*/
+	if (rtw_xmit_tdls_coalesce(padapter, pmgntframe, ptxmgmt) !=_SUCCESS) {
+		rtw_free_xmitbuf(pxmitpriv,pmgntframe->pxmitbuf);
+		rtw_free_xmitframe(pxmitpriv, pmgntframe);
+		goto exit;
+	}
+
+	if (wait_ack) {
+		ret = dump_mgntframe_and_wait_ack(padapter, pmgntframe);
+	} else {
+		dump_mgntframe(padapter, pmgntframe);
+		ret = _SUCCESS;
+	}
+	ret = _SUCCESS;
+exit:
+
+	return ret;
+}
+
+int On_TDLS_Dis_Rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct sta_info *ptdls_sta = NULL, *psta = rtw_get_stainfo(&(padapter->stapriv), get_bssid(&(padapter->mlmepriv)));
+	struct recv_priv *precvpriv = &(padapter->recvpriv);
+	u8 *ptr = precv_frame->u.hdr.rx_data, *psa;
+	struct rx_pkt_attrib *pattrib = &(precv_frame->u.hdr.attrib);
+	struct tdls_info *ptdlsinfo = &(padapter->tdlsinfo);
+	u8 empty_addr[ETH_ALEN] = { 0x00 };
+	int UndecoratedSmoothedPWDB;
+	struct tdls_txmgmt txmgmt;	
+	int ret = _SUCCESS;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	/* WFDTDLS: for sigma test, not to setup direct link automatically */
+	ptdlsinfo->dev_discovered = _TRUE;
+
+	psa = get_sa(ptr);
+	ptdls_sta = rtw_get_stainfo(&(padapter->stapriv), psa);
+	if (ptdls_sta != NULL)
+		ptdls_sta->sta_stats.rx_tdls_disc_rsp_pkts++;
+
+#ifdef CONFIG_TDLS_AUTOSETUP
+	if (ptdls_sta != NULL) {
+		/* Record the tdls sta with lowest signal strength */
+		if (ptdlsinfo->sta_maximum == _TRUE && ptdls_sta->alive_count >= 1 ) {
+			if (_rtw_memcmp(ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {
+				_rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
+				ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.RxPWDBAll;
+			} else {
+				if (ptdlsinfo->ss_record.RxPWDBAll < pattrib->phy_info.RxPWDBAll) {
+					_rtw_memcpy(ptdlsinfo->ss_record.macaddr, psa, ETH_ALEN);
+					ptdlsinfo->ss_record.RxPWDBAll = pattrib->phy_info.RxPWDBAll;
+				}
+			}
+		}
+	} else {
+		if (ptdlsinfo->sta_maximum == _TRUE) {
+			if (_rtw_memcmp( ptdlsinfo->ss_record.macaddr, empty_addr, ETH_ALEN)) {
+				/* All traffics are busy, do not set up another direct link. */
+				ret = _FAIL;
+				goto exit;
+			} else {
+				if (pattrib->phy_info.RxPWDBAll > ptdlsinfo->ss_record.RxPWDBAll) {
+					_rtw_memcpy(txmgmt.peer, ptdlsinfo->ss_record.macaddr, ETH_ALEN);
+					/* issue_tdls_teardown(padapter, ptdlsinfo->ss_record.macaddr, _FALSE); */
+				} else {
+					ret = _FAIL;
+					goto exit;
+				}
+			}
+		}
+
+		rtw_hal_get_def_var(padapter, HAL_DEF_UNDERCORATEDSMOOTHEDPWDB, &UndecoratedSmoothedPWDB);
+
+		if (pattrib->phy_info.RxPWDBAll + TDLS_SIGNAL_THRESH >= UndecoratedSmoothedPWDB) {
+			DBG_871X("pattrib->RxPWDBAll=%d, pdmpriv->UndecoratedSmoothedPWDB=%d\n", pattrib->phy_info.RxPWDBAll, UndecoratedSmoothedPWDB);
+			_rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);
+			issue_tdls_setup_req(padapter, &txmgmt, _FALSE);
+		}
+	}
+#endif /* CONFIG_TDLS_AUTOSETUP */
+
+exit:
+	return ret;
+
+}
+
+sint On_TDLS_Setup_Req(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	u8 *psa, *pmyid;
+	struct sta_info *ptdls_sta= NULL;
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	_irqL irqL;
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	u8 *prsnie, *ppairwise_cipher;
+	u8 i, k;
+	u8 ccmp_included=0, rsnie_included=0;
+	u16 j, pairwise_count;
+	u8 SNonce[32];
+	u32 timeout_interval = TPK_RESEND_COUNT;
+	sint parsing_length;	/* Frame body length, without icv_len */
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 FIXED_IE = 5;
+	unsigned char		supportRate[16];
+	int				supportRateNum = 0;
+	struct tdls_txmgmt txmgmt;
+
+	if (ptdlsinfo->ap_prohibited == _TRUE)
+		goto exit;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	psa = get_sa(ptr);
+	ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+	pmyid = adapter_mac_addr(padapter);
+	ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+			-prx_pkt_attrib->hdrlen
+			-prx_pkt_attrib->iv_len
+			-prx_pkt_attrib->icv_len
+			-LLC_HEADER_SIZE
+			-ETH_TYPE_LEN
+			-PAYLOAD_TYPE_LEN
+			-FIXED_IE;
+
+	if (ptdls_sta == NULL) {
+		ptdls_sta = rtw_alloc_stainfo(pstapriv, psa);
+	} else {
+		if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
+			/* If the direct link is already set up */
+			/* Process as re-setup after tear down */
+			DBG_871X("re-setup a direct link\n");
+		}
+		/* Already receiving TDLS setup request */
+		else if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
+			DBG_871X("receive duplicated TDLS setup request frame in handshaking\n");
+			goto exit;
+		}
+		/* When receiving and sending setup_req to the same link at the same time */
+		/* STA with higher MAC_addr would be initiator */
+		else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
+			DBG_871X("receive setup_req after sending setup_req\n");
+			for (i=0;i<6;i++){
+				if(*(pmyid+i)==*(psa+i)){
+				}
+				else if(*(pmyid+i)>*(psa+i)){
+					ptdls_sta->tdls_sta_state = TDLS_INITIATOR_STATE;
+					break;
+				}else if(*(pmyid+i)<*(psa+i)){
+					goto exit;
+				}
+			}
+		}
+	}
+
+	if (ptdls_sta) {
+		txmgmt.dialog_token = *(ptr+2);	/* Copy dialog token */
+		txmgmt.status_code = _STATS_SUCCESSFUL_;
+
+		/* Parsing information element */
+		for (j=FIXED_IE; j<parsing_length;) {
+
+			pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+			switch (pIE->ElementID) {
+			case _SUPPORTEDRATES_IE_:
+				_rtw_memcpy(supportRate, pIE->data, pIE->Length);
+				supportRateNum = pIE->Length;
+				break;
+			case _COUNTRY_IE_:
+				break;
+			case _EXT_SUPPORTEDRATES_IE_:
+				if (supportRateNum<=sizeof(supportRate)) {
+					_rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
+					supportRateNum += pIE->Length;
+				}
+				break;
+			case _SUPPORTED_CH_IE_:
+				break;
+			case _RSN_IE_2_:
+				rsnie_included=1;
+				if (prx_pkt_attrib->encrypt) {
+					prsnie=(u8*)pIE;
+					/* Check CCMP pairwise_cipher presence. */
+					ppairwise_cipher=prsnie+10;
+					_rtw_memcpy(ptdls_sta->TDLS_RSNIE, pIE->data, pIE->Length);
+					pairwise_count = *(u16*)(ppairwise_cipher-2);
+					for (k=0; k<pairwise_count; k++) {
+						if (_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4)==_TRUE)
+							ccmp_included=1;
+					}
+
+					if (ccmp_included == 0)
+						txmgmt.status_code=_STATS_INVALID_RSNIE_;
+				}
+				break;
+			case _EXT_CAP_IE_:
+				break;
+			case _VENDOR_SPECIFIC_IE_:
+				break;
+			case _FTIE_:
+				if (prx_pkt_attrib->encrypt)
+					_rtw_memcpy(SNonce, (ptr+j+52), 32);
+				break;
+			case _TIMEOUT_ITVL_IE_:
+				if (prx_pkt_attrib->encrypt)
+					timeout_interval = cpu_to_le32(*(u32*)(ptr+j+3));
+				break;
+			case _RIC_Descriptor_IE_:
+				break;
+#ifdef CONFIG_80211N_HT				
+			case _HT_CAPABILITY_IE_:
+				rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
+				break;
+#endif	
+#ifdef CONFIG_80211AC_VHT				
+			case EID_AID:
+				break;
+			case EID_VHTCapability:
+				rtw_tdls_process_vht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
+				break;
+#endif
+			case EID_BSSCoexistence:
+				break;
+			case _LINK_ID_IE_:
+				if (_rtw_memcmp(get_bssid(pmlmepriv), pIE->data, 6) == _FALSE)
+					txmgmt.status_code=_STATS_NOT_IN_SAME_BSS_;
+				break;
+			default:
+				break;
+			}
+
+			j += (pIE->Length + 2);
+			
+		}
+
+		/* Check status code */
+		/* If responder STA has/hasn't security on AP, but request hasn't/has RSNIE, it should reject */
+		if (txmgmt.status_code == _STATS_SUCCESSFUL_) {
+			if (rsnie_included && prx_pkt_attrib->encrypt == 0)
+				txmgmt.status_code = _STATS_SEC_DISABLED_;
+			else if (rsnie_included==0 && prx_pkt_attrib->encrypt)
+				txmgmt.status_code = _STATS_INVALID_PARAMETERS_;
+
+#ifdef CONFIG_WFD
+			/* WFD test plan version 0.18.2 test item 5.1.5 */
+			/* SoUT does not use TDLS if AP uses weak security */
+			if (padapter->wdinfo.wfd_tdls_enable && (rsnie_included && prx_pkt_attrib->encrypt != _AES_))
+					txmgmt.status_code = _STATS_SEC_DISABLED_;
+#endif /* CONFIG_WFD */
+		}
+
+		ptdls_sta->tdls_sta_state|= TDLS_INITIATOR_STATE;
+		if (prx_pkt_attrib->encrypt) {
+			_rtw_memcpy(ptdls_sta->SNonce, SNonce, 32);
+
+			if (timeout_interval <= 300) 
+				ptdls_sta->TDLS_PeerKey_Lifetime = TPK_RESEND_COUNT;
+			else
+				ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
+		}
+
+		/* Update station supportRate */
+		ptdls_sta->bssratelen = supportRateNum;
+		_rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
+
+		if (!(ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE))
+			ptdlsinfo->sta_cnt++;
+		/* -2: AP + BC/MC sta, -4: default key */
+		if (ptdlsinfo->sta_cnt == MAX_ALLOWED_TDLS_STA_NUM)
+			ptdlsinfo->sta_maximum = _TRUE;
+
+#ifdef CONFIG_WFD
+		rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length);
+#endif
+
+	}else {
+		goto exit;
+	}
+
+	_rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);
+
+	if (rtw_tdls_is_driver_setup(padapter)) {
+		issue_tdls_setup_rsp(padapter, &txmgmt);
+
+		if (txmgmt.status_code==_STATS_SUCCESSFUL_) {
+			_set_timer( &ptdls_sta->handshake_timer, TDLS_HANDSHAKE_TIME);
+		}else {
+			free_tdls_sta(padapter, ptdls_sta);
+		}
+	}
+		
+exit:
+	
+	return _SUCCESS;
+}
+
+int On_TDLS_Setup_Rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct sta_info *ptdls_sta= NULL;
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	_irqL irqL;
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	u8 *psa;
+	u16 status_code=0;
+	sint parsing_length;	/* Frame body length, without icv_len */
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 FIXED_IE =7;
+	u8 ANonce[32];
+	u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;
+	u16 pairwise_count, j, k;
+	u8 verify_ccmp=0;
+	unsigned char		supportRate[16];
+	int				supportRateNum = 0;
+	struct tdls_txmgmt txmgmt;
+	int ret = _SUCCESS;
+	u32 timeout_interval = TPK_RESEND_COUNT;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	psa = get_sa(ptr);
+	ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+	if (NULL == ptdls_sta) {
+		ret = _FAIL;
+		goto exit;
+	}
+
+	ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+			-prx_pkt_attrib->hdrlen
+			-prx_pkt_attrib->iv_len
+			-prx_pkt_attrib->icv_len
+			-LLC_HEADER_SIZE
+			-ETH_TYPE_LEN
+			-PAYLOAD_TYPE_LEN
+			-FIXED_IE;
+
+	_rtw_memcpy(&status_code, ptr+2, 2);
+	
+	if (status_code != 0) {
+		DBG_871X( "[TDLS] %s status_code = %d, free_tdls_sta\n", __FUNCTION__, status_code );
+		free_tdls_sta(padapter, ptdls_sta);
+		ret = _FAIL;
+		goto exit;
+	}
+
+	status_code = 0;
+
+	/* parsing information element */
+	for (j = FIXED_IE; j<parsing_length;) {
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+		switch (pIE->ElementID) {
+		case _SUPPORTEDRATES_IE_:
+			_rtw_memcpy(supportRate, pIE->data, pIE->Length);
+			supportRateNum = pIE->Length;
+			break;
+		case _COUNTRY_IE_:
+			break;
+		case _EXT_SUPPORTEDRATES_IE_:
+			if (supportRateNum<=sizeof(supportRate)) {
+				_rtw_memcpy(supportRate+supportRateNum, pIE->data, pIE->Length);
+				supportRateNum += pIE->Length;
+			}
+			break;
+		case _SUPPORTED_CH_IE_:
+			break;
+		case _RSN_IE_2_:
+			prsnie=(u8*)pIE;
+			/* Check CCMP pairwise_cipher presence. */
+			ppairwise_cipher=prsnie+10;
+			_rtw_memcpy(&pairwise_count, (u16*)(ppairwise_cipher-2), 2);
+			for (k=0;k<pairwise_count;k++) {
+				if (_rtw_memcmp( ppairwise_cipher+4*k, RSN_CIPHER_SUITE_CCMP, 4) == _TRUE)
+					verify_ccmp=1;
+			}
+		case _EXT_CAP_IE_:
+			break;
+		case _VENDOR_SPECIFIC_IE_:
+			if (_rtw_memcmp((u8 *)pIE + 2, WMM_INFO_OUI, 6) == _TRUE) {	
+				/* WMM Info ID and OUI */
+				if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
+					ptdls_sta->qos_option = _TRUE;
+			}
+			break;
+		case _FTIE_:
+			pftie=(u8*)pIE;
+			_rtw_memcpy(ANonce, (ptr+j+20), 32);
+			break;
+		case _TIMEOUT_ITVL_IE_:
+			ptimeout_ie=(u8*)pIE;
+			timeout_interval = cpu_to_le32(*(u32*)(ptimeout_ie+3));
+			break;
+		case _RIC_Descriptor_IE_:
+			break;
+#ifdef CONFIG_80211N_HT			
+		case _HT_CAPABILITY_IE_:
+			rtw_tdls_process_ht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
+			break;
+#endif			
+#ifdef CONFIG_80211AC_VHT
+		case EID_AID:
+			/* todo in the future if necessary */
+			break;
+		case EID_VHTCapability:
+			rtw_tdls_process_vht_cap(padapter, ptdls_sta, pIE->data, pIE->Length);
+			break;
+		case EID_OpModeNotification:
+			rtw_process_vht_op_mode_notify(padapter, pIE->data, ptdls_sta);
+			break;	
+#endif
+		case EID_BSSCoexistence:
+			break;
+		case _LINK_ID_IE_:
+			plinkid_ie=(u8*)pIE;
+			break;
+		default:
+			break;
+		}
+
+		j += (pIE->Length + 2);
+
+	}
+
+	ptdls_sta->bssratelen = supportRateNum;
+	_rtw_memcpy(ptdls_sta->bssrateset, supportRate, supportRateNum);
+	_rtw_memcpy(ptdls_sta->ANonce, ANonce, 32);
+
+#ifdef CONFIG_WFD
+	rtw_tdls_process_wfd_ie(ptdlsinfo, ptr + FIXED_IE, parsing_length);
+#endif
+
+	if (status_code != _STATS_SUCCESSFUL_) {
+		txmgmt.status_code = status_code;
+	} else {
+		if (prx_pkt_attrib->encrypt) {
+			if (verify_ccmp == 1) {
+				txmgmt.status_code = _STATS_SUCCESSFUL_;
+				if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
+					wpa_tdls_generate_tpk(padapter, ptdls_sta);
+					if (tdls_verify_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL) {
+						DBG_871X( "[TDLS] %s tdls_verify_mic fail, free_tdls_sta\n", __FUNCTION__);
+						free_tdls_sta(padapter, ptdls_sta);
+						ret = _FAIL;
+						goto exit;
+					}
+					ptdls_sta->TDLS_PeerKey_Lifetime = timeout_interval;
+				}
+			}
+			else
+			{
+				txmgmt.status_code = _STATS_INVALID_RSNIE_;
+			}
+
+		}else{
+			txmgmt.status_code = _STATS_SUCCESSFUL_;
+		}
+	}
+
+	if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
+		_rtw_memcpy(txmgmt.peer, prx_pkt_attrib->src, ETH_ALEN);
+		issue_tdls_setup_cfm(padapter, &txmgmt);
+
+		if (txmgmt.status_code == _STATS_SUCCESSFUL_) {
+			ptdlsinfo->link_established = _TRUE;
+
+			if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE) {
+				ptdls_sta->tdls_sta_state |= TDLS_LINKED_STATE;
+				ptdls_sta->state |= _FW_LINKED;
+				_cancel_timer_ex( &ptdls_sta->handshake_timer);
+			}
+
+			if (prx_pkt_attrib->encrypt)
+				rtw_tdls_set_key(padapter, ptdls_sta);
+
+			rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);
+
+		}
+	}
+
+exit:
+	if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
+		return ret;
+	else
+		return _SUCCESS;
+
+}
+
+int On_TDLS_Setup_Cfm(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct sta_info *ptdls_sta= NULL;
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	_irqL irqL;
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	u8 *psa; 
+	u16 status_code=0;
+	sint parsing_length;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 FIXED_IE =5;
+	u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL, *ppairwise_cipher=NULL;
+	u16 j, pairwise_count;
+	int ret = _SUCCESS;
+
+	psa = get_sa(ptr);
+	ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+	if (ptdls_sta == NULL) {
+		DBG_871X("[%s] Direct Link Peer = "MAC_FMT" not found\n", __FUNCTION__, MAC_ARG(psa));
+		ret = _FAIL;
+		goto exit;
+	}
+
+	ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+			-prx_pkt_attrib->hdrlen
+			-prx_pkt_attrib->iv_len
+			-prx_pkt_attrib->icv_len
+			-LLC_HEADER_SIZE
+			-ETH_TYPE_LEN
+			-PAYLOAD_TYPE_LEN
+			-FIXED_IE;
+
+	_rtw_memcpy(&status_code, ptr+2, 2);
+
+	if (status_code!= 0) {
+		DBG_871X("[%s] status_code = %d\n, free_tdls_sta", __FUNCTION__, status_code);
+		free_tdls_sta(padapter, ptdls_sta);
+		ret = _FAIL;
+		goto exit;
+	}
+
+	/* Parsing information element */
+	for (j = FIXED_IE; j < parsing_length;) {
+
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr + j);
+
+		switch (pIE->ElementID) {
+			case _RSN_IE_2_:
+				prsnie = (u8 *)pIE;
+				break;
+			case _VENDOR_SPECIFIC_IE_:
+				if (_rtw_memcmp((u8 *)pIE + 2, WMM_PARA_OUI, 6) == _TRUE) {	
+					/* WMM Parameter ID and OUI */
+					ptdls_sta->qos_option = _TRUE;
+				}
+				break;				
+			case _FTIE_:
+				pftie = (u8 *)pIE;
+				break;
+			case _TIMEOUT_ITVL_IE_:
+				ptimeout_ie = (u8 *)pIE;
+				break;
+#ifdef CONFIG_80211N_HT				
+			case _HT_EXTRA_INFO_IE_:
+				break;
+#endif
+#ifdef CONFIG_80211AC_VHT
+			case EID_VHTOperation:
+				break;
+			case EID_OpModeNotification:
+				rtw_process_vht_op_mode_notify(padapter, pIE->data, ptdls_sta);
+				break;	
+#endif
+			case _LINK_ID_IE_:
+				plinkid_ie = (u8 *)pIE;
+				break;
+			default:
+				break;
+		}
+
+		j += (pIE->Length + 2);
+		
+	}
+
+	if (prx_pkt_attrib->encrypt) {
+		/* Verify mic in FTIE MIC field */
+		if (rtw_tdls_is_driver_setup(padapter) &&
+			(tdls_verify_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie) == _FAIL)) {
+			free_tdls_sta(padapter, ptdls_sta);
+			ret = _FAIL;
+			goto exit;
+		}
+	}
+
+	if (rtw_tdls_is_driver_setup(padapter)) {
+		ptdlsinfo->link_established = _TRUE;
+
+		if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE) {
+			ptdls_sta->tdls_sta_state|=TDLS_LINKED_STATE;
+			ptdls_sta->state |= _FW_LINKED;
+			_cancel_timer_ex(&ptdls_sta->handshake_timer);
+		}
+
+		if (prx_pkt_attrib->encrypt) {
+			rtw_tdls_set_key(padapter, ptdls_sta);
+
+			/* Start  TPK timer */
+			ptdls_sta->TPK_count = 0;
+			_set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
+		}
+
+		rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ESTABLISHED);
+	}
+
+exit:
+	return ret;
+
+}
+
+int On_TDLS_Dis_Req(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *psta_ap;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	sint parsing_length;	/* Frame body length, without icv_len */
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 FIXED_IE = 3, *dst;
+	u16 j;
+	struct tdls_txmgmt txmgmt;
+	int ret = _SUCCESS;
+
+	if (rtw_tdls_is_driver_setup(padapter) == _FALSE)
+		goto exit;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	txmgmt.dialog_token = *(ptr+2);
+	_rtw_memcpy(&txmgmt.peer, precv_frame->u.hdr.attrib.src, ETH_ALEN);
+	txmgmt.action_code = TDLS_DISCOVERY_RESPONSE;
+	parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+			-prx_pkt_attrib->hdrlen
+			-prx_pkt_attrib->iv_len
+			-prx_pkt_attrib->icv_len
+			-LLC_HEADER_SIZE
+			-ETH_TYPE_LEN
+			-PAYLOAD_TYPE_LEN
+			-FIXED_IE;
+
+	/* Parsing information element */
+	for (j=FIXED_IE; j<parsing_length;) {
+
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+		switch (pIE->ElementID) {
+		case _LINK_ID_IE_:
+			psta_ap = rtw_get_stainfo(pstapriv, pIE->data);
+			if (psta_ap == NULL)
+				goto exit;
+			dst = pIE->data + 12;
+			if (MacAddr_isBcst(dst) == _FALSE && (_rtw_memcmp(adapter_mac_addr(padapter), dst, 6) == _FALSE))
+				goto exit;
+			break;
+		default:
+			break;
+		}
+
+		j += (pIE->Length + 2);
+		
+	}
+
+	issue_tdls_dis_rsp(padapter, &txmgmt, prx_pkt_attrib->privacy);
+		
+exit:
+	return ret;
+	
+}
+
+int On_TDLS_Teardown(_adapter *padapter, union recv_frame *precv_frame)
+{
+	u8 *psa;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);	
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct sta_priv 	*pstapriv = &padapter->stapriv;
+	struct sta_info *ptdls_sta= NULL;
+	_irqL irqL;
+	u8 reason;
+
+	reason = *(ptr + prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE + ETH_TYPE_LEN + PAYLOAD_TYPE_LEN + 2);
+	DBG_871X("[TDLS] %s Reason code(%d)\n", __FUNCTION__,reason);
+
+	psa = get_sa(ptr);
+
+	ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+	if (ptdls_sta != NULL) {
+		if (rtw_tdls_is_driver_setup(padapter))
+			rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEAR_STA);
+	}
+
+	return _SUCCESS;
+	
+}
+
+#if 0
+u8 TDLS_check_ch_state(uint state){
+	if (state & TDLS_CH_SWITCH_ON_STATE &&
+		state & TDLS_PEER_AT_OFF_STATE) {
+		if (state & TDLS_PEER_SLEEP_STATE)
+			return 2;	/* U-APSD + ch. switch */
+		else
+			return 1;	/* ch. switch */
+	}else
+		return 0;
+}
+#endif
+
+int On_TDLS_Peer_Traffic_Indication(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct rx_pkt_attrib	*pattrib = &precv_frame->u.hdr.attrib;
+	struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->src);	
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct tdls_txmgmt txmgmt;
+
+	ptr +=pattrib->hdrlen + pattrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+
+	if (ptdls_sta != NULL) {
+		txmgmt.dialog_token = *(ptr+2);
+		issue_tdls_peer_traffic_rsp(padapter, ptdls_sta, &txmgmt);
+		//issue_nulldata_to_TDLS_peer_STA(padapter, ptdls_sta->hwaddr, 0, 0, 0);
+	} else {
+		DBG_871X("from unknown sta:"MAC_FMT"\n", MAC_ARG(pattrib->src));
+		return _FAIL;
+	}
+
+	return _SUCCESS;
+}
+
+/* We process buffered data for 1. U-APSD, 2. ch. switch, 3. U-APSD + ch. switch here */
+int On_TDLS_Peer_Traffic_Rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct rx_pkt_attrib	*pattrib = & precv_frame->u.hdr.attrib;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->src);
+	u8 wmmps_ac=0;
+	/* u8 state=TDLS_check_ch_state(ptdls_sta->tdls_sta_state); */
+	int i;
+	
+	ptdls_sta->sta_stats.rx_data_pkts++;
+
+	ptdls_sta->tdls_sta_state &= ~(TDLS_WAIT_PTR_STATE);
+
+	/* Check 4-AC queue bit */
+	if (ptdls_sta->uapsd_vo || ptdls_sta->uapsd_vi || ptdls_sta->uapsd_be || ptdls_sta->uapsd_bk)
+		wmmps_ac=1;
+
+	/* If it's a direct link and have buffered frame */
+	if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
+		if (wmmps_ac) {
+			_irqL irqL;	 
+			_list	*xmitframe_plist, *xmitframe_phead;
+			struct xmit_frame *pxmitframe=NULL;
+		
+			_enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);	
+
+			xmitframe_phead = get_list_head(&ptdls_sta->sleep_q);
+			xmitframe_plist = get_next(xmitframe_phead);
+
+			/* transmit buffered frames */
+			while (rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist) == _FALSE) {
+				pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+				xmitframe_plist = get_next(xmitframe_plist);
+				rtw_list_delete(&pxmitframe->list);
+
+				ptdls_sta->sleepq_len--;
+				ptdls_sta->sleepq_ac_len--;
+				if (ptdls_sta->sleepq_len>0) {
+					pxmitframe->attrib.mdata = 1;
+					pxmitframe->attrib.eosp = 0;
+				} else {
+					pxmitframe->attrib.mdata = 0;
+					pxmitframe->attrib.eosp = 1;
+				}
+				pxmitframe->attrib.triggered = 1;
+
+				rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+			}
+
+			if (ptdls_sta->sleepq_len==0)
+				DBG_871X("no buffered packets for tdls to xmit\n");
+			else {
+				DBG_871X("error!psta->sleepq_len=%d\n", ptdls_sta->sleepq_len);
+				ptdls_sta->sleepq_len=0;
+			}
+
+			_exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);			
+		
+		}
+
+	}
+
+	return _SUCCESS;
+}
+
+#ifdef CONFIG_TDLS_CH_SW
+sint On_TDLS_Ch_Switch_Req(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
+	struct sta_info *ptdls_sta= NULL;
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	u8 *psa; 
+	sint parsing_length;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 FIXED_IE = 4;
+	u16 j;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct tdls_txmgmt txmgmt;
+	u16 switch_time= CH_SWITCH_TIME * 1000, switch_timeout=CH_SWITCH_TIMEOUT * 1000;
+
+	if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
+	{	DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
+		return _SUCCESS;
+	}
+	
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	psa = get_sa(ptr);
+	ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+	ptdls_sta->ch_switch_time=switch_time;
+	ptdls_sta->ch_switch_timeout=switch_timeout;
+
+	ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len+LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	parsing_length= ((union recv_frame *)precv_frame)->u.hdr.len
+			-prx_pkt_attrib->hdrlen
+			-prx_pkt_attrib->iv_len
+			-prx_pkt_attrib->icv_len
+			-LLC_HEADER_SIZE
+			-ETH_TYPE_LEN
+			-PAYLOAD_TYPE_LEN
+			-FIXED_IE;
+
+	pchsw_info->off_ch_num = *(ptr + 2);
+
+	if (*(ptr + 2) == 2) {
+		pchsw_info->off_ch_num = 11;
+	}
+
+	if (pchsw_info->off_ch_num != pmlmeext->cur_channel) {
+		pchsw_info->delay_switch_back = _FALSE;
+	}
+
+	/* Parsing information element */
+	for (j=FIXED_IE; j<parsing_length;) {
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+		switch (pIE->ElementID) {
+		case EID_SecondaryChnlOffset:
+			padapter->tdlsinfo.chsw_info.ch_offset = *(pIE->data);
+			break;
+		case _LINK_ID_IE_:
+			break;
+		case _CH_SWITCH_TIMING_:
+			ptdls_sta->ch_switch_time = (RTW_GET_LE16(pIE->data) >= CH_SWITCH_TIME * 1000) ?
+				RTW_GET_LE16(pIE->data) : CH_SWITCH_TIME * 1000;
+			ptdls_sta->ch_switch_timeout = (RTW_GET_LE16(pIE->data + 2) >= CH_SWITCH_TIMEOUT * 1000) ?
+				RTW_GET_LE16(pIE->data + 2) : CH_SWITCH_TIMEOUT * 1000;
+			DBG_871X("%s ch_switch_time:%d, ch_switch_timeout:%d\n"
+				, __FUNCTION__, RTW_GET_LE16(pIE->data), RTW_GET_LE16(pIE->data + 2));
+		default:
+			break;
+		}
+
+		j += (pIE->Length + 2);
+	}
+
+	/* Todo: check status */
+	txmgmt.status_code = 0;
+	_rtw_memcpy(txmgmt.peer, psa, ETH_ALEN);
+	
+	ATOMIC_SET(&pchsw_info->chsw_on, _TRUE);
+
+	rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_RESP);
+
+	return _SUCCESS;
+}
+
+sint On_TDLS_Ch_Switch_Rsp(_adapter *padapter, union recv_frame *precv_frame)
+{
+	struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
+	struct sta_info *ptdls_sta= NULL;
+   	struct sta_priv *pstapriv = &padapter->stapriv;
+	u8 *ptr = precv_frame->u.hdr.rx_data;
+	struct rx_pkt_attrib	*prx_pkt_attrib = &precv_frame->u.hdr.attrib;
+	u8 *psa; 
+	sint parsing_length;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 FIXED_IE = 4;
+	u16 status_code, j, switch_time, switch_timeout;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	int ret = _SUCCESS;
+
+	if (padapter->tdlsinfo.ch_switch_prohibited == _TRUE)
+	{	DBG_871X("[TDLS] Ignore %s since ch_switch_prohibited = _TRUE\n", __FUNCTION__);
+		return _SUCCESS;
+	}
+
+	psa = get_sa(ptr);
+	ptdls_sta = rtw_get_stainfo(pstapriv, psa);
+
+	/* If we receive Unsolicited TDLS Channel Switch Response when channel switch is running, */
+	/* we will go back to base channel and terminate this channel switch procedure */
+	if (ATOMIC_READ(&pchsw_info->chsw_on) == _TRUE) {
+		if (pmlmeext->cur_channel != rtw_get_oper_ch(padapter)) {
+			DBG_871X("receive unsolicited channel switch response \n");
+			rtw_tdls_cmd(padapter, NULL, TDLS_CH_SW_BACK);
+			goto exit;
+		}
+	}
+
+	ptr +=prx_pkt_attrib->hdrlen + prx_pkt_attrib->iv_len + LLC_HEADER_SIZE+ETH_TYPE_LEN+PAYLOAD_TYPE_LEN;
+	parsing_length = ((union recv_frame *)precv_frame)->u.hdr.len
+			-prx_pkt_attrib->hdrlen
+			-prx_pkt_attrib->iv_len
+			-prx_pkt_attrib->icv_len
+			-LLC_HEADER_SIZE
+			-ETH_TYPE_LEN
+			-PAYLOAD_TYPE_LEN
+			-FIXED_IE;
+
+	_rtw_memcpy(&status_code, ptr+2, 2);
+
+	if (status_code != 0) {
+		DBG_871X("[%s] status_code:%d\n", __FUNCTION__, status_code);
+		pchsw_info->ch_sw_state &= ~(TDLS_CH_SW_INITIATOR_STATE);
+		ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
+		ret = _FAIL;
+		goto exit;
+	}
+	
+	/* Parsing information element */
+	for (j = FIXED_IE; j < parsing_length;) {
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(ptr+ j);
+
+		switch (pIE->ElementID) {
+		case _LINK_ID_IE_:
+			break;
+		case _CH_SWITCH_TIMING_:
+			_rtw_memcpy(&switch_time, pIE->data, 2);
+			if (switch_time > ptdls_sta->ch_switch_time)
+				_rtw_memcpy(&ptdls_sta->ch_switch_time, &switch_time, 2);
+
+			_rtw_memcpy(&switch_timeout, pIE->data + 2, 2);
+			if (switch_timeout > ptdls_sta->ch_switch_timeout)
+				_rtw_memcpy(&ptdls_sta->ch_switch_timeout, &switch_timeout, 2);
+			break;
+		default:
+			break;
+		}
+
+		j += (pIE->Length + 2);
+	}
+
+	if ((pmlmeext->cur_channel == rtw_get_oper_ch(padapter)) &&
+		(pchsw_info->ch_sw_state & TDLS_WAIT_CH_RSP_STATE)) {
+		ATOMIC_SET(&pchsw_info->chsw_on, _TRUE);
+		rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW);
+	}
+
+exit:
+	return ret;
+}
+#endif /* CONFIG_TDLS_CH_SW */
+
+#ifdef CONFIG_WFD
+void wfd_ie_tdls(_adapter * padapter, u8 *pframe, u32 *pktlen )
+{
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct wifi_display_info	*pwfd_info = padapter->tdlsinfo.wfd_info;
+	u8 wfdie[ MAX_WFD_IE_LEN] = { 0x00 };
+	u32 wfdielen = 0;
+
+	if (!hal_chk_wl_func(padapter, WL_FUNC_MIRACAST))
+		return;
+
+	/* WFD OUI */
+	wfdielen = 0;
+	wfdie[ wfdielen++ ] = 0x50;
+	wfdie[ wfdielen++ ] = 0x6F;
+	wfdie[ wfdielen++ ] = 0x9A;
+	wfdie[ wfdielen++ ] = 0x0A;	/* WFA WFD v1.0 */
+
+	/*
+	 *	Commented by Albert 20110825
+	 *	According to the WFD Specification, the negotiation request frame should contain 3 WFD attributes
+	 *	1. WFD Device Information
+	 *	2. Associated BSSID ( Optional )
+	 *	3. Local IP Adress ( Optional )
+	 */
+
+	/* WFD Device Information ATTR */
+	/* Type: */
+	wfdie[ wfdielen++ ] = WFD_ATTR_DEVICE_INFO;
+
+	/* Length: */
+	/* Note: In the WFD specification, the size of length field is 2. */
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	/* Value1: */
+	/* WFD device information */
+	/* available for WFD session + Preferred TDLS + WSD ( WFD Service Discovery ) */
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->wfd_device_type | WFD_DEVINFO_SESSION_AVAIL 
+								| WFD_DEVINFO_PC_TDLS | WFD_DEVINFO_WSD);
+	wfdielen += 2;
+
+	/* Value2: */
+	/* Session Management Control Port */
+	/* Default TCP port for RTSP messages is 554 */
+	RTW_PUT_BE16(wfdie + wfdielen, pwfd_info->tdls_rtsp_ctrlport);
+	wfdielen += 2;
+
+	/* Value3: */
+	/* WFD Device Maximum Throughput */
+	/* 300Mbps is the maximum throughput */
+	RTW_PUT_BE16(wfdie + wfdielen, 300);
+	wfdielen += 2;
+
+	/* Associated BSSID ATTR */
+	/* Type: */
+	wfdie[ wfdielen++ ] = WFD_ATTR_ASSOC_BSSID;
+
+	/* Length: */
+	/* Note: In the WFD specification, the size of length field is 2. */
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0006);
+	wfdielen += 2;
+
+	/* Value: */
+	/* Associated BSSID */
+	if (check_fwstate( pmlmepriv, _FW_LINKED) == _TRUE)
+		_rtw_memcpy(wfdie + wfdielen, &pmlmepriv->assoc_bssid[ 0 ], ETH_ALEN);
+	else
+		_rtw_memset(wfdie + wfdielen, 0x00, ETH_ALEN);
+
+	/* Local IP Address ATTR */
+	wfdie[ wfdielen++ ] = WFD_ATTR_LOCAL_IP_ADDR;
+
+	/* Length: */
+	/* Note: In the WFD specification, the size of length field is 2. */
+	RTW_PUT_BE16(wfdie + wfdielen, 0x0005);
+	wfdielen += 2;
+
+	/* Version: */
+	/* 0x01: Version1;IPv4 */
+	wfdie[ wfdielen++ ] = 0x01;	
+
+	/* IPv4 Address */
+	_rtw_memcpy( wfdie + wfdielen, pwfd_info->ip_address, 4 );
+	wfdielen += 4;
+	
+	pframe = rtw_set_ie(pframe, _VENDOR_SPECIFIC_IE_, wfdielen, (unsigned char *) wfdie, pktlen);
+	
+}
+#endif /* CONFIG_WFD */
+
+void rtw_build_tdls_setup_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
+
+ 	int i = 0 ;
+	u32 time;
+	u8 *pframe_head;
+
+	/* SNonce */
+	if (pattrib->encrypt) {
+		for (i=0;i<8;i++) {
+			time=rtw_get_current_time();
+			_rtw_memcpy(&ptdls_sta->SNonce[4*i], (u8 *)&time, 4);
+		}
+	}
+
+	pframe_head = pframe;	/* For rtw_tdls_set_ht_cap() */
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+
+	pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
+	pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
+	pframe = rtw_tdls_set_sup_ch(&(padapter->mlmeextpriv), pframe, pattrib);
+	pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);
+
+	if (pattrib->encrypt)
+		pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib,  _TRUE, ptdls_sta);
+
+	pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
+
+	if (pattrib->encrypt) {
+		pframe = rtw_tdls_set_ftie(ptxmgmt
+									, pframe
+									, pattrib
+									, NULL
+									, ptdls_sta->SNonce);
+
+		pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
+	}
+
+#ifdef CONFIG_80211N_HT
+	/* Sup_reg_classes(optional) */
+	if (pregistrypriv->ht_enable == _TRUE)
+		pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);
+#endif
+
+	pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
+
+	pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+	if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
+		pframe = rtw_tdls_set_qos_cap(pframe, pattrib);
+
+#ifdef CONFIG_80211AC_VHT
+	if ((padapter->mlmepriv.htpriv.ht_option == _TRUE) && (pmlmeext->cur_channel > 14)
+		&& REGSTY_IS_11AC_ENABLE(pregistrypriv)
+		&& hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
+		&& (!padapter->mlmepriv.country_ent || COUNTRY_CHPLAN_EN_11AC(padapter->mlmepriv.country_ent))
+	) {
+		pframe = rtw_tdls_set_aid(padapter, pframe, pattrib);
+		pframe = rtw_tdls_set_vht_cap(padapter, pframe, pattrib);
+	}
+#endif
+
+#ifdef CONFIG_WFD
+	if (padapter->wdinfo.wfd_tdls_enable == 1)
+		wfd_ie_tdls(padapter, pframe, &(pattrib->pktlen));
+#endif
+
+}
+
+void rtw_build_tdls_setup_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_info *ptdls_sta;
+	u8 k; /* for random ANonce */
+	u8  *pftie=NULL, *ptimeout_ie = NULL, *plinkid_ie = NULL, *prsnie = NULL, *pftie_mic = NULL;
+	u32 time;
+	u8 *pframe_head;
+
+	ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
+
+	if (ptdls_sta == NULL)
+		DBG_871X("[%s] %d ptdls_sta is NULL\n", __FUNCTION__, __LINE__);
+
+	if (pattrib->encrypt && ptdls_sta != NULL) {
+		for (k=0;k<8;k++) {
+			time = rtw_get_current_time();
+			_rtw_memcpy(&ptdls_sta->ANonce[4*k], (u8*)&time, 4);
+		}
+	}
+
+	pframe_head = pframe;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
+
+	if (ptxmgmt->status_code != 0) {
+		DBG_871X("[%s] status_code:%04x \n", __FUNCTION__, ptxmgmt->status_code);
+		return;
+	}
+	
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
+	pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
+	pframe = rtw_tdls_set_sup_ch(&(padapter->mlmeextpriv), pframe, pattrib);
+	pframe = rtw_tdls_set_sup_reg_class(pframe, pattrib);
+
+	if (pattrib->encrypt) {
+		prsnie = pframe;
+		pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib,  _FALSE, ptdls_sta);
+	}
+
+	pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
+
+	if (pattrib->encrypt) {
+		if (rtw_tdls_is_driver_setup(padapter) == _TRUE)
+			wpa_tdls_generate_tpk(padapter, ptdls_sta);
+
+		pftie = pframe;
+		pftie_mic = pframe+4;
+		pframe = rtw_tdls_set_ftie(ptxmgmt
+									, pframe
+									, pattrib
+									, ptdls_sta->ANonce
+									, ptdls_sta->SNonce);
+
+		ptimeout_ie = pframe;
+		pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _FALSE, ptdls_sta);
+	}
+
+#ifdef CONFIG_80211N_HT
+	/* Sup_reg_classes(optional) */
+	if (pregistrypriv->ht_enable == _TRUE)
+		pframe = rtw_tdls_set_ht_cap(padapter, pframe_head, pattrib);
+#endif
+
+	pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
+
+	plinkid_ie = pframe;
+	pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+
+	/* Fill FTIE mic */
+	if (pattrib->encrypt && rtw_tdls_is_driver_setup(padapter) == _TRUE)
+		wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 2, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
+
+	if ((pregistrypriv->wmm_enable == _TRUE) || (padapter->mlmepriv.htpriv.ht_option == _TRUE))
+		pframe = rtw_tdls_set_qos_cap(pframe, pattrib);
+
+#ifdef CONFIG_80211AC_VHT
+	if ((padapter->mlmepriv.htpriv.ht_option == _TRUE) && (pmlmeext->cur_channel > 14)
+		&& REGSTY_IS_11AC_ENABLE(pregistrypriv)
+		&& hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
+		&& (!padapter->mlmepriv.country_ent || COUNTRY_CHPLAN_EN_11AC(padapter->mlmepriv.country_ent))
+	) {
+		pframe = rtw_tdls_set_aid(padapter, pframe, pattrib);
+		pframe = rtw_tdls_set_vht_cap(padapter, pframe, pattrib);
+		pframe = rtw_tdls_set_vht_op_mode_notify(padapter, pframe, pattrib, pmlmeext->cur_bwmode);
+	}
+#endif
+
+#ifdef CONFIG_WFD
+	if (padapter->wdinfo.wfd_tdls_enable)
+		wfd_ie_tdls(padapter, pframe, &(pattrib->pktlen));
+#endif
+
+}
+
+void rtw_build_tdls_setup_cfm_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_info *ptdls_sta=rtw_get_stainfo( (&padapter->stapriv) , pattrib->dst);
+
+	unsigned int ie_len;
+	unsigned char *p;
+	u8 wmm_param_ele[24] = {0};
+	u8  *pftie=NULL, *ptimeout_ie=NULL, *plinkid_ie=NULL, *prsnie=NULL, *pftie_mic=NULL;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+
+	if (ptxmgmt->status_code!=0)
+		return;
+	
+	if (pattrib->encrypt) {
+		prsnie = pframe;
+		pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
+	}
+	
+	if (pattrib->encrypt) {
+		pftie = pframe;
+		pftie_mic = pframe+4;
+		pframe = rtw_tdls_set_ftie(ptxmgmt
+									, pframe
+									, pattrib
+									, ptdls_sta->ANonce
+									, ptdls_sta->SNonce);
+
+		ptimeout_ie = pframe;
+		pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib, _TRUE, ptdls_sta);
+
+		if (rtw_tdls_is_driver_setup(padapter) == _TRUE) {
+			/* Start TPK timer */
+			ptdls_sta->TPK_count=0;
+			_set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
+		}
+	}
+
+	/* HT operation; todo */
+	
+	plinkid_ie = pframe;
+	pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+	if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))
+		wpa_tdls_ftie_mic(ptdls_sta->tpk.kck, 3, plinkid_ie, prsnie, ptimeout_ie, pftie, pftie_mic);
+
+	if (ptdls_sta->qos_option == _TRUE)
+		pframe = rtw_tdls_set_wmm_params(padapter, pframe, pattrib);
+
+#ifdef CONFIG_80211AC_VHT
+	if ((padapter->mlmepriv.htpriv.ht_option == _TRUE)
+		&& (ptdls_sta->vhtpriv.vht_option == _TRUE) && (pmlmeext->cur_channel > 14)
+		&& REGSTY_IS_11AC_ENABLE(pregistrypriv)
+		&& hal_chk_proto_cap(padapter, PROTO_CAP_11AC)
+		&& (!padapter->mlmepriv.country_ent || COUNTRY_CHPLAN_EN_11AC(padapter->mlmepriv.country_ent))
+	) {
+		pframe = rtw_tdls_set_vht_operation(padapter, pframe, pattrib, pmlmeext->cur_channel);
+		pframe = rtw_tdls_set_vht_op_mode_notify(padapter, pframe, pattrib, pmlmeext->cur_bwmode);
+	}
+#endif
+}
+
+void rtw_build_tdls_teardown_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_info *ptdls_sta = rtw_get_stainfo( &(padapter->stapriv) , pattrib->dst);
+	u8  *pftie = NULL, *pftie_mic = NULL, *plinkid_ie = NULL;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
+
+	if (pattrib->encrypt) {
+		pftie = pframe;
+		pftie_mic = pframe + 4;
+		pframe = rtw_tdls_set_ftie(ptxmgmt
+									, pframe
+									, pattrib
+									, ptdls_sta->ANonce
+									, ptdls_sta->SNonce);
+	}
+
+	plinkid_ie = pframe;
+	if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+	else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+	if (pattrib->encrypt && (rtw_tdls_is_driver_setup(padapter) == _TRUE))
+		wpa_tdls_teardown_ftie_mic(ptdls_sta->tpk.kck, plinkid_ie, ptxmgmt->status_code, 1, 4, pftie, pftie_mic);
+}
+
+void rtw_build_tdls_dis_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+	struct pkt_attrib *pattrib = &pxmitframe->attrib;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+}
+
+void rtw_build_tdls_dis_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt, u8 privacy)
+{
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	u8 *pframe_head, pktlen_index;
+
+	pktlen_index = pattrib->pktlen;
+	pframe_head = pframe;
+
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_PUBLIC);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_capability(padapter, pframe, pattrib);
+
+	pframe = rtw_tdls_set_supported_rate(padapter, pframe, pattrib);
+
+	pframe = rtw_tdls_set_sup_ch(pmlmeext, pframe, pattrib);
+
+	if (privacy)
+		pframe = rtw_tdls_set_rsnie(ptxmgmt, pframe, pattrib, _TRUE, NULL);
+
+	pframe = rtw_tdls_set_ext_cap(pframe, pattrib);
+
+	if (privacy) {
+		pframe = rtw_tdls_set_ftie(ptxmgmt, pframe, pattrib, NULL, NULL);
+		pframe = rtw_tdls_set_timeout_interval(ptxmgmt, pframe, pattrib,  _TRUE, NULL);
+	}
+
+#ifdef CONFIG_80211N_HT
+	if (pregistrypriv->ht_enable == _TRUE)
+		pframe = rtw_tdls_set_ht_cap(padapter, pframe_head - pktlen_index, pattrib);
+#endif
+
+	pframe = rtw_tdls_set_bss_coexist(padapter, pframe, pattrib);
+	pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+
+}
+
+
+void rtw_build_tdls_peer_traffic_indication_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	u8 AC_queue=0;
+	struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+
+	if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+	else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+	/* PTI control */
+	/* PU buffer status */
+	if (ptdls_sta->uapsd_bk & BIT(1))
+		AC_queue=BIT(0);
+	if (ptdls_sta->uapsd_be & BIT(1))
+		AC_queue=BIT(1);
+	if (ptdls_sta->uapsd_vi & BIT(1))
+		AC_queue=BIT(2);
+	if (ptdls_sta->uapsd_vo & BIT(1))
+		AC_queue=BIT(3);
+	pframe = rtw_set_ie(pframe, _PTI_BUFFER_STATUS_, 1, &AC_queue, &(pattrib->pktlen));
+	
+}
+
+void rtw_build_tdls_peer_traffic_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_info *ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_dialog(pframe, pattrib, ptxmgmt);
+
+	if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+	else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+}
+
+#ifdef CONFIG_TDLS_CH_SW
+void rtw_build_tdls_ch_switch_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_priv 	*pstapriv = &padapter->stapriv;
+	struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
+	u16 switch_time= CH_SWITCH_TIME * 1000, switch_timeout=CH_SWITCH_TIMEOUT * 1000;
+
+	ptdls_sta->ch_switch_time=switch_time;
+	ptdls_sta->ch_switch_timeout=switch_timeout;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_target_ch(padapter, pframe, pattrib);
+	pframe = rtw_tdls_set_reg_class(pframe, pattrib, ptdls_sta);
+
+	if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+	else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+	pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);
+
+}
+
+void rtw_build_tdls_ch_switch_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_priv 	*pstapriv = &padapter->stapriv;	
+	struct sta_info *ptdls_sta = rtw_get_stainfo(pstapriv, pattrib->dst);
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_tdls_set_category(pframe, pattrib, RTW_WLAN_CATEGORY_TDLS);
+	pframe = rtw_tdls_set_action(pframe, pattrib, ptxmgmt);
+	pframe = rtw_tdls_set_status_code(pframe, pattrib, ptxmgmt);
+
+	if (ptdls_sta->tdls_sta_state & TDLS_INITIATOR_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _FALSE);
+	else if (ptdls_sta->tdls_sta_state & TDLS_RESPONDER_STATE)
+		pframe = rtw_tdls_set_linkid(pframe, pattrib, _TRUE);
+
+	pframe = rtw_tdls_set_ch_sw(pframe, pattrib, ptdls_sta);
+}
+#endif
+
+#ifdef CONFIG_WFD
+void rtw_build_tunneled_probe_req_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+	struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
+	u8 category = RTW_WLAN_CATEGORY_P2P;
+	u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
+	u8 probe_req = 4;
+	u8 wfdielen = 0;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(probe_req), &(pattrib->pktlen));
+
+	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		wfdielen = build_probe_req_wfd_ie(pwdinfo, pframe);
+		pframe += wfdielen;
+		pattrib->pktlen += wfdielen;
+	} else if (!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) {
+		wfdielen = build_probe_req_wfd_ie(pbuddy_wdinfo, pframe);
+		pframe += wfdielen;
+		pattrib->pktlen += wfdielen;
+	}
+	
+}
+
+void rtw_build_tunneled_probe_rsp_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe)
+{
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
+	struct wifidirect_info *pbuddy_wdinfo = &padapter->pbuddy_adapter->wdinfo;
+	u8 category = RTW_WLAN_CATEGORY_P2P;
+	u8 WFA_OUI[3] = { 0x50, 0x6f, 0x9a};
+	u8 probe_rsp = 5;
+	u8 wfdielen = 0;
+
+	pframe = rtw_tdls_set_payload_type(pframe, pattrib);
+	pframe = rtw_set_fixed_ie(pframe, 1, &(category), &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 3, WFA_OUI, &(pattrib->pktlen));
+	pframe = rtw_set_fixed_ie(pframe, 1, &(probe_rsp), &(pattrib->pktlen));
+
+	if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE)) {
+		wfdielen = build_probe_resp_wfd_ie(pwdinfo, pframe, 1);
+		pframe += wfdielen;
+		pattrib->pktlen += wfdielen;
+	} else if (!rtw_p2p_chk_state(pbuddy_wdinfo, P2P_STATE_NONE)) {
+		wfdielen = build_probe_resp_wfd_ie(pbuddy_wdinfo, pframe, 1);
+		pframe += wfdielen;
+		pattrib->pktlen += wfdielen;
+	}
+
+}
+#endif /* CONFIG_WFD */
+
+void _tdls_tpk_timer_hdl(void *FunctionContext)
+{
+	struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+	struct tdls_txmgmt txmgmt;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	ptdls_sta->TPK_count++;
+	/* TPK_timer expired in a second */
+	/* Retry timer should set at least 301 sec. */
+	if (ptdls_sta->TPK_count >= ptdls_sta->TDLS_PeerKey_Lifetime) {
+		DBG_871X("[TDLS] %s, Re-Setup TDLS link with "MAC_FMT" since TPK lifetime expires!\n", __FUNCTION__, MAC_ARG(ptdls_sta->hwaddr));
+		ptdls_sta->TPK_count=0;
+		_rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
+		issue_tdls_setup_req(ptdls_sta->padapter, &txmgmt, _FALSE);
+	}
+
+	_set_timer(&ptdls_sta->TPK_timer, ONE_SEC);
+}
+
+#ifdef CONFIG_TDLS_CH_SW
+void _tdls_ch_switch_timer_hdl(void *FunctionContext)
+{
+	struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+	_adapter *padapter = ptdls_sta->padapter;
+	struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
+
+	//DBG_871X("%s %d, tdls_sta_state:0x%08x\n", __FUNCTION__, __LINE__, ptdls_sta->tdls_sta_state);
+
+	if (padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)) {
+		if (!(pchsw_info->ch_sw_state & TDLS_PEER_AT_OFF_STATE)) {
+			rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_CH_SW_BACK);
+			ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
+			DBG_871X("[TDLS] %s, can't get traffic from op_ch:%d\n", __FUNCTION__, rtw_get_oper_ch(padapter));
+		} else {
+			//DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
+			//_set_timer(&ptdls_sta->delay_timer, padapter->mlmeextpriv.mlmext_info.bcn_interval - 5 - ptdls_sta->ch_switch_timeout/1000);
+		}
+	} else {
+		//DBG_871X("%s %d, op_ch:%d, tdls_state:0x%08x\n", __FUNCTION__, __LINE__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
+	}
+
+#if 0
+	if (!(pchsw_info->ch_sw_state & TDLS_PEER_AT_OFF_STATE)) {
+		//SelectChannel(padapter, padapter->mlmeextpriv.cur_channel);
+		ATOMIC_SET(&pchsw_info->chsw_on, _FALSE);
+		DBG_871X("%s %d, op_ch:%d, tdls_state:0x%08x\n", __FUNCTION__, __LINE__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
+	}
+
+	if (pchsw_info->ch_sw_state & TDLS_CH_SW_INITIATOR_STATE) {
+		if (padapter->mlmeextpriv.cur_channel != rtw_get_oper_ch(padapter)) {
+			DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
+			_set_timer(&ptdls_sta->delay_timer, padapter->mlmeextpriv.mlmext_info.bcn_interval - 5 - ptdls_sta->ch_switch_timeout/1000);
+			//_set_timer(&ptdls_sta->delay_timer, 1000);
+		} else {
+			DBG_871X("%s %d\n", __FUNCTION__, __LINE__);
+			issue_tdls_ch_switch_req(padapter, ptdls_sta);
+			//_set_timer(&ptdls_sta->delay_timer, 500);
+		}
+	}
+#endif
+}
+
+void _tdls_delay_timer_hdl(void *FunctionContext)
+{
+	struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+	_adapter *padapter = ptdls_sta->padapter;
+	struct tdls_ch_switch *pchsw_info = &padapter->tdlsinfo.chsw_info;
+
+	DBG_871X("[TDLS] %s, op_ch:%d, tdls_state:0x%08x\n", __FUNCTION__, rtw_get_oper_ch(padapter), ptdls_sta->tdls_sta_state);
+	pchsw_info->delay_switch_back = _TRUE;
+}
+#endif
+
+void _tdls_handshake_timer_hdl(void *FunctionContext)
+{
+	struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+	_adapter *padapter = ptdls_sta->padapter;
+	struct tdls_txmgmt txmgmt;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	_rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
+	txmgmt.status_code = _RSON_TDLS_TEAR_UN_RSN_;
+
+	if (ptdls_sta != NULL) {
+		DBG_871X("[TDLS] Handshake time out\n");
+		if (ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) 
+		{
+			issue_tdls_teardown(padapter, &txmgmt, _TRUE);
+		}
+		else
+		{
+			rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_TEAR_STA);
+		}
+	}
+}
+
+void _tdls_pti_timer_hdl(void *FunctionContext)
+{
+	struct sta_info *ptdls_sta = (struct sta_info *)FunctionContext;
+	_adapter *padapter = ptdls_sta->padapter;
+	struct tdls_txmgmt txmgmt;
+
+	_rtw_memset(&txmgmt, 0x00, sizeof(struct tdls_txmgmt));
+	_rtw_memcpy(txmgmt.peer, ptdls_sta->hwaddr, ETH_ALEN);
+	txmgmt.status_code = _RSON_TDLS_TEAR_TOOFAR_;
+
+	if (ptdls_sta != NULL) {
+		if (ptdls_sta->tdls_sta_state & TDLS_WAIT_PTR_STATE) {
+			DBG_871X("[TDLS] Doesn't receive PTR from peer dev:"MAC_FMT"; "
+				"Send TDLS Tear Down\n", MAC_ARG(ptdls_sta->hwaddr));
+			issue_tdls_teardown(padapter, &txmgmt, _FALSE);
+		}
+	}
+}
+
+void rtw_init_tdls_timer(_adapter *padapter, struct sta_info *psta)
+{
+	psta->padapter=padapter;
+	_init_timer(&psta->TPK_timer, padapter->pnetdev, _tdls_tpk_timer_hdl, psta);
+#ifdef CONFIG_TDLS_CH_SW	
+	_init_timer(&psta->ch_sw_timer, padapter->pnetdev, _tdls_ch_switch_timer_hdl, psta);
+	_init_timer(&psta->delay_timer, padapter->pnetdev, _tdls_delay_timer_hdl, psta);
+#endif
+	_init_timer(&psta->handshake_timer, padapter->pnetdev, _tdls_handshake_timer_hdl, psta);
+	_init_timer(&psta->pti_timer, padapter->pnetdev, _tdls_pti_timer_hdl, psta);
+}
+
+void rtw_free_tdls_timer(struct sta_info *psta)
+{
+	_cancel_timer_ex(&psta->TPK_timer);
+#ifdef CONFIG_TDLS_CH_SW	
+	_cancel_timer_ex(&psta->ch_sw_timer);
+	_cancel_timer_ex(&psta->delay_timer);
+#endif
+	_cancel_timer_ex(&psta->handshake_timer);
+	_cancel_timer_ex(&psta->pti_timer);
+}
+
+u8	update_sgi_tdls(_adapter *padapter, struct sta_info *psta)
+{
+	return query_ra_short_GI(psta);
+}
+
+u32 update_mask_tdls(_adapter *padapter, struct sta_info *psta)
+{
+	unsigned char sta_band = 0;
+	unsigned int tx_ra_bitmap=0;
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+	WLAN_BSSID_EX *pcur_network = (WLAN_BSSID_EX *)&pmlmepriv->cur_network.network;
+
+	rtw_hal_update_sta_rate_mask(padapter, psta);
+	tx_ra_bitmap = psta->ra_mask;
+
+	if (pcur_network->Configuration.DSConfig > 14) {
+		if (tx_ra_bitmap & 0xffff000)
+			sta_band |= WIRELESS_11_5N | WIRELESS_11A;
+		else
+			sta_band |= WIRELESS_11A;
+	} else {
+		if (tx_ra_bitmap & 0xffff000)
+			sta_band |= WIRELESS_11_24N | WIRELESS_11G | WIRELESS_11B;
+		else if (tx_ra_bitmap & 0xff0)
+			sta_band |= WIRELESS_11G |WIRELESS_11B;
+		else
+			sta_band |= WIRELESS_11B;
+	}
+
+	psta->wireless_mode = sta_band;
+
+	psta->raid = rtw_hal_networktype_to_raid(padapter,psta);
+	tx_ra_bitmap |= ((psta->raid<<28)&0xf0000000);
+	return tx_ra_bitmap;
+}
+
+int rtw_tdls_is_driver_setup(_adapter *padapter)
+{
+	return padapter->tdlsinfo.driver_setup;
+}
+
+const char * rtw_tdls_action_txt(enum TDLS_ACTION_FIELD action)
+{
+	switch (action) {
+	case TDLS_SETUP_REQUEST:
+		return "TDLS_SETUP_REQUEST";
+	case TDLS_SETUP_RESPONSE:
+		return "TDLS_SETUP_RESPONSE";
+	case TDLS_SETUP_CONFIRM:
+		return "TDLS_SETUP_CONFIRM";
+	case TDLS_TEARDOWN:
+		return "TDLS_TEARDOWN";
+	case TDLS_PEER_TRAFFIC_INDICATION:
+		return "TDLS_PEER_TRAFFIC_INDICATION";
+	case TDLS_CHANNEL_SWITCH_REQUEST:
+		return "TDLS_CHANNEL_SWITCH_REQUEST";
+	case TDLS_CHANNEL_SWITCH_RESPONSE:
+		return "TDLS_CHANNEL_SWITCH_RESPONSE";
+	case TDLS_PEER_PSM_REQUEST:
+		return "TDLS_PEER_PSM_REQUEST";
+	case TDLS_PEER_PSM_RESPONSE:
+		return "TDLS_PEER_PSM_RESPONSE";
+	case TDLS_PEER_TRAFFIC_RESPONSE:
+		return "TDLS_PEER_TRAFFIC_RESPONSE";
+	case TDLS_DISCOVERY_REQUEST:
+		return "TDLS_DISCOVERY_REQUEST";
+	case TDLS_DISCOVERY_RESPONSE:
+		return "TDLS_DISCOVERY_RESPONSE";
+	default:
+		return "UNKNOWN";
+	}
+}
+
+#endif /* CONFIG_TDLS */
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_vht.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_vht.c
new file mode 100644
index 000000000..137bcce49
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_vht.c
@@ -0,0 +1,807 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_VHT_C
+
+#include <drv_types.h>
+
+#ifdef CONFIG_80211AC_VHT
+// 				20/40/80,	ShortGI,	MCS Rate 
+const u16 VHT_MCS_DATA_RATE[3][2][30] = 
+	{	{	{13, 26, 39, 52, 78, 104, 117, 130, 156, 156,
+			 26, 52, 78, 104, 156, 208, 234, 260, 312, 312,
+			 39, 78, 117, 156, 234, 312, 351, 390, 468, 520},			// Long GI, 20MHz
+			{14, 29, 43, 58, 87, 116, 130, 144, 173, 173,
+			29, 58, 87, 116, 173, 231, 260, 289, 347, 347,
+			43,	87, 130, 173, 260, 347,390,	433,	520, 578}	},		// Short GI, 20MHz
+		{	{27, 54, 81, 108, 162, 216, 243, 270, 324, 360, 
+			54, 108, 162, 216, 324, 432, 486, 540, 648, 720,
+			81, 162, 243, 324, 486, 648, 729, 810, 972, 1080}, 		// Long GI, 40MHz
+			{30, 60, 90, 120, 180, 240, 270, 300,360, 400, 
+			60, 120, 180, 240, 360, 480, 540, 600, 720, 800,
+			90, 180, 270, 360, 540, 720, 810, 900, 1080, 1200}},		// Short GI, 40MHz
+		{	{59, 117,  176, 234, 351, 468, 527, 585, 702, 780,
+			117, 234, 351, 468, 702, 936, 1053, 1170, 1404, 1560,
+			176, 351, 527, 702, 1053, 1404, 1580, 1755, 2106, 2340},	/* Long GI, 80MHz */
+			{65, 130, 195, 260, 390, 520, 585, 650, 780, 867, 
+			130, 260, 390, 520, 780, 1040, 1170, 1300, 1560,1734,
+			195, 390, 585, 780, 1170, 1560, 1755, 1950, 2340, 2600}	}	/* Short GI, 80MHz */
+	};
+
+u8	rtw_get_vht_highest_rate(u8 *pvht_mcs_map)
+{
+	u8	i, j;
+	u8	bit_map;
+	u8	vht_mcs_rate = 0;
+	
+	for(i = 0; i < 2; i++)
+	{
+		if(pvht_mcs_map[i] != 0xff)
+		{
+			for(j = 0; j < 8; j += 2)
+			{
+				bit_map = (pvht_mcs_map[i] >> j) & 3;
+				
+				if(bit_map != 3)
+					vht_mcs_rate = MGN_VHT1SS_MCS7 + 10*j/2 + i*40 + bit_map;  //VHT rate indications begin from 0x90
+			}
+		}
+	}
+	
+	/* DBG_871X("HighestVHTMCSRate is %x\n", vht_mcs_rate); */
+	return vht_mcs_rate;
+}
+
+u8	rtw_vht_mcsmap_to_nss(u8 *pvht_mcs_map)
+{
+	u8	i, j;
+	u8	bit_map;
+	u8	nss = 0;
+	
+	for(i = 0; i < 2; i++)
+	{
+		if(pvht_mcs_map[i] != 0xff)
+		{
+			for(j = 0; j < 8; j += 2)
+			{
+				bit_map = (pvht_mcs_map[i] >> j) & 3;
+				
+				if(bit_map != 3)
+					nss++;
+			}
+		}
+	}
+	
+	/* DBG_871X("%s : %dSS\n", __FUNCTION__, nss); */
+	return nss;
+}
+
+void	rtw_vht_nss_to_mcsmap(u8 nss, u8 *target_mcs_map, u8 *cur_mcs_map)
+{
+	u8	i, j;
+	u8	cur_rate, target_rate;
+	
+	for(i = 0; i < 2; i++)
+	{
+		target_mcs_map[i] = 0;
+		for(j = 0; j < 8; j+=2)
+		{
+			cur_rate = (cur_mcs_map[i] >> j) & 3;
+			if(cur_rate == 3)  //0x3 indicates not supported that num of SS
+				target_rate = 3;
+			else if(nss <= ((j/2)+i*4))
+				target_rate = 3;
+			else	
+				target_rate = cur_rate;
+
+			target_mcs_map[i] |= (target_rate << j);
+		}
+	}
+	
+	//DBG_871X("%s : %dSS\n", __FUNCTION__, nss);
+}
+
+u16	rtw_vht_mcs_to_data_rate(u8 bw, u8 short_GI, u8 vht_mcs_rate)
+{
+	if(vht_mcs_rate > MGN_VHT3SS_MCS9)
+		vht_mcs_rate = MGN_VHT3SS_MCS9;
+	/* DBG_871X("bw=%d, short_GI=%d, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)=%d\n", bw, short_GI, ((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)); */
+	return VHT_MCS_DATA_RATE[bw][short_GI][((vht_mcs_rate - MGN_VHT1SS_MCS0)&0x3f)];
+}
+
+void	rtw_vht_use_default_setting(_adapter *padapter)
+{
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	BOOLEAN		bHwLDPCSupport = _FALSE, bHwSTBCSupport = _FALSE;
+	BOOLEAN		bHwSupportBeamformer = _FALSE, bHwSupportBeamformee = _FALSE;
+	u8	rf_type = 0;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	pvhtpriv->sgi_80m = TEST_FLAG(pregistrypriv->short_gi, BIT2) ? _TRUE : _FALSE;
+
+	// LDPC support
+	rtw_hal_get_def_var(padapter, HAL_DEF_RX_LDPC, (u8 *)&bHwLDPCSupport);
+	CLEAR_FLAGS(pvhtpriv->ldpc_cap);
+	if(bHwLDPCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->ldpc_cap, BIT0))
+			SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX);
+	}
+	rtw_hal_get_def_var(padapter, HAL_DEF_TX_LDPC, (u8 *)&bHwLDPCSupport);
+	if(bHwLDPCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->ldpc_cap, BIT1))
+			SET_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX);
+	}
+	if (pvhtpriv->ldpc_cap)
+		DBG_871X("[VHT] Support LDPC = 0x%02X\n", pvhtpriv->ldpc_cap);
+
+	// STBC
+	rtw_hal_get_def_var(padapter, HAL_DEF_TX_STBC, (u8 *)&bHwSTBCSupport);
+	CLEAR_FLAGS(pvhtpriv->stbc_cap);
+	if(bHwSTBCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->stbc_cap, BIT1))
+			SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX);
+	}
+	rtw_hal_get_def_var(padapter, HAL_DEF_RX_STBC, (u8 *)&bHwSTBCSupport);
+	if(bHwSTBCSupport)
+	{
+		if(TEST_FLAG(pregistrypriv->stbc_cap, BIT0))
+			SET_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX);
+	}
+	if (pvhtpriv->stbc_cap)
+		DBG_871X("[VHT] Support STBC = 0x%02X\n", pvhtpriv->stbc_cap);
+
+	// Beamforming setting
+	rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMER, (u8 *)&bHwSupportBeamformer);
+	rtw_hal_get_def_var(padapter, HAL_DEF_EXPLICIT_BEAMFORMEE, (u8 *)&bHwSupportBeamformee);
+	CLEAR_FLAGS(pvhtpriv->beamform_cap);
+	if (TEST_FLAG(pregistrypriv->beamform_cap, BIT0) && bHwSupportBeamformer) {
+		#ifdef CONFIG_CONCURRENT_MODE
+			if ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
+				SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+				DBG_871X("[VHT] CONCURRENT AP Support Beamformer\n");
+			} else
+			DBG_871X("[VHT] CONCURRENT not AP ;not allow  Support Beamformer\n");
+		#else
+			SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+			DBG_871X("[VHT] Support Beamformer\n");
+		#endif
+	}
+	if(TEST_FLAG(pregistrypriv->beamform_cap, BIT1) && bHwSupportBeamformee)
+	{
+		SET_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
+		DBG_871X("[VHT] Support Beamformee\n");
+	}
+
+	pvhtpriv->ampdu_len = pregistrypriv->ampdu_factor;
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+	if (rf_type == RF_3T3R)
+		pvhtpriv->vht_mcs_map[0] = 0xea;	/* support 1SS MCS 0~9 2SS MCS 0~9 3SS MCS 0~9 */
+	else if(rf_type == RF_2T2R)
+		pvhtpriv->vht_mcs_map[0] = 0xfa;	/* support 1SS MCS 0~9 2SS MCS 0~9 */
+	else
+		pvhtpriv->vht_mcs_map[0] = 0xfe;	/* Only support 1SS MCS 0~9; */
+	pvhtpriv->vht_mcs_map[1] = 0xff;
+
+	if(pregistrypriv->vht_rate_sel == 1)
+	{			
+		pvhtpriv->vht_mcs_map[0] = 0xfc;	// support 1SS MCS 0~7
+	}
+	else if(pregistrypriv->vht_rate_sel == 2)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xfd;	// Support 1SS MCS 0~8
+	}
+	else if(pregistrypriv->vht_rate_sel == 3)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xfe;	// Support 1SS MCS 0~9
+	}
+	else if(pregistrypriv->vht_rate_sel == 4)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xf0;	// support 1SS MCS 0~7 2SS MCS 0~7
+	}
+	else if(pregistrypriv->vht_rate_sel == 5)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xf5;	// support 1SS MCS 0~8 2SS MCS 0~8
+	}
+	else if(pregistrypriv->vht_rate_sel == 6)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xfa;	// support 1SS MCS 0~9 2SS MCS 0~9
+	}
+	else if(pregistrypriv->vht_rate_sel == 7)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xf8;	// support 1SS MCS 0-7 2SS MCS 0~9
+	}
+	else if(pregistrypriv->vht_rate_sel == 8)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xf9;	// support 1SS MCS 0-8 2SS MCS 0~9
+	}
+	else if(pregistrypriv->vht_rate_sel == 9)
+	{
+		pvhtpriv->vht_mcs_map[0] = 0xf4;	// support 1SS MCS 0-7 2SS MCS 0~8
+	}
+
+	pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
+}
+
+u64	rtw_vht_rate_to_bitmap(u8 *pVHTRate)
+{
+
+	u8	i,j , tmpRate;
+	u64	RateBitmap = 0;
+	u8 Bits_3ss = 6;
+		
+	for(i = j= 0; i < Bits_3ss; i+=2, j+=10)
+	{
+		/* every two bits means single sptial stream */
+		tmpRate = (pVHTRate[0] >> i) & 3;
+
+		switch(tmpRate){
+		case 2:
+			RateBitmap = RateBitmap | (0x03ff << j);
+			break;
+		case 1:
+			RateBitmap = RateBitmap | (0x01ff << j);
+		break;
+
+		case 0:
+			RateBitmap = RateBitmap | (0x00ff << j);
+		break;
+
+		default:
+			break;
+		}
+	}
+	DBG_871X("RateBitmap=%016llx , pVHTRate[0]=%02x, pVHTRate[1]=%02x\n", RateBitmap, pVHTRate[0], pVHTRate[1]);
+	return RateBitmap;
+}
+
+void	update_sta_vht_info_apmode(_adapter *padapter, PVOID sta)
+{
+	struct sta_info	*psta = (struct sta_info *)sta;
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct vht_priv	*pvhtpriv_ap = &pmlmepriv->vhtpriv;
+	struct vht_priv	*pvhtpriv_sta = &psta->vhtpriv;
+	struct ht_priv		*phtpriv_sta = &psta->htpriv;
+	u8	cur_ldpc_cap = 0, cur_stbc_cap = 0, bw_mode = 0;
+	u16	cur_beamform_cap = 0;
+	u8	*pcap_mcs;
+
+	if (pvhtpriv_sta->vht_option == _FALSE) {
+		return;
+	}
+
+	bw_mode = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&pvhtpriv_sta->vht_op_mode_notify);
+	
+	//if (bw_mode > psta->bw_mode)
+	psta->bw_mode = bw_mode;
+
+	// B4 Rx LDPC
+	if (TEST_FLAG(pvhtpriv_ap->ldpc_cap, LDPC_VHT_ENABLE_TX) && 
+		GET_VHT_CAPABILITY_ELE_RX_LDPC(pvhtpriv_sta->vht_cap))
+	{
+		SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
+		DBG_871X("Current STA(%d) VHT LDPC = %02X\n", psta->aid, cur_ldpc_cap);
+	}
+	pvhtpriv_sta->ldpc_cap = cur_ldpc_cap;
+
+	if (psta->bw_mode > pmlmeext->cur_bwmode)
+		psta->bw_mode = pmlmeext->cur_bwmode;
+
+	if (psta->bw_mode == CHANNEL_WIDTH_80) {
+		// B5 Short GI for 80 MHz
+		pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
+		//DBG_871X("Current STA ShortGI80MHz = %d\n", pvhtpriv_sta->sgi_80m);
+	} else if (psta->bw_mode >= CHANNEL_WIDTH_160) {
+		// B5 Short GI for 80 MHz
+		pvhtpriv_sta->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI160M(pvhtpriv_sta->vht_cap) & pvhtpriv_ap->sgi_80m) ? _TRUE : _FALSE;
+		//DBG_871X("Current STA ShortGI160MHz = %d\n", pvhtpriv_sta->sgi_80m);
+	}
+
+	// B8 B9 B10 Rx STBC
+	if (TEST_FLAG(pvhtpriv_ap->stbc_cap, STBC_VHT_ENABLE_TX) && 
+		GET_VHT_CAPABILITY_ELE_RX_STBC(pvhtpriv_sta->vht_cap))
+	{
+		SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));	
+		DBG_871X("Current STA(%d) VHT STBC = %02X\n", psta->aid, cur_stbc_cap);
+	}
+	pvhtpriv_sta->stbc_cap = cur_stbc_cap;
+
+#ifdef CONFIG_BEAMFORMING
+	// B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee
+	if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) && 
+		GET_VHT_CAPABILITY_ELE_SU_BFEE(pvhtpriv_sta->vht_cap))
+	{
+		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
+		/*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
+		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pvhtpriv_sta->vht_cap)<<8);
+	}
+
+	// B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer
+	if (TEST_FLAG(pvhtpriv_ap->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
+		GET_VHT_CAPABILITY_ELE_SU_BFER(pvhtpriv_sta->vht_cap))
+	{
+		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+		/*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
+		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pvhtpriv_sta->vht_cap)<<12);
+	}
+	pvhtpriv_sta->beamform_cap = cur_beamform_cap;
+	if (cur_beamform_cap) {
+		DBG_871X("Current STA(%d) VHT Beamforming Setting = %02X\n", psta->aid, cur_beamform_cap);
+	}
+ #endif
+
+	// B23 B24 B25 Maximum A-MPDU Length Exponent
+	pvhtpriv_sta->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pvhtpriv_sta->vht_cap);
+
+	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pvhtpriv_sta->vht_cap);
+	_rtw_memcpy(pvhtpriv_sta->vht_mcs_map, pcap_mcs, 2);
+
+	pvhtpriv_sta->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv_sta->vht_mcs_map);
+
+}
+
+void	update_hw_vht_param(_adapter *padapter)
+{
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	ht_AMPDU_len;
+
+	ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
+
+	if(pvhtpriv->ampdu_len > ht_AMPDU_len)
+		rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
+}
+
+void VHT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	cur_ldpc_cap = 0, cur_stbc_cap = 0, rf_type = RF_1T1R;
+	u16	cur_beamform_cap = 0;
+	u8	*pcap_mcs;
+	u8	vht_mcs[2];
+
+	if(pIE==NULL) return;
+
+	if(pvhtpriv->vht_option == _FALSE)	return;
+
+	pmlmeinfo->VHT_enable = 1;
+
+	// B4 Rx LDPC
+	if (TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_TX) && 
+		GET_VHT_CAPABILITY_ELE_RX_LDPC(pIE->data))
+	{
+		SET_FLAG(cur_ldpc_cap, (LDPC_VHT_ENABLE_TX | LDPC_VHT_CAP_TX));
+		DBG_871X("Current VHT LDPC Setting = %02X\n", cur_ldpc_cap);
+	}
+	pvhtpriv->ldpc_cap = cur_ldpc_cap;
+
+	// B5 Short GI for 80 MHz
+	pvhtpriv->sgi_80m = (GET_VHT_CAPABILITY_ELE_SHORT_GI80M(pIE->data) & pvhtpriv->sgi_80m) ? _TRUE : _FALSE;
+	//DBG_871X("Current ShortGI80MHz = %d\n", pvhtpriv->sgi_80m);
+
+	// B8 B9 B10 Rx STBC
+	if (TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX) && 
+		GET_VHT_CAPABILITY_ELE_RX_STBC(pIE->data))
+	{
+		SET_FLAG(cur_stbc_cap, (STBC_VHT_ENABLE_TX | STBC_VHT_CAP_TX));	
+		DBG_871X("Current VHT STBC Setting = %02X\n", cur_stbc_cap);
+	}
+	pvhtpriv->stbc_cap = cur_stbc_cap;
+#ifdef CONFIG_BEAMFORMING
+	// B11 SU Beamformer Capable, the target supports Beamformer and we are Beamformee
+	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE) && 
+		GET_VHT_CAPABILITY_ELE_SU_BFEE(pIE->data))
+	{
+		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE);
+		/*Shift to BEAMFORMING_VHT_BEAMFORMER_STS_CAP*/
+		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFEE_STS_CAP(pIE->data)<<8);
+	}
+
+	// B12 SU Beamformee Capable, the target supports Beamformee and we are Beamformer
+	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE) &&
+		GET_VHT_CAPABILITY_ELE_SU_BFER(pIE->data))
+	{
+		SET_FLAG(cur_beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE);
+		/*Shit to BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM*/
+		SET_FLAG(cur_beamform_cap, GET_VHT_CAPABILITY_ELE_SU_BFER_SOUND_DIM_NUM(pIE->data)<<12);
+		
+	}
+	pvhtpriv->beamform_cap = cur_beamform_cap;
+	if (cur_beamform_cap) {
+		DBG_871X("Current VHT Beamforming Setting = %02X\n", cur_beamform_cap);
+	}
+ #endif
+	// B23 B24 B25 Maximum A-MPDU Length Exponent
+	pvhtpriv->ampdu_len = GET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pIE->data);
+
+	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pIE->data);
+	_rtw_memcpy(vht_mcs, pcap_mcs, 2);
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	if ((rf_type == RF_1T1R) || (rf_type == RF_1T2R))
+		vht_mcs[0] |= 0xfc;
+	else if (rf_type == RF_2T2R)
+		vht_mcs[0] |= 0xf0;
+	else if (rf_type == RF_3T3R)
+		vht_mcs[0] |= 0xc0;
+
+	_rtw_memcpy(pvhtpriv->vht_mcs_map, vht_mcs, 2);
+
+	pvhtpriv->vht_highest_rate = rtw_get_vht_highest_rate(pvhtpriv->vht_mcs_map);
+}
+
+void VHT_operation_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+
+	if(pIE==NULL) return;
+
+	if(pvhtpriv->vht_option == _FALSE)	return;
+}
+
+void rtw_process_vht_op_mode_notify(_adapter *padapter, u8 *pframe, PVOID sta)
+{
+	struct sta_info		*psta = (struct sta_info *)sta;
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct registry_priv *regsty = adapter_to_regsty(padapter);
+	u8	target_bw;
+	u8	target_rxss, current_rxss;
+	u8	update_ra = _FALSE;
+	u8	vht_mcs_map[2] = {};
+
+	if(pvhtpriv->vht_option == _FALSE)
+		return;
+
+	target_bw = GET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(pframe);
+	target_rxss = (GET_VHT_OPERATING_MODE_FIELD_RX_NSS(pframe)+1);
+
+	if (target_bw != psta->bw_mode) {
+		if (hal_is_bw_support(padapter, target_bw)
+			&& REGSTY_IS_BW_5G_SUPPORT(regsty, target_bw)
+		) {
+			update_ra = _TRUE;
+			psta->bw_mode = target_bw;
+		}
+	}
+
+	current_rxss = rtw_vht_mcsmap_to_nss(psta->vhtpriv.vht_mcs_map);
+	if (target_rxss != current_rxss) {
+		update_ra = _TRUE;
+
+		rtw_vht_nss_to_mcsmap(target_rxss, vht_mcs_map, psta->vhtpriv.vht_mcs_map);
+		_rtw_memcpy(psta->vhtpriv.vht_mcs_map, vht_mcs_map, 2);
+		
+		rtw_hal_update_sta_rate_mask(padapter, psta);
+	}
+
+	if (update_ra) {
+		rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
+	}
+}
+
+u32	rtw_build_vht_operation_ie(_adapter *padapter, u8 *pbuf, u8 channel)
+{
+	struct registry_priv	*pregistrypriv = &padapter->registrypriv;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+	//struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	u8	ChnlWidth, center_freq, bw_mode, rf_type = 0;
+	u32	len = 0;
+	u8	operation[5];
+	
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	
+	_rtw_memset(operation, 0, 5);
+
+	bw_mode = REGSTY_BW_5G(pregistrypriv); /* TODO: control op bw with other info */
+
+	if (hal_chk_bw_cap(padapter, BW_CAP_80M | BW_CAP_160M)
+		&& REGSTY_BW_5G(pregistrypriv) >= CHANNEL_WIDTH_80
+	) {
+		center_freq = rtw_get_center_ch(channel, bw_mode, HAL_PRIME_CHNL_OFFSET_LOWER);
+		ChnlWidth = 1;
+	} else {
+		center_freq = 0;
+		ChnlWidth = 0;
+	}
+
+	
+	SET_VHT_OPERATION_ELE_CHL_WIDTH(operation, ChnlWidth);
+	//center frequency
+	SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ1(operation, center_freq);//Todo: need to set correct center channel
+	SET_VHT_OPERATION_ELE_CHL_CENTER_FREQ2(operation,0);
+	
+	if (padapter->registrypriv.rf_config != RF_MAX_TYPE)
+		rf_type = padapter->registrypriv.rf_config;
+	
+	switch (rf_type) {
+	case RF_1T1R:
+	operation[3] = 0xfe;
+	operation[4] = 0xff;
+	break;
+	case RF_1T2R:
+	case RF_2T2R:
+	case RF_2T2R_GREEN:
+	operation[3] = 0xfa;
+	operation[4] = 0xff;
+	break;
+	case RF_2T3R:
+	case RF_2T4R:
+	case RF_3T3R:
+	case RF_3T4R:
+	operation[3] = 0xea;
+	operation[4] = 0xff;
+	break;
+	case RF_4T4R:
+	operation[3] = 0xaa;
+	operation[4] = 0xff;
+	break;
+	default:
+	DBG_871X("%s, %d, unknown rf type\n", __func__, __LINE__);
+	}
+
+	rtw_set_ie(pbuf, EID_VHTOperation, 5, operation, &len);
+
+	return len;
+}
+
+u32	rtw_build_vht_op_mode_notify_ie(_adapter *padapter, u8 *pbuf, u8 bw)
+{
+	//struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv	*pvhtpriv = &pmlmepriv->vhtpriv;
+	u32	len = 0;
+	u8	opmode = 0, rf_type = 0;
+	u8	chnl_width, rx_nss;
+
+	chnl_width = bw;
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	if(rf_type == RF_3T3R)
+		rx_nss = 3;
+	else if(rf_type == RF_2T2R)
+		rx_nss = 2;
+	else
+		rx_nss = 1;
+
+	SET_VHT_OPERATING_MODE_FIELD_CHNL_WIDTH(&opmode, chnl_width);
+	SET_VHT_OPERATING_MODE_FIELD_RX_NSS(&opmode, (rx_nss-1));
+	SET_VHT_OPERATING_MODE_FIELD_RX_NSS_TYPE(&opmode, 0); //Todo
+
+	pvhtpriv->vht_op_mode_notify = opmode;
+
+	pbuf = rtw_set_ie(pbuf, EID_OpModeNotification, 1, &opmode, &len);
+
+	return len;
+}
+
+u32	rtw_build_vht_cap_ie(_adapter *padapter, u8 *pbuf)
+{
+	u8	bw, rf_type, rf_num;
+	u16	HighestRate;
+	u8	*pcap, *pcap_mcs;
+	u32	len = 0;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv	*pvhtpriv = &pmlmepriv->vhtpriv;
+
+	pcap = pvhtpriv->vht_cap;
+	_rtw_memset(pcap, 0, 32);
+	
+	/* B0 B1 Maximum MPDU Length */
+	SET_VHT_CAPABILITY_ELE_MAX_MPDU_LENGTH(pcap, 2); 
+	
+	/* B2 B3 Supported Channel Width Set */
+	if (hal_chk_bw_cap(padapter, BW_CAP_160M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_160)) {
+		if (hal_chk_bw_cap(padapter, BW_CAP_80_80M) && REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_80_80))
+			SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 2);
+		else
+			SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 1);
+	} else {
+		SET_VHT_CAPABILITY_ELE_CHL_WIDTH(pcap, 0);
+	}
+
+	// B4 Rx LDPC
+	if(TEST_FLAG(pvhtpriv->ldpc_cap, LDPC_VHT_ENABLE_RX))
+	{
+		SET_VHT_CAPABILITY_ELE_RX_LDPC(pcap, 1);
+	}
+
+	// B5 ShortGI for 80MHz
+	SET_VHT_CAPABILITY_ELE_SHORT_GI80M(pcap, pvhtpriv->sgi_80m? 1 : 0); // We can receive Short GI of 80M
+
+	// B6 ShortGI for 160MHz
+	//SET_VHT_CAPABILITY_ELE_SHORT_GI160M(pcap, pvhtpriv->sgi_80m? 1 : 0);
+
+	// B7 Tx STBC
+	if(TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_TX))
+	{
+		SET_VHT_CAPABILITY_ELE_TX_STBC(pcap, 1);
+	}
+
+	// B8 B9 B10 Rx STBC
+	if(TEST_FLAG(pvhtpriv->stbc_cap, STBC_VHT_ENABLE_RX))
+	{
+		rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+		if ((rf_type == RF_2T2R) || (rf_type == RF_1T2R)) 
+			rf_num = 1;		
+		else if (rf_type == RF_1T1R) 
+			rf_num = 1;		
+		
+		SET_VHT_CAPABILITY_ELE_RX_STBC(pcap, rf_num);
+	}
+
+	// B11 SU Beamformer Capable
+	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMER_ENABLE)) {		
+		SET_VHT_CAPABILITY_ELE_SU_BFER(pcap, 1);
+		// B16 17 18 Number of Sounding Dimensions
+		rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMER_CAP, (u8 *)&rf_num);
+		SET_VHT_CAPABILITY_ELE_SOUNDING_DIMENSIONS(pcap, rf_num);
+	}
+
+	// B12 SU Beamformee Capable
+	if (TEST_FLAG(pvhtpriv->beamform_cap, BEAMFORMING_VHT_BEAMFORMEE_ENABLE)) {
+		SET_VHT_CAPABILITY_ELE_SU_BFEE(pcap, 1);
+		// B13 14 15 Compressed Steering Number of Beamformer Antennas Supported
+		rtw_hal_get_def_var(padapter, HAL_DEF_BEAMFORMEE_CAP, (u8 *)&rf_num);
+		SET_VHT_CAPABILITY_ELE_BFER_ANT_SUPP(pcap, rf_num);
+	}
+
+	// B19 MU Beamformer Capable
+	SET_VHT_CAPABILITY_ELE_MU_BFER(pcap, 0);  //HW don't support mu bfee/bfer
+	// B20 MU Beamformee Capable
+	SET_VHT_CAPABILITY_ELE_MU_BFEE(pcap, 0);
+	// B21 VHT TXOP PS
+	SET_VHT_CAPABILITY_ELE_TXOP_PS(pcap, 0);
+	// B22 +HTC-VHT Capable
+	SET_VHT_CAPABILITY_ELE_HTC_VHT(pcap, 1);
+	// B23 24 25 Maximum A-MPDU Length Exponent
+	if (pregistrypriv->ampdu_factor != 0xFE)
+	{
+		SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, pregistrypriv->ampdu_factor);
+	}
+	else
+	{
+		SET_VHT_CAPABILITY_ELE_MAX_RXAMPDU_FACTOR(pcap, 7);
+	}
+	// B26 27 VHT Link Adaptation Capable
+	SET_VHT_CAPABILITY_ELE_LINK_ADAPTION(pcap, 0);
+
+	pcap_mcs = GET_VHT_CAPABILITY_ELE_RX_MCS(pcap);
+	_rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
+
+	pcap_mcs = GET_VHT_CAPABILITY_ELE_TX_MCS(pcap);
+	_rtw_memcpy(pcap_mcs, pvhtpriv->vht_mcs_map, 2);
+
+	/* find the largest bw supported by both registry and hal */
+	bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
+
+	HighestRate = VHT_MCS_DATA_RATE[bw][pvhtpriv->sgi_80m][((pvhtpriv->vht_highest_rate - MGN_VHT1SS_MCS0)&0x3f)];
+	HighestRate = (HighestRate+1) >> 1;
+
+	SET_VHT_CAPABILITY_ELE_MCS_RX_HIGHEST_RATE(pcap, HighestRate); //indicate we support highest rx rate is 600Mbps.
+	SET_VHT_CAPABILITY_ELE_MCS_TX_HIGHEST_RATE(pcap, HighestRate); //indicate we support highest tx rate is 600Mbps.
+
+	pbuf = rtw_set_ie(pbuf, EID_VHTCapability, 12, pcap, &len);
+
+	return len;
+}
+
+u32 rtw_restructure_vht_ie(_adapter *padapter, u8 *in_ie, u8 *out_ie, uint in_len, uint *pout_len)
+{
+	u32	ielen=0, out_len=0;
+	u8	cap_len=0, notify_len=0, notify_bw=0, operation_bw=0, supported_chnl_width=0;
+	u8	*p, *pframe;
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv	*pvhtpriv = &pmlmepriv->vhtpriv;
+
+	rtw_vht_use_default_setting(padapter);
+
+	p = rtw_get_ie(in_ie+12, EID_VHTCapability, &ielen, in_len-12);
+	if (p && ielen>0) {
+		supported_chnl_width = GET_VHT_CAPABILITY_ELE_CHL_WIDTH(p+2);
+		
+		// VHT Capabilities element
+		cap_len = rtw_build_vht_cap_ie(padapter, out_ie+*pout_len);
+		*pout_len += cap_len;
+
+		// Get HT BW
+		p = rtw_get_ie(in_ie+12, _HT_EXTRA_INFO_IE_, &ielen, in_len-12);
+		if (p && ielen>0) {
+			struct HT_info_element *pht_info = (struct HT_info_element *)(p+2);
+			if (pht_info->infos[0] & BIT(2))
+				operation_bw = CHANNEL_WIDTH_40;
+			else
+				operation_bw = CHANNEL_WIDTH_20;
+		}
+
+		// VHT Operation element
+		p = rtw_get_ie(in_ie+12, EID_VHTOperation, &ielen, in_len-12);
+		if (p && ielen>0) {
+			out_len = *pout_len;
+			if (GET_VHT_OPERATION_ELE_CHL_WIDTH(p+2) >= 1) {
+				if (supported_chnl_width == 2)
+					operation_bw = CHANNEL_WIDTH_80_80;
+				else if (supported_chnl_width == 1)
+					operation_bw = CHANNEL_WIDTH_160;
+				else
+					operation_bw = CHANNEL_WIDTH_80;
+			}
+			pframe = rtw_set_ie(out_ie+out_len, EID_VHTOperation, ielen, p+2 , pout_len);
+		}
+
+		/* find the largest bw supported by both registry and hal */
+		notify_bw = hal_largest_bw(padapter, REGSTY_BW_5G(pregistrypriv));
+
+		if (notify_bw > operation_bw)
+			notify_bw = operation_bw;
+
+		// Operating Mode Notification element
+		notify_len = rtw_build_vht_op_mode_notify_ie(padapter, out_ie+*pout_len, notify_bw);
+		*pout_len += notify_len;
+
+		pvhtpriv->vht_option = _TRUE;
+	}
+	
+	return (pvhtpriv->vht_option);
+	
+}
+
+void VHTOnAssocRsp(_adapter *padapter)
+{
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct vht_priv		*pvhtpriv = &pmlmepriv->vhtpriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8	ht_AMPDU_len;
+	
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if (!pmlmeinfo->HT_enable)
+		return;
+
+	if (!pmlmeinfo->VHT_enable)
+		return;
+
+	ht_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;
+
+	if(pvhtpriv->ampdu_len > ht_AMPDU_len)
+		rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&pvhtpriv->ampdu_len));
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MAX_TIME, (u8 *)(&pvhtpriv->vht_highest_rate));
+}
+
+#endif //CONFIG_80211AC_VHT
+
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi.c
new file mode 100644
index 000000000..cf4a995f8
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi.c
@@ -0,0 +1,1326 @@
+#ifdef CONFIG_WAPI_SUPPORT
+
+#include <linux/unistd.h>
+#include <linux/etherdevice.h>
+#include <drv_types.h>
+#include <rtw_wapi.h>
+
+
+u32 wapi_debug_component =
+//				WAPI_INIT	|
+//				WAPI_API    	|
+//				WAPI_TX    	|
+//				WAPI_RX    	|
+				WAPI_ERR ; //always open err flags on
+
+void WapiFreeAllStaInfo(_adapter *padapter)
+{
+	PRT_WAPI_T				pWapiInfo;
+	PRT_WAPI_STA_INFO		pWapiStaInfo;
+	PRT_WAPI_BKID			pWapiBkid;
+
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	pWapiInfo = &padapter->wapiInfo;
+
+	//Pust to Idle List
+	rtw_wapi_return_all_sta_info(padapter);
+
+	//Sta Info List
+	while(!list_empty(&(pWapiInfo->wapiSTAIdleList)))
+	{
+		pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+		list_del_init(&pWapiStaInfo->list);
+	}
+
+	//BKID List
+	while(!list_empty(&(pWapiInfo->wapiBKIDIdleList)))
+	{
+		pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+		list_del_init(&pWapiBkid->list);
+	}
+	WAPI_TRACE(WAPI_INIT, "<=========== %s\n", __FUNCTION__);
+	return;
+}
+
+void WapiSetIE(_adapter *padapter)
+{
+	PRT_WAPI_T		pWapiInfo = &(padapter->wapiInfo);
+	//PRT_WAPI_BKID	pWapiBkid;
+	u16		protocolVer = 1;
+	u16		akmCnt = 1;
+	u16		suiteCnt = 1;
+	u16		capability = 0;
+	u8		OUI[3];
+
+	OUI[0] = 0x00;
+	OUI[1] = 0x14;
+	OUI[2] = 0x72;
+
+	pWapiInfo->wapiIELength = 0;
+//protocol version
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &protocolVer, 2);
+	pWapiInfo->wapiIELength +=2;
+//akm
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &akmCnt, 2);
+	pWapiInfo->wapiIELength +=2;
+
+	if(pWapiInfo->bWapiPSK){
+		memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+		pWapiInfo->wapiIELength +=3;
+		pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x2;
+		pWapiInfo->wapiIELength +=1;
+	}else{
+		memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+		pWapiInfo->wapiIELength +=3;
+		pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+		pWapiInfo->wapiIELength +=1;
+	}
+
+//usk
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &suiteCnt, 2);
+	pWapiInfo->wapiIELength +=2;
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+	pWapiInfo->wapiIELength +=3;
+	pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+	pWapiInfo->wapiIELength +=1;
+
+//msk
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength,OUI, 3);
+	pWapiInfo->wapiIELength +=3;
+	pWapiInfo->wapiIE[pWapiInfo->wapiIELength] = 0x1;
+	pWapiInfo->wapiIELength +=1;
+
+//Capbility
+	memcpy(pWapiInfo->wapiIE+pWapiInfo->wapiIELength, &capability, 2);
+	pWapiInfo->wapiIELength +=2;
+}
+
+
+/*  PN1 > PN2, return 1,
+ *  else return 0.
+ */
+u32 WapiComparePN(u8 *PN1, u8 *PN2)
+{
+	char i;
+
+	if ((NULL == PN1) || (NULL == PN2))
+		return 1;
+
+	// overflow case
+	if ((PN2[15] - PN1[15]) & 0x80)
+		return 1;
+
+	for (i=16; i>0; i--)
+	{
+		if(PN1[i-1] == PN2[i-1])
+		    	continue;
+		else if(PN1[i-1] > PN2[i-1])
+			return 1;
+		else
+			return 0;
+	}
+
+	return 0;
+}
+
+u8
+WapiGetEntryForCamWrite(_adapter *padapter,u8 *pMacAddr,u8 KID,BOOLEAN IsMsk)
+{
+	PRT_WAPI_T		pWapiInfo=NULL;
+	//PRT_WAPI_CAM_ENTRY	pEntry=NULL;
+	u8 i=0;
+	u8 ret = 0xff;
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	pWapiInfo =  &padapter->wapiInfo;
+
+	//exist?
+	for(i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+	{
+		if(pWapiInfo->wapiCamEntry[i].IsUsed
+			&& (_rtw_memcmp(pMacAddr, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN) == _TRUE)
+			&& pWapiInfo->wapiCamEntry[i].keyidx == KID
+			&& pWapiInfo->wapiCamEntry[i].type == IsMsk)
+		{
+			ret = pWapiInfo->wapiCamEntry[i].entry_idx; //cover it
+			break;
+		}
+	}
+
+	if(i == WAPI_CAM_ENTRY_NUM) //not found
+	{
+		for(i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+		{
+			if(pWapiInfo->wapiCamEntry[i].IsUsed == 0)
+			{
+				pWapiInfo->wapiCamEntry[i].IsUsed = 1;
+				pWapiInfo->wapiCamEntry[i].type = IsMsk;
+				pWapiInfo->wapiCamEntry[i].keyidx = KID;
+				_rtw_memcpy(pWapiInfo->wapiCamEntry[i].PeerMacAddr, pMacAddr,ETH_ALEN);
+				ret = pWapiInfo->wapiCamEntry[i].entry_idx;
+				break;
+			}
+		}
+	}
+
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+	return ret;
+
+/*
+	if(RTIsListEmpty(&pWapiInfo->wapiCamIdleList)){
+		RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n"));
+		return 0;
+	}
+
+	pEntry = (PRT_WAPI_CAM_ENTRY)RTRemoveHeadList(&pWapiInfo->wapiCamIdleList);
+	RTInsertTailList(&pWapiInfo->wapiCamUsedList, &pEntry->list);
+
+	RT_TRACE(COMP_SEC,DBG_LOUD,("<====WapiGetCamEntry(),Get Entry Idx:%d.but we just return 4 for test\n",pEntry->entry_idx));
+
+	return pEntry->entry_idx;*/
+}
+
+u8 WapiGetEntryForCamClear(_adapter *padapter,u8 *pPeerMac,u8 keyid,u8 IsMsk)
+{
+	PRT_WAPI_T		pWapiInfo=NULL;
+	u8		i=0;
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	pWapiInfo =  &padapter->wapiInfo;
+
+	for(i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+	{
+		if(pWapiInfo->wapiCamEntry[i].IsUsed
+			&& (_rtw_memcmp(pPeerMac, pWapiInfo->wapiCamEntry[i].PeerMacAddr, ETH_ALEN) == _TRUE)
+			&& pWapiInfo->wapiCamEntry[i].keyidx == keyid
+			&& pWapiInfo->wapiCamEntry[i].type == IsMsk)
+		{
+				pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+				pWapiInfo->wapiCamEntry[i].keyidx = 2;
+				_rtw_memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr,0,ETH_ALEN);
+
+				WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+				return pWapiInfo->wapiCamEntry[i].entry_idx;
+		}
+	}
+
+	WAPI_TRACE(WAPI_API,"<====WapiGetReturnCamEntry(), No this cam entry.\n");
+	return 0xff;
+/*
+	if(RTIsListEmpty(&pWapiInfo->wapiCamUsedList)){
+		RT_TRACE(COMP_SEC,DBG_LOUD,("No Entry for wapi!!!\n"));
+		return FALSE;
+	}
+
+	pList = &pWapiInfo->wapiCamUsedList;
+	while(pList->Flink != &pWapiInfo->wapiCamUsedList)
+	{
+		pEntry = (PRT_WAPI_CAM_ENTRY)pList->Flink;
+		if(PlatformCompareMemory(pPeerMac,pEntry->PeerMacAddr, ETHER_ADDRLEN)== 0
+			&& keyid == pEntry->keyidx)
+		{
+			RTRemoveEntryList(pList);
+			RTInsertHeadList(&pWapiInfo->wapiCamIdleList, pList);
+			return pEntry->entry_idx;
+		}
+		pList = pList->Flink;
+	}
+
+	return 0;
+*/
+}
+
+void
+WapiResetAllCamEntry(_adapter *padapter)
+{
+	PRT_WAPI_T		pWapiInfo;
+	int				i;
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	pWapiInfo =  &padapter->wapiInfo;
+
+	for (i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+	{
+		_rtw_memset(pWapiInfo->wapiCamEntry[i].PeerMacAddr, 0, ETH_ALEN);
+		pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+	 	pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid
+	 	pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2;
+ 	}
+
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+
+	return;
+}
+
+u8 WapiWriteOneCamEntry(
+	_adapter 	*padapter,
+	u8 			*pMacAddr,
+	u8 			KeyId,
+	u8			EntryId,
+	u8 			EncAlg,
+	u8 			bGroupKey,
+	u8 			*pKey
+)
+{
+	u8 retVal = 0;
+	u16 usConfig = 0;
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	if(EntryId >= 32)
+	{
+		WAPI_TRACE(WAPI_ERR, "<=== CamAddOneEntry(): ulKeyId exceed!\n");
+		return retVal;
+	}
+
+	usConfig=usConfig|(0x01<<15)|((u16)(EncAlg)<<2)|(KeyId);
+
+	if(EncAlg == _SMS4_ )
+	{
+		if(bGroupKey == 1)
+			usConfig |= (0x01<<6);
+		if((EntryId % 2)==1)  // ==0 sec key; == 1mic key
+			usConfig |= (0x01<<5);
+	}
+
+	write_cam(padapter, EntryId, usConfig, pMacAddr, pKey);
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+    	return 1;
+}
+
+void rtw_wapi_init(_adapter *padapter)
+{
+	PRT_WAPI_T		pWapiInfo;
+	int				i;
+
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	RT_ASSERT_RET(padapter);
+
+	if (!padapter->WapiSupport)
+	{
+		WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+		return;
+	}
+
+	pWapiInfo =  &padapter->wapiInfo;
+	pWapiInfo->bWapiEnable = false;
+
+	//Init BKID List
+	INIT_LIST_HEAD(&pWapiInfo->wapiBKIDIdleList);
+	INIT_LIST_HEAD(&pWapiInfo->wapiBKIDStoreList);
+	for(i=0;i<WAPI_MAX_BKID_NUM;i++)
+	{
+		list_add_tail(&pWapiInfo->wapiBKID[i].list, &pWapiInfo->wapiBKIDIdleList);
+	}
+
+	//Init STA List
+	INIT_LIST_HEAD(&pWapiInfo->wapiSTAIdleList);
+	INIT_LIST_HEAD(&pWapiInfo->wapiSTAUsedList);
+	for(i=0;i<WAPI_MAX_STAINFO_NUM;i++)
+	{
+		list_add_tail(&pWapiInfo->wapiSta[i].list, &pWapiInfo->wapiSTAIdleList);
+	}
+
+	 for (i=0;i<WAPI_CAM_ENTRY_NUM;i++)
+	 {
+		pWapiInfo->wapiCamEntry[i].IsUsed = 0;
+	 	pWapiInfo->wapiCamEntry[i].keyidx = 2; //invalid
+	 	pWapiInfo->wapiCamEntry[i].entry_idx = 4+i*2;
+ 	}
+
+	WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_free(_adapter *padapter)
+{
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	RT_ASSERT_RET(padapter);
+
+	if (!padapter->WapiSupport)
+	{
+		WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+		return;
+	}
+
+	WapiFreeAllStaInfo(padapter);
+
+	WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_disable_tx(_adapter *padapter)
+{
+	WAPI_TRACE(WAPI_INIT, "===========> %s\n", __FUNCTION__);
+	RT_ASSERT_RET(padapter);
+
+	if (!padapter->WapiSupport)
+	{
+		WAPI_TRACE(WAPI_INIT, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+		return;
+	}
+
+	padapter->wapiInfo.wapiTxMsk.bTxEnable = false;
+	padapter->wapiInfo.wapiTxMsk.bSet = false;
+
+	WAPI_TRACE(WAPI_INIT, "<========== %s\n", __FUNCTION__);
+}
+
+u8 rtw_wapi_is_wai_packet(_adapter* padapter,u8 *pkt_data)
+{
+	PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+	struct mlme_priv 	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv   *psecuritypriv = &padapter->securitypriv;
+	PRT_WAPI_STA_INFO pWapiSta = NULL;
+	u8 WaiPkt = 0, *pTaddr, bFind = false;
+	u8 Offset_TypeWAI = 0 ;	// (mac header len + llc length)
+	
+	WAPI_TRACE(WAPI_TX|WAPI_RX, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return 0;
+	}
+
+	 Offset_TypeWAI = 24 + 6 ;
+
+	//YJ,add,091103. Data frame may also have skb->data[30]=0x88 and skb->data[31]=0xb4.
+	if ((pkt_data[1]&0x40) !=0)
+	{
+		//DBG_871X("data is privacy \n");
+	    	return 0;
+	}
+	
+	pTaddr = GetAddr2Ptr(pkt_data);
+	if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+		bFind = false;
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+			if (_rtw_memcmp(pTaddr, pWapiSta->PeerMacAddr, 6) == _TRUE) {
+				bFind = true;
+				break;
+			}
+		}
+	}
+
+	WAPI_TRACE(WAPI_TX|WAPI_RX, "%s: bFind=%d pTaddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(pTaddr));
+
+	if (pkt_data[0] == WIFI_QOS_DATA_TYPE)
+	{
+		Offset_TypeWAI += 2;
+	}
+
+	// 88b4?
+	if( (pkt_data[Offset_TypeWAI]==0x88) && (pkt_data[Offset_TypeWAI+1]==0xb4) ){
+		WaiPkt = pkt_data[Offset_TypeWAI+5];
+
+		psecuritypriv->hw_decrypted = _TRUE;
+	}else{
+		WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): non wai packet\n",__FUNCTION__);
+	}
+
+	WAPI_TRACE(WAPI_TX|WAPI_RX, "%s(): Recvd WAI frame. IsWAIPkt(%d)\n",__FUNCTION__, WaiPkt);
+
+	return	WaiPkt;
+}
+
+
+void rtw_wapi_update_info(_adapter *padapter, union recv_frame *precv_frame)
+{
+	PRT_WAPI_T     pWapiInfo = &(padapter->wapiInfo);
+	struct recv_frame_hdr *precv_hdr;
+	u8 	*ptr;
+	u8 	*pTA;
+	u8 	*pRecvPN;
+
+
+	WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+	precv_hdr = &precv_frame->u.hdr;
+	ptr = precv_hdr->rx_data;
+
+	if (precv_hdr->attrib.qos == 1)
+	{
+		precv_hdr->UserPriority = GetTid(ptr);
+	}
+	else
+	{
+		precv_hdr->UserPriority = 0;
+	}
+
+	pTA = GetAddr2Ptr(ptr);
+	_rtw_memcpy((u8 *)precv_hdr->WapiSrcAddr, pTA, 6);
+	pRecvPN = ptr + precv_hdr->attrib.hdrlen + 2;
+	_rtw_memcpy((u8 *)precv_hdr->WapiTempPN, pRecvPN, 16);
+
+	WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__);
+}
+
+/****************************************************************************
+TRUE-----------------Drop
+FALSE---------------- handle
+add to support WAPI to N-mode
+*****************************************************************************/
+u8 rtw_wapi_check_for_drop(
+	_adapter *padapter,
+	union recv_frame *precv_frame
+)
+{
+	PRT_WAPI_T     pWapiInfo = &(padapter->wapiInfo);
+	u8			*pLastRecvPN = NULL;
+	u8			bFind = false;
+	PRT_WAPI_STA_INFO	pWapiSta = NULL;
+	u8 			bDrop = false;
+	struct recv_frame_hdr *precv_hdr = &precv_frame->u.hdr;
+	u8					WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8 					WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8 					*ptr = precv_frame->u.hdr.rx_data;
+	int					i;
+
+	WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return false;
+	}
+
+	if(precv_hdr->bIsWaiPacket !=0)
+	{
+		if(precv_hdr->bIsWaiPacket== 0x8)
+		{
+
+			DBG_871X("rtw_wapi_check_for_drop: dump packet \n");
+			for(i=0;i<50;i++)
+			{
+				DBG_871X("%02X  ",ptr[i]);
+				if((i+1) %8 ==0)
+					DBG_871X("\n");
+			}
+			DBG_871X("\n rtw_wapi_check_for_drop: dump packet \n");
+
+			for(i=0;i<16;i++)
+			{
+				if(ptr[i+27] !=0)
+					break;
+			}
+
+			if(i== 16)
+			{
+				WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: drop with zero BKID \n");
+				return true;
+			}
+			else
+			{
+				return false;
+			}
+		}
+			else
+				return false;
+	}
+
+	if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+		bFind = false;
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if (_rtw_memcmp(precv_hdr->WapiSrcAddr, pWapiSta->PeerMacAddr, ETH_ALEN) == _TRUE) {
+				bFind = true;
+				break;
+			}
+		}
+	}
+	WAPI_TRACE(WAPI_RX, "%s: bFind=%d prxb->WapiSrcAddr="MAC_FMT"\n", __FUNCTION__, bFind, MAC_ARG(precv_hdr->WapiSrcAddr));
+
+	if(bFind)
+	{
+		if(IS_MCAST(precv_hdr->attrib.ra))
+		{
+			WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: multicast case \n");
+			pLastRecvPN = pWapiSta->lastRxMulticastPN;
+		}
+		else
+		{
+			WAPI_TRACE(WAPI_RX,"rtw_wapi_check_for_drop: unicast case \n");
+			switch(precv_hdr->UserPriority)
+			{
+				case 0:
+				case 3:
+					pLastRecvPN = pWapiSta->lastRxUnicastPNBEQueue;
+					break;
+				case 1:
+				case 2:
+					pLastRecvPN = pWapiSta->lastRxUnicastPNBKQueue;
+					break;
+				case 4:
+				case 5:
+					pLastRecvPN = pWapiSta->lastRxUnicastPNVIQueue;
+					break;
+				case 6:
+				case 7:
+					pLastRecvPN = pWapiSta->lastRxUnicastPNVOQueue;
+					break;
+				default:
+					WAPI_TRACE(WAPI_ERR,"%s: Unknown TID \n",__FUNCTION__);
+					break;
+			}
+		}
+
+		if(!WapiComparePN(precv_hdr->WapiTempPN,pLastRecvPN))
+		{
+			WAPI_TRACE(WAPI_RX,"%s: Equal PN!!\n",__FUNCTION__);
+			if(IS_MCAST(precv_hdr->attrib.ra))
+				_rtw_memcpy(pLastRecvPN,WapiAEMultiCastPNInitialValueSrc,16);
+			else
+				_rtw_memcpy(pLastRecvPN,WapiAEPNInitialValueSrc,16);
+			bDrop = true;
+		}
+		else
+		{
+			_rtw_memcpy(pLastRecvPN,precv_hdr->WapiTempPN,16);
+		}
+	}
+
+	WAPI_TRACE(WAPI_RX, "<========== %s\n", __FUNCTION__);
+	return bDrop;
+}
+
+void rtw_build_probe_resp_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+{
+	PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+	u8 WapiIELength = 0;
+
+	WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport)  || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+		return;
+	}
+
+	WapiSetIE(padapter);
+	WapiIELength = pWapiInfo->wapiIELength;
+	pframe[0] = _WAPI_IE_;
+	pframe[1] = WapiIELength;
+	_rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+	pframe += WapiIELength+2;
+	pattrib->pktlen += WapiIELength+2;
+
+	WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_build_beacon_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+{
+	PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+	u8 WapiIELength = 0;
+	WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport)  || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+		return;
+	}
+
+	WapiSetIE(padapter);
+	WapiIELength = pWapiInfo->wapiIELength;
+	pframe[0] = _WAPI_IE_;
+	pframe[1] = WapiIELength;
+	_rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+	pframe += WapiIELength+2;
+	pattrib->pktlen += WapiIELength+2;
+
+	WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_build_assoc_req_wapi_ie(_adapter *padapter, unsigned char *pframe, struct pkt_attrib *pattrib)
+{
+	PRT_WAPI_BKID		pWapiBKID;
+	u16					bkidNum;
+	PRT_WAPI_T			pWapiInfo = &(padapter->wapiInfo);
+	u8					WapiIELength = 0;
+
+	WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported!\n", __FUNCTION__);
+		return;
+	}
+
+	WapiSetIE(padapter);
+	WapiIELength = pWapiInfo->wapiIELength;
+	bkidNum = 0;
+	if(!list_empty(&(pWapiInfo->wapiBKIDStoreList))){
+		list_for_each_entry(pWapiBKID, &pWapiInfo->wapiBKIDStoreList, list) {
+			bkidNum ++;
+			_rtw_memcpy(pWapiInfo->wapiIE+WapiIELength+2, pWapiBKID->bkid,16);
+			WapiIELength += 16;
+		}
+	}
+	_rtw_memcpy(pWapiInfo->wapiIE+WapiIELength, &bkidNum, 2);
+	WapiIELength += 2;
+
+	 pframe[0] = _WAPI_IE_;
+	 pframe[1] = WapiIELength;
+	_rtw_memcpy(pframe+2, pWapiInfo->wapiIE, WapiIELength);
+	pframe += WapiIELength+2;
+	pattrib->pktlen += WapiIELength+2;
+	WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_on_assoc_ok(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+	PRT_WAPI_T pWapiInfo = &(padapter->wapiInfo);
+	PRT_WAPI_STA_INFO pWapiSta;
+	u8 WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	//u8 WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8 WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+
+	WAPI_TRACE(WAPI_MLME, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+	pWapiSta =(PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAIdleList.next, RT_WAPI_STA_INFO, list);
+	list_del_init(&pWapiSta->list);
+	list_add_tail(&pWapiSta->list, &pWapiInfo->wapiSTAUsedList);
+	_rtw_memcpy(pWapiSta->PeerMacAddr,padapter->mlmeextpriv.mlmext_info.network.MacAddress,6);
+	_rtw_memcpy(pWapiSta->lastRxMulticastPN, WapiAEMultiCastPNInitialValueSrc, 16);
+	_rtw_memcpy(pWapiSta->lastRxUnicastPN, WapiAEPNInitialValueSrc, 16);
+
+	//For chenk PN error with Qos Data after s3: add by ylb 20111114
+	_rtw_memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiAEPNInitialValueSrc,16);
+	_rtw_memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiAEPNInitialValueSrc,16);
+	_rtw_memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiAEPNInitialValueSrc,16);
+	_rtw_memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiAEPNInitialValueSrc,16);
+
+	WAPI_TRACE(WAPI_MLME, "<========== %s\n", __FUNCTION__);
+}
+
+
+void rtw_wapi_return_one_sta_info(_adapter *padapter, u8 *MacAddr)
+{
+	PRT_WAPI_T				pWapiInfo;
+	PRT_WAPI_STA_INFO		pWapiStaInfo = NULL;
+	PRT_WAPI_BKID			pWapiBkid = NULL;
+	struct mlme_priv 	*pmlmepriv = &padapter->mlmepriv;
+
+	pWapiInfo = &padapter->wapiInfo;
+
+	WAPI_TRACE(WAPI_API, "==========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+       if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+       {
+             while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+                 {
+                        pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+                           list_del_init(&pWapiBkid->list);
+                           _rtw_memset(pWapiBkid->bkid,0,16);
+                        list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+                 }
+        }
+
+
+	WAPI_TRACE(WAPI_API, " %s: after clear bkid \n", __FUNCTION__);
+
+
+	//Remove STA info
+	if(list_empty(&(pWapiInfo->wapiSTAUsedList))){
+		WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is null \n", __FUNCTION__);
+		return;
+	}else{
+
+		WAPI_TRACE(WAPI_API, " %s: wapiSTAUsedList is not null \n", __FUNCTION__);
+#if 0
+		pWapiStaInfo=(PRT_WAPI_STA_INFO)list_entry((pWapiInfo->wapiSTAUsedList.next),RT_WAPI_STA_INFO,list);
+
+		list_for_each_entry(pWapiStaInfo, &(pWapiInfo->wapiSTAUsedList), list) {
+
+			DBG_871X("MAC Addr %02x-%02x-%02x-%02x-%02x-%02x \n",MacAddr[0],MacAddr[1],MacAddr[2],MacAddr[3],MacAddr[4],MacAddr[5]);
+
+
+			DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]);
+
+			if(pWapiStaInfo == NULL)
+			{
+				WAPI_TRACE(WAPI_API, " %s: pWapiStaInfo == NULL Case \n", __FUNCTION__);
+				return;
+			}
+
+			if(pWapiStaInfo->PeerMacAddr == NULL)
+			{
+				WAPI_TRACE(WAPI_API, " %s: pWapiStaInfo->PeerMacAddr == NULL Case \n", __FUNCTION__);
+				return;
+			}
+
+			if(MacAddr == NULL)
+			{
+				WAPI_TRACE(WAPI_API, " %s: MacAddr == NULL Case \n", __FUNCTION__);
+				return;
+			}
+
+			if (_rtw_memcmp(pWapiStaInfo->PeerMacAddr, MacAddr, ETH_ALEN) == _TRUE) {
+				pWapiStaInfo->bAuthenticateInProgress = false;
+				pWapiStaInfo->bSetkeyOk = false;
+				_rtw_memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+				list_del_init(&pWapiStaInfo->list);
+				list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+				break;
+			}
+
+		}
+#endif
+
+		while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+		{
+			pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+
+			DBG_871X("peer Addr %02x-%02x-%02x-%02x-%02x-%02x \n",pWapiStaInfo->PeerMacAddr[0],pWapiStaInfo->PeerMacAddr[1],pWapiStaInfo->PeerMacAddr[2],pWapiStaInfo->PeerMacAddr[3],pWapiStaInfo->PeerMacAddr[4],pWapiStaInfo->PeerMacAddr[5]);
+
+			list_del_init(&pWapiStaInfo->list);
+			memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+			pWapiStaInfo->bSetkeyOk = 0;
+			list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+		}
+
+	}
+
+        WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+	return;
+}
+
+void rtw_wapi_return_all_sta_info(_adapter *padapter)
+{
+	PRT_WAPI_T				pWapiInfo;
+	PRT_WAPI_STA_INFO		pWapiStaInfo;
+	PRT_WAPI_BKID			pWapiBkid;
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	pWapiInfo = &padapter->wapiInfo;
+
+	if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+	//Sta Info List
+	while(!list_empty(&(pWapiInfo->wapiSTAUsedList)))
+	{
+		pWapiStaInfo = (PRT_WAPI_STA_INFO)list_entry(pWapiInfo->wapiSTAUsedList.next, RT_WAPI_STA_INFO, list);
+		list_del_init(&pWapiStaInfo->list);
+		memset(pWapiStaInfo->PeerMacAddr,0,ETH_ALEN);
+		pWapiStaInfo->bSetkeyOk = 0;
+		list_add_tail(&pWapiStaInfo->list, &pWapiInfo->wapiSTAIdleList);
+	}
+
+	//BKID List
+	while(!list_empty(&(pWapiInfo->wapiBKIDStoreList)))
+	{
+		pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDStoreList.next, RT_WAPI_BKID, list);
+		list_del_init(&pWapiBkid->list);
+		memset(pWapiBkid->bkid,0,16);
+		list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDIdleList);
+	}
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_clear_cam_entry(_adapter *padapter, u8 *pMacAddr)
+{
+	u8 UcIndex = 0;
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+	UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 0);
+	if(UcIndex != 0xff){
+		//CAM_mark_invalid(Adapter, UcIndex);
+		CAM_empty_entry(padapter, UcIndex);
+	}
+
+	UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 0);
+	if(UcIndex != 0xff){
+		//CAM_mark_invalid(Adapter, UcIndex);
+		CAM_empty_entry(padapter, UcIndex);
+	}
+
+	UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 0, 1);
+	if(UcIndex != 0xff){
+		//CAM_mark_invalid(Adapter, UcIndex);
+		CAM_empty_entry(padapter, UcIndex);
+	}
+
+	UcIndex = WapiGetEntryForCamClear(padapter, pMacAddr, 1, 1);
+	if(UcIndex != 0xff){
+		//CAM_mark_invalid(padapter, UcIndex);
+		CAM_empty_entry(padapter, UcIndex);
+	}
+
+	WAPI_TRACE(WAPI_API, "<========== %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_clear_all_cam_entry(_adapter *padapter)
+{
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_MLME, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+	invalidate_cam_all(padapter); // is this ok?
+	WapiResetAllCamEntry(padapter);
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+}
+
+void rtw_wapi_set_key(_adapter *padapter, RT_WAPI_KEY *pWapiKey, RT_WAPI_STA_INFO *pWapiSta, u8 bGroupKey, u8 bUseDefaultKey)
+{
+	PRT_WAPI_T		pWapiInfo =  &padapter->wapiInfo;
+	u8				*pMacAddr = pWapiSta->PeerMacAddr;
+	u32 EntryId = 0;
+	BOOLEAN IsPairWise = false ;
+	u8 EncAlgo;
+
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_API, "<========== %s, WAPI not supported or not enabled!\n", __FUNCTION__);
+		return;
+	}
+
+	EncAlgo = _SMS4_;
+
+	//For Tx bc/mc pkt,use defualt key entry
+	if(bUseDefaultKey)
+	{
+		// when WAPI update key, keyid will be 0 or 1 by turns.
+		if (pWapiKey->keyId == 0)
+			EntryId = 0;
+		else
+			EntryId = 2;
+	}
+	else
+	{
+		// tx/rx unicast pkt, or rx broadcast, find the key entry by peer's MacAddr
+		EntryId = WapiGetEntryForCamWrite(padapter,pMacAddr,pWapiKey->keyId,bGroupKey);
+	}
+
+	if(EntryId == 0xff){
+		WAPI_TRACE(WAPI_API, "===>No entry for WAPI setkey! !!\n");
+		return;
+	}
+
+	//EntryId is also used to diff Sec key and Mic key
+	//Sec Key
+	WapiWriteOneCamEntry(padapter,
+					pMacAddr,
+					pWapiKey->keyId, //keyid
+					EntryId,	//entry
+					EncAlgo, //type
+					bGroupKey, //pairwise or group key
+					pWapiKey->dataKey);
+	//MIC key
+	WapiWriteOneCamEntry(padapter,
+					pMacAddr,
+					pWapiKey->keyId, //keyid
+					EntryId+1,	//entry
+					EncAlgo, //type
+					bGroupKey, //pairwise or group key
+					pWapiKey->micKey);
+
+	WAPI_TRACE(WAPI_API, "Set Wapi Key :KeyId:%d,EntryId:%d,PairwiseKey:%d.\n",pWapiKey->keyId,EntryId,!bGroupKey);
+	WAPI_TRACE(WAPI_API, "===========> %s\n", __FUNCTION__);
+
+}
+
+#if 0
+//YJ,test,091013
+void wapi_test_set_key(struct _adapter *padapter, u8* buf)
+{ /*Data: keyType(1) + bTxEnable(1) + bAuthenticator(1) + bUpdate(1) + PeerAddr(6) + DataKey(16) + MicKey(16) + KeyId(1)*/
+	PRT_WAPI_T			pWapiInfo = &padapter->wapiInfo;
+	PRT_WAPI_BKID		pWapiBkid;
+	PRT_WAPI_STA_INFO	pWapiSta;
+	u8					data[43];
+	bool					bTxEnable;
+	bool					bUpdate;
+	bool					bAuthenticator;
+	u8					PeerAddr[6];
+	u8					WapiAEPNInitialValueSrc[16] = {0x37,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8					WapiASUEPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+	u8					WapiAEMultiCastPNInitialValueSrc[16] = {0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C,0x36,0x5C} ;
+
+	WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__);
+
+	if (!padapter->WapiSupport){
+	    return;
+	}
+
+	copy_from_user(data, buf, 43);
+	bTxEnable = data[1];
+	bAuthenticator = data[2];
+	bUpdate = data[3];
+ 	memcpy(PeerAddr,data+4,6);
+
+	if(data[0] == 0x3){
+		if(!list_empty(&(pWapiInfo->wapiBKIDIdleList))){
+			pWapiBkid = (PRT_WAPI_BKID)list_entry(pWapiInfo->wapiBKIDIdleList.next, RT_WAPI_BKID, list);
+			list_del_init(&pWapiBkid->list);
+			memcpy(pWapiBkid->bkid, data+10, 16);
+			WAPI_DATA(WAPI_INIT, "SetKey - BKID", pWapiBkid->bkid, 16);
+			list_add_tail(&pWapiBkid->list, &pWapiInfo->wapiBKIDStoreList);
+		}
+	}else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(pWapiSta->PeerMacAddr,PeerAddr,6)){
+				pWapiSta->bAuthenticatorInUpdata = false;
+				switch(data[0]){
+				case 1:              //usk
+					if(bAuthenticator){         //authenticator
+						memcpy(pWapiSta->lastTxUnicastPN,WapiAEPNInitialValueSrc,16);
+						if(!bUpdate) {     //first
+							WAPI_TRACE(WAPI_INIT,"AE fisrt set usk \n");
+							pWapiSta->wapiUsk.bSet = true;
+							memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+							memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+							pWapiSta->wapiUsk.keyId = *(data+42);
+							pWapiSta->wapiUsk.bTxEnable = true;
+							WAPI_DATA(WAPI_INIT, "SetKey - AE USK Data Key", pWapiSta->wapiUsk.dataKey, 16);
+							WAPI_DATA(WAPI_INIT, "SetKey - AE USK Mic Key", pWapiSta->wapiUsk.micKey, 16);
+						}
+						else               //update
+						{
+							WAPI_TRACE(WAPI_INIT, "AE update usk \n");
+							pWapiSta->wapiUskUpdate.bSet = true;
+							pWapiSta->bAuthenticatorInUpdata = true;
+							memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+							memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+							memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+							memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							pWapiSta->wapiUskUpdate.keyId = *(data+42);
+							pWapiSta->wapiUskUpdate.bTxEnable = true;
+						}
+					}
+					else{
+						if(!bUpdate){
+							WAPI_TRACE(WAPI_INIT,"ASUE fisrt set usk \n");
+							if(bTxEnable){
+								pWapiSta->wapiUsk.bTxEnable = true;
+								memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							}else{
+								pWapiSta->wapiUsk.bSet = true;
+								memcpy(pWapiSta->wapiUsk.dataKey,data+10,16);
+								memcpy(pWapiSta->wapiUsk.micKey,data+26,16);
+								pWapiSta->wapiUsk.keyId = *(data+42);
+								pWapiSta->wapiUsk.bTxEnable = false;
+							}
+						}else{
+							WAPI_TRACE(WAPI_INIT,"ASUE update usk \n");
+							if(bTxEnable){
+								pWapiSta->wapiUskUpdate.bTxEnable = true;
+								if(pWapiSta->wapiUskUpdate.bSet){
+									memcpy(pWapiSta->wapiUsk.dataKey,pWapiSta->wapiUskUpdate.dataKey,16);
+									memcpy(pWapiSta->wapiUsk.micKey,pWapiSta->wapiUskUpdate.micKey,16);
+									pWapiSta->wapiUsk.keyId=pWapiSta->wapiUskUpdate.keyId;
+									memcpy(pWapiSta->lastRxUnicastPNBEQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNBKQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNVIQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPNVOQueue,WapiASUEPNInitialValueSrc,16);
+									memcpy(pWapiSta->lastRxUnicastPN,WapiASUEPNInitialValueSrc,16);
+									pWapiSta->wapiUskUpdate.bTxEnable = false;
+									pWapiSta->wapiUskUpdate.bSet = false;
+								}
+								memcpy(pWapiSta->lastTxUnicastPN,WapiASUEPNInitialValueSrc,16);
+							}else{
+								pWapiSta->wapiUskUpdate.bSet = true;
+								memcpy(pWapiSta->wapiUskUpdate.dataKey,data+10,16);
+								memcpy(pWapiSta->wapiUskUpdate.micKey,data+26,16);
+								pWapiSta->wapiUskUpdate.keyId = *(data+42);
+								pWapiSta->wapiUskUpdate.bTxEnable = false;
+							}
+						}
+					}
+					break;
+				case 2:		//msk
+					if(bAuthenticator){          //authenticator
+						pWapiInfo->wapiTxMsk.bSet = true;
+						memcpy(pWapiInfo->wapiTxMsk.dataKey,data+10,16);
+						memcpy(pWapiInfo->wapiTxMsk.micKey,data+26,16);
+						pWapiInfo->wapiTxMsk.keyId = *(data+42);
+						pWapiInfo->wapiTxMsk.bTxEnable = true;
+						memcpy(pWapiInfo->lastTxMulticastPN,WapiAEMultiCastPNInitialValueSrc,16);
+
+						if(!bUpdate){      //first
+							WAPI_TRACE(WAPI_INIT, "AE fisrt set msk \n");
+							if(!pWapiSta->bSetkeyOk)
+								pWapiSta->bSetkeyOk = true;
+							pWapiInfo->bFirstAuthentiateInProgress= false;
+						}else{               //update
+							WAPI_TRACE(WAPI_INIT,"AE update msk \n");
+						}
+
+						WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Data Key", pWapiInfo->wapiTxMsk.dataKey, 16);
+						WAPI_DATA(WAPI_INIT, "SetKey - AE MSK Mic Key", pWapiInfo->wapiTxMsk.micKey, 16);
+					}
+					else{
+						if(!bUpdate){
+							WAPI_TRACE(WAPI_INIT,"ASUE fisrt set msk \n");
+							pWapiSta->wapiMsk.bSet = true;
+							memcpy(pWapiSta->wapiMsk.dataKey,data+10,16);
+							memcpy(pWapiSta->wapiMsk.micKey,data+26,16);
+							pWapiSta->wapiMsk.keyId = *(data+42);
+							pWapiSta->wapiMsk.bTxEnable = false;
+							if(!pWapiSta->bSetkeyOk)
+								pWapiSta->bSetkeyOk = true;
+							pWapiInfo->bFirstAuthentiateInProgress= false;
+							WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Data Key", pWapiSta->wapiMsk.dataKey, 16);
+							WAPI_DATA(WAPI_INIT, "SetKey - ASUE MSK Mic Key", pWapiSta->wapiMsk.micKey, 16);
+						}else{
+							WAPI_TRACE(WAPI_INIT,"ASUE update msk \n");
+							pWapiSta->wapiMskUpdate.bSet = true;
+							memcpy(pWapiSta->wapiMskUpdate.dataKey,data+10,16);
+							memcpy(pWapiSta->wapiMskUpdate.micKey,data+26,16);
+							pWapiSta->wapiMskUpdate.keyId = *(data+42);
+							pWapiSta->wapiMskUpdate.bTxEnable = false;
+						}
+					}
+					break;
+				default:
+					WAPI_TRACE(WAPI_ERR,"Unknown Flag \n");
+					break;
+				}
+			}
+		}
+	}
+	WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__);
+}
+
+
+void wapi_test_init(struct _adapter *padapter)
+{
+	u8 keybuf[100];
+	u8 mac_addr[6]={0x00,0xe0,0x4c,0x72,0x04,0x70};
+	u8 UskDataKey[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
+	u8 UskMicKey[16]={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f};
+	u8 UskId = 0;
+	u8 MskDataKey[16]={0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f};
+	u8 MskMicKey[16]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f};
+	u8 MskId = 0;
+
+	WAPI_TRACE(WAPI_INIT, "===========>%s\n", __FUNCTION__);
+
+	//Enable Wapi
+	WAPI_TRACE(WAPI_INIT, "%s: Enable wapi!!!!\n", __FUNCTION__);
+	padapter->wapiInfo.bWapiEnable = true;
+	padapter->pairwise_key_type = KEY_TYPE_SMS4;
+	ieee->group_key_type = KEY_TYPE_SMS4;
+	padapter->wapiInfo.extra_prefix_len = WAPI_EXT_LEN;
+	padapter->wapiInfo.extra_postfix_len = SMS4_MIC_LEN;
+
+	//set usk
+	WAPI_TRACE(WAPI_INIT, "%s: Set USK!!!!\n", __FUNCTION__);
+	memset(keybuf,0,100);
+	keybuf[0] = 1;                           //set usk
+	keybuf[1] = 1; 				//enable tx
+	keybuf[2] = 1; 				//AE
+	keybuf[3] = 0; 				//not update
+
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,UskDataKey,16);
+	memcpy(keybuf+26,UskMicKey,16);
+	keybuf[42]=UskId;
+	wapi_test_set_key(padapter, keybuf);
+
+	memset(keybuf,0,100);
+	keybuf[0] = 1;                           //set usk
+	keybuf[1] = 1; 				//enable tx
+	keybuf[2] = 0; 				//AE
+	keybuf[3] = 0; 				//not update
+
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,UskDataKey,16);
+	memcpy(keybuf+26,UskMicKey,16);
+	keybuf[42]=UskId;
+	wapi_test_set_key(padapter, keybuf);
+
+	//set msk
+	WAPI_TRACE(WAPI_INIT, "%s: Set MSK!!!!\n", __FUNCTION__);
+	memset(keybuf,0,100);
+	keybuf[0] = 2;                                //set msk
+	keybuf[1] = 1;                               //Enable TX
+	keybuf[2] = 1; 				//AE
+	keybuf[3] = 0;                              //not update
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,MskDataKey,16);
+	memcpy(keybuf+26,MskMicKey,16);
+	keybuf[42] = MskId;
+	wapi_test_set_key(padapter, keybuf);
+
+	memset(keybuf,0,100);
+	keybuf[0] = 2;                                //set msk
+	keybuf[1] = 1;                               //Enable TX
+	keybuf[2] = 0; 				//AE
+	keybuf[3] = 0;                              //not update
+	memcpy(keybuf+4,mac_addr,6);
+	memcpy(keybuf+10,MskDataKey,16);
+	memcpy(keybuf+26,MskMicKey,16);
+	keybuf[42] = MskId;
+	wapi_test_set_key(padapter, keybuf);
+	WAPI_TRACE(WAPI_INIT, "<===========%s\n", __FUNCTION__);
+}
+#endif
+
+void rtw_wapi_get_iv(_adapter *padapter,u8 *pRA, u8*IV)
+{
+	PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
+       PRT_WAPI_T         pWapiInfo = &padapter->wapiInfo;
+	bool	bPNOverflow = false;
+	bool	bFindMatchPeer = false;
+	PRT_WAPI_STA_INFO  pWapiSta = NULL;
+
+	pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)IV;
+
+	WAPI_DATA(WAPI_RX,"wapi_get_iv: pra",pRA,6);
+
+	if(IS_MCAST(pRA)){
+		if(!pWapiInfo->wapiTxMsk.bTxEnable){
+			 WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+			 return;
+		}
+
+		if(pWapiInfo->wapiTxMsk.keyId <= 1){
+			 pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+			 pWapiExt->Reserved = 0;
+			 bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
+			 memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
+		}
+	}
+	else
+	{
+		if(list_empty(&pWapiInfo->wapiSTAUsedList)){
+			WAPI_TRACE(WAPI_RX,"rtw_wapi_get_iv: list is empty \n");
+			_rtw_memset(IV,10,18);
+			return;
+		}
+		else{
+				list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+					WAPI_DATA(WAPI_RX,"rtw_wapi_get_iv: peermacaddr ",pWapiSta->PeerMacAddr,6);
+					if (_rtw_memcmp((u8*)pWapiSta->PeerMacAddr, pRA, 6) == _TRUE) {
+						bFindMatchPeer = true;
+						break;
+					}
+				}
+
+				WAPI_TRACE(WAPI_RX,"bFindMatchPeer: %d \n",bFindMatchPeer);
+				WAPI_DATA(WAPI_RX,"Addr",pRA,6);
+
+				if (bFindMatchPeer){
+					if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable))
+						return;
+
+					if (pWapiSta->wapiUsk.keyId <= 1){
+						if(pWapiSta->wapiUskUpdate.bTxEnable)
+							pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+						else
+							pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
+
+						pWapiExt->Reserved = 0;
+						bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
+						_rtw_memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
+
+					}
+				}
+		}
+
+	}
+
+}
+
+bool rtw_wapi_drop_for_key_absent(_adapter *padapter,u8 *pRA)
+{
+	PRT_WAPI_T         pWapiInfo = &padapter->wapiInfo;
+	bool				bFindMatchPeer = false;
+	bool				bDrop = false;
+	PRT_WAPI_STA_INFO  pWapiSta = NULL;
+	struct security_priv 		*psecuritypriv = &padapter->securitypriv;
+
+	WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: ra ",pRA,6);
+
+	if(psecuritypriv->dot11PrivacyAlgrthm == _SMS4_)
+	{
+		if ((!padapter->WapiSupport) || (!pWapiInfo->bWapiEnable))
+			return true;
+
+		if(IS_MCAST(pRA)){
+			if(!pWapiInfo->wapiTxMsk.bTxEnable){
+				bDrop = true;
+				WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: multicast key is absent \n");
+				return bDrop;
+			}
+		}
+		else{
+				if(!list_empty(&pWapiInfo->wapiSTAUsedList)){
+					list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list){
+						WAPI_DATA(WAPI_RX,"rtw_wapi_drop_for_key_absent: pWapiSta->PeerMacAddr ",pWapiSta->PeerMacAddr,6);
+						if (_rtw_memcmp(pRA, pWapiSta->PeerMacAddr, 6) == _TRUE){
+							bFindMatchPeer = true;
+							break;
+						}
+					}
+					if (bFindMatchPeer)	{
+						if (!pWapiSta->wapiUsk.bTxEnable){
+							bDrop = true;
+							WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: unicast key is absent \n");
+							return bDrop;
+						}
+					}
+					else{
+						bDrop = true;
+						WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no peer find \n");
+						return bDrop;
+					}
+
+				}
+				else{
+						bDrop = true;
+						WAPI_TRACE(WAPI_RX,"rtw_wapi_drop_for_key_absent: no sta  exist \n");
+						return bDrop;
+				}
+		}
+	}
+	else
+	{
+		return bDrop;
+	}
+
+	return bDrop;
+}
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi_sms4.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi_sms4.c
new file mode 100644
index 000000000..aa6419390
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wapi_sms4.c
@@ -0,0 +1,923 @@
+#ifdef CONFIG_WAPI_SUPPORT
+
+#include <linux/unistd.h>
+#include <linux/etherdevice.h>
+#include <drv_types.h>
+#include <rtw_wapi.h>
+
+
+#ifdef CONFIG_WAPI_SW_SMS4
+
+#define WAPI_LITTLE_ENDIAN
+//#define BIG_ENDIAN
+#define ENCRYPT  0
+#define DECRYPT  1
+
+
+/**********************************************************
+ **********************************************************/
+const u8 Sbox[256] = {
+0xd6,0x90,0xe9,0xfe,0xcc,0xe1,0x3d,0xb7,0x16,0xb6,0x14,0xc2,0x28,0xfb,0x2c,0x05,
+0x2b,0x67,0x9a,0x76,0x2a,0xbe,0x04,0xc3,0xaa,0x44,0x13,0x26,0x49,0x86,0x06,0x99,
+0x9c,0x42,0x50,0xf4,0x91,0xef,0x98,0x7a,0x33,0x54,0x0b,0x43,0xed,0xcf,0xac,0x62,
+0xe4,0xb3,0x1c,0xa9,0xc9,0x08,0xe8,0x95,0x80,0xdf,0x94,0xfa,0x75,0x8f,0x3f,0xa6,
+0x47,0x07,0xa7,0xfc,0xf3,0x73,0x17,0xba,0x83,0x59,0x3c,0x19,0xe6,0x85,0x4f,0xa8,
+0x68,0x6b,0x81,0xb2,0x71,0x64,0xda,0x8b,0xf8,0xeb,0x0f,0x4b,0x70,0x56,0x9d,0x35,
+0x1e,0x24,0x0e,0x5e,0x63,0x58,0xd1,0xa2,0x25,0x22,0x7c,0x3b,0x01,0x21,0x78,0x87,
+0xd4,0x00,0x46,0x57,0x9f,0xd3,0x27,0x52,0x4c,0x36,0x02,0xe7,0xa0,0xc4,0xc8,0x9e,
+0xea,0xbf,0x8a,0xd2,0x40,0xc7,0x38,0xb5,0xa3,0xf7,0xf2,0xce,0xf9,0x61,0x15,0xa1,
+0xe0,0xae,0x5d,0xa4,0x9b,0x34,0x1a,0x55,0xad,0x93,0x32,0x30,0xf5,0x8c,0xb1,0xe3,
+0x1d,0xf6,0xe2,0x2e,0x82,0x66,0xca,0x60,0xc0,0x29,0x23,0xab,0x0d,0x53,0x4e,0x6f,
+0xd5,0xdb,0x37,0x45,0xde,0xfd,0x8e,0x2f,0x03,0xff,0x6a,0x72,0x6d,0x6c,0x5b,0x51,
+0x8d,0x1b,0xaf,0x92,0xbb,0xdd,0xbc,0x7f,0x11,0xd9,0x5c,0x41,0x1f,0x10,0x5a,0xd8,
+0x0a,0xc1,0x31,0x88,0xa5,0xcd,0x7b,0xbd,0x2d,0x74,0xd0,0x12,0xb8,0xe5,0xb4,0xb0,
+0x89,0x69,0x97,0x4a,0x0c,0x96,0x77,0x7e,0x65,0xb9,0xf1,0x09,0xc5,0x6e,0xc6,0x84,
+0x18,0xf0,0x7d,0xec,0x3a,0xdc,0x4d,0x20,0x79,0xee,0x5f,0x3e,0xd7,0xcb,0x39,0x48
+};
+
+const u32 CK[32] = {
+	0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
+	0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
+	0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
+	0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
+	0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
+	0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
+	0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
+	0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279 };
+
+#define Rotl(_x, _y) (((_x) << (_y)) | ((_x) >> (32 - (_y))))
+
+#define ByteSub(_A) (Sbox[(_A) >> 24 & 0xFF] << 24 | \
+                     Sbox[(_A) >> 16 & 0xFF] << 16 | \
+                     Sbox[(_A) >>  8 & 0xFF] <<  8 | \
+                     Sbox[(_A) & 0xFF])
+
+#define L1(_B) ((_B) ^ Rotl(_B, 2) ^ Rotl(_B, 10) ^ Rotl(_B, 18) ^ Rotl(_B, 24))
+#define L2(_B) ((_B) ^ Rotl(_B, 13) ^ Rotl(_B, 23))
+
+static void
+xor_block(void *dst, void *src1, void *src2)
+/* 128-bit xor: *dst = *src1 xor *src2. Pointers must be 32-bit aligned  */
+{
+    ((u32 *)dst)[0] = ((u32 *)src1)[0] ^ ((u32 *)src2)[0];
+    ((u32 *)dst)[1] = ((u32 *)src1)[1] ^ ((u32 *)src2)[1];
+    ((u32 *)dst)[2] = ((u32 *)src1)[2] ^ ((u32 *)src2)[2];
+    ((u32 *)dst)[3] = ((u32 *)src1)[3] ^ ((u32 *)src2)[3];
+}
+
+
+void SMS4Crypt(u8 *Input, u8 *Output, u32 *rk)
+{
+	 u32 r, mid, x0, x1, x2, x3, *p;
+	 p = (u32 *)Input;
+	 x0 = p[0];
+	 x1 = p[1];
+	 x2 = p[2];
+	 x3 = p[3];
+#ifdef WAPI_LITTLE_ENDIAN
+	 x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+	 x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+	 x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+	 x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+	 for (r = 0; r < 32; r += 4)
+	 {
+		  mid = x1 ^ x2 ^ x3 ^ rk[r + 0];
+		  mid = ByteSub(mid);
+		  x0 ^= L1(mid);
+		  mid = x2 ^ x3 ^ x0 ^ rk[r + 1];
+		  mid = ByteSub(mid);
+		  x1 ^= L1(mid);
+		  mid = x3 ^ x0 ^ x1 ^ rk[r + 2];
+		  mid = ByteSub(mid);
+		  x2 ^= L1(mid);
+		  mid = x0 ^ x1 ^ x2 ^ rk[r + 3];
+		  mid = ByteSub(mid);
+		  x3 ^= L1(mid);
+	 }
+#ifdef WAPI_LITTLE_ENDIAN
+	 x0 = Rotl(x0, 16); x0 = ((x0 & 0x00FF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+	 x1 = Rotl(x1, 16); x1 = ((x1 & 0x00FF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+	 x2 = Rotl(x2, 16); x2 = ((x2 & 0x00FF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+	 x3 = Rotl(x3, 16); x3 = ((x3 & 0x00FF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+	 p = (u32 *)Output;
+	 p[0] = x3;
+	 p[1] = x2;
+	 p[2] = x1;
+	 p[3] = x0;
+}
+
+
+
+void SMS4KeyExt(u8 *Key, u32 *rk, u32 CryptFlag)
+{
+	 u32 r, mid, x0, x1, x2, x3, *p;
+
+	 p = (u32 *)Key;
+	 x0 = p[0];
+	 x1 = p[1];
+	 x2 = p[2];
+	 x3 = p[3];
+#ifdef WAPI_LITTLE_ENDIAN
+	 x0 = Rotl(x0, 16); x0 = ((x0 & 0xFF00FF) << 8) | ((x0 & 0xFF00FF00) >> 8);
+	 x1 = Rotl(x1, 16); x1 = ((x1 & 0xFF00FF) << 8) | ((x1 & 0xFF00FF00) >> 8);
+	 x2 = Rotl(x2, 16); x2 = ((x2 & 0xFF00FF) << 8) | ((x2 & 0xFF00FF00) >> 8);
+	 x3 = Rotl(x3, 16); x3 = ((x3 & 0xFF00FF) << 8) | ((x3 & 0xFF00FF00) >> 8);
+#endif
+
+	 x0 ^= 0xa3b1bac6;
+	 x1 ^= 0x56aa3350;
+	 x2 ^= 0x677d9197;
+	 x3 ^= 0xb27022dc;
+	 for (r = 0; r < 32; r += 4)
+	 {
+		  mid = x1 ^ x2 ^ x3 ^ CK[r + 0];
+		  mid = ByteSub(mid);
+		  rk[r + 0] = x0 ^= L2(mid);
+		  mid = x2 ^ x3 ^ x0 ^ CK[r + 1];
+		  mid = ByteSub(mid);
+		  rk[r + 1] = x1 ^= L2(mid);
+		  mid = x3 ^ x0 ^ x1 ^ CK[r + 2];
+		  mid = ByteSub(mid);
+		  rk[r + 2] = x2 ^= L2(mid);
+		  mid = x0 ^ x1 ^ x2 ^ CK[r + 3];
+		  mid = ByteSub(mid);
+		  rk[r + 3] = x3 ^= L2(mid);
+	 }
+	 if (CryptFlag == DECRYPT)
+	 {
+	 	  for (r = 0; r < 16; r++)
+	 	  	 mid = rk[r], rk[r] = rk[31 - r], rk[31 - r] = mid;
+	 }
+}
+
+
+void WapiSMS4Cryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+                                                u8 *Output, u16 *OutputLength, u32 CryptFlag)
+{
+	u32 blockNum,i,j, rk[32];
+	u16 remainder;
+	u8 blockIn[16],blockOut[16], tempIV[16], k;
+
+	*OutputLength = 0;
+	remainder = InputLength & 0x0F;
+	blockNum = InputLength >> 4;
+	if(remainder !=0)
+		blockNum++;
+	else
+		remainder = 16;
+
+	for(k=0;k<16;k++)
+		tempIV[k] = IV[15-k];
+
+	memcpy(blockIn, tempIV, 16);
+
+      SMS4KeyExt((u8 *)Key, rk,CryptFlag);
+
+	for(i=0; i<blockNum-1; i++)
+	{
+		SMS4Crypt((u8 *)blockIn, blockOut, rk);
+             xor_block(&Output[i*16], &Input[i*16], blockOut);
+		memcpy(blockIn,blockOut,16);
+	}
+
+	*OutputLength = i*16;
+
+	SMS4Crypt((u8 *)blockIn, blockOut, rk);
+
+	for(j=0; j<remainder; j++)
+	{
+		Output[i*16+j] = Input[i*16+j] ^ blockOut[j];
+	}
+      *OutputLength += remainder;
+
+}
+
+void WapiSMS4Encryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+                                                    u8 *Output, u16 *OutputLength)
+{
+
+	WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
+}
+
+void WapiSMS4Decryption(u8 *Key, u8 *IV, u8 *Input, u16 InputLength,
+                                                    u8 *Output, u16 *OutputLength)
+{
+	// OFB mode: is also ENCRYPT flag
+	WapiSMS4Cryption(Key, IV, Input, InputLength, Output, OutputLength, ENCRYPT);
+}
+
+void WapiSMS4CalculateMic(u8 *Key, u8 *IV, u8 *Input1, u8 Input1Length,
+                                                 u8 *Input2, u16 Input2Length, u8 *Output, u8 *OutputLength)
+{
+	u32 blockNum, i, remainder, rk[32];
+	u8 BlockIn[16], BlockOut[16], TempBlock[16], tempIV[16], k;
+
+	*OutputLength = 0;
+	remainder = Input1Length & 0x0F;
+	blockNum = Input1Length >> 4;
+
+	for(k=0;k<16;k++)
+		tempIV[k] = IV[15-k];
+
+	memcpy(BlockIn, tempIV, 16);
+
+	SMS4KeyExt((u8 *)Key, rk, ENCRYPT);
+
+	SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+
+	for(i=0; i<blockNum; i++){
+		xor_block(BlockIn, (Input1+i*16), BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+	}
+
+	if(remainder !=0){
+		memset(TempBlock, 0, 16);
+		memcpy(TempBlock, (Input1+blockNum*16), remainder);
+
+		xor_block(BlockIn, TempBlock, BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+      }
+
+	remainder = Input2Length & 0x0F;
+	blockNum = Input2Length >> 4;
+
+  	for(i=0; i<blockNum; i++){
+		xor_block(BlockIn, (Input2+i*16), BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+	}
+
+	if(remainder !=0){
+		memset(TempBlock, 0, 16);
+		memcpy(TempBlock, (Input2+blockNum*16), remainder);
+
+		xor_block(BlockIn, TempBlock, BlockOut);
+		SMS4Crypt((u8 *)BlockIn, BlockOut, rk);
+	}
+
+	memcpy(Output, BlockOut, 16);
+	*OutputLength = 16;
+}
+
+void SecCalculateMicSMS4(
+	u8		KeyIdx,
+	u8        *MicKey,
+	u8        *pHeader,
+	u8        *pData,
+	u16       DataLen,
+	u8        *MicBuffer
+	)
+{
+#if 0
+	struct ieee80211_hdr_3addr_qos *header;
+	u8 TempBuf[34], TempLen = 32, MicLen, QosOffset, *IV;
+	u16 *pTemp, fc;
+
+	WAPI_TRACE(WAPI_TX|WAPI_RX, "=========>%s\n", __FUNCTION__);
+
+	header = (struct ieee80211_hdr_3addr_qos *)pHeader;
+	memset(TempBuf, 0, 34);
+	memcpy(TempBuf, pHeader, 2); //FrameCtrl
+	pTemp = (u16*)TempBuf;
+	*pTemp &= 0xc78f;       //bit4,5,6,11,12,13
+
+	memcpy((TempBuf+2), (pHeader+4), 12); //Addr1, Addr2
+	memcpy((TempBuf+14), (pHeader+22), 2); // SeqCtrl
+	pTemp = (u16*)(TempBuf + 14);
+	*pTemp &= 0x000f;
+
+	memcpy((TempBuf+16), (pHeader+16), 6); //Addr3
+
+	fc = le16_to_cpu(header->frame_ctl);
+
+
+
+	if (GetFrDs((u16*)&fc) && GetToDs((u16 *)&fc))
+	{
+		memcpy((TempBuf+22), (pHeader+24), 6);
+		QosOffset = 30;
+	}else{
+		memset((TempBuf+22), 0, 6);
+		QosOffset = 24;
+	}
+
+	if((fc & 0x0088) == 0x0088){
+		memcpy((TempBuf+28), (pHeader+QosOffset), 2);
+		TempLen += 2;
+		//IV = pHeader + QosOffset + 2 + SNAP_SIZE + sizeof(u16) + 2;
+		IV = pHeader + QosOffset + 2 + 2;
+	}else{
+		IV = pHeader + QosOffset + 2;
+		//IV = pHeader + QosOffset + SNAP_SIZE + sizeof(u16) + 2;
+	}
+
+	TempBuf[TempLen-1] = (u8)(DataLen & 0xff);
+	TempBuf[TempLen-2] = (u8)((DataLen & 0xff00)>>8);
+	TempBuf[TempLen-4] = KeyIdx;
+
+	WAPI_DATA(WAPI_TX, "CalculateMic - KEY", MicKey, 16);
+	WAPI_DATA(WAPI_TX, "CalculateMic - IV", IV, 16);
+	WAPI_DATA(WAPI_TX, "CalculateMic - TempBuf", TempBuf, TempLen);
+	WAPI_DATA(WAPI_TX, "CalculateMic - pData", pData, DataLen);
+
+	WapiSMS4CalculateMic(MicKey, IV, TempBuf, TempLen,
+	                                             pData, DataLen, MicBuffer, &MicLen);
+
+	if (MicLen != 16)
+		WAPI_TRACE(WAPI_ERR,"%s: MIC Length Error!!\n",__FUNCTION__);
+
+	WAPI_TRACE(WAPI_TX|WAPI_RX, "<=========%s\n", __FUNCTION__);
+#endif
+}
+
+/* AddCount: 1 or 2.
+ *  If overflow, return 1,
+ *  else return 0.
+ */
+u8 WapiIncreasePN(u8 *PN, u8 AddCount)
+{
+	u8  i;
+
+	if (NULL == PN)
+		return 1;
+	//YJ,test,091102
+	/*
+	if(AddCount == 2){
+		DBG_8192C("############################%s(): PN[0]=0x%x\n", __FUNCTION__, PN[0]);
+		if(PN[0] == 0x48){
+			PN[0] += AddCount;
+			return 1;
+		}else{
+			PN[0] += AddCount;
+			return 0;
+		}
+	}
+	*/
+	//YJ,test,091102,end
+
+	for (i=0; i<16; i++)
+	{
+		if (PN[i] + AddCount <= 0xff)
+		{
+			PN[i] += AddCount;
+			return 0;
+		}
+		else
+		{
+			PN[i] += AddCount;
+			AddCount = 1;
+		}
+	}
+	return 1;
+}
+
+
+void WapiGetLastRxUnicastPNForQoSData(
+	u8 			UserPriority,
+	PRT_WAPI_STA_INFO    pWapiStaInfo,
+	u8 *PNOut
+)
+{
+	WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+	switch(UserPriority)
+	{
+		case 0:
+		case 3:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBEQueue,16);
+			      break;
+		case 1:
+		case 2:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNBKQueue,16);
+			      break;
+		case 4:
+		case 5:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVIQueue,16);
+			      break;
+		case 6:
+		case 7:
+			      memcpy(PNOut,pWapiStaInfo->lastRxUnicastPNVOQueue,16);
+			      break;
+		default:
+				WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+				break;
+	}
+	WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+
+void WapiSetLastRxUnicastPNForQoSData(
+	u8 		UserPriority,
+	u8           *PNIn,
+	PRT_WAPI_STA_INFO    pWapiStaInfo
+)
+{
+	WAPI_TRACE(WAPI_RX, "===========> %s\n", __FUNCTION__);
+	switch(UserPriority)
+	{
+		case 0:
+		case 3:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNBEQueue,PNIn,16);
+			      break;
+		case 1:
+		case 2:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNBKQueue,PNIn,16);
+			      break;
+		case 4:
+		case 5:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNVIQueue,PNIn,16);
+			      break;
+		case 6:
+		case 7:
+			      memcpy(pWapiStaInfo->lastRxUnicastPNVOQueue,PNIn,16);
+			      break;
+		default:
+				WAPI_TRACE(WAPI_ERR, "%s: Unknown TID \n", __FUNCTION__);
+				break;
+	}
+	WAPI_TRACE(WAPI_RX, "<=========== %s\n", __FUNCTION__);
+}
+
+
+/****************************************************************************
+ FALSE not RX-Reorder
+ TRUE do RX Reorder
+add to support WAPI to N-mode
+*****************************************************************************/
+u8 WapiCheckPnInSwDecrypt(
+	_adapter *padapter,
+	struct sk_buff *pskb
+)
+{
+	u8 				ret = false;
+
+#if 0
+	struct ieee80211_hdr_3addr_qos *header;
+	u16 				fc;
+	u8				*pDaddr, *pTaddr, *pRaddr;
+
+	header = (struct ieee80211_hdr_3addr_qos *)pskb->data;
+	pTaddr = header->addr2;
+	pRaddr = header->addr1;
+	fc = le16_to_cpu(header->frame_ctl);
+
+	if(GetToDs(&fc))
+		pDaddr = header->addr3;
+	else
+		pDaddr = header->addr1;
+
+	if ((_rtw_memcmp(pRaddr, padapter->pnetdev->dev_addr, ETH_ALEN) == 0)
+		&&	! (pDaddr)
+		&& (GetFrameType(&fc) == WIFI_QOS_DATA_TYPE))
+		//&& ieee->pHTInfo->bCurrentHTSupport &&
+		//ieee->pHTInfo->bCurRxReorderEnable)
+		ret = false;
+	else
+		ret = true;
+#endif
+	WAPI_TRACE(WAPI_RX, "%s: return %d\n", __FUNCTION__, ret);
+	return ret;
+}
+
+int SecSMS4HeaderFillIV(_adapter *padapter, u8 *pxmitframe)
+{
+	struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib;
+	u8 * frame = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
+	u8 *pSecHeader = NULL, *pos = NULL, *pRA = NULL;
+	u8 bPNOverflow = false, bFindMatchPeer = false, hdr_len = 0;
+	PWLAN_HEADER_WAPI_EXTENSION pWapiExt = NULL;
+	PRT_WAPI_T         pWapiInfo = &padapter->wapiInfo;
+	PRT_WAPI_STA_INFO  pWapiSta = NULL;
+	int ret = 0;
+
+	WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+	return ret;
+#if 0
+	hdr_len = sMacHdrLng;
+	if (GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE)
+	{
+		hdr_len += 2;
+	}
+	//hdr_len += SNAP_SIZE + sizeof(u16);
+
+	pos = skb_push(pskb, padapter->wapiInfo.extra_prefix_len);
+	memmove(pos, pos+padapter->wapiInfo.extra_prefix_len, hdr_len);
+
+	pSecHeader = pskb->data + hdr_len;
+	pWapiExt = (PWLAN_HEADER_WAPI_EXTENSION)pSecHeader;
+	pRA = pskb->data + 4;
+
+	WAPI_DATA(WAPI_TX, "FillIV - Before Fill IV", pskb->data, pskb->len);
+
+	//Address 1 is always receiver's address
+	if( IS_MCAST(pRA) ){
+		if(!pWapiInfo->wapiTxMsk.bTxEnable){
+			WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+			return -2;
+		}
+		if(pWapiInfo->wapiTxMsk.keyId <= 1){
+			pWapiExt->KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+			pWapiExt->Reserved = 0;
+			bPNOverflow = WapiIncreasePN(pWapiInfo->lastTxMulticastPN, 1);
+			memcpy(pWapiExt->PN, pWapiInfo->lastTxMulticastPN, 16);
+			if (bPNOverflow){
+				// Update MSK Notification.
+				WAPI_TRACE(WAPI_ERR,"===============>%s():multicast PN overflow\n",__FUNCTION__);
+				rtw_wapi_app_event_handler(padapter,NULL,0,pRA, false, false, true, 0, false);
+			}
+		}else{
+			WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Multicast KeyIdx!!\n",__FUNCTION__);
+			ret = -3;
+		}
+	}
+    	else{
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if(!memcmp(pWapiSta->PeerMacAddr,pRA,6)){
+    				bFindMatchPeer = true;
+				break;
+			}
+		}
+		if (bFindMatchPeer){
+			if((!pWapiSta->wapiUskUpdate.bTxEnable) && (!pWapiSta->wapiUsk.bTxEnable)){
+				WAPI_TRACE(WAPI_ERR,"%s: bTxEnable = 0!!\n",__FUNCTION__);
+				return -4;
+			}
+			if (pWapiSta->wapiUsk.keyId <= 1){
+				if(pWapiSta->wapiUskUpdate.bTxEnable)
+					pWapiExt->KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+				else
+					pWapiExt->KeyIdx = pWapiSta->wapiUsk.keyId;
+
+				pWapiExt->Reserved = 0;
+				bPNOverflow = WapiIncreasePN(pWapiSta->lastTxUnicastPN, 2);
+				memcpy(pWapiExt->PN, pWapiSta->lastTxUnicastPN, 16);
+				if (bPNOverflow){
+					// Update USK Notification.
+					WAPI_TRACE(WAPI_ERR,"===============>%s():unicast PN overflow\n",__FUNCTION__);
+					rtw_wapi_app_event_handler(padapter,NULL,0,pWapiSta->PeerMacAddr, false, true, false, 0, false);
+				}
+			}else{
+				WAPI_TRACE(WAPI_ERR,"%s: Invalid Wapi Unicast KeyIdx!!\n",__FUNCTION__);
+				ret = -5;
+			}
+		}
+		else{
+			WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta "MAC_FMT"!!\n",__FUNCTION__, MAC_ARG(pRA));
+			ret = -6;
+		}
+    	}
+
+	WAPI_DATA(WAPI_TX, "FillIV - After Fill IV", pskb->data, pskb->len);
+	WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+	return ret;
+#endif
+}
+
+// WAPI SW Enc: must have done Coalesce!
+void SecSWSMS4Encryption(
+	_adapter *padapter,
+	u8 * pxmitframe
+	)
+{
+	PRT_WAPI_T		pWapiInfo = &padapter->wapiInfo;
+	PRT_WAPI_STA_INFO   pWapiSta = NULL;
+	u8 *pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_SIZE;
+	struct pkt_attrib *pattrib = &((struct xmit_frame*)pxmitframe)->attrib;
+
+	u8 *SecPtr = NULL, *pRA, *pMicKey = NULL, *pDataKey = NULL, *pIV = NULL;
+	u8 IVOffset, DataOffset, bFindMatchPeer = false, KeyIdx = 0, MicBuffer[16];
+	u16 OutputLength;
+
+	WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+	WAPI_TRACE(WAPI_TX,"hdrlen: %d \n",pattrib->hdrlen);
+
+	return;
+
+	DataOffset = pattrib->hdrlen + pattrib->iv_len;
+
+	pRA = pframe + 4;
+
+
+	if( IS_MCAST(pRA) ){
+		KeyIdx = pWapiInfo->wapiTxMsk.keyId;
+		pIV = pWapiInfo->lastTxMulticastPN;
+		pMicKey = pWapiInfo->wapiTxMsk.micKey;
+		pDataKey = pWapiInfo->wapiTxMsk.dataKey;
+	}else{
+		if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+			list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+				if (0 == memcmp(pWapiSta->PeerMacAddr, pRA, 6)){
+					bFindMatchPeer = true;
+					break;
+				}
+			}
+
+			if (bFindMatchPeer){
+				if (pWapiSta->wapiUskUpdate.bTxEnable){
+					KeyIdx = pWapiSta->wapiUskUpdate.keyId;
+					WAPI_TRACE(WAPI_TX, "%s(): Use update USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+					pIV = pWapiSta->lastTxUnicastPN;
+					pMicKey = pWapiSta->wapiUskUpdate.micKey;
+					pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+				}else{
+					KeyIdx = pWapiSta->wapiUsk.keyId;
+					WAPI_TRACE(WAPI_TX, "%s(): Use USK!! KeyIdx=%d\n", __FUNCTION__, KeyIdx);
+					pIV = pWapiSta->lastTxUnicastPN;
+					pMicKey = pWapiSta->wapiUsk.micKey;
+					pDataKey = pWapiSta->wapiUsk.dataKey;
+				}
+  			}else{
+				WAPI_TRACE(WAPI_ERR,"%s: Can not find Peer Sta!!\n",__FUNCTION__);
+				return;
+			}
+		}else{
+			WAPI_TRACE(WAPI_ERR,"%s: wapiSTAUsedList is empty!!\n",__FUNCTION__);
+			return;
+		}
+	}
+
+	SecPtr = pframe;
+	SecCalculateMicSMS4(KeyIdx, pMicKey, SecPtr, (SecPtr+DataOffset), pattrib->pktlen, MicBuffer);
+
+	WAPI_DATA(WAPI_TX, "Encryption - MIC", MicBuffer, padapter->wapiInfo.extra_postfix_len);
+
+	memcpy(pframe+pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen-pattrib->icv_len,
+			(u8 *)MicBuffer,
+			padapter->wapiInfo.extra_postfix_len
+			);
+
+
+	WapiSMS4Encryption(pDataKey, pIV, (SecPtr+DataOffset),pattrib->pktlen+pattrib->icv_len, (SecPtr+DataOffset), &OutputLength);
+
+	WAPI_DATA(WAPI_TX, "Encryption - After SMS4 encryption",pframe,pattrib->hdrlen+pattrib->iv_len+pattrib->pktlen);
+
+	WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+}
+
+u8 SecSWSMS4Decryption(
+	_adapter *padapter,
+	u8 		*precv_frame,
+	struct recv_priv *precv_priv
+	)
+{
+	PRT_WAPI_T pWapiInfo = &padapter->wapiInfo;
+	struct recv_frame_hdr *precv_hdr;
+	PRT_WAPI_STA_INFO   pWapiSta = NULL;
+	u8 IVOffset, DataOffset, bFindMatchPeer = false, bUseUpdatedKey = false;
+	u8 KeyIdx, MicBuffer[16], lastRxPNforQoS[16];
+	u8 *pRA, *pTA, *pMicKey, *pDataKey, *pLastRxPN, *pRecvPN, *pSecData, *pRecvMic, *pos;
+	u8 TID = 0;
+	u16 OutputLength, DataLen;
+	u8   bQosData;
+	struct sk_buff * 	pskb;
+
+	WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
+
+	return 0;
+
+	precv_hdr = &((union recv_frame*)precv_frame)->u.hdr;
+	pskb = (struct sk_buff *)(precv_hdr->rx_data);
+	precv_hdr->bWapiCheckPNInDecrypt = WapiCheckPnInSwDecrypt(padapter, pskb);
+	WAPI_TRACE(WAPI_RX, "=========>%s: check PN  %d\n", __FUNCTION__,precv_hdr->bWapiCheckPNInDecrypt);
+	WAPI_DATA(WAPI_RX, "Decryption - Before decryption", pskb->data, pskb->len);
+
+	IVOffset = sMacHdrLng;
+	bQosData = GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE;
+	if (bQosData){
+		IVOffset += 2;
+	}
+
+	//if(GetHTC())
+	//	IVOffset += 4;
+
+	//IVOffset += SNAP_SIZE + sizeof(u16);
+
+	DataOffset = IVOffset + padapter->wapiInfo.extra_prefix_len;
+
+	pRA = pskb->data + 4;
+	pTA = pskb->data + 10;
+	KeyIdx = *(pskb->data + IVOffset);
+	pRecvPN = pskb->data + IVOffset + 2;
+	pSecData = pskb->data + DataOffset;
+	DataLen = pskb->len - DataOffset;
+	pRecvMic = pskb->data + pskb->len - padapter->wapiInfo.extra_postfix_len;
+	TID = GetTid(pskb->data);
+
+	if (!list_empty(&(pWapiInfo->wapiSTAUsedList))){
+		list_for_each_entry(pWapiSta, &pWapiInfo->wapiSTAUsedList, list) {
+			if (0 == memcmp(pWapiSta->PeerMacAddr, pTA, 6)){
+				bFindMatchPeer = true;
+				break;
+			}
+		}
+	}
+
+	if (!bFindMatchPeer){
+		WAPI_TRACE(WAPI_ERR, "%s: Can not find Peer Sta "MAC_FMT" for Key Info!!!\n", __FUNCTION__, MAC_ARG(pTA));
+		return false;
+	}
+
+	if( IS_MCAST(pRA) ){
+		WAPI_TRACE(WAPI_RX, "%s: Multicast decryption !!!\n", __FUNCTION__);
+		if (pWapiSta->wapiMsk.keyId == KeyIdx && pWapiSta->wapiMsk.bSet){
+			pLastRxPN = pWapiSta->lastRxMulticastPN;
+			if (!WapiComparePN(pRecvPN, pLastRxPN)){
+				WAPI_TRACE(WAPI_ERR, "%s: MSK PN is not larger than last, Dropped!!!\n", __FUNCTION__);
+				WAPI_DATA(WAPI_ERR, "pRecvPN:", pRecvPN, 16);
+				WAPI_DATA(WAPI_ERR, "pLastRxPN:", pLastRxPN, 16);
+				return false;
+			}
+
+			memcpy(pLastRxPN, pRecvPN, 16);
+			pMicKey = pWapiSta->wapiMsk.micKey;
+			pDataKey = pWapiSta->wapiMsk.dataKey;
+		}else if (pWapiSta->wapiMskUpdate.keyId == KeyIdx && pWapiSta->wapiMskUpdate.bSet){
+			WAPI_TRACE(WAPI_RX, "%s: Use Updated MSK for Decryption !!!\n", __FUNCTION__);
+			bUseUpdatedKey = true;
+			memcpy(pWapiSta->lastRxMulticastPN, pRecvPN, 16);
+			pMicKey = pWapiSta->wapiMskUpdate.micKey;
+			pDataKey = pWapiSta->wapiMskUpdate.dataKey;
+		}else{
+			WAPI_TRACE(WAPI_ERR, "%s: Can not find MSK with matched KeyIdx(%d), Dropped !!!\n", __FUNCTION__,KeyIdx);
+			return false;
+		}
+	}
+	else{
+		WAPI_TRACE(WAPI_RX, "%s: Unicast decryption !!!\n", __FUNCTION__);
+		if (pWapiSta->wapiUsk.keyId == KeyIdx && pWapiSta->wapiUsk.bSet){
+			WAPI_TRACE(WAPI_RX, "%s: Use USK for Decryption!!!\n", __FUNCTION__);
+			if(precv_hdr->bWapiCheckPNInDecrypt){
+				if(GetFrameType(pskb->data) == WIFI_QOS_DATA_TYPE){
+					WapiGetLastRxUnicastPNForQoSData(TID, pWapiSta, lastRxPNforQoS);
+					pLastRxPN = lastRxPNforQoS;
+				}else{
+					pLastRxPN = pWapiSta->lastRxUnicastPN;
+				}
+				if (!WapiComparePN(pRecvPN, pLastRxPN)){
+					return false;
+				}
+				if(bQosData){
+					WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+				}else{
+					memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+				}
+			}else{
+				memcpy(precv_hdr->WapiTempPN,pRecvPN,16);
+			}
+
+			if (check_fwstate(&padapter->mlmepriv, WIFI_STATION_STATE))
+			{
+				if ((pRecvPN[0] & 0x1) == 0){
+					WAPI_TRACE(WAPI_ERR, "%s: Rx USK PN is not odd when Infra STA mode, Dropped !!!\n", __FUNCTION__);
+					return false;
+				}
+			}
+
+			pMicKey = pWapiSta->wapiUsk.micKey;
+			pDataKey = pWapiSta->wapiUsk.dataKey;
+		}
+		else if (pWapiSta->wapiUskUpdate.keyId == KeyIdx && pWapiSta->wapiUskUpdate.bSet ){
+			WAPI_TRACE(WAPI_RX, "%s: Use Updated USK for Decryption!!!\n", __FUNCTION__);
+			if(pWapiSta->bAuthenticatorInUpdata)
+				bUseUpdatedKey = true;
+			else
+				bUseUpdatedKey = false;
+
+			if(bQosData){
+				WapiSetLastRxUnicastPNForQoSData(TID, pRecvPN, pWapiSta);
+			}else{
+				memcpy(pWapiSta->lastRxUnicastPN, pRecvPN, 16);
+			}
+			pMicKey = pWapiSta->wapiUskUpdate.micKey;
+			pDataKey = pWapiSta->wapiUskUpdate.dataKey;
+		}else{
+			WAPI_TRACE(WAPI_ERR, "%s: No valid USK!!!KeyIdx=%d pWapiSta->wapiUsk.keyId=%d pWapiSta->wapiUskUpdate.keyId=%d\n", __FUNCTION__, KeyIdx, pWapiSta->wapiUsk.keyId, pWapiSta->wapiUskUpdate.keyId);
+			//dump_buf(pskb->data,pskb->len);
+			return false;
+		}
+	}
+
+	WAPI_DATA(WAPI_RX, "Decryption - DataKey", pDataKey, 16);
+	WAPI_DATA(WAPI_RX, "Decryption - IV", pRecvPN, 16);
+	WapiSMS4Decryption(pDataKey, pRecvPN, pSecData, DataLen, pSecData, &OutputLength);
+
+	if (OutputLength != DataLen)
+		WAPI_TRACE(WAPI_ERR, "%s:  Output Length Error!!!!\n", __FUNCTION__);
+
+	WAPI_DATA(WAPI_RX, "Decryption - After decryption", pskb->data, pskb->len);
+
+	DataLen -= padapter->wapiInfo.extra_postfix_len;
+
+	SecCalculateMicSMS4(KeyIdx, pMicKey, pskb->data, pSecData, DataLen, MicBuffer);
+
+	WAPI_DATA(WAPI_RX, "Decryption - MIC received", pRecvMic, SMS4_MIC_LEN);
+	WAPI_DATA(WAPI_RX, "Decryption - MIC calculated", MicBuffer, SMS4_MIC_LEN);
+
+	if (0 == memcmp(MicBuffer, pRecvMic, padapter->wapiInfo.extra_postfix_len)){
+		WAPI_TRACE(WAPI_RX, "%s: Check MIC OK!!\n", __FUNCTION__);
+		if (bUseUpdatedKey){
+			// delete the old key
+			if ( IS_MCAST(pRA) ){
+				WAPI_TRACE(WAPI_API, "%s(): AE use new update MSK!!\n", __FUNCTION__);
+				pWapiSta->wapiMsk.keyId = pWapiSta->wapiMskUpdate.keyId;
+				memcpy(pWapiSta->wapiMsk.dataKey, pWapiSta->wapiMskUpdate.dataKey, 16);
+				memcpy(pWapiSta->wapiMsk.micKey, pWapiSta->wapiMskUpdate.micKey, 16);
+				pWapiSta->wapiMskUpdate.bTxEnable = pWapiSta->wapiMskUpdate.bSet = false;
+			}else{
+				WAPI_TRACE(WAPI_API, "%s(): AE use new update USK!!\n", __FUNCTION__);
+				pWapiSta->wapiUsk.keyId = pWapiSta->wapiUskUpdate.keyId;
+				memcpy(pWapiSta->wapiUsk.dataKey, pWapiSta->wapiUskUpdate.dataKey, 16);
+				memcpy(pWapiSta->wapiUsk.micKey, pWapiSta->wapiUskUpdate.micKey, 16);
+				pWapiSta->wapiUskUpdate.bTxEnable = pWapiSta->wapiUskUpdate.bSet = false;
+			}
+		}
+	}else{
+		WAPI_TRACE(WAPI_ERR, "%s:  Check MIC Error, Dropped !!!!\n", __FUNCTION__);
+		return false;
+	}
+
+	pos = pskb->data;
+	memmove(pos+padapter->wapiInfo.extra_prefix_len, pos, IVOffset);
+	skb_pull(pskb, padapter->wapiInfo.extra_prefix_len);
+
+	WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+
+	return true;
+}
+
+u32	rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
+{
+
+	u8	*pframe;
+	u32 res = _SUCCESS;
+
+	WAPI_TRACE(WAPI_TX, "=========>%s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_TX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
+		return _FAIL;
+	}
+
+	if(((struct xmit_frame*)pxmitframe)->buf_addr==NULL)
+		return _FAIL;
+
+	pframe = ((struct xmit_frame*)pxmitframe)->buf_addr + TXDESC_OFFSET;
+
+	SecSWSMS4Encryption(padapter, pxmitframe);
+
+	WAPI_TRACE(WAPI_TX, "<=========%s\n", __FUNCTION__);
+	return res;
+}
+
+u32	rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
+{
+	u8	*pframe;
+	u32 res = _SUCCESS;
+
+	WAPI_TRACE(WAPI_RX, "=========>%s\n", __FUNCTION__);
+
+	if ((!padapter->WapiSupport) || (!padapter->wapiInfo.bWapiEnable))
+	{
+		WAPI_TRACE(WAPI_RX, "<========== %s, WAPI not supported or enabled!\n", __FUNCTION__);
+		return _FAIL;
+	}
+
+
+	//drop packet when hw decrypt fail
+       //return tempraily
+	return _FAIL;
+
+	//pframe=(unsigned char *)((union recv_frame*)precvframe)->u.hdr.rx_data;
+
+	if (false == SecSWSMS4Decryption(padapter, precvframe, &padapter->recvpriv))
+	{
+		WAPI_TRACE(WAPI_ERR, "%s():SMS4 decrypt frame error\n",__FUNCTION__);
+		return _FAIL;
+	}
+
+	WAPI_TRACE(WAPI_RX, "<=========%s\n", __FUNCTION__);
+	return res;
+}
+
+#else
+
+u32	rtw_sms4_encrypt(_adapter *padapter, u8 *pxmitframe)
+{
+	WAPI_TRACE(WAPI_TX, "=========>Dummy %s\n", __FUNCTION__);
+	WAPI_TRACE(WAPI_TX, "<=========Dummy %s\n", __FUNCTION__);
+	return _SUCCESS;
+}
+
+u32	rtw_sms4_decrypt(_adapter *padapter, u8 *precvframe)
+{
+	WAPI_TRACE(WAPI_RX, "=========>Dummy %s\n", __FUNCTION__);
+	WAPI_TRACE(WAPI_RX, "<=========Dummy %s\n", __FUNCTION__);
+	return _SUCCESS;
+}
+
+#endif
+
+#endif
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wlan_util.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wlan_util.c
new file mode 100644
index 000000000..66bd0a07c
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_wlan_util.c
@@ -0,0 +1,4738 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_WLAN_UTIL_C_
+
+#include <drv_types.h>
+
+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
+#include <linux/inetdevice.h>
+#endif
+
+unsigned char ARTHEROS_OUI1[] = {0x00, 0x03, 0x7f};
+unsigned char ARTHEROS_OUI2[] = {0x00, 0x13, 0x74};
+
+unsigned char BROADCOM_OUI1[] = {0x00, 0x10, 0x18};
+unsigned char BROADCOM_OUI2[] = {0x00, 0x0a, 0xf7};
+unsigned char BROADCOM_OUI3[] = {0x00, 0x05, 0xb5};
+
+
+unsigned char CISCO_OUI[] = {0x00, 0x40, 0x96};
+unsigned char MARVELL_OUI[] = {0x00, 0x50, 0x43};
+unsigned char RALINK_OUI[] = {0x00, 0x0c, 0x43};
+unsigned char REALTEK_OUI[] = {0x00, 0xe0, 0x4c};
+unsigned char AIRGOCAP_OUI[] = {0x00, 0x0a, 0xf5};
+
+unsigned char REALTEK_96B_IE[] = {0x00, 0xe0, 0x4c, 0x02, 0x01, 0x20};
+
+extern unsigned char RTW_WPA_OUI[];
+extern unsigned char WPA_TKIP_CIPHER[4];
+extern unsigned char RSN_TKIP_CIPHER[4];
+
+#define R2T_PHY_DELAY	(0)
+
+//#define WAIT_FOR_BCN_TO_MIN	(3000)
+#define WAIT_FOR_BCN_TO_MIN	(6000)
+#define WAIT_FOR_BCN_TO_MAX	(20000)
+
+#define DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS 1000
+#define DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD 3
+
+static u8 rtw_basic_rate_cck[4] = {
+	IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
+	IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK
+};
+
+static u8 rtw_basic_rate_ofdm[3] = {
+	IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
+	IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
+};
+
+static u8 rtw_basic_rate_mix[7] = {
+	IEEE80211_CCK_RATE_1MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_2MB|IEEE80211_BASIC_RATE_MASK,
+	IEEE80211_CCK_RATE_5MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_CCK_RATE_11MB|IEEE80211_BASIC_RATE_MASK,
+	IEEE80211_OFDM_RATE_6MB|IEEE80211_BASIC_RATE_MASK, IEEE80211_OFDM_RATE_12MB|IEEE80211_BASIC_RATE_MASK,
+	IEEE80211_OFDM_RATE_24MB|IEEE80211_BASIC_RATE_MASK
+};
+
+int new_bcn_max = 3;
+
+int cckrates_included(unsigned char *rate, int ratelen)
+{
+	int	i;
+	
+	for(i = 0; i < ratelen; i++)
+	{
+		if  (  (((rate[i]) & 0x7f) == 2)	|| (((rate[i]) & 0x7f) == 4) ||
+			   (((rate[i]) & 0x7f) == 11)  || (((rate[i]) & 0x7f) == 22) )
+			return _TRUE;
+	}
+
+	return _FALSE;
+
+}
+
+int cckratesonly_included(unsigned char *rate, int ratelen)
+{
+	int	i;
+	
+	for(i = 0; i < ratelen; i++)
+	{
+		if  ( (((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
+			   (((rate[i]) & 0x7f) != 11)  && (((rate[i]) & 0x7f) != 22) )
+			return _FALSE;
+	}
+	
+	return _TRUE;
+}
+
+s8 rtw_get_tx_nss(_adapter *adapter, struct sta_info *psta)
+{
+	u8 rf_type = RF_1T1R, custom_rf_type, vht_mcs[2];
+	s8 nss = 1;
+
+	custom_rf_type = adapter->registrypriv.rf_config;
+	rtw_hal_get_hwreg(adapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+	
+	if (!psta)
+		return nss;
+	
+	/* rf_config is dependent on efuse or sw config */
+	if (custom_rf_type != RF_MAX_TYPE)
+		rf_type = custom_rf_type;
+	
+#ifdef CONFIG_80211AC_VHT
+	if (psta->vhtpriv.vht_option) {
+		u8 vht_mcs[2];
+		struct mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
+		struct vht_priv	*pvhtpriv_ap = &pmlmepriv->vhtpriv;
+		
+		_rtw_memcpy(vht_mcs, psta->vhtpriv.vht_mcs_map, 2);
+		/* doesn't support 5~8 SS so far */
+		vht_mcs[1] = 0xff;
+		switch (rf_type) {
+		case RF_1T1R:
+		case RF_1T2R:
+			vht_mcs[0] |= 0xfc;
+			break;
+		case RF_2T2R:
+		case RF_2T4R:
+		case RF_2T2R_GREEN:
+		case RF_2T3R:
+			vht_mcs[0] |= 0xf0;
+			break;
+		case RF_3T3R:
+		case RF_3T4R:
+			vht_mcs[0] |= 0xc0;
+			break;
+		default:
+			DBG_871X("%s,%d, unknown rf type\n", __func__, __LINE__);
+			break;
+		}
+		nss = rtw_vht_mcsmap_to_nss(vht_mcs);
+	} else
+#endif /* CONFIG_80211AC_VHT */
+	if (psta->htpriv.ht_option) {
+		u8 supp_mcs_set[4];
+
+		_rtw_memcpy(supp_mcs_set, psta->htpriv.ht_cap.supp_mcs_set, 4);
+		
+		switch (rf_type) {
+		case RF_1T1R:
+		case RF_1T2R:
+			supp_mcs_set[1] = supp_mcs_set[2] = supp_mcs_set[3] = 0;
+			break;
+		case RF_2T2R:
+		case RF_2T4R:
+		case RF_2T2R_GREEN:
+		case RF_2T3R:
+			supp_mcs_set[2] = supp_mcs_set[3] = 0;
+			break;
+		case RF_3T3R:
+		case RF_3T4R:
+			supp_mcs_set[3] = 0;
+			break;
+		default:
+			DBG_871X("%s,%d, unknown rf type\n", __func__, __LINE__);
+			break;
+		}
+		nss = rtw_ht_mcsset_to_nss(supp_mcs_set);
+	}
+	
+	DBG_871X("%s: %d SS, rf_type=%d\n", __func__, nss, rf_type);
+	return nss;
+}
+
+u8 networktype_to_raid(_adapter *adapter,struct sta_info *psta)
+{
+	unsigned char raid;
+	switch(psta->wireless_mode)
+	{
+		case WIRELESS_11B:
+			raid = RATR_INX_WIRELESS_B;
+			break;
+		case WIRELESS_11A:
+		case WIRELESS_11G:
+			raid = RATR_INX_WIRELESS_G;
+			break;
+		case WIRELESS_11BG:
+			raid = RATR_INX_WIRELESS_GB;
+			break;
+		case WIRELESS_11_24N:
+		case WIRELESS_11_5N:
+			raid = RATR_INX_WIRELESS_N;
+			break;
+		case WIRELESS_11A_5N:
+		case WIRELESS_11G_24N:
+			raid = RATR_INX_WIRELESS_NG;
+			break;
+		case WIRELESS_11BG_24N:
+			raid = RATR_INX_WIRELESS_NGB;
+			break;
+		default:
+			raid = RATR_INX_WIRELESS_GB;
+			break;	
+
+	}
+	return raid;
+	
+}
+
+u8 networktype_to_raid_ex(_adapter *adapter, struct sta_info *psta)
+{
+	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
+	u8 raid = RATEID_IDX_BGN_40M_1SS, cur_rf_type, rf_type, custom_rf_type;
+	s8 tx_nss;
+
+	tx_nss = rtw_get_tx_nss(adapter, psta);
+
+	switch(psta->wireless_mode)
+	{
+		case WIRELESS_11B:
+			raid = RATEID_IDX_B;
+			break;
+		case WIRELESS_11A:
+		case WIRELESS_11G:
+			raid = RATEID_IDX_G;
+			break;
+		case WIRELESS_11BG:
+			raid = RATEID_IDX_BG;
+			break;
+		case WIRELESS_11_24N:
+		case WIRELESS_11_5N:
+		case WIRELESS_11A_5N:
+		case WIRELESS_11G_24N:
+			if (tx_nss == 1)
+				raid = RATEID_IDX_GN_N1SS;
+			else if (tx_nss == 2)
+				raid = RATEID_IDX_GN_N2SS;
+			else if (tx_nss == 3)
+				raid = RATEID_IDX_BGN_3SS;
+			else
+				DBG_871X("tx_nss error!(tx_nss=%d)\n", tx_nss);
+			break;
+		case WIRELESS_11B_24N:
+		case WIRELESS_11BG_24N:
+			if (psta->bw_mode == CHANNEL_WIDTH_20) {
+				if (tx_nss == 1)
+					raid = RATEID_IDX_BGN_20M_1SS_BN;
+				else if (tx_nss == 2)
+					raid = RATEID_IDX_BGN_20M_2SS_BN;
+				else if (tx_nss == 3)
+					raid = RATEID_IDX_BGN_3SS;
+				else
+				DBG_871X("tx_nss error!(tx_nss=%d)\n", tx_nss);
+			} else {
+				if (tx_nss == 1)
+					raid = RATEID_IDX_BGN_40M_1SS;
+				else if (tx_nss == 2)
+					raid = RATEID_IDX_BGN_40M_2SS;
+				else if (tx_nss == 3)
+					raid = RATEID_IDX_BGN_3SS;
+				else
+				DBG_871X("tx_nss error!(tx_nss=%d)\n", tx_nss);
+			}
+			break;
+#ifdef CONFIG_80211AC_VHT
+		case WIRELESS_11_5AC:
+			if (tx_nss == 1)
+				raid = RATEID_IDX_VHT_1SS;
+			else if (tx_nss == 2)
+				raid = RATEID_IDX_VHT_2SS;
+			else if (tx_nss == 3)
+				raid = RATEID_IDX_VHT_3SS;
+			else
+				DBG_871X("tx_nss error!(tx_nss=%d)\n", tx_nss);
+			break;
+		case WIRELESS_11_24AC:
+			if (psta->bw_mode >= CHANNEL_WIDTH_80)
+			{
+				if (tx_nss == 1)
+					raid = RATEID_IDX_VHT_1SS;
+				else if (tx_nss == 2)
+					raid = RATEID_IDX_VHT_2SS;
+				else if (tx_nss == 3)
+					raid = RATEID_IDX_VHT_3SS;
+				else
+					DBG_871X("tx_nss error!(tx_nss=%d)\n", tx_nss);
+			}
+			else
+			{
+				if (tx_nss == 1)
+					raid = RATEID_IDX_MIX1;
+				else if (tx_nss == 2)
+					raid = RATEID_IDX_MIX2;
+				else if (tx_nss == 3)
+					raid = RATEID_IDX_VHT_3SS;
+				else
+					DBG_871X("tx_nss error!(tx_nss=%d)\n", tx_nss);
+			}
+			break;
+#endif
+		default:
+			DBG_871X("unexpected wireless mode!(psta->wireless_mode=%x)\n", psta->wireless_mode);
+			break;	
+
+	}
+	
+	/* DBG_871X("psta->wireless_mode=%x,  tx_nss=%d\n", psta->wireless_mode, tx_nss); */
+	
+	return raid;
+	
+}
+
+u8 judge_network_type(_adapter *padapter, unsigned char *rate, int ratelen)
+{
+	u8 network_type = 0;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+
+	if(pmlmeext->cur_channel > 14)
+	{
+		if (pmlmeinfo->VHT_enable)
+			network_type = WIRELESS_11AC;
+		else if (pmlmeinfo->HT_enable)
+			network_type = WIRELESS_11_5N;
+
+		network_type |= WIRELESS_11A;
+	}
+	else
+	{
+		if (pmlmeinfo->HT_enable)
+		{
+			network_type = WIRELESS_11_24N;
+		}
+
+		if ((cckratesonly_included(rate, ratelen)) == _TRUE)
+		{
+			network_type |= WIRELESS_11B;
+		}
+		else if((cckrates_included(rate, ratelen)) == _TRUE)
+		{
+			network_type |= WIRELESS_11BG;
+		}
+		else
+		{
+			network_type |= WIRELESS_11G;
+		}
+	}
+		
+	return 	network_type;
+}
+
+unsigned char ratetbl_val_2wifirate(unsigned char rate);
+unsigned char ratetbl_val_2wifirate(unsigned char rate)
+{
+	unsigned char val = 0;
+
+	switch (rate & 0x7f) 
+	{
+		case 0:
+			val = IEEE80211_CCK_RATE_1MB;
+			break;
+
+		case 1:
+			val = IEEE80211_CCK_RATE_2MB;
+			break;
+
+		case 2:
+			val = IEEE80211_CCK_RATE_5MB;
+			break;
+
+		case 3:
+			val = IEEE80211_CCK_RATE_11MB;
+			break;
+			
+		case 4:
+			val = IEEE80211_OFDM_RATE_6MB;
+			break;
+
+		case 5:
+			val = IEEE80211_OFDM_RATE_9MB;
+			break;
+
+		case 6:
+			val = IEEE80211_OFDM_RATE_12MB;
+			break;
+			
+		case 7:
+			val = IEEE80211_OFDM_RATE_18MB;
+			break;
+
+		case 8:
+			val = IEEE80211_OFDM_RATE_24MB;
+			break;
+			
+		case 9:
+			val = IEEE80211_OFDM_RATE_36MB;
+			break;
+
+		case 10:
+			val = IEEE80211_OFDM_RATE_48MB;
+			break;
+		
+		case 11:
+			val = IEEE80211_OFDM_RATE_54MB;
+			break;
+
+	}
+
+	return val;
+
+}
+
+int is_basicrate(_adapter *padapter, unsigned char rate);
+int is_basicrate(_adapter *padapter, unsigned char rate)
+{
+	int i;
+	unsigned char val;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	
+	for(i = 0; i < NumRates; i++)
+	{
+		val = pmlmeext->basicrate[i];
+
+		if ((val != 0xff) && (val != 0xfe))
+		{
+			if (rate == ratetbl_val_2wifirate(val))
+			{
+				return _TRUE;
+			}
+		}
+	}
+	
+	return _FALSE;
+}
+
+unsigned int ratetbl2rateset(_adapter *padapter, unsigned char *rateset);
+unsigned int ratetbl2rateset(_adapter *padapter, unsigned char *rateset)
+{
+	int i;
+	unsigned char rate;
+	unsigned int	len = 0;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	for (i = 0; i < NumRates; i++)
+	{
+		rate = pmlmeext->datarate[i];
+
+		switch (rate)
+		{
+			case 0xff:
+				return len;
+				
+			case 0xfe:
+				continue;
+				
+			default:
+				rate = ratetbl_val_2wifirate(rate);
+
+				if (is_basicrate(padapter, rate) == _TRUE)
+				{
+					rate |= IEEE80211_BASIC_RATE_MASK;
+				}
+				
+				rateset[len] = rate;
+				len++;
+				break;
+		}
+	}
+	return len;
+}
+
+void get_rate_set(_adapter *padapter, unsigned char *pbssrate, int *bssrate_len)
+{
+	unsigned char supportedrates[NumRates];
+
+	_rtw_memset(supportedrates, 0, NumRates);
+	*bssrate_len = ratetbl2rateset(padapter, supportedrates);
+	_rtw_memcpy(pbssrate, supportedrates, *bssrate_len);
+}
+
+void set_mcs_rate_by_mask(u8 *mcs_set, u32 mask)
+{
+	u8 mcs_rate_1r = (u8)(mask&0xff);
+	u8 mcs_rate_2r = (u8)((mask>>8)&0xff);
+	u8 mcs_rate_3r = (u8)((mask>>16)&0xff);
+	u8 mcs_rate_4r = (u8)((mask>>24)&0xff);
+
+	mcs_set[0] &= mcs_rate_1r;
+	mcs_set[1] &= mcs_rate_2r;
+	mcs_set[2] &= mcs_rate_3r;
+	mcs_set[3] &= mcs_rate_4r;
+}
+
+void UpdateBrateTbl(
+	IN PADAPTER		Adapter,
+	IN u8			*mBratesOS
+)
+{
+	u8	i;
+	u8	rate;
+
+	// 1M, 2M, 5.5M, 11M, 6M, 12M, 24M are mandatory.
+	for(i=0;i<NDIS_802_11_LENGTH_RATES_EX;i++)
+	{
+		rate = mBratesOS[i] & 0x7f;
+		switch(rate)
+		{
+			case IEEE80211_CCK_RATE_1MB:
+			case IEEE80211_CCK_RATE_2MB:
+			case IEEE80211_CCK_RATE_5MB:
+			case IEEE80211_CCK_RATE_11MB:
+			case IEEE80211_OFDM_RATE_6MB:
+			case IEEE80211_OFDM_RATE_12MB:
+			case IEEE80211_OFDM_RATE_24MB:
+				mBratesOS[i] |= IEEE80211_BASIC_RATE_MASK;
+				break;
+		}
+	}
+
+}
+
+void UpdateBrateTblForSoftAP(u8 *bssrateset, u32 bssratelen)
+{
+	u8	i;
+	u8	rate;
+
+	for(i=0;i<bssratelen;i++)
+	{
+		rate = bssrateset[i] & 0x7f;
+		switch(rate)
+		{
+			case IEEE80211_CCK_RATE_1MB:
+			case IEEE80211_CCK_RATE_2MB:
+			case IEEE80211_CCK_RATE_5MB:
+			case IEEE80211_CCK_RATE_11MB:
+				bssrateset[i] |= IEEE80211_BASIC_RATE_MASK;
+				break;
+		}
+	}
+
+}
+static void Set_NETYPE1_MSR(_adapter *padapter, u8 type)
+{
+	rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS1, (u8 *)(&type));
+}
+
+static void Set_NETYPE0_MSR(_adapter *padapter, u8 type)
+{
+	rtw_hal_set_hwreg(padapter, HW_VAR_MEDIA_STATUS, (u8 *)(&type));
+}
+
+void Set_MSR(_adapter *padapter, u8 type)
+{
+#ifdef CONFIG_CONCURRENT_MODE
+	if(padapter->iface_type == IFACE_PORT1)
+	{
+		Set_NETYPE1_MSR(padapter, type);
+	}
+	else
+#endif
+	{
+		Set_NETYPE0_MSR(padapter, type);
+	}
+}
+
+inline u8 rtw_get_oper_ch(_adapter *adapter)
+{
+	return adapter_to_dvobj(adapter)->oper_channel;
+}
+
+inline void rtw_set_oper_ch(_adapter *adapter, u8 ch)
+{
+#ifdef DBG_CH_SWITCH
+	const int len = 128;
+	char msg[128] = {0};
+	int cnt = 0;
+	int i = 0;
+#endif  /* DBG_CH_SWITCH */
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	
+	if (dvobj->oper_channel != ch) {
+		dvobj->on_oper_ch_time = rtw_get_current_time();
+
+#ifdef DBG_CH_SWITCH
+		cnt += snprintf(msg+cnt, len-cnt, "switch to ch %3u", ch);
+
+		for (i = 0; i < dvobj->iface_nums; i++) {
+			_adapter *iface = dvobj->padapters[i];
+			cnt += snprintf(msg+cnt, len-cnt, " ["ADPT_FMT":", ADPT_ARG(iface));
+			if (iface->mlmeextpriv.cur_channel == ch)
+				cnt += snprintf(msg+cnt, len-cnt, "C");
+			else
+				cnt += snprintf(msg+cnt, len-cnt, "_");
+			if (iface->wdinfo.listen_channel == ch && !rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_NONE))
+				cnt += snprintf(msg+cnt, len-cnt, "L");
+			else
+				cnt += snprintf(msg+cnt, len-cnt, "_");
+			cnt += snprintf(msg+cnt, len-cnt, "]");
+		}
+
+		DBG_871X(FUNC_ADPT_FMT" %s\n", FUNC_ADPT_ARG(adapter), msg);
+#endif /* DBG_CH_SWITCH */
+	}
+
+	dvobj->oper_channel = ch;
+}
+
+inline u8 rtw_get_oper_bw(_adapter *adapter)
+{
+	return adapter_to_dvobj(adapter)->oper_bwmode;
+}
+
+inline void rtw_set_oper_bw(_adapter *adapter, u8 bw)
+{
+	adapter_to_dvobj(adapter)->oper_bwmode = bw;
+}
+
+inline u8 rtw_get_oper_choffset(_adapter *adapter)
+{
+	return adapter_to_dvobj(adapter)->oper_ch_offset;
+}
+
+inline void rtw_set_oper_choffset(_adapter *adapter, u8 offset)
+{
+	adapter_to_dvobj(adapter)->oper_ch_offset = offset;
+}
+
+u8 rtw_get_offset_by_ch(u8 channel)
+{
+	u8 offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+
+	if(channel>=1 && channel<=4)
+	{
+		offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+	}
+	else if(channel>=5 && channel<=14)
+	{
+		offset = HAL_PRIME_CHNL_OFFSET_UPPER;						
+	}
+	else
+	{
+		switch(channel)
+		{
+			case 36:
+			case 44:
+			case 52:
+			case 60:
+			case 100:
+			case 108:
+			case 116:
+			case 124:
+			case 132:
+			case 149:
+			case 157:
+				offset = HAL_PRIME_CHNL_OFFSET_LOWER;				
+				break;		
+			case 40:
+			case 48:
+			case 56:
+			case 64:
+			case 104:
+			case 112:
+			case 120:
+			case 128:
+			case 136:
+			case 153:
+			case 161:				
+				offset = HAL_PRIME_CHNL_OFFSET_UPPER;				
+				break;				
+			default:
+				offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+				break;
+		}
+
+	}
+
+	return offset;
+		
+}
+
+u8	rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset)
+{
+	u8	center_ch = channel;
+
+	if(chnl_bw == CHANNEL_WIDTH_80)
+	{
+		if((channel == 36) || (channel == 40) || (channel == 44) || (channel == 48) )
+			center_ch = 42;
+		if((channel == 52) || (channel == 56) || (channel == 60) || (channel == 64) )
+			center_ch = 58;
+		if((channel == 100) || (channel == 104) || (channel == 108) || (channel == 112) )
+			center_ch = 106;
+		if((channel == 116) || (channel == 120) || (channel == 124) || (channel == 128) )
+			center_ch = 122;
+		if((channel == 132) || (channel == 136) || (channel == 140) || (channel == 144) )
+			center_ch = 138;
+		if((channel == 149) || (channel == 153) || (channel == 157) || (channel == 161) )
+			center_ch = 155;
+		else if(channel <= 14)
+			center_ch = 7;
+	}
+	else if(chnl_bw == CHANNEL_WIDTH_40)
+	{
+		if (chnl_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
+			center_ch = channel + 2;
+		else
+			center_ch = channel - 2;
+	}
+
+	return center_ch;
+}
+
+inline u32 rtw_get_on_oper_ch_time(_adapter *adapter)
+{
+	return adapter_to_dvobj(adapter)->on_oper_ch_time;
+}
+
+inline u32 rtw_get_on_cur_ch_time(_adapter *adapter)
+{
+	if (adapter->mlmeextpriv.cur_channel == adapter_to_dvobj(adapter)->oper_channel)
+		return adapter_to_dvobj(adapter)->on_oper_ch_time;
+	else
+		return 0;
+}
+
+void SelectChannel(_adapter *padapter, unsigned char channel)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;	
+
+	_enter_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
+
+#ifdef CONFIG_DFS_MASTER
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
+	bool ori_overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
+	bool new_overlap_radar_detect_ch = _rtw_rfctl_overlap_radar_detect_ch(rfctl, channel
+		, adapter_to_dvobj(padapter)->oper_bwmode, adapter_to_dvobj(padapter)->oper_ch_offset);
+
+	if (!ori_overlap_radar_detect_ch && new_overlap_radar_detect_ch)
+		rtw_odm_radar_detect_enable(padapter);
+
+	if (new_overlap_radar_detect_ch && IS_UNDER_CAC(rfctl)) {
+		u8 pause = 0xFF;
+
+		rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &pause);
+	}
+#endif /* CONFIG_DFS_MASTER */
+
+	//saved channel info
+	rtw_set_oper_ch(padapter, channel);
+
+	rtw_hal_set_chan(padapter, channel);
+
+#ifdef CONFIG_DFS_MASTER
+	if (ori_overlap_radar_detect_ch && !new_overlap_radar_detect_ch) {
+		u8 pause = 0x00;
+
+		rtw_odm_radar_detect_disable(padapter);
+		rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &pause);
+	}
+}
+#endif /* CONFIG_DFS_MASTER */
+
+	_exit_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
+		
+}
+
+void SetBWMode(_adapter *padapter, unsigned short bwmode, unsigned char channel_offset)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	_enter_critical_mutex(&(adapter_to_dvobj(padapter)->setbw_mutex), NULL);
+
+#ifdef CONFIG_DFS_MASTER
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
+	bool ori_overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
+	bool new_overlap_radar_detect_ch = _rtw_rfctl_overlap_radar_detect_ch(rfctl
+		, adapter_to_dvobj(padapter)->oper_channel, bwmode, channel_offset);
+
+	if (!ori_overlap_radar_detect_ch && new_overlap_radar_detect_ch)
+		rtw_odm_radar_detect_enable(padapter);
+
+	if (new_overlap_radar_detect_ch && IS_UNDER_CAC(rfctl)) {
+		u8 pause = 0xFF;
+
+		rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &pause);
+	}
+#endif /* CONFIG_DFS_MASTER */
+
+	//saved bw info
+	rtw_set_oper_bw(padapter, bwmode);
+	rtw_set_oper_choffset(padapter, channel_offset);
+
+	rtw_hal_set_bwmode(padapter, (CHANNEL_WIDTH)bwmode, channel_offset);
+
+#ifdef CONFIG_DFS_MASTER
+	if (ori_overlap_radar_detect_ch && !new_overlap_radar_detect_ch) {
+		u8 pause = 0x00;
+
+		rtw_odm_radar_detect_disable(padapter);
+		rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &pause);
+	}
+}
+#endif /* CONFIG_DFS_MASTER */
+
+	_exit_critical_mutex(&(adapter_to_dvobj(padapter)->setbw_mutex), NULL);
+}
+
+void set_channel_bwmode(_adapter *padapter, unsigned char channel, unsigned char channel_offset, unsigned short bwmode)
+{
+	u8 center_ch, chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+
+	if ( padapter->bNotifyChannelChange )
+	{
+		DBG_871X( "[%s] ch = %d, offset = %d, bwmode = %d\n", __FUNCTION__, channel, channel_offset, bwmode );
+	}
+
+	center_ch = rtw_get_center_ch(channel, bwmode, channel_offset);
+
+	if(bwmode == CHANNEL_WIDTH_80)
+	{
+		if(center_ch > channel)
+			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;
+		else if(center_ch < channel)
+			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;
+		else
+			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	}
+	_enter_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
+
+#ifdef CONFIG_DFS_MASTER
+{
+	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
+	bool ori_overlap_radar_detect_ch = rtw_rfctl_overlap_radar_detect_ch(rfctl);
+	bool new_overlap_radar_detect_ch = _rtw_rfctl_overlap_radar_detect_ch(rfctl, channel, bwmode, channel_offset);
+
+	if (!ori_overlap_radar_detect_ch && new_overlap_radar_detect_ch)
+		rtw_odm_radar_detect_enable(padapter);
+
+	if (new_overlap_radar_detect_ch && IS_UNDER_CAC(rfctl)) {
+		u8 pause = 0xFF;
+
+		rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &pause);
+	}
+#endif /* CONFIG_DFS_MASTER */
+
+	//set Channel
+	//saved channel/bw info
+	rtw_set_oper_ch(padapter, channel);
+	rtw_set_oper_bw(padapter, bwmode);
+	rtw_set_oper_choffset(padapter, channel_offset);
+
+	rtw_hal_set_chnl_bw(padapter, center_ch, bwmode, channel_offset, chnl_offset80); // set center channel
+
+#ifdef CONFIG_DFS_MASTER
+	if (ori_overlap_radar_detect_ch && !new_overlap_radar_detect_ch) {
+		u8 pause = 0x00;
+
+		rtw_odm_radar_detect_disable(padapter);
+		rtw_hal_set_hwreg(padapter, HW_VAR_TXPAUSE, &pause);
+	}
+}
+#endif /* CONFIG_DFS_MASTER */
+
+	_exit_critical_mutex(&(adapter_to_dvobj(padapter)->setch_mutex), NULL);
+}
+
+int get_bsstype(unsigned short capability)
+{
+	if (capability & BIT(0))
+	{
+		return WIFI_FW_AP_STATE;
+	}
+	else if (capability & BIT(1))
+	{
+		return WIFI_FW_ADHOC_STATE;
+	}
+	else
+	{
+		return 0;		
+	}
+}
+
+__inline u8 *get_my_bssid(WLAN_BSSID_EX *pnetwork)
+{	
+	return (pnetwork->MacAddress); 
+}
+
+u16 get_beacon_interval(WLAN_BSSID_EX *bss)
+{
+	unsigned short val;
+	_rtw_memcpy((unsigned char *)&val, rtw_get_beacon_interval_from_ie(bss->IEs), 2);
+
+	return le16_to_cpu(val);	
+
+}
+
+int is_client_associated_to_ap(_adapter *padapter)
+{
+	struct mlme_ext_priv	*pmlmeext;
+	struct mlme_ext_info	*pmlmeinfo;
+
+	if(!padapter)
+		return _FAIL;
+
+	pmlmeext = &padapter->mlmeextpriv;
+	pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_STATION_STATE))
+	{
+		return _TRUE;
+	}
+	else
+	{
+		return _FAIL;
+	}
+}
+
+int is_client_associated_to_ibss(_adapter *padapter)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	if ((pmlmeinfo->state & WIFI_FW_ASSOC_SUCCESS) && ((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
+	{
+		return _TRUE;
+	}
+	else
+	{
+		return _FAIL;
+	}
+}
+
+int is_IBSS_empty(_adapter *padapter)
+{
+	unsigned int i;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	for (i = IBSS_START_MAC_ID; i < NUM_STA; i++)
+	{
+		if (pmlmeinfo->FW_sta_info[i].status == 1)
+		{
+			return _FAIL;
+		}
+	}
+	
+	return _TRUE;
+	
+}
+
+unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval)
+{
+	if ((bcn_interval << 2) < WAIT_FOR_BCN_TO_MIN)
+	{
+		return WAIT_FOR_BCN_TO_MIN;
+	} 
+	else if ((bcn_interval << 2) > WAIT_FOR_BCN_TO_MAX)
+	{
+		return WAIT_FOR_BCN_TO_MAX;
+	}	
+	else
+	{
+		return ((bcn_interval << 2));
+	}
+}
+
+void CAM_empty_entry(
+	PADAPTER     	Adapter,	
+	u8 			ucIndex
+)
+{
+	rtw_hal_set_hwreg(Adapter, HW_VAR_CAM_EMPTY_ENTRY, (u8 *)(&ucIndex));
+}
+
+void invalidate_cam_all(_adapter *padapter)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+	u8 val8 = 0;
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_CAM_INVALID_ALL, &val8);
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	rtw_sec_cam_map_clr_all(&cam_ctl->used);
+	_rtw_memset(dvobj->cam_cache, 0, sizeof(struct sec_cam_ent) * SEC_CAM_ENT_NUM_SW_LIMIT);
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+}
+
+void _clear_cam_entry(_adapter *padapter, u8 entry)
+{
+	unsigned char null_sta[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+	unsigned char null_key[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00};
+
+	rtw_sec_write_cam_ent(padapter, entry, 0, null_sta, null_key);
+}
+
+inline void write_cam(_adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
+{
+#ifdef CONFIG_WRITE_CACHE_ONLY
+	write_cam_cache(adapter, id ,ctrl, mac, key);
+#else
+	rtw_sec_write_cam_ent(adapter, id, ctrl, mac, key);
+	write_cam_cache(adapter, id ,ctrl, mac, key);
+#endif
+}
+
+inline void clear_cam_entry(_adapter *adapter, u8 id)
+{
+	_clear_cam_entry(adapter, id);
+	clear_cam_cache(adapter, id);
+}
+
+inline void write_cam_from_cache(_adapter *adapter, u8 id)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+	struct sec_cam_ent cache;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	_rtw_memcpy(&cache, &dvobj->cam_cache[id], sizeof(struct sec_cam_ent));
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+
+	rtw_sec_write_cam_ent(adapter, id, cache.ctrl, cache.mac, cache.key);
+}
+
+void write_cam_cache(_adapter *adapter, u8 id, u16 ctrl, u8 *mac, u8 *key)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+
+	dvobj->cam_cache[id].ctrl = ctrl;
+	_rtw_memcpy(dvobj->cam_cache[id].mac, mac, ETH_ALEN);
+	_rtw_memcpy(dvobj->cam_cache[id].key, key, 16);
+
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+}
+
+void clear_cam_cache(_adapter *adapter, u8 id)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+
+	_rtw_memset(&(dvobj->cam_cache[id]), 0, sizeof(struct sec_cam_ent));
+
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+}
+
+s16 rtw_get_camid(_adapter *adapter, struct sta_info *sta, s16 kid)
+{
+	u8 macid;
+	s16 camid;
+
+	//cam_entry:
+	//0~3 for default key
+
+	//for concurrent mode (ap+sta, sta+sta):
+	//default key is disable, using sw encrypt/decrypt
+	//camid 0, 1, 2, 3 is default entry for default key/group key
+	//macid = 1 is for bc/mc stainfo, no mapping to camid
+	//macid = 0 mapping to camid 4
+	//for macid >=2, camid = macid+3;
+
+	if (sta) {
+		struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
+		macid = sta->mac_id;
+
+		if((mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) {
+			if((macid == 1) || (macid>(NUM_STA-4))){
+				DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" failed, mac_id=%d\n", FUNC_ADPT_ARG(adapter), macid);
+				camid = -1;
+				goto exit;
+			}
+		}
+
+		if(macid==0)
+			camid = 4;
+		else if(macid >=2)
+			camid = macid + 3;
+		else
+			camid = 4;
+	}
+	else {
+		/* default key is disabled */
+		camid = -1;
+	}
+
+exit:
+	return (s16)camid;
+}
+
+inline bool _rtw_camctl_chk_cap(_adapter *adapter, u8 cap)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+
+	if (cam_ctl->sec_cap & cap)
+		return _TRUE;
+	return _FALSE;
+}
+
+inline void _rtw_camctl_set_flags(_adapter *adapter, u32 flags)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+
+	cam_ctl->flags |= flags;
+}
+
+inline void rtw_camctl_set_flags(_adapter *adapter, u32 flags)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	_rtw_camctl_set_flags(adapter, flags);
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+}
+
+inline void _rtw_camctl_clr_flags(_adapter *adapter, u32 flags)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+
+	cam_ctl->flags &= ~flags;
+}
+
+inline void rtw_camctl_clr_flags(_adapter *adapter, u32 flags)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	_rtw_camctl_clr_flags(adapter, flags);
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+}
+
+inline bool _rtw_camctl_chk_flags(_adapter *adapter, u32 flags)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+
+	if (cam_ctl->flags & flags)
+		return _TRUE;
+	return _FALSE;
+}
+
+void dump_sec_cam_map(void *sel, struct sec_cam_bmp *map, u8 max_num)
+{
+	DBG_871X_SEL_NL(sel, "0x%08x\n", map->m0);
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	if (max_num && max_num > 32)
+		DBG_871X_SEL_NL(sel, "0x%08x\n", map->m1);
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	if (max_num && max_num > 64)
+		DBG_871X_SEL_NL(sel, "0x%08x\n", map->m2);
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	if (max_num && max_num > 96)
+		DBG_871X_SEL_NL(sel, "0x%08x\n", map->m3);
+#endif
+}
+
+inline bool rtw_sec_camid_is_set(struct sec_cam_bmp *map, u8 id)
+{
+	if (id < 32)
+		return (map->m0 & BIT(id));
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		return (map->m1 & BIT(id - 32));
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		return (map->m2 & BIT(id - 64));
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		return (map->m3 & BIT(id - 96));
+#endif
+	else
+		rtw_warn_on(1);
+
+	return 0;
+}
+
+inline void rtw_sec_cam_map_set(struct sec_cam_bmp *map, u8 id)
+{
+	if (id < 32)
+		map->m0 |= BIT(id);
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		map->m1 |= BIT(id - 32);
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		map->m2 |= BIT(id - 64);
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		map->m3 |= BIT(id - 96);
+#endif
+	else
+		rtw_warn_on(1);
+}
+
+inline void rtw_sec_cam_map_clr(struct sec_cam_bmp *map, u8 id)
+{
+	if (id < 32)
+		map->m0 &= ~BIT(id);
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		map->m1 &= ~BIT(id-32);
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		map->m2 &= ~BIT(id-64);
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		map->m3 &= ~BIT(id-96);
+#endif
+	else
+		rtw_warn_on(1);
+}
+
+inline void rtw_sec_cam_map_clr_all(struct sec_cam_bmp *map)
+{
+	map->m0 = 0;
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	map->m1 = 0;
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	map->m2 = 0;
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	map->m3 = 0;
+#endif
+}
+
+inline bool rtw_sec_camid_is_drv_forbid(struct cam_ctl_t *cam_ctl, u8 id)
+{
+	struct sec_cam_bmp forbid_map;
+
+	forbid_map.m0 = 0x00000ff0;
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	forbid_map.m1 = 0x00000000;
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	forbid_map.m2 = 0x00000000;
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	forbid_map.m3 = 0x00000000;
+#endif
+
+	if (id < 32)
+		return (forbid_map.m0 & BIT(id));
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		return (forbid_map.m1 & BIT(id - 32));
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		return (forbid_map.m2 & BIT(id - 64));
+#endif
+#if (SEC_CAM_ENT_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		return (forbid_map.m3 & BIT(id - 96));
+#endif
+	else
+		rtw_warn_on(1);
+
+	return 1;
+}
+
+bool _rtw_sec_camid_is_used(struct cam_ctl_t *cam_ctl, u8 id)
+{
+	bool ret = _FALSE;
+
+	if (id >= cam_ctl->num) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	#if 0 /* for testing */
+	if (rtw_sec_camid_is_drv_forbid(cam_ctl, id)) {
+		ret = _TRUE;
+		goto exit;
+	}
+	#endif
+
+	ret = rtw_sec_camid_is_set(&cam_ctl->used, id);
+
+exit:
+	return ret;
+}
+
+inline bool rtw_sec_camid_is_used(struct cam_ctl_t *cam_ctl, u8 id)
+{
+	_irqL irqL;
+	bool ret;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	ret = _rtw_sec_camid_is_used(cam_ctl, id);
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+
+	return ret;
+}
+
+inline bool _rtw_camid_is_gk(_adapter *adapter, u8 cam_id)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	bool ret = _FALSE;
+
+	if (cam_id >= cam_ctl->num) {
+		rtw_warn_on(1);
+		goto exit;
+	}
+
+	if (_rtw_sec_camid_is_used(cam_ctl, cam_id) == _FALSE)
+		goto exit;
+	
+	ret = (dvobj->cam_cache[cam_id].ctrl&BIT6)?_TRUE:_FALSE;
+
+exit:
+	return ret;
+}
+
+inline bool rtw_camid_is_gk(_adapter *adapter, u8 cam_id)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+	bool ret;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	ret = _rtw_camid_is_gk(adapter, cam_id);
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+
+	return ret;
+}
+
+bool cam_cache_chk(_adapter *adapter, u8 id, u8 *addr, s16 kid, s8 gk)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	bool ret = _FALSE;
+
+	if (addr && _rtw_memcmp(dvobj->cam_cache[id].mac, addr, ETH_ALEN) == _FALSE)
+		goto exit;
+	if (kid >= 0 && kid != (dvobj->cam_cache[id].ctrl&0x03))
+		goto exit;
+	if (gk != -1 && (gk?_TRUE:_FALSE) != _rtw_camid_is_gk(adapter, id))
+		goto exit;
+
+	ret = _TRUE;
+
+exit:
+	return ret;
+}
+
+s16 _rtw_camid_search(_adapter *adapter, u8 *addr, s16 kid, s8 gk)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	int i;
+	s16 cam_id = -1;
+
+	for (i = 0; i < cam_ctl->num; i++) {
+		if (cam_cache_chk(adapter, i, addr, kid, gk)) {
+			cam_id = i;
+			break;
+		}
+	}
+
+	if (0) {
+		if (addr)
+			DBG_871X(FUNC_ADPT_FMT" addr:"MAC_FMT" kid:%d, gk:%d, return cam_id:%d\n"
+				, FUNC_ADPT_ARG(adapter), MAC_ARG(addr), kid, gk, cam_id);
+		else
+			DBG_871X(FUNC_ADPT_FMT" addr:%p kid:%d, gk:%d, return cam_id:%d\n"
+				, FUNC_ADPT_ARG(adapter), addr, kid, gk, cam_id);
+	}
+
+	return cam_id;
+}
+
+s16 rtw_camid_search(_adapter *adapter, u8 *addr, s16 kid, s8 gk)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+	s16 cam_id = -1;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+	cam_id = _rtw_camid_search(adapter, addr, kid, gk);
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+
+	return cam_id;
+}
+
+s16 rtw_camid_alloc(_adapter *adapter, struct sta_info *sta, u8 kid, bool *used)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+	s16 cam_id = -1;
+
+	*used = _FALSE;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+
+#ifdef DYNAMIC_CAMID_ALLOC
+	{
+		struct mlme_ext_info *mlmeinfo = &adapter->mlmeextpriv.mlmext_info;
+
+		if((((mlmeinfo->state&0x03) == WIFI_FW_AP_STATE) || ((mlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE))
+			&& !sta) {
+			/* AP/Ad-hoc mode group key: static alloction to default key by key ID */
+			if (kid > 3) {
+				DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key with invalid key id:%u\n"
+					, FUNC_ADPT_ARG(adapter), kid);
+				rtw_warn_on(1);
+				goto bitmap_handle;
+			}
+			cam_id = kid;
+		}
+		else {
+			int i;
+			u8 *addr = sta?sta->hwaddr:NULL;
+			#if 0 /* for testing */
+			static u8 start_id = 0;
+			#else
+			u8 start_id = 0;
+			#endif
+
+			if(!sta) {
+				if (!(mlmeinfo->state & WIFI_FW_ASSOC_SUCCESS)) {
+					/* bypass STA mode group key setting before connected(ex:WEP) because bssid is not ready */
+					goto bitmap_handle;
+				}
+
+				addr = get_bssid(&adapter->mlmepriv);
+			}
+
+			/* find cam entry which has the same addr, kid (, gk bit) */
+			if (_rtw_camctl_chk_cap(adapter, SEC_CAP_CHK_BMC) == _TRUE)
+				i = _rtw_camid_search(adapter, addr, kid, sta?_FALSE:_TRUE);
+			else
+				i = _rtw_camid_search(adapter, addr, kid, -1);
+
+			if (i >= 0) {
+				cam_id = i;
+				goto bitmap_handle;
+			}
+
+			for (i = 0; i < cam_ctl->num; i++) {
+				/* bypass default key which is allocated statically */
+				if (((i + start_id) % cam_ctl->num) < 4)
+					continue;
+
+				if (_rtw_sec_camid_is_used(cam_ctl, ((i + start_id) % cam_ctl->num)) == _FALSE)
+					break;
+			}
+
+			if (i == cam_ctl->num) {
+				if (sta)
+					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" pairwise key with "MAC_FMT" id:%u no room\n"
+					, FUNC_ADPT_ARG(adapter), MAC_ARG(addr), kid);
+				else
+					DBG_871X_LEVEL(_drv_always_, FUNC_ADPT_FMT" group key with "MAC_FMT" id:%u no room\n"
+					, FUNC_ADPT_ARG(adapter), MAC_ARG(addr), kid);
+				rtw_warn_on(1);
+				goto bitmap_handle;
+			}
+
+			cam_id = ((i + start_id) % cam_ctl->num);
+			start_id = ((i + start_id + 1) % cam_ctl->num);
+		}
+	}
+#else
+	cam_id = rtw_get_camid(adapter, sta, kid);
+#endif /* DYNAMIC_CAMID_ALLOC */
+
+bitmap_handle:
+	if (cam_id >= 0) {
+		*used = _rtw_sec_camid_is_used(cam_ctl, cam_id);
+		rtw_sec_cam_map_set(&cam_ctl->used, cam_id);
+	}
+
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+
+	return cam_id;
+}
+
+void rtw_camid_free(_adapter *adapter, u8 cam_id)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	struct cam_ctl_t *cam_ctl = &dvobj->cam_ctl;
+	_irqL irqL;
+
+	_enter_critical_bh(&cam_ctl->lock, &irqL);
+
+	if (cam_id < cam_ctl->num)
+		rtw_sec_cam_map_clr(&cam_ctl->used, cam_id);
+
+	_exit_critical_bh(&cam_ctl->lock, &irqL);
+}
+
+int allocate_fw_sta_entry(_adapter *padapter)
+{
+	unsigned int mac_id;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	for (mac_id = IBSS_START_MAC_ID; mac_id < NUM_STA; mac_id++)
+	{
+		if (pmlmeinfo->FW_sta_info[mac_id].status == 0)
+		{
+			pmlmeinfo->FW_sta_info[mac_id].status = 1;
+			pmlmeinfo->FW_sta_info[mac_id].retry = 0;
+			break;
+		}
+	}
+	
+	return mac_id;
+}
+
+void flush_all_cam_entry(_adapter *padapter)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
+
+#ifdef CONFIG_CONCURRENT_MODE
+	if(check_buddy_fwstate(padapter, _FW_LINKED) == _TRUE)
+	{
+		if(check_fwstate(pmlmepriv, WIFI_STATION_STATE))
+		{
+			struct sta_priv	*pstapriv = &padapter->stapriv;
+			struct sta_info	*psta;
+
+			psta = rtw_get_stainfo(pstapriv, pmlmeinfo->network.MacAddress);
+			if(psta) {
+				if(psta->state & WIFI_AP_STATE)
+				{}   //clear cam when ap free per sta_info        
+				else {
+					rtw_clearstakey_cmd(padapter, psta, _FALSE);
+				}
+			}
+		}
+		else if(check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE)
+		{
+			/* clear default key */
+			int i, cam_id;
+			u8 null_addr[ETH_ALEN]= {0,0,0,0,0,0};
+
+			for (i=0;i<4;i++) {
+				cam_id = rtw_camid_search(padapter, null_addr, i, -1);
+				if (cam_id >= 0) {
+					clear_cam_entry(padapter, cam_id);
+					rtw_camid_free(padapter, cam_id);
+				}
+			}
+
+			/* clear default key related key search setting */
+			#ifdef DYNAMIC_CAMID_ALLOC
+			rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)_FALSE);
+			#endif
+
+			/* leave pairwise key when ap free per sta_info */
+		}
+	}
+	else
+#endif //CONFIG_CONCURRENT_MODE
+	{
+		invalidate_cam_all(padapter);
+		/* clear default key related key search setting */
+		#ifdef DYNAMIC_CAMID_ALLOC
+		rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8*)_FALSE);
+		#endif
+	}
+
+	_rtw_memset((u8 *)(pmlmeinfo->FW_sta_info), 0, sizeof(pmlmeinfo->FW_sta_info));
+	
+}
+
+#if defined(CONFIG_P2P) && defined(CONFIG_WFD)
+void rtw_process_wfd_ie(_adapter *adapter, u8 *wfd_ie, u8 wfd_ielen, const char *tag)
+{
+	struct wifidirect_info *wdinfo = &adapter->wdinfo;
+
+	u8 *attr_content;
+	u32 attr_contentlen = 0;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		return;
+
+	DBG_871X("[%s] Found WFD IE\n", tag);
+	attr_content = rtw_get_wfd_attr_content(wfd_ie, wfd_ielen, WFD_ATTR_DEVICE_INFO, NULL, &attr_contentlen);
+	if (attr_content && attr_contentlen) {
+		wdinfo->wfd_info->peer_rtsp_ctrlport = RTW_GET_BE16(attr_content + 2);
+		DBG_871X("[%s] Peer PORT NUM = %d\n", tag, wdinfo->wfd_info->peer_rtsp_ctrlport);
+	}
+}
+
+void rtw_process_wfd_ies(_adapter *adapter, u8 *ies, u8 ies_len, const char *tag)
+{
+	u8 *wfd_ie;
+	u32	wfd_ielen;
+
+	if (!hal_chk_wl_func(adapter, WL_FUNC_MIRACAST))
+		return;
+
+	wfd_ie = rtw_get_wfd_ie(ies, ies_len, NULL, &wfd_ielen);
+	while (wfd_ie) {
+		rtw_process_wfd_ie(adapter, wfd_ie, wfd_ielen, tag);
+		wfd_ie = rtw_get_wfd_ie(wfd_ie + wfd_ielen, (ies + ies_len) - (wfd_ie + wfd_ielen), NULL, &wfd_ielen);
+	}
+}
+#endif /* defined(CONFIG_P2P) && defined(CONFIG_WFD) */
+
+int WMM_param_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs	pIE)
+{
+	//struct registry_priv	*pregpriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);	
+	
+	if(pmlmepriv->qospriv.qos_option==0)
+	{
+		pmlmeinfo->WMM_enable = 0;
+		return _FALSE;
+	}	
+	
+	if(_rtw_memcmp(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element)))
+	{
+		return _FALSE;
+	}
+	else
+	{
+		_rtw_memcpy(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element));
+	}
+	pmlmeinfo->WMM_enable = 1;
+	return _TRUE;
+
+	/*if (pregpriv->wifi_spec == 1)
+	{
+		if (pmlmeinfo->WMM_enable == 1)
+		{
+			//todo: compare the parameter set count & decide wheher to update or not
+			return _FAIL;
+		}
+		else
+		{
+			pmlmeinfo->WMM_enable = 1;
+			_rtw_rtw_memcpy(&(pmlmeinfo->WMM_param), (pIE->data + 6), sizeof(struct WMM_para_element));
+			return _TRUE;
+		}
+	}
+	else
+	{
+		pmlmeinfo->WMM_enable = 0;
+		return _FAIL;
+	}*/
+	
+}
+
+void WMMOnAssocRsp(_adapter *padapter)
+{
+	u8	ACI, ACM, AIFS, ECWMin, ECWMax, aSifsTime;
+	u8	acm_mask;
+	u16	TXOP;
+	u32	acParm, i;
+	u32	edca[4], inx[4];
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct xmit_priv		*pxmitpriv = &padapter->xmitpriv;
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+
+	acm_mask = 0;
+
+	if (IsSupported5G(pmlmeext->cur_wireless_mode) || 
+		(pmlmeext->cur_wireless_mode & WIRELESS_11_24N) )
+		aSifsTime = 16;
+	else
+		aSifsTime = 10;
+
+	if (pmlmeinfo->WMM_enable == 0)
+	{
+		padapter->mlmepriv.acm_mask = 0;
+
+		AIFS = aSifsTime + (2 * pmlmeinfo->slotTime);
+
+		if (pmlmeext->cur_wireless_mode & (WIRELESS_11G |WIRELESS_11A)) {
+			ECWMin = 4;
+			ECWMax = 10;
+		} else if (pmlmeext->cur_wireless_mode & WIRELESS_11B) {
+			ECWMin = 5;
+			ECWMax = 10;
+		} else {
+			ECWMin = 4;
+			ECWMax = 10;
+		}
+
+		TXOP = 0;
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
+
+		ECWMin = 2;
+		ECWMax = 3;
+		TXOP = 0x2f;
+		acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+		rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
+	}
+	else
+	{
+		edca[0] = edca[1] = edca[2] = edca[3] = 0;
+
+		for (i = 0; i < 4; i++)  
+		{
+			ACI = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 5) & 0x03;
+			ACM = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN >> 4) & 0x01;
+
+			//AIFS = AIFSN * slot time + SIFS - r2t phy delay
+			AIFS = (pmlmeinfo->WMM_param.ac_param[i].ACI_AIFSN & 0x0f) * pmlmeinfo->slotTime + aSifsTime;
+
+			ECWMin = (pmlmeinfo->WMM_param.ac_param[i].CW & 0x0f);
+			ECWMax = (pmlmeinfo->WMM_param.ac_param[i].CW & 0xf0) >> 4;
+			TXOP = le16_to_cpu(pmlmeinfo->WMM_param.ac_param[i].TXOP_limit);
+
+			acParm = AIFS | (ECWMin << 8) | (ECWMax << 12) | (TXOP << 16);
+
+			switch (ACI)
+			{
+				case 0x0:
+					rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BE, (u8 *)(&acParm));
+					acm_mask |= (ACM? BIT(1):0);
+					edca[XMIT_BE_QUEUE] = acParm;
+					break;
+
+				case 0x1:
+					rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_BK, (u8 *)(&acParm));
+					//acm_mask |= (ACM? BIT(0):0);
+					edca[XMIT_BK_QUEUE] = acParm;
+					break;
+
+				case 0x2:
+					rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VI, (u8 *)(&acParm));
+					acm_mask |= (ACM? BIT(2):0);
+					edca[XMIT_VI_QUEUE] = acParm;
+					break;
+
+				case 0x3:
+					rtw_hal_set_hwreg(padapter, HW_VAR_AC_PARAM_VO, (u8 *)(&acParm));
+					acm_mask |= (ACM? BIT(3):0);
+					edca[XMIT_VO_QUEUE] = acParm;
+					break;							
+			}
+
+			DBG_871X("WMM(%x): %x, %x\n", ACI, ACM, acParm);
+		}
+
+		if(padapter->registrypriv.acm_method == 1)
+			rtw_hal_set_hwreg(padapter, HW_VAR_ACM_CTRL, (u8 *)(&acm_mask));
+		else
+			padapter->mlmepriv.acm_mask = acm_mask;
+
+		inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
+
+		if(pregpriv->wifi_spec==1)
+		{
+			u32	j, tmp, change_inx=_FALSE;
+
+			//entry indx: 0->vo, 1->vi, 2->be, 3->bk.
+			for(i=0; i<4; i++)
+			{
+				for(j=i+1; j<4; j++)
+				{
+					//compare CW and AIFS
+					if((edca[j] & 0xFFFF) < (edca[i] & 0xFFFF))
+					{
+						change_inx = _TRUE;
+					}
+					else if((edca[j] & 0xFFFF) == (edca[i] & 0xFFFF))
+					{
+						//compare TXOP
+						if((edca[j] >> 16) > (edca[i] >> 16))
+							change_inx = _TRUE;
+					}
+				
+					if(change_inx)
+					{
+						tmp = edca[i];
+						edca[i] = edca[j];
+						edca[j] = tmp;
+
+						tmp = inx[i];
+						inx[i] = inx[j];
+						inx[j] = tmp;
+
+						change_inx = _FALSE;
+					}
+				}
+			}
+		}
+
+		for(i=0; i<4; i++) {
+			pxmitpriv->wmm_para_seq[i] = inx[i];
+			DBG_871X("wmm_para_seq(%d): %d\n", i, pxmitpriv->wmm_para_seq[i]);
+		}
+	}
+}
+
+static void bwmode_update_check(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+#ifdef CONFIG_80211N_HT
+	unsigned char	 new_bwmode;
+	unsigned char  new_ch_offset;
+	struct HT_info_element	 *pHT_info;
+	struct mlme_priv	*pmlmepriv = &(padapter->mlmepriv);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct registry_priv *pregistrypriv = &padapter->registrypriv;
+	struct ht_priv			*phtpriv = &pmlmepriv->htpriv;
+	u8	cbw40_enable=0;
+
+	if(!pIE)
+		return;
+
+	if(phtpriv->ht_option == _FALSE)	return;
+
+	if(pmlmeext->cur_bwmode >= CHANNEL_WIDTH_80)	return;
+
+	if(pIE->Length > sizeof(struct HT_info_element))
+		return;
+	
+	pHT_info = (struct HT_info_element *)pIE->data;
+
+	if (hal_chk_bw_cap(padapter, BW_CAP_40M)) {
+		if (pmlmeext->cur_channel > 14) {
+			if (REGSTY_IS_BW_5G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
+				cbw40_enable = 1;
+		} else {
+			if (REGSTY_IS_BW_2G_SUPPORT(pregistrypriv, CHANNEL_WIDTH_40))
+				cbw40_enable = 1;
+		}
+	}
+
+	if((pHT_info->infos[0] & BIT(2)) && cbw40_enable)
+	{
+		new_bwmode = CHANNEL_WIDTH_40;
+
+		switch (pHT_info->infos[0] & 0x3)
+		{
+			case 1:
+				new_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+				break;
+			
+			case 3:
+				new_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+				break;
+				
+			default:
+				new_bwmode = CHANNEL_WIDTH_20;
+				new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+				break;
+		}
+	}
+	else
+	{
+		new_bwmode = CHANNEL_WIDTH_20;
+		new_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+	}	
+
+	
+	if ((new_bwmode != pmlmeext->cur_bwmode || new_ch_offset != pmlmeext->cur_ch_offset)
+		&& new_bwmode < pmlmeext->cur_bwmode
+	) {
+		pmlmeinfo->bwmode_updated = _TRUE;
+		
+		pmlmeext->cur_bwmode = new_bwmode;
+		pmlmeext->cur_ch_offset = new_ch_offset;
+
+		//update HT info also
+		HT_info_handler(padapter, pIE);
+	}
+	else
+	{
+		pmlmeinfo->bwmode_updated = _FALSE;
+	}
+		
+
+	if(_TRUE == pmlmeinfo->bwmode_updated)
+	{
+		struct sta_info *psta;
+		WLAN_BSSID_EX 	*cur_network = &(pmlmeinfo->network);
+		struct sta_priv	*pstapriv = &padapter->stapriv;
+	
+		//set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+		
+		//update ap's stainfo
+		psta = rtw_get_stainfo(pstapriv, cur_network->MacAddress);
+		if(psta)
+		{
+			struct ht_priv	*phtpriv_sta = &psta->htpriv;
+			
+			if(phtpriv_sta->ht_option)
+			{				
+				// bwmode				
+				psta->bw_mode = pmlmeext->cur_bwmode;
+				phtpriv_sta->ch_offset = pmlmeext->cur_ch_offset;		
+			}
+			else
+			{
+				psta->bw_mode = CHANNEL_WIDTH_20;
+				phtpriv_sta->ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+			}
+
+			rtw_dm_ra_mask_wk_cmd(padapter, (u8 *)psta);
+		}
+
+		//pmlmeinfo->bwmode_updated = _FALSE;//bwmode_updated done, reset it!
+	}	
+#endif //CONFIG_80211N_HT
+}
+
+void HT_caps_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+#ifdef CONFIG_80211N_HT
+	unsigned int	i;
+	u8	rf_type = RF_1T1R;
+	u8	max_AMPDU_len, min_MPDU_spacing;
+	u8	cur_ldpc_cap=0, cur_stbc_cap=0, cur_beamform_cap=0;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;	
+	struct ht_priv			*phtpriv = &pmlmepriv->htpriv;
+	struct registry_priv 	*pregistrypriv = &padapter->registrypriv;
+	
+	if(pIE==NULL) return;
+	
+	if(phtpriv->ht_option == _FALSE)	return;
+
+	pmlmeinfo->HT_caps_enable = 1;
+	
+	for (i = 0; i < (pIE->Length); i++)
+	{
+		if (i != 2)
+		{
+			//	Commented by Albert 2010/07/12
+			//	Got the endian issue here.
+			pmlmeinfo->HT_caps.u.HT_cap[i] &= (pIE->data[i]);
+		}
+		else
+		{
+			/* AMPDU Parameters field */
+
+			/* Get MIN of MAX AMPDU Length Exp */
+			if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3) > (pIE->data[i] & 0x3))
+			{
+				max_AMPDU_len = (pIE->data[i] & 0x3);
+			}
+			else
+			{
+				max_AMPDU_len = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x3);
+			}
+
+			/* Get MAX of MIN MPDU Start Spacing */
+			if ((pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) > (pIE->data[i] & 0x1c))
+			{
+				min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c);
+			}
+			else
+			{
+				min_MPDU_spacing = (pIE->data[i] & 0x1c);
+			}
+
+			pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para = max_AMPDU_len | min_MPDU_spacing;
+		}
+	}
+
+	//	Commented by Albert 2010/07/12
+	//	Have to handle the endian issue after copying.
+	//	HT_ext_caps didn't be used yet.	
+	pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info = le16_to_cpu( pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info );
+	pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps = le16_to_cpu( pmlmeinfo->HT_caps.u.HT_cap_element.HT_ext_caps );
+
+	rtw_hal_get_hwreg(padapter, HW_VAR_RF_TYPE, (u8 *)(&rf_type));
+
+
+	//update the MCS set
+	for (i = 0; i < 16; i++)
+		pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate[i] &= pmlmeext->default_supported_mcs_set[i];
+			
+	//update the MCS rates
+	switch(rf_type)
+	{
+		case RF_1T1R:
+		case RF_1T2R:
+			set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_1R);							
+			break;
+		case RF_2T2R:
+			#ifdef CONFIG_DISABLE_MCS13TO15
+			if(pmlmeext->cur_bwmode == CHANNEL_WIDTH_40 && pregistrypriv->wifi_spec != 1 )				
+				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R_13TO15_OFF);				
+			else
+				set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
+#else //CONFIG_DISABLE_MCS13TO15
+			set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_2R);
+#endif //CONFIG_DISABLE_MCS13TO15
+			break;
+		case RF_3T3R:
+			set_mcs_rate_by_mask(pmlmeinfo->HT_caps.u.HT_cap_element.MCS_rate, MCS_RATE_3R);
+			break;
+		default:
+			DBG_871X("[warning] rf_type %d is not expected\n", rf_type);
+	}
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+		// Config STBC setting
+		if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAP_ELE_TX_STBC(pIE->data))
+		{
+			SET_FLAG(cur_stbc_cap, STBC_HT_ENABLE_TX);
+			DBG_871X("Enable HT Tx STBC !\n");
+		}
+		phtpriv->stbc_cap = cur_stbc_cap;
+
+#ifdef CONFIG_BEAMFORMING
+		// Config Tx beamforming setting
+		if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) && 
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pIE->data))
+		{
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
+			/* Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/
+			SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pIE->data) << 6);
+		}
+
+		if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) &&
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pIE->data))
+		{
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
+			/* Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/
+			SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pIE->data) << 4);
+		}
+		phtpriv->beamform_cap = cur_beamform_cap;
+		if (cur_beamform_cap) {
+			DBG_871X("AP HT Beamforming Cap = 0x%02X\n", cur_beamform_cap);
+		}
+#endif /*CONFIG_BEAMFORMING*/
+	} else {
+		/*WIFI_STATION_STATEorI_ADHOC_STATE or WIFI_ADHOC_MASTER_STATE*/
+		// Config LDPC Coding Capability
+		if (TEST_FLAG(phtpriv->ldpc_cap, LDPC_HT_ENABLE_TX) && GET_HT_CAP_ELE_LDPC_CAP(pIE->data))
+		{
+			SET_FLAG(cur_ldpc_cap, (LDPC_HT_ENABLE_TX | LDPC_HT_CAP_TX));
+			DBG_871X("Enable HT Tx LDPC!\n");
+		}
+		phtpriv->ldpc_cap = cur_ldpc_cap;
+
+		// Config STBC setting
+		if (TEST_FLAG(phtpriv->stbc_cap, STBC_HT_ENABLE_TX) && GET_HT_CAP_ELE_RX_STBC(pIE->data))
+		{
+			SET_FLAG(cur_stbc_cap, (STBC_HT_ENABLE_TX | STBC_HT_CAP_TX) );
+			DBG_871X("Enable HT Tx STBC!\n");
+		}
+		phtpriv->stbc_cap = cur_stbc_cap;
+
+#ifdef CONFIG_BEAMFORMING
+		// Config Tx beamforming setting
+		if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE) && 
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_STEERING_CAP(pIE->data))
+		{
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE);
+			/* Shift to BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP*/
+			SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_CHNL_ESTIMATION_NUM_ANTENNAS(pIE->data) << 6);
+		}
+
+		if (TEST_FLAG(phtpriv->beamform_cap, BEAMFORMING_HT_BEAMFORMER_ENABLE) &&
+			GET_HT_CAP_TXBF_EXPLICIT_COMP_FEEDBACK_CAP(pIE->data))
+		{
+			SET_FLAG(cur_beamform_cap, BEAMFORMING_HT_BEAMFORMEE_ENABLE);
+			/* Shift to BEAMFORMING_HT_BEAMFORMER_STEER_NUM*/
+			SET_FLAG(cur_beamform_cap, GET_HT_CAP_TXBF_COMP_STEERING_NUM_ANTENNAS(pIE->data) << 4);
+		}
+		phtpriv->beamform_cap = cur_beamform_cap;
+		if (cur_beamform_cap) {
+			DBG_871X("Client HT Beamforming Cap = 0x%02X\n", cur_beamform_cap);
+		}
+#endif /*CONFIG_BEAMFORMING*/
+	}
+
+#endif //CONFIG_80211N_HT
+}
+
+void HT_info_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+#ifdef CONFIG_80211N_HT
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct mlme_priv 		*pmlmepriv = &padapter->mlmepriv;	
+	struct ht_priv			*phtpriv = &pmlmepriv->htpriv;
+
+	if(pIE==NULL) return;
+
+	if(phtpriv->ht_option == _FALSE)	return;
+
+
+	if(pIE->Length > sizeof(struct HT_info_element))
+		return;
+	
+	pmlmeinfo->HT_info_enable = 1;
+	_rtw_memcpy(&(pmlmeinfo->HT_info), pIE->data, pIE->Length);
+#endif //CONFIG_80211N_HT
+	return;
+}
+
+void HTOnAssocRsp(_adapter *padapter)
+{
+	unsigned char		max_AMPDU_len;
+	unsigned char		min_MPDU_spacing;
+	//struct registry_priv	 *pregpriv = &padapter->registrypriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	DBG_871X("%s\n", __FUNCTION__);
+
+	if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
+	{
+		pmlmeinfo->HT_enable = 1;
+	}
+	else
+	{
+		pmlmeinfo->HT_enable = 0;
+		//set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+		return;
+	}
+	
+	//handle A-MPDU parameter field
+	/* 	
+		AMPDU_para [1:0]:Max AMPDU Len => 0:8k , 1:16k, 2:32k, 3:64k
+		AMPDU_para [4:2]:Min MPDU Start Spacing	
+	*/
+	max_AMPDU_len = pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x03;	
+	
+	min_MPDU_spacing = (pmlmeinfo->HT_caps.u.HT_cap_element.AMPDU_para & 0x1c) >> 2;	
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_MIN_SPACE, (u8 *)(&min_MPDU_spacing));
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_AMPDU_FACTOR, (u8 *)(&max_AMPDU_len));
+
+#if 0 //move to rtw_update_ht_cap()
+	if ((pregpriv->bw_mode > 0) &&
+		(pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & BIT(1)) && 
+		(pmlmeinfo->HT_info.infos[0] & BIT(2)))
+	{
+		//switch to the 40M Hz mode accoring to the AP
+		pmlmeext->cur_bwmode = CHANNEL_WIDTH_40;
+		switch ((pmlmeinfo->HT_info.infos[0] & 0x3))
+		{
+			case EXTCHNL_OFFSET_UPPER:
+				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_LOWER;
+				break;
+			
+			case EXTCHNL_OFFSET_LOWER:
+				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_UPPER;
+				break;
+				
+			default:
+				pmlmeext->cur_ch_offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
+				break;
+		}
+		
+		//SelectChannel(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset);
+	}
+#endif
+
+	//set_channel_bwmode(padapter, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+#if 0 //move to rtw_update_ht_cap()
+	//
+	// Config SM Power Save setting
+	//
+	pmlmeinfo->SM_PS = (pmlmeinfo->HT_caps.u.HT_cap_element.HT_caps_info & 0x0C) >> 2;
+	if(pmlmeinfo->SM_PS == WLAN_HT_CAP_SM_PS_STATIC)
+	{
+		/*u8 i;
+		//update the MCS rates
+		for (i = 0; i < 16; i++)
+		{
+			pmlmeinfo->HT_caps.HT_cap_element.MCS_rate[i] &= MCS_rate_1R[i];
+		}*/
+		DBG_871X("%s(): WLAN_HT_CAP_SM_PS_STATIC\n",__FUNCTION__);
+	}
+
+	//
+	// Config current HT Protection mode.
+	//
+	pmlmeinfo->HT_protection = pmlmeinfo->HT_info.infos[1] & 0x3;
+#endif
+	
+}
+
+void ERP_IE_handler(_adapter *padapter, PNDIS_802_11_VARIABLE_IEs pIE)
+{
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	if(pIE->Length>1)
+		return;
+	
+	pmlmeinfo->ERP_enable = 1;
+	_rtw_memcpy(&(pmlmeinfo->ERP_IE), pIE->data, pIE->Length);
+}
+
+void VCS_update(_adapter *padapter, struct sta_info *psta)
+{
+	struct registry_priv	 *pregpriv = &padapter->registrypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+	switch (pregpriv->vrtl_carrier_sense)/* 0:off 1:on 2:auto */
+	{
+		case 0: //off
+			psta->rtsen = 0;
+			psta->cts2self = 0;
+			break;
+			
+		case 1: //on
+			if (pregpriv->vcs_type == 1) /* 1:RTS/CTS 2:CTS to self */
+			{
+				psta->rtsen = 1;
+				psta->cts2self = 0;
+			}
+			else
+			{
+				psta->rtsen = 0;
+				psta->cts2self = 1;
+			}
+			break;
+			
+		case 2: //auto
+		default:
+			if (((pmlmeinfo->ERP_enable) && (pmlmeinfo->ERP_IE & BIT(1)))
+				/*||(pmlmepriv->ht_op_mode & HT_INFO_OPERATION_MODE_NON_GF_DEVS_PRESENT)*/
+				) {
+				if (pregpriv->vcs_type == 1) {
+					psta->rtsen = 1;
+					psta->cts2self = 0;
+				} else {
+					psta->rtsen = 0;
+					psta->cts2self = 1;
+				}
+			} else {
+				psta->rtsen = 0;
+				psta->cts2self = 0;
+			}	
+			break;
+	}
+}
+
+void	update_ldpc_stbc_cap(struct sta_info *psta)
+{
+#ifdef CONFIG_80211N_HT
+
+#ifdef CONFIG_80211AC_VHT
+	if (psta->vhtpriv.vht_option) {
+		if(TEST_FLAG(psta->vhtpriv.ldpc_cap, LDPC_VHT_ENABLE_TX))
+			psta->ldpc = 1;
+
+		if(TEST_FLAG(psta->vhtpriv.stbc_cap, STBC_VHT_ENABLE_TX))
+			psta->stbc = 1;
+	}
+	else
+#endif //CONFIG_80211AC_VHT
+	if (psta->htpriv.ht_option) {
+		if(TEST_FLAG(psta->htpriv.ldpc_cap, LDPC_HT_ENABLE_TX))
+			psta->ldpc = 1;
+
+		if(TEST_FLAG(psta->htpriv.stbc_cap, STBC_HT_ENABLE_TX))
+			psta->stbc = 1;
+	} else {
+		psta->ldpc = 0;
+		psta->stbc = 0;
+	}
+
+#endif //CONFIG_80211N_HT
+}
+
+
+/*
+ * rtw_get_bcn_keys: get beacon keys from recv frame
+ *
+ * TODO:
+ *	WLAN_EID_COUNTRY
+ *	WLAN_EID_ERP_INFO
+ *	WLAN_EID_CHANNEL_SWITCH
+ *	WLAN_EID_PWR_CONSTRAINT
+ */
+int rtw_get_bcn_keys(ADAPTER *Adapter, u8 *pframe, u32 packet_len,
+		struct beacon_keys *recv_beacon)
+{
+	int left;
+	u16 capability;
+	unsigned char *pos;
+	struct rtw_ieee802_11_elems elems;
+	struct rtw_ieee80211_ht_cap *pht_cap = NULL;
+	struct HT_info_element *pht_info = NULL;
+
+	_rtw_memset(recv_beacon, 0, sizeof(*recv_beacon));
+
+	/* checking capabilities */
+	capability = le16_to_cpu(*(unsigned short *)(pframe + WLAN_HDR_A3_LEN + 10));
+
+	/* checking IEs */
+	left = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr) - _BEACON_IE_OFFSET_;
+	pos = pframe + sizeof(struct rtw_ieee80211_hdr_3addr) + _BEACON_IE_OFFSET_;
+	if (rtw_ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed)
+		return _FALSE;
+
+	/* check bw and channel offset */
+	if (elems.ht_capabilities) {
+		if (elems.ht_capabilities_len != sizeof(*pht_cap))
+			return _FALSE;
+
+		pht_cap = (struct rtw_ieee80211_ht_cap *) elems.ht_capabilities;
+		recv_beacon->ht_cap_info = pht_cap->cap_info;
+	}
+
+	if (elems.ht_operation) {
+		if (elems.ht_operation_len != sizeof(*pht_info))
+			return _FALSE;
+
+		pht_info = (struct HT_info_element *) elems.ht_operation;
+		recv_beacon->ht_info_infos_0_sco = pht_info->infos[0] & 0x03;
+	}
+
+	/* Checking for channel */
+	if (elems.ds_params && elems.ds_params_len == sizeof(recv_beacon->bcn_channel))
+		_rtw_memcpy(&recv_beacon->bcn_channel, elems.ds_params,
+				sizeof(recv_beacon->bcn_channel));
+	else if (pht_info)
+		/* In 5G, some ap do not have DSSET IE checking HT info for channel */
+		recv_beacon->bcn_channel = pht_info->primary_channel;
+	else {
+		/* we don't find channel IE, so don't check it */
+		//DBG_871X("Oops: %s we don't find channel IE, so don't check it \n", __func__);
+		recv_beacon->bcn_channel = Adapter->mlmeextpriv.cur_channel;
+	}
+
+	/* checking SSID */
+	if (elems.ssid) {
+	       if (elems.ssid_len > sizeof(recv_beacon->ssid))
+			return _FALSE;
+
+	       _rtw_memcpy(recv_beacon->ssid, elems.ssid, elems.ssid_len);
+	       recv_beacon->ssid_len = elems.ssid_len;
+	} else; // means hidden ssid
+
+	/* checking RSN first */
+	if (elems.rsn_ie && elems.rsn_ie_len) {
+		recv_beacon->encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+		rtw_parse_wpa2_ie(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+			&recv_beacon->group_cipher, &recv_beacon->pairwise_cipher,
+			&recv_beacon->is_8021x);
+	}
+	/* checking WPA secon */
+	else if (elems.wpa_ie && elems.wpa_ie_len) {
+		recv_beacon->encryp_protocol = ENCRYP_PROTOCOL_WPA;
+		rtw_parse_wpa_ie(elems.wpa_ie - 2, elems.wpa_ie_len + 2,
+			&recv_beacon->group_cipher, &recv_beacon->pairwise_cipher,
+			&recv_beacon->is_8021x);
+	}
+	else if (capability & BIT(4)) {
+		recv_beacon->encryp_protocol = ENCRYP_PROTOCOL_WEP;
+	}
+
+	return _TRUE;
+}
+
+void rtw_dump_bcn_keys(struct beacon_keys *recv_beacon)
+{
+	int i;
+	char *p;
+	u8 ssid[IW_ESSID_MAX_SIZE + 1];
+
+	_rtw_memcpy(ssid, recv_beacon->ssid, recv_beacon->ssid_len);
+	ssid[recv_beacon->ssid_len] = '\0';
+
+	DBG_871X("%s: ssid = %s\n", __func__, ssid);
+	DBG_871X("%s: channel = %x\n", __func__, recv_beacon->bcn_channel);
+	DBG_871X("%s: ht_cap = %x\n", __func__,	recv_beacon->ht_cap_info);
+	DBG_871X("%s: ht_info_infos_0_sco = %x\n", __func__, recv_beacon->ht_info_infos_0_sco);
+	DBG_871X("%s: sec=%d, group = %x, pair = %x, 8021X = %x\n", __func__,
+		recv_beacon->encryp_protocol, recv_beacon->group_cipher,
+		recv_beacon->pairwise_cipher, recv_beacon->is_8021x);
+}
+
+int rtw_check_bcn_info(ADAPTER *Adapter, u8 *pframe, u32 packet_len)
+{
+#if 0
+	unsigned int		len;
+	unsigned char		*p;
+	unsigned short	val16, subtype;
+	struct wlan_network *cur_network = &(Adapter->mlmepriv.cur_network);
+	//u8 wpa_ie[255],rsn_ie[255];
+	u16 wpa_len=0,rsn_len=0;
+	u8 encryp_protocol = 0;
+	WLAN_BSSID_EX *bssid;
+	int group_cipher = 0, pairwise_cipher = 0, is_8021x = 0;
+	unsigned char *pbuf;
+	u32 wpa_ielen = 0;
+	u8 *pbssid = GetAddr3Ptr(pframe);
+	u32 hidden_ssid = 0;
+	u8 cur_network_type, network_type=0;
+	struct HT_info_element *pht_info = NULL;
+	struct rtw_ieee80211_ht_cap *pht_cap = NULL;
+	u32 bcn_channel;
+	unsigned short 	ht_cap_info;
+	unsigned char	ht_info_infos_0;
+#endif
+	unsigned int len;
+	u8 *pbssid = GetAddr3Ptr(pframe);
+	struct mlme_priv *pmlmepriv = &Adapter->mlmepriv;
+	struct wlan_network *cur_network = &(Adapter->mlmepriv.cur_network);
+	struct beacon_keys recv_beacon;
+
+	if (is_client_associated_to_ap(Adapter) == _FALSE)
+		return _TRUE;
+
+	len = packet_len - sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	if (len > MAX_IE_SZ) {
+		DBG_871X("%s IE too long for survey event\n", __func__);
+		return _FAIL;
+	}
+
+	if (_rtw_memcmp(cur_network->network.MacAddress, pbssid, 6) == _FALSE) {
+		DBG_871X("Oops: rtw_check_network_encrypt linked but recv other bssid bcn\n" MAC_FMT MAC_FMT,
+				MAC_ARG(pbssid), MAC_ARG(cur_network->network.MacAddress));
+		return _TRUE;
+	}
+
+	if (rtw_get_bcn_keys(Adapter, pframe, packet_len, &recv_beacon) == _FALSE)
+		return _TRUE; // parsing failed => broken IE
+
+	// don't care hidden ssid, use current beacon ssid directly
+	if (recv_beacon.ssid_len == 0) {
+	       _rtw_memcpy(recv_beacon.ssid, pmlmepriv->cur_beacon_keys.ssid,
+			       pmlmepriv->cur_beacon_keys.ssid_len);
+	       recv_beacon.ssid_len = pmlmepriv->cur_beacon_keys.ssid_len;
+	}
+
+	if (_rtw_memcmp(&recv_beacon, &pmlmepriv->cur_beacon_keys, sizeof(recv_beacon)) == _TRUE)
+	{
+		pmlmepriv->new_beacon_cnts = 0;
+	}
+	else if ((pmlmepriv->new_beacon_cnts == 0) ||
+		_rtw_memcmp(&recv_beacon, &pmlmepriv->new_beacon_keys, sizeof(recv_beacon)) == _FALSE)
+	{
+		DBG_871X_LEVEL(_drv_err_, "%s: start new beacon (seq=%d)\n", __func__, GetSequence(pframe));
+
+		if (pmlmepriv->new_beacon_cnts == 0) {
+			DBG_871X_LEVEL(_drv_err_, "%s: cur beacon key\n", __func__);
+			DBG_871X_EXP(_drv_err_, rtw_dump_bcn_keys(&pmlmepriv->cur_beacon_keys));
+		}
+
+		DBG_871X_LEVEL(_drv_err_, "%s: new beacon key\n", __func__);
+		DBG_871X_EXP(_drv_err_, rtw_dump_bcn_keys(&recv_beacon));
+
+		memcpy(&pmlmepriv->new_beacon_keys, &recv_beacon, sizeof(recv_beacon));
+		pmlmepriv->new_beacon_cnts = 1;
+	}
+	else
+	{
+		DBG_871X_LEVEL(_drv_err_, "%s: new beacon again (seq=%d)\n", __func__, GetSequence(pframe));
+		pmlmepriv->new_beacon_cnts++;
+	}
+
+	// if counter >= max, it means beacon is changed really
+	if (pmlmepriv->new_beacon_cnts >= new_bcn_max)
+	{
+		DBG_871X_LEVEL(_drv_err_, "%s: new beacon occur!!\n", __func__);
+
+		// check bw mode change only?
+		pmlmepriv->cur_beacon_keys.ht_cap_info = recv_beacon.ht_cap_info;
+		pmlmepriv->cur_beacon_keys.ht_info_infos_0_sco = recv_beacon.ht_info_infos_0_sco;
+
+		if (_rtw_memcmp(&recv_beacon, &pmlmepriv->cur_beacon_keys,
+					sizeof(recv_beacon)) == _FALSE) {
+			// beacon is changed, have to do disconnect/connect
+			return _FAIL;
+		}
+
+		DBG_871X("%s bw mode change\n", __func__);
+		DBG_871X("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+				cur_network->BcnInfo.ht_cap_info,
+				cur_network->BcnInfo.ht_info_infos_0);
+
+		cur_network->BcnInfo.ht_cap_info = recv_beacon.ht_cap_info;
+		cur_network->BcnInfo.ht_info_infos_0 =
+			(cur_network->BcnInfo.ht_info_infos_0 & (~0x03)) |
+			recv_beacon.ht_info_infos_0_sco;
+
+		DBG_871X("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+				cur_network->BcnInfo.ht_cap_info,
+				cur_network->BcnInfo.ht_info_infos_0);
+
+		memcpy(&pmlmepriv->cur_beacon_keys, &recv_beacon, sizeof(recv_beacon));
+		pmlmepriv->new_beacon_cnts = 0;
+	}
+
+	return _SUCCESS;
+
+#if 0
+	bssid = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
+	if (bssid == NULL) {
+		DBG_871X("%s rtw_zmalloc fail !!!\n", __func__);
+		return _TRUE;
+	}
+
+	if ((pmlmepriv->timeBcnInfoChkStart != 0) && (rtw_get_passing_time_ms(pmlmepriv->timeBcnInfoChkStart) > DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS))
+	{
+		pmlmepriv->timeBcnInfoChkStart = 0;
+		pmlmepriv->NumOfBcnInfoChkFail = 0;
+	}
+
+	subtype = GetFrameSubType(pframe) >> 4;
+
+	if(subtype==WIFI_BEACON)
+		bssid->Reserved[0] = 1;
+
+	bssid->Length = sizeof(WLAN_BSSID_EX) - MAX_IE_SZ + len;
+
+	/* below is to copy the information element */
+	bssid->IELength = len;
+	_rtw_memcpy(bssid->IEs, (pframe + sizeof(struct rtw_ieee80211_hdr_3addr)), bssid->IELength);
+
+	/* check bw and channel offset */
+	/* parsing HT_CAP_IE */
+	p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_CAPABILITY_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+	if(p && len>0) {
+			pht_cap = (struct rtw_ieee80211_ht_cap *)(p + 2);
+			ht_cap_info = pht_cap->cap_info;
+	} else {
+			ht_cap_info = 0;
+	}
+	/* parsing HT_INFO_IE */
+	p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+	if(p && len>0) {
+			pht_info = (struct HT_info_element *)(p + 2);
+			ht_info_infos_0 = pht_info->infos[0];
+	} else {
+			ht_info_infos_0 = 0;
+	}
+	if (ht_cap_info != cur_network->BcnInfo.ht_cap_info ||
+		((ht_info_infos_0&0x03) != (cur_network->BcnInfo.ht_info_infos_0&0x03))) {
+			DBG_871X("%s bcn now: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+						   	ht_cap_info, ht_info_infos_0);
+			DBG_871X("%s bcn link: ht_cap_info:%x ht_info_infos_0:%x\n", __func__,
+						   	cur_network->BcnInfo.ht_cap_info, cur_network->BcnInfo.ht_info_infos_0);
+			DBG_871X("%s bw mode change\n", __func__);
+			{	
+				//bcn_info_update
+				cur_network->BcnInfo.ht_cap_info = ht_cap_info;
+				cur_network->BcnInfo.ht_info_infos_0 = ht_info_infos_0;
+				//to do : need to check that whether modify related register of BB or not 
+			}
+			//goto _mismatch;
+	}
+
+	/* Checking for channel */
+	p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _DSSET_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+	if (p) {
+			bcn_channel = *(p + 2);
+	} else {/* In 5G, some ap do not have DSSET IE checking HT info for channel */
+			rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _HT_ADD_INFO_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_);
+			if(pht_info) {
+					bcn_channel = pht_info->primary_channel;
+			} else { /* we don't find channel IE, so don't check it */
+					//DBG_871X("Oops: %s we don't find channel IE, so don't check it \n", __func__);
+					bcn_channel = Adapter->mlmeextpriv.cur_channel;
+			}
+	}
+	if (bcn_channel != Adapter->mlmeextpriv.cur_channel) {
+			DBG_871X("%s beacon channel:%d cur channel:%d disconnect\n", __func__,
+						   bcn_channel, Adapter->mlmeextpriv.cur_channel);
+			goto _mismatch;
+	}
+
+	/* checking SSID */
+	if ((p = rtw_get_ie(bssid->IEs + _FIXED_IE_LENGTH_, _SSID_IE_, &len, bssid->IELength - _FIXED_IE_LENGTH_)) == NULL) {
+		DBG_871X("%s marc: cannot find SSID for survey event\n", __func__);
+		hidden_ssid = _TRUE;
+	} else {
+		hidden_ssid = _FALSE;
+	}
+
+	if((NULL != p) && (_FALSE == hidden_ssid && (*(p + 1)))) {
+		_rtw_memcpy(bssid->Ssid.Ssid, (p + 2), *(p + 1));
+		bssid->Ssid.SsidLength = *(p + 1);
+	} else {
+		bssid->Ssid.SsidLength = 0;
+		bssid->Ssid.Ssid[0] = '\0';
+	}
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,("%s bssid.Ssid.Ssid:%s bssid.Ssid.SsidLength:%d "
+				"cur_network->network.Ssid.Ssid:%s len:%d\n", __func__, bssid->Ssid.Ssid,
+				bssid->Ssid.SsidLength, cur_network->network.Ssid.Ssid,
+				cur_network->network.Ssid.SsidLength));
+
+	if (_rtw_memcmp(bssid->Ssid.Ssid, cur_network->network.Ssid.Ssid, 32) == _FALSE ||
+			bssid->Ssid.SsidLength != cur_network->network.Ssid.SsidLength) {
+		if (bssid->Ssid.Ssid[0] != '\0' && bssid->Ssid.SsidLength != 0) { /* not hidden ssid */
+			DBG_871X("%s(), SSID is not match\n", __func__);
+			goto _mismatch;
+		}
+	}
+
+	/* check encryption info */
+	val16 = rtw_get_capability((WLAN_BSSID_EX *)bssid);
+
+	if (val16 & BIT(4))
+		bssid->Privacy = 1;
+	else
+		bssid->Privacy = 0;
+
+	RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+			("%s(): cur_network->network.Privacy is %d, bssid.Privacy is %d\n",
+			 __func__, cur_network->network.Privacy,bssid->Privacy));
+	if (cur_network->network.Privacy != bssid->Privacy) {
+		DBG_871X("%s(), privacy is not match\n",__func__);
+		goto _mismatch;
+	}
+
+	rtw_get_sec_ie(bssid->IEs, bssid->IELength, NULL,&rsn_len,NULL,&wpa_len);
+
+	if (rsn_len > 0) {
+		encryp_protocol = ENCRYP_PROTOCOL_WPA2;
+	} else if (wpa_len > 0) {
+		encryp_protocol = ENCRYP_PROTOCOL_WPA;
+	} else {
+		if (bssid->Privacy)
+			encryp_protocol = ENCRYP_PROTOCOL_WEP;
+	}
+
+	if (cur_network->BcnInfo.encryp_protocol != encryp_protocol) {
+		DBG_871X("%s(): enctyp is not match\n",__func__);
+		goto _mismatch;
+	}
+
+	if (encryp_protocol == ENCRYP_PROTOCOL_WPA || encryp_protocol == ENCRYP_PROTOCOL_WPA2) {
+		pbuf = rtw_get_wpa_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
+		if(pbuf && (wpa_ielen>0)) {
+			if (_SUCCESS == rtw_parse_wpa_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
+				RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+						("%s pnetwork->pairwise_cipher: %d, group_cipher is %d, is_8021x is %d\n", __func__,
+						 pairwise_cipher, group_cipher, is_8021x));
+			}
+		} else {
+			pbuf = rtw_get_wpa2_ie(&bssid->IEs[12], &wpa_ielen, bssid->IELength-12);
+
+			if(pbuf && (wpa_ielen>0)) {
+				if (_SUCCESS == rtw_parse_wpa2_ie(pbuf, wpa_ielen+2, &group_cipher, &pairwise_cipher, &is_8021x)) {
+					RT_TRACE(_module_rtl871x_mlme_c_,_drv_info_,
+							("%s pnetwork->pairwise_cipher: %d, pnetwork->group_cipher is %d, is_802x is %d\n",
+							 __func__, pairwise_cipher, group_cipher, is_8021x));
+				}
+			}
+		}
+
+		RT_TRACE(_module_rtl871x_mlme_c_,_drv_err_,
+				("%s cur_network->group_cipher is %d: %d\n",__func__, cur_network->BcnInfo.group_cipher, group_cipher));
+		if (pairwise_cipher != cur_network->BcnInfo.pairwise_cipher || group_cipher != cur_network->BcnInfo.group_cipher) {
+			DBG_871X("%s pairwise_cipher(%x:%x) or group_cipher(%x:%x) is not match\n",__func__,
+					pairwise_cipher, cur_network->BcnInfo.pairwise_cipher,
+					group_cipher, cur_network->BcnInfo.group_cipher);
+			goto _mismatch;
+		}
+
+		if (is_8021x != cur_network->BcnInfo.is_8021x) {
+			DBG_871X("%s authentication is not match\n", __func__);
+			goto _mismatch;
+		}
+	}
+
+	rtw_mfree((u8 *)bssid, sizeof(WLAN_BSSID_EX));
+	return _SUCCESS;
+
+_mismatch:
+	rtw_mfree((u8 *)bssid, sizeof(WLAN_BSSID_EX));
+
+	if (pmlmepriv->NumOfBcnInfoChkFail == 0)
+	{
+		pmlmepriv->timeBcnInfoChkStart = rtw_get_current_time();
+	}
+
+	pmlmepriv->NumOfBcnInfoChkFail++;
+	DBG_871X("%s by "ADPT_FMT" - NumOfChkFail = %d (SeqNum of this Beacon frame = %d).\n", __func__, ADPT_ARG(Adapter), pmlmepriv->NumOfBcnInfoChkFail, GetSequence(pframe));
+
+	if ((pmlmepriv->timeBcnInfoChkStart != 0) && (rtw_get_passing_time_ms(pmlmepriv->timeBcnInfoChkStart) <= DISCONNECT_BY_CHK_BCN_FAIL_OBSERV_PERIOD_IN_MS) 
+		&& (pmlmepriv->NumOfBcnInfoChkFail >= DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD))
+	{
+		DBG_871X("%s by "ADPT_FMT" - NumOfChkFail = %d >= threshold : %d (in %d ms), return FAIL.\n", __func__, ADPT_ARG(Adapter), pmlmepriv->NumOfBcnInfoChkFail, 
+			DISCONNECT_BY_CHK_BCN_FAIL_THRESHOLD, rtw_get_passing_time_ms(pmlmepriv->timeBcnInfoChkStart));
+		pmlmepriv->timeBcnInfoChkStart = 0;
+		pmlmepriv->NumOfBcnInfoChkFail = 0;
+		return _FAIL;
+	}
+
+	return _SUCCESS;
+#endif
+}
+
+void update_beacon_info(_adapter *padapter, u8 *pframe, uint pkt_len, struct sta_info *psta)
+{
+	unsigned int i;
+	unsigned int len;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+		
+#ifdef CONFIG_TDLS
+	struct tdls_info *ptdlsinfo = &padapter->tdlsinfo;
+	u8 tdls_prohibited[] = { 0x00, 0x00, 0x00, 0x00, 0x10 }; //bit(38): TDLS_prohibited
+#endif //CONFIG_TDLS
+		
+	len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
+
+	for (i = 0; i < len;)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
+		
+		switch (pIE->ElementID)
+		{
+			case _VENDOR_SPECIFIC_IE_:		
+				//to update WMM paramter set while receiving beacon
+				if (_rtw_memcmp(pIE->data, WMM_PARA_OUI, 6) && pIE->Length == WLAN_WMM_LEN)	//WMM
+				{
+					(WMM_param_handler(padapter, pIE))? report_wmm_edca_update(padapter): 0;
+				}
+
+				break;
+
+			case _HT_EXTRA_INFO_IE_:	//HT info				
+				//HT_info_handler(padapter, pIE);
+				bwmode_update_check(padapter, pIE);
+				break;
+#ifdef CONFIG_80211AC_VHT
+			case EID_OpModeNotification:
+				rtw_process_vht_op_mode_notify(padapter, pIE->data, psta);
+				break;
+#endif //CONFIG_80211AC_VHT
+			case _ERPINFO_IE_:
+				ERP_IE_handler(padapter, pIE);
+				VCS_update(padapter, psta);
+				break;
+
+#ifdef CONFIG_TDLS
+			case _EXT_CAP_IE_:
+				if( check_ap_tdls_prohibited(pIE->data, pIE->Length) == _TRUE )
+					ptdlsinfo->ap_prohibited = _TRUE;
+				if (check_ap_tdls_ch_switching_prohibited(pIE->data, pIE->Length) == _TRUE)
+					ptdlsinfo->ch_switch_prohibited = _TRUE;
+				break;
+#endif //CONFIG_TDLS
+			default:
+				break;
+		}
+		
+		i += (pIE->Length + 2);
+	}
+}
+
+#ifdef CONFIG_DFS
+void process_csa_ie(_adapter *padapter, u8 *pframe, uint pkt_len)
+{
+	unsigned int i;
+	unsigned int len;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	u8 new_ch_no = 0; 
+
+	if(padapter->mlmepriv.handle_dfs == _TRUE )
+		return;
+	
+	len = pkt_len - (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN);
+
+	for (i = 0; i < len;)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + (_BEACON_IE_OFFSET_ + WLAN_HDR_A3_LEN) + i);
+		
+		switch (pIE->ElementID)
+		{
+			case _CH_SWTICH_ANNOUNCE_:
+				padapter->mlmepriv.handle_dfs = _TRUE;
+				_rtw_memcpy(&new_ch_no, pIE->data+1, 1);
+				rtw_set_csa_cmd(padapter, new_ch_no);
+				break;
+			default:
+				break;
+		}
+		
+		i += (pIE->Length + 2);
+	}
+}
+#endif //CONFIG_DFS
+
+unsigned int is_ap_in_tkip(_adapter *padapter)
+{
+	u32 i;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+
+	if (rtw_get_capability((WLAN_BSSID_EX *)cur_network) & WLAN_CAPABILITY_PRIVACY)
+	{
+		for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
+		{
+			pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
+		
+			switch (pIE->ElementID)
+			{
+				case _VENDOR_SPECIFIC_IE_:
+					if ((_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4)) && (_rtw_memcmp((pIE->data + 12), WPA_TKIP_CIPHER, 4))) 
+					{
+						return _TRUE;
+					}
+					break;
+				
+				case _RSN_IE_2_:
+					if (_rtw_memcmp((pIE->data + 8), RSN_TKIP_CIPHER, 4)) 
+					{
+						return _TRUE;
+					}
+					
+				default:
+					break;
+			}
+		
+			i += (pIE->Length + 2);
+		}
+		
+		return _FALSE;
+	}
+	else
+	{
+		return _FALSE;
+	}
+	
+}
+
+unsigned int should_forbid_n_rate(_adapter * padapter)
+{
+	u32 i;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	WLAN_BSSID_EX  *cur_network = &pmlmepriv->cur_network.network;
+
+	if (rtw_get_capability((WLAN_BSSID_EX *)cur_network) & WLAN_CAPABILITY_PRIVACY)
+	{
+		for (i = sizeof(NDIS_802_11_FIXED_IEs); i < cur_network->IELength;)
+		{
+			pIE = (PNDIS_802_11_VARIABLE_IEs)(cur_network->IEs + i);
+
+			switch (pIE->ElementID)
+			{
+				case _VENDOR_SPECIFIC_IE_:
+					if (_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4) &&
+						((_rtw_memcmp((pIE->data + 12), WPA_CIPHER_SUITE_CCMP, 4)) ||
+						  (_rtw_memcmp((pIE->data + 16), WPA_CIPHER_SUITE_CCMP, 4))))
+						return _FALSE;
+					break;
+
+				case _RSN_IE_2_:
+					if  ((_rtw_memcmp((pIE->data + 8), RSN_CIPHER_SUITE_CCMP, 4))  ||
+					       (_rtw_memcmp((pIE->data + 12), RSN_CIPHER_SUITE_CCMP, 4)))
+						return _FALSE;
+
+				default:
+					break;
+			}
+
+			i += (pIE->Length + 2);
+		}
+
+		return _TRUE;
+	}
+	else
+	{
+		return _FALSE;
+	}
+
+}
+
+
+unsigned int is_ap_in_wep(_adapter *padapter)
+{
+	u32 i;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+
+	if (rtw_get_capability((WLAN_BSSID_EX *)cur_network) & WLAN_CAPABILITY_PRIVACY)
+	{
+		for (i = sizeof(NDIS_802_11_FIXED_IEs); i < pmlmeinfo->network.IELength;)
+		{
+			pIE = (PNDIS_802_11_VARIABLE_IEs)(pmlmeinfo->network.IEs + i);
+
+			switch (pIE->ElementID)
+			{
+				case _VENDOR_SPECIFIC_IE_:
+					if (_rtw_memcmp(pIE->data, RTW_WPA_OUI, 4))
+						return _FALSE;
+					break;
+
+				case _RSN_IE_2_:
+					return _FALSE;
+
+				default:
+					break;
+			}
+
+			i += (pIE->Length + 2);
+		}
+
+		return _TRUE;
+	}
+	else
+	{
+		return _FALSE;
+	}
+
+}
+
+int wifirate2_ratetbl_inx(unsigned char rate);
+int wifirate2_ratetbl_inx(unsigned char rate)
+{
+	int	inx = 0;
+	rate = rate & 0x7f;
+
+	switch (rate) 
+	{
+		case 54*2:
+			inx = 11;
+			break;
+
+		case 48*2:
+			inx = 10;
+			break;
+
+		case 36*2:
+			inx = 9;
+			break;
+
+		case 24*2:
+			inx = 8;
+			break;
+			
+		case 18*2:
+			inx = 7;
+			break;
+
+		case 12*2:
+			inx = 6;
+			break;
+
+		case 9*2:
+			inx = 5;
+			break;
+			
+		case 6*2:
+			inx = 4;
+			break;
+
+		case 11*2:
+			inx = 3;
+			break;
+		case 11:
+			inx = 2;
+			break;
+
+		case 2*2:
+			inx = 1;
+			break;
+		
+		case 1*2:
+			inx = 0;
+			break;
+
+	}
+	return inx;	
+}
+
+unsigned int update_basic_rate(unsigned char *ptn, unsigned int ptn_sz)
+{
+	unsigned int i, num_of_rate;
+	unsigned int mask = 0;
+	
+	num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
+		
+	for (i = 0; i < num_of_rate; i++)
+	{
+		if ((*(ptn + i)) & 0x80)
+		{
+			mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
+		}
+	}
+	return mask;
+}
+
+unsigned int update_supported_rate(unsigned char *ptn, unsigned int ptn_sz)
+{
+	unsigned int i, num_of_rate;
+	unsigned int mask = 0;
+	
+	num_of_rate = (ptn_sz > NumRates)? NumRates: ptn_sz;
+		
+	for (i = 0; i < num_of_rate; i++)
+	{
+		mask |= 0x1 << wifirate2_ratetbl_inx(*(ptn + i));
+	}
+
+	return mask;
+}
+
+unsigned int update_MCS_rate(struct HT_caps_element *pHT_caps)
+{
+	unsigned int mask = 0;
+	
+	mask = ((pHT_caps->u.HT_cap_element.MCS_rate[0] << 12) | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 20));
+						
+	return mask;
+}
+
+int support_short_GI(_adapter *padapter, struct HT_caps_element *pHT_caps, u8 bwmode)
+{
+	unsigned char					bit_offset;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	if (!(pmlmeinfo->HT_enable))
+		return _FAIL; 
+
+	bit_offset = (bwmode & CHANNEL_WIDTH_40)? 6: 5;
+	
+	if (pHT_caps->u.HT_cap_element.HT_caps_info & (0x1 << bit_offset))
+	{
+		return _SUCCESS;
+	}
+	else
+	{
+		return _FAIL;
+	}		
+}
+
+unsigned char get_highest_rate_idx(u32 mask)
+{
+	int i;
+	unsigned char rate_idx=0;
+
+	for(i=31; i>=0; i--)
+	{
+		if(mask & BIT(i))
+		{
+			rate_idx = i;
+			break;
+		}
+	}
+
+	return rate_idx;
+}
+
+unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps);
+unsigned char get_highest_mcs_rate(struct HT_caps_element *pHT_caps)
+{
+	int i, mcs_rate;
+	
+	mcs_rate = (pHT_caps->u.HT_cap_element.MCS_rate[0] | (pHT_caps->u.HT_cap_element.MCS_rate[1] << 8));
+	
+	for (i = 15; i >= 0; i--)
+	{
+		if (mcs_rate & (0x1 << i))
+		{
+			break;
+		}
+	}
+	
+	return i;
+}
+
+void Update_RA_Entry(_adapter *padapter, struct sta_info *psta)
+{
+	rtw_hal_update_ra_mask(psta, 0);
+}
+
+void enable_rate_adaptive(_adapter *padapter, struct sta_info *psta);
+void enable_rate_adaptive(_adapter *padapter, struct sta_info *psta)
+{
+	Update_RA_Entry(padapter, psta);
+}
+
+void set_sta_rate(_adapter *padapter, struct sta_info *psta)
+{
+	//rate adaptive	
+	enable_rate_adaptive(padapter, psta);
+}
+
+// Update RRSR and Rate for USERATE
+void update_tx_basic_rate(_adapter *padapter, u8 wirelessmode)
+{
+	NDIS_802_11_RATES_EX	supported_rates;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+#ifdef CONFIG_P2P
+	struct wifidirect_info*	pwdinfo = &padapter->wdinfo;
+
+	//	Added by Albert 2011/03/22
+	//	In the P2P mode, the driver should not support the b mode.
+	//	So, the Tx packet shouldn't use the CCK rate
+	if(!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		return;
+#endif //CONFIG_P2P
+#ifdef CONFIG_INTEL_WIDI
+	if (padapter->mlmepriv.widi_state != INTEL_WIDI_STATE_NONE)
+		return;
+#endif //CONFIG_INTEL_WIDI
+
+	_rtw_memset(supported_rates, 0, NDIS_802_11_LENGTH_RATES_EX);
+
+	//clear B mod if current channel is in 5G band, avoid tx cck rate in 5G band.
+	if(pmlmeext->cur_channel > 14)
+		wirelessmode &= ~(WIRELESS_11B);
+
+	if ((wirelessmode & WIRELESS_11B) && (wirelessmode == WIRELESS_11B)) {
+		_rtw_memcpy(supported_rates, rtw_basic_rate_cck, 4);
+	} else if (wirelessmode & WIRELESS_11B) {
+		_rtw_memcpy(supported_rates, rtw_basic_rate_mix, 7);
+	} else {
+		_rtw_memcpy(supported_rates, rtw_basic_rate_ofdm, 3);
+	}
+
+	if (wirelessmode & WIRELESS_11B)
+		update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
+	else
+		update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
+
+	rtw_hal_set_hwreg(padapter, HW_VAR_BASIC_RATE, supported_rates);
+}
+
+unsigned char check_assoc_AP(u8 *pframe, uint len)
+{
+	unsigned int	i;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+
+	for (i = sizeof(NDIS_802_11_FIXED_IEs); i < len;)
+	{
+		pIE = (PNDIS_802_11_VARIABLE_IEs)(pframe + i);
+		
+		switch (pIE->ElementID)
+		{
+			case _VENDOR_SPECIFIC_IE_:
+				if ((_rtw_memcmp(pIE->data, ARTHEROS_OUI1, 3)) || (_rtw_memcmp(pIE->data, ARTHEROS_OUI2, 3)))
+				{
+					DBG_871X("link to Artheros AP\n");
+					return HT_IOT_PEER_ATHEROS;
+				}
+				else if (	(_rtw_memcmp(pIE->data, BROADCOM_OUI1, 3))
+						|| (_rtw_memcmp(pIE->data, BROADCOM_OUI2, 3))
+						|| (_rtw_memcmp(pIE->data, BROADCOM_OUI3, 3)))						
+				{
+					DBG_871X("link to Broadcom AP\n");
+					return HT_IOT_PEER_BROADCOM;
+				}
+				else if (_rtw_memcmp(pIE->data, MARVELL_OUI, 3))
+				{
+					DBG_871X("link to Marvell AP\n");
+					return HT_IOT_PEER_MARVELL;
+				}
+				else if (_rtw_memcmp(pIE->data, RALINK_OUI, 3))
+				{
+					DBG_871X("link to Ralink AP\n");
+					return HT_IOT_PEER_RALINK;
+				}
+				else if (_rtw_memcmp(pIE->data, CISCO_OUI, 3))
+				{
+					DBG_871X("link to Cisco AP\n");
+					return HT_IOT_PEER_CISCO;
+				}
+				else if (_rtw_memcmp(pIE->data, REALTEK_OUI, 3))
+				{
+					u32	Vender = HT_IOT_PEER_REALTEK;
+
+					if(pIE->Length >= 5) {
+						if(pIE->data[4]==1)
+						{
+							//if(pIE->data[5] & RT_HT_CAP_USE_LONG_PREAMBLE)
+							//	bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_LONG_PREAMBLE;
+
+							if(pIE->data[5] & RT_HT_CAP_USE_92SE)
+							{
+								//bssDesc->BssHT.RT2RT_HT_Mode |= RT_HT_CAP_USE_92SE;
+								Vender = HT_IOT_PEER_REALTEK_92SE;
+							}
+						}
+
+						if(pIE->data[5] & RT_HT_CAP_USE_SOFTAP)
+							Vender = HT_IOT_PEER_REALTEK_SOFTAP;
+
+						if(pIE->data[4] == 2)
+						{
+							if(pIE->data[6] & RT_HT_CAP_USE_JAGUAR_BCUT) {
+								Vender = HT_IOT_PEER_REALTEK_JAGUAR_BCUTAP;
+								DBG_871X("link to Realtek JAGUAR_BCUTAP\n");
+							}
+							if(pIE->data[6] & RT_HT_CAP_USE_JAGUAR_CCUT) {
+								Vender = HT_IOT_PEER_REALTEK_JAGUAR_CCUTAP;
+								DBG_871X("link to Realtek JAGUAR_CCUTAP\n");
+							}
+						}
+					}
+				
+					DBG_871X("link to Realtek AP\n");
+					return Vender;
+				}
+				else if (_rtw_memcmp(pIE->data, AIRGOCAP_OUI,3))
+				{
+					DBG_871X("link to Airgo Cap\n");
+					return HT_IOT_PEER_AIRGO;
+				}
+				else
+				{
+					break;
+				}
+						
+			default:
+				break;
+		}
+				
+		i += (pIE->Length + 2);
+	}
+	
+	DBG_871X("link to new AP\n");
+	return HT_IOT_PEER_UNKNOWN;
+}
+
+void update_capinfo(PADAPTER Adapter, u16 updateCap)
+{
+	struct mlme_ext_priv	*pmlmeext = &Adapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	BOOLEAN		ShortPreamble;
+
+	// Check preamble mode, 2005.01.06, by rcnjko.
+	// Mark to update preamble value forever, 2008.03.18 by lanhsin
+	//if( pMgntInfo->RegPreambleMode == PREAMBLE_AUTO )
+	{
+			
+		if(updateCap & cShortPreamble)
+		{ // Short Preamble
+			if(pmlmeinfo->preamble_mode != PREAMBLE_SHORT) // PREAMBLE_LONG or PREAMBLE_AUTO
+			{
+				ShortPreamble = _TRUE;
+				pmlmeinfo->preamble_mode = PREAMBLE_SHORT;
+				rtw_hal_set_hwreg( Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble );
+			}
+		}
+		else
+		{ // Long Preamble
+			if(pmlmeinfo->preamble_mode != PREAMBLE_LONG)  // PREAMBLE_SHORT or PREAMBLE_AUTO
+			{
+				ShortPreamble = _FALSE;
+				pmlmeinfo->preamble_mode = PREAMBLE_LONG;
+				rtw_hal_set_hwreg( Adapter, HW_VAR_ACK_PREAMBLE, (u8 *)&ShortPreamble );
+			}
+		}
+	}
+
+	if ( updateCap & cIBSS ) {
+		//Filen: See 802.11-2007 p.91
+		pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
+	}
+	else
+	{
+		//Filen: See 802.11-2007 p.90
+		if( pmlmeext->cur_wireless_mode & (WIRELESS_11_24N | WIRELESS_11A | WIRELESS_11_5N | WIRELESS_11AC))
+		{
+			pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+		}
+		else if( pmlmeext->cur_wireless_mode & (WIRELESS_11G))
+		{
+			if( (updateCap & cShortSlotTime) /* && (!(pMgntInfo->pHTInfo->RT2RT_HT_Mode & RT_HT_CAP_USE_LONG_PREAMBLE)) */)
+			{ // Short Slot Time
+				pmlmeinfo->slotTime = SHORT_SLOT_TIME;
+			}
+			else
+			{ // Long Slot Time
+				pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
+			}
+		}
+		else
+		{
+			//B Mode
+			pmlmeinfo->slotTime = NON_SHORT_SLOT_TIME;
+		}
+ 	}
+ 
+	rtw_hal_set_hwreg( Adapter, HW_VAR_SLOT_TIME, &pmlmeinfo->slotTime );
+
+}
+
+/*
+* set adapter.mlmeextpriv.mlmext_info.HT_enable
+* set adapter.mlmeextpriv.cur_wireless_mode
+* set SIFS register
+* set mgmt tx rate
+*/
+void update_wireless_mode(_adapter *padapter)
+{
+	int ratelen, network_type = 0;
+	u32 SIFS_Timer;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	unsigned char			*rate = cur_network->SupportedRates;
+#ifdef CONFIG_P2P
+	struct wifidirect_info	*pwdinfo= &(padapter->wdinfo);
+#endif //CONFIG_P2P
+
+	ratelen = rtw_get_rateset_len(cur_network->SupportedRates);
+
+	if ((pmlmeinfo->HT_info_enable) && (pmlmeinfo->HT_caps_enable))
+	{
+		pmlmeinfo->HT_enable = 1;
+	}
+
+	if(pmlmeext->cur_channel > 14)
+	{
+		if (pmlmeinfo->VHT_enable)
+			network_type = WIRELESS_11AC;
+		else if (pmlmeinfo->HT_enable)
+			network_type = WIRELESS_11_5N;
+
+		network_type |= WIRELESS_11A;
+	}
+	else
+	{
+		if (pmlmeinfo->VHT_enable)
+			network_type = WIRELESS_11AC;
+		else if (pmlmeinfo->HT_enable)
+			network_type = WIRELESS_11_24N;
+	
+		if ((cckratesonly_included(rate, ratelen)) == _TRUE)
+		{
+			network_type |= WIRELESS_11B;
+		}
+		else if((cckrates_included(rate, ratelen)) == _TRUE)
+		{
+			network_type |= WIRELESS_11BG;
+		}
+		else
+		{
+			network_type |= WIRELESS_11G;
+		}
+	}
+
+	pmlmeext->cur_wireless_mode = network_type & padapter->registrypriv.wireless_mode;
+	/* DBG_871X("network_type=%02x, padapter->registrypriv.wireless_mode=%02x\n", network_type, padapter->registrypriv.wireless_mode); */
+/*
+	if((pmlmeext->cur_wireless_mode==WIRELESS_11G) ||
+		(pmlmeext->cur_wireless_mode==WIRELESS_11BG))//WIRELESS_MODE_G)
+		SIFS_Timer = 0x0a0a;//CCK
+	else
+		SIFS_Timer = 0x0e0e;//pHalData->SifsTime; //OFDM
+*/
+	
+	SIFS_Timer = 0x0a0a0808; //0x0808 -> for CCK, 0x0a0a -> for OFDM
+                             //change this value if having IOT issues.
+		
+	rtw_hal_set_hwreg( padapter, HW_VAR_RESP_SIFS,  (u8 *)&SIFS_Timer);
+
+	rtw_hal_set_hwreg( padapter, HW_VAR_WIRELESS_MODE,  (u8 *)&(pmlmeext->cur_wireless_mode));
+
+	if ((pmlmeext->cur_wireless_mode & WIRELESS_11B)
+		&& rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
+		update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
+	else
+		update_mgnt_tx_rate(padapter, IEEE80211_OFDM_RATE_6MB);
+}
+
+void fire_write_MAC_cmd(_adapter *padapter, unsigned int addr, unsigned int value);
+void fire_write_MAC_cmd(_adapter *padapter, unsigned int addr, unsigned int value)
+{
+#if 0
+	struct cmd_obj					*ph2c;
+	struct reg_rw_parm			*pwriteMacPara;
+	struct cmd_priv					*pcmdpriv = &(padapter->cmdpriv);
+
+	if ((ph2c = (struct cmd_obj*)rtw_zmalloc(sizeof(struct cmd_obj))) == NULL)
+	{
+		return;
+	}	
+
+	if ((pwriteMacPara = (struct reg_rw_parm*)rtw_malloc(sizeof(struct reg_rw_parm))) == NULL) 
+	{		
+		rtw_mfree((unsigned char *)ph2c, sizeof(struct cmd_obj));
+		return;
+	}
+	
+	pwriteMacPara->rw = 1;
+	pwriteMacPara->addr = addr;
+	pwriteMacPara->value = value;
+	
+	init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteMacPara, GEN_CMD_CODE(_Write_MACREG));
+	rtw_enqueue_cmd(pcmdpriv, ph2c);
+#endif	
+}
+
+void update_sta_basic_rate(struct sta_info *psta, u8 wireless_mode)
+{
+	if(IsSupportedTxCCK(wireless_mode))
+	{
+		// Only B, B/G, and B/G/N AP could use CCK rate
+		_rtw_memcpy(psta->bssrateset, rtw_basic_rate_cck, 4);
+		psta->bssratelen = 4;
+	}
+	else
+	{
+		_rtw_memcpy(psta->bssrateset, rtw_basic_rate_ofdm, 3);
+		psta->bssratelen = 3;
+	}
+}
+
+int update_sta_support_rate(_adapter *padapter, u8* pvar_ie, uint var_ie_len, int cam_idx)
+{
+	unsigned int	ie_len;
+	PNDIS_802_11_VARIABLE_IEs	pIE;
+	int	supportRateNum = 0;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	
+	pIE = (PNDIS_802_11_VARIABLE_IEs)rtw_get_ie(pvar_ie, _SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
+	if (pIE == NULL)
+	{
+		return _FAIL;
+	}
+	
+	_rtw_memcpy(pmlmeinfo->FW_sta_info[cam_idx].SupportedRates, pIE->data, ie_len);
+	supportRateNum = ie_len;
+				
+	pIE = (PNDIS_802_11_VARIABLE_IEs)rtw_get_ie(pvar_ie, _EXT_SUPPORTEDRATES_IE_, &ie_len, var_ie_len);
+	if (pIE)
+	{
+		_rtw_memcpy((pmlmeinfo->FW_sta_info[cam_idx].SupportedRates + supportRateNum), pIE->data, ie_len);
+	}
+
+	return _SUCCESS;
+	
+}
+
+void process_addba_req(_adapter *padapter, u8 *paddba_req, u8 *addr)
+{
+	struct sta_info *psta;
+	u16 tid, start_seq, param;	
+	struct recv_reorder_ctrl *preorder_ctrl;
+	struct sta_priv *pstapriv = &padapter->stapriv;	
+	struct ADDBA_request	*preq = (struct ADDBA_request*)paddba_req;
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	u8 size;
+
+	psta = rtw_get_stainfo(pstapriv, addr);
+	if (!psta)
+		goto exit;
+
+	start_seq = le16_to_cpu(preq->BA_starting_seqctrl) >> 4;
+
+	param = le16_to_cpu(preq->BA_para_set);
+	tid = (param>>2)&0x0f;
+
+	preorder_ctrl = &psta->recvreorder_ctrl[tid];
+
+	#ifdef CONFIG_UPDATE_INDICATE_SEQ_WHILE_PROCESS_ADDBA_REQ
+	preorder_ctrl->indicate_seq = start_seq;
+	#ifdef DBG_RX_SEQ
+	DBG_871X("DBG_RX_SEQ %s:%d IndicateSeq: %d, start_seq: %d\n", __func__, __LINE__,
+		preorder_ctrl->indicate_seq, start_seq);
+	#endif
+	#else
+	preorder_ctrl->indicate_seq = 0xffff;
+	#endif
+
+	preorder_ctrl->enable = rtw_rx_ampdu_is_accept(padapter);
+	size = rtw_rx_ampdu_size(padapter);
+
+	if (preorder_ctrl->enable == _TRUE) {
+		preorder_ctrl->ampdu_size = size;
+		issue_addba_rsp(padapter, addr, tid, 0, size);
+	} else {
+		issue_addba_rsp(padapter, addr, tid, 37, size); /* reject ADDBA Req */
+	}
+
+exit:
+	return;
+}
+
+void update_TSF(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
+{	
+	u8* pIE;
+	u32 *pbuf;
+		
+	pIE = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+	pbuf = (u32*)pIE;
+
+	pmlmeext->TSFValue = le32_to_cpu(*(pbuf+1));
+	
+	pmlmeext->TSFValue = pmlmeext->TSFValue << 32;
+
+	pmlmeext->TSFValue |= le32_to_cpu(*pbuf);
+}
+
+void correct_TSF(_adapter *padapter, struct mlme_ext_priv *pmlmeext)
+{
+	rtw_hal_set_hwreg(padapter, HW_VAR_CORRECT_TSF, 0);
+}
+
+void adaptive_early_32k(struct mlme_ext_priv *pmlmeext, u8 *pframe, uint len)
+{	
+	int i;
+	u8* pIE;
+	u32 *pbuf;
+	u64 tsf=0;
+	u32 delay_ms;
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+
+	pmlmeext->bcn_cnt++;
+
+	pIE = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+	pbuf = (u32*)pIE;
+
+	tsf = le32_to_cpu(*(pbuf+1));	
+	tsf = tsf << 32;
+	tsf |= le32_to_cpu(*pbuf);
+
+	//DBG_871X("%s(): tsf_upper= 0x%08x, tsf_lower=0x%08x\n", __func__, (u32)(tsf>>32), (u32)tsf);
+
+	//delay = (timestamp mod 1024*100)/1000 (unit: ms)
+	//delay_ms = do_div(tsf, (pmlmeinfo->bcn_interval*1024))/1000;
+	delay_ms = rtw_modular64(tsf, (pmlmeinfo->bcn_interval*1024));
+	delay_ms = delay_ms/1000;
+
+	if(delay_ms >= 8)
+	{
+		pmlmeext->bcn_delay_cnt[8]++;
+		//pmlmeext->bcn_delay_ratio[8] = (pmlmeext->bcn_delay_cnt[8] * 100) /pmlmeext->bcn_cnt;
+	}
+	else
+	{
+		pmlmeext->bcn_delay_cnt[delay_ms]++;
+		//pmlmeext->bcn_delay_ratio[delay_ms] = (pmlmeext->bcn_delay_cnt[delay_ms] * 100) /pmlmeext->bcn_cnt;
+	}
+
+/*
+	DBG_871X("%s(): (a)bcn_cnt = %d\n", __func__, pmlmeext->bcn_cnt);
+
+
+	for(i=0; i<9; i++)
+	{
+		DBG_871X("%s():bcn_delay_cnt[%d]=%d,  bcn_delay_ratio[%d]=%d\n", __func__, i, 
+			pmlmeext->bcn_delay_cnt[i] , i, pmlmeext->bcn_delay_ratio[i]);			
+	}	
+*/
+
+	//dump for  adaptive_early_32k
+	if(pmlmeext->bcn_cnt > 100 && (pmlmeext->adaptive_tsf_done==_TRUE))
+	{	
+		u8 ratio_20_delay, ratio_80_delay;
+		u8 DrvBcnEarly, DrvBcnTimeOut;
+
+		ratio_20_delay = 0;
+		ratio_80_delay = 0;
+		DrvBcnEarly = 0xff;
+		DrvBcnTimeOut = 0xff;
+	
+		DBG_871X("%s(): bcn_cnt = %d\n", __func__, pmlmeext->bcn_cnt);
+
+		for(i=0; i<9; i++)
+		{
+			pmlmeext->bcn_delay_ratio[i] = (pmlmeext->bcn_delay_cnt[i] * 100) /pmlmeext->bcn_cnt;
+			
+		
+			//DBG_871X("%s():bcn_delay_cnt[%d]=%d,  bcn_delay_ratio[%d]=%d\n", __func__, i, 
+			//	pmlmeext->bcn_delay_cnt[i] , i, pmlmeext->bcn_delay_ratio[i]);
+
+			ratio_20_delay += pmlmeext->bcn_delay_ratio[i];
+			ratio_80_delay += pmlmeext->bcn_delay_ratio[i];
+		
+			if(ratio_20_delay > 20 && DrvBcnEarly == 0xff)
+			{			
+				DrvBcnEarly = i;
+				//DBG_871X("%s(): DrvBcnEarly = %d\n", __func__, DrvBcnEarly);
+			}	
+
+			if(ratio_80_delay > 80 && DrvBcnTimeOut == 0xff)
+			{
+				DrvBcnTimeOut = i;
+				//DBG_871X("%s(): DrvBcnTimeOut = %d\n", __func__, DrvBcnTimeOut);
+			}
+			
+			//reset adaptive_early_32k cnt
+			pmlmeext->bcn_delay_cnt[i] = 0;
+			pmlmeext->bcn_delay_ratio[i] = 0;			
+		}	
+
+		pmlmeext->DrvBcnEarly = DrvBcnEarly;
+		pmlmeext->DrvBcnTimeOut = DrvBcnTimeOut;
+
+		pmlmeext->bcn_cnt = 0;		
+	}	
+	
+}
+
+
+void beacon_timing_control(_adapter *padapter)
+{
+	rtw_hal_bcn_related_reg_setting(padapter);
+}
+
+#define CONFIG_SHARED_BMC_MACID
+
+void dump_macid_map(void *sel, struct macid_bmp *map, u8 max_num)
+{
+	DBG_871X_SEL_NL(sel, "0x%08x\n", map->m0);
+#if (MACID_NUM_SW_LIMIT > 32)
+	if (max_num && max_num > 32)
+		DBG_871X_SEL_NL(sel, "0x%08x\n", map->m1);
+#endif
+#if (MACID_NUM_SW_LIMIT > 64)
+	if (max_num && max_num > 64)
+		DBG_871X_SEL_NL(sel, "0x%08x\n", map->m2);
+#endif
+#if (MACID_NUM_SW_LIMIT > 96)
+	if (max_num && max_num > 96)
+		DBG_871X_SEL_NL(sel, "0x%08x\n", map->m3);
+#endif
+}
+
+inline bool rtw_macid_is_set(struct macid_bmp *map, u8 id)
+{
+	if (id < 32)
+		return (map->m0 & BIT(id));
+#if (MACID_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		return (map->m1 & BIT(id-32));
+#endif
+#if (MACID_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		return (map->m2 & BIT(id-64));
+#endif
+#if (MACID_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		return (map->m3 & BIT(id-96));
+#endif
+	else
+		rtw_warn_on(1);
+
+	return 0;
+}
+
+inline void rtw_macid_map_set(struct macid_bmp *map, u8 id)
+{
+	if (id < 32)
+		map->m0 |= BIT(id);
+#if (MACID_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		map->m1 |= BIT(id-32);
+#endif
+#if (MACID_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		map->m2 |= BIT(id-64);
+#endif
+#if (MACID_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		map->m3 |= BIT(id-96);
+#endif
+	else
+		rtw_warn_on(1);
+}
+
+inline void rtw_macid_map_clr(struct macid_bmp *map, u8 id)
+{
+	if (id < 32)
+		map->m0 &= ~BIT(id);
+#if (MACID_NUM_SW_LIMIT > 32)
+	else if (id < 64)
+		map->m1 &= ~BIT(id-32);
+#endif
+#if (MACID_NUM_SW_LIMIT > 64)
+	else if (id < 96)
+		map->m2 &= ~BIT(id-64);
+#endif
+#if (MACID_NUM_SW_LIMIT > 96)
+	else if (id < 128)
+		map->m3 &= ~BIT(id-96);
+#endif
+	else
+		rtw_warn_on(1);
+}
+
+inline bool rtw_macid_is_used(struct macid_ctl_t *macid_ctl, u8 id)
+{
+	return rtw_macid_is_set(&macid_ctl->used, id);
+}
+
+inline bool rtw_macid_is_bmc(struct macid_ctl_t *macid_ctl, u8 id)
+{
+	return rtw_macid_is_set(&macid_ctl->bmc, id);
+}
+
+inline s8 rtw_macid_get_if_g(struct macid_ctl_t *macid_ctl, u8 id)
+{
+	int i;
+
+#ifdef CONFIG_SHARED_BMC_MACID
+	if (rtw_macid_is_bmc(macid_ctl,id))
+		return -1;
+#endif
+
+	for (i=0;i<IFACE_ID_MAX;i++) {
+		if (rtw_macid_is_set(&macid_ctl->if_g[i], id))
+			return i;
+	}
+	return -1;
+}
+
+inline s8 rtw_macid_get_ch_g(struct macid_ctl_t *macid_ctl, u8 id)
+{
+	int i;
+
+	for (i=0;i<2;i++) {
+		if (rtw_macid_is_set(&macid_ctl->ch_g[i], id))
+			return i;
+	}
+	return -1;
+}
+
+void rtw_alloc_macid(_adapter *padapter, struct sta_info *psta)
+{
+	int i;
+	_irqL irqL;
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	struct macid_bmp *used_map = &macid_ctl->used;
+	//static u8 last_id = 0; /* for testing */
+	u8 last_id = 0;
+
+	if (_rtw_memcmp(psta->hwaddr, adapter_mac_addr(padapter), ETH_ALEN)) {
+		psta->mac_id = macid_ctl->num;
+		return;
+	}
+
+#ifdef CONFIG_SHARED_BMC_MACID
+	if(_rtw_memcmp(psta->hwaddr, bc_addr, ETH_ALEN)) {
+		/* use shared broadcast & multicast macid 1 */
+		_enter_critical_bh(&macid_ctl->lock, &irqL);
+		rtw_macid_map_set(used_map, 1);
+		rtw_macid_map_set(&macid_ctl->bmc, 1);
+		for (i=0;i<IFACE_ID_MAX;i++)
+			rtw_macid_map_set(&macid_ctl->if_g[padapter->iface_id], 1);
+		/* TODO ch_g? */
+		_exit_critical_bh(&macid_ctl->lock, &irqL);
+		i = 1;
+		goto assigned;
+	}
+#endif
+
+	_enter_critical_bh(&macid_ctl->lock, &irqL);
+
+	for (i=last_id;i<macid_ctl->num;i++) {
+		#ifdef CONFIG_SHARED_BMC_MACID
+		if (i == 1)
+			continue;
+		#endif
+		if (!rtw_macid_is_used(macid_ctl, i))
+			break;
+	}
+
+	if (i < macid_ctl->num) {
+
+		rtw_macid_map_set(used_map, i);
+
+		if(_rtw_memcmp(psta->hwaddr, bc_addr, ETH_ALEN))
+			rtw_macid_map_set(&macid_ctl->bmc, i);
+
+		rtw_macid_map_set(&macid_ctl->if_g[padapter->iface_id], i);
+
+		/* TODO ch_g? */
+
+		last_id++;
+		last_id %= macid_ctl->num;
+	}
+
+	_exit_critical_bh(&macid_ctl->lock, &irqL);
+
+	if (i >= macid_ctl->num) {
+		psta->mac_id = macid_ctl->num;
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" if%u, hwaddr:"MAC_FMT" no available macid\n"
+			, FUNC_ADPT_ARG(padapter), padapter->iface_id+1, MAC_ARG(psta->hwaddr));
+		rtw_warn_on(1);
+		goto exit;
+	} else {
+		goto assigned;
+	}
+
+assigned:
+	psta->mac_id = i;
+	DBG_871X(FUNC_ADPT_FMT" if%u, hwaddr:"MAC_FMT" macid:%u\n"
+		, FUNC_ADPT_ARG(padapter), padapter->iface_id+1, MAC_ARG(psta->hwaddr), psta->mac_id);
+
+exit:
+	return;
+}
+
+void rtw_release_macid(_adapter *padapter, struct sta_info *psta)
+{
+	_irqL irqL;
+	u8 bc_addr[ETH_ALEN] = {0xff,0xff,0xff,0xff,0xff,0xff};
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+
+	if (_rtw_memcmp(psta->hwaddr, adapter_mac_addr(padapter), ETH_ALEN))
+		return;
+
+#ifdef CONFIG_SHARED_BMC_MACID
+	if(_rtw_memcmp(psta->hwaddr, bc_addr, ETH_ALEN))
+		return;
+
+	if (psta->mac_id == 1) {
+		DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" if%u, hwaddr:"MAC_FMT" with macid:%u\n"
+			, FUNC_ADPT_ARG(padapter), padapter->iface_id+1, MAC_ARG(psta->hwaddr), psta->mac_id);
+		rtw_warn_on(1);
+		return;
+	}
+#endif
+
+	_enter_critical_bh(&macid_ctl->lock, &irqL);
+
+	if (psta->mac_id < macid_ctl->num) {
+		int i;
+
+		if (!rtw_macid_is_used(macid_ctl, psta->mac_id)) {
+			DBG_871X_LEVEL(_drv_err_, FUNC_ADPT_FMT" if%u, hwaddr:"MAC_FMT" macid:%u not used\n"
+				, FUNC_ADPT_ARG(padapter), padapter->iface_id+1, MAC_ARG(psta->hwaddr), psta->mac_id);
+			rtw_warn_on(1);
+		}
+
+		rtw_macid_map_clr(&macid_ctl->used, psta->mac_id);
+		rtw_macid_map_clr(&macid_ctl->bmc, psta->mac_id);
+		for (i=0;i<IFACE_ID_MAX;i++)
+			rtw_macid_map_clr(&macid_ctl->if_g[i], psta->mac_id);
+		for (i=0;i<2;i++)
+			rtw_macid_map_clr(&macid_ctl->ch_g[i], psta->mac_id);
+	}
+
+	_exit_critical_bh(&macid_ctl->lock, &irqL);
+
+	psta->mac_id = macid_ctl->num;
+}
+
+//For 8188E RA
+u8 rtw_search_max_mac_id(_adapter *padapter)
+{
+	u8 max_mac_id=0;
+	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
+	struct macid_ctl_t *macid_ctl = dvobj_to_macidctl(dvobj);
+	int i;
+	_irqL irqL;
+
+	/* TODO: Only search for connected macid? */
+
+	_enter_critical_bh(&macid_ctl->lock, &irqL);
+	for(i=(macid_ctl->num-1); i>0 ; i--) {
+		if (!rtw_macid_is_used(macid_ctl, i))
+			break;
+	}
+	_exit_critical_bh(&macid_ctl->lock, &irqL);
+	max_mac_id = i;
+
+	return max_mac_id;
+}		
+
+inline void rtw_macid_ctl_set_h2c_msr(struct macid_ctl_t *macid_ctl, u8 id, u8 h2c_msr)
+{
+	if (id >= macid_ctl->num) {
+		rtw_warn_on(1);
+		return;
+	}
+
+	macid_ctl->h2c_msr[id] = h2c_msr;
+	if (0)
+		DBG_871X("macid:%u, h2c_msr:"H2C_MSR_FMT"\n", id, H2C_MSR_ARG(&macid_ctl->h2c_msr[id]));
+}
+
+inline void rtw_macid_ctl_init(struct macid_ctl_t *macid_ctl)
+{
+	_rtw_spinlock_init(&macid_ctl->lock);
+}
+
+inline void rtw_macid_ctl_deinit(struct macid_ctl_t *macid_ctl)
+{
+	_rtw_spinlock_free(&macid_ctl->lock);
+}
+
+#if 0
+unsigned int setup_beacon_frame(_adapter *padapter, unsigned char *beacon_frame)
+{
+	unsigned short				ATIMWindow;
+	unsigned char					*pframe;
+	struct tx_desc 				*ptxdesc;
+	struct rtw_ieee80211_hdr 	*pwlanhdr;
+	unsigned short				*fctrl;
+	unsigned int					rate_len, len = 0;
+	struct xmit_priv			*pxmitpriv = &(padapter->xmitpriv);
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+	WLAN_BSSID_EX 		*cur_network = &(pmlmeinfo->network);
+	u8	bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	
+	_rtw_memset(beacon_frame, 0, 256);
+	
+	pframe = beacon_frame + TXDESC_SIZE;
+	
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;	
+	
+	fctrl = &(pwlanhdr->frame_ctl);
+	*(fctrl) = 0;
+	
+	_rtw_memcpy(pwlanhdr->addr1, bc_addr, ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr2, adapter_mac_addr(padapter), ETH_ALEN);
+	_rtw_memcpy(pwlanhdr->addr3, get_my_bssid(cur_network), ETH_ALEN);
+	
+	SetFrameSubType(pframe, WIFI_BEACON);
+	
+	pframe += sizeof(struct rtw_ieee80211_hdr_3addr);	
+	len = sizeof(struct rtw_ieee80211_hdr_3addr);
+
+	//timestamp will be inserted by hardware
+	pframe += 8;
+	len += 8;
+
+	// beacon interval: 2 bytes
+	_rtw_memcpy(pframe, (unsigned char *)(rtw_get_beacon_interval_from_ie(cur_network->IEs)), 2); 
+
+	pframe += 2;
+	len += 2;
+
+	// capability info: 2 bytes
+	_rtw_memcpy(pframe, (unsigned char *)(rtw_get_capability_from_ie(cur_network->IEs)), 2);
+
+	pframe += 2;
+	len += 2;
+
+	// SSID
+	pframe = rtw_set_ie(pframe, _SSID_IE_, cur_network->Ssid.SsidLength, cur_network->Ssid.Ssid, &len);
+
+	// supported rates...
+	rate_len = rtw_get_rateset_len(cur_network->SupportedRates);
+	pframe = rtw_set_ie(pframe, _SUPPORTEDRATES_IE_, ((rate_len > 8)? 8: rate_len), cur_network->SupportedRates, &len);
+
+	// DS parameter set
+	pframe = rtw_set_ie(pframe, _DSSET_IE_, 1, (unsigned char *)&(cur_network->Configuration.DSConfig), &len);
+
+	// IBSS Parameter Set...
+	//ATIMWindow = cur->Configuration.ATIMWindow;
+	ATIMWindow = 0;
+	pframe = rtw_set_ie(pframe, _IBSS_PARA_IE_, 2, (unsigned char *)(&ATIMWindow), &len);
+
+	//todo: ERP IE
+	
+	// EXTERNDED SUPPORTED RATE
+	if (rate_len > 8)
+	{
+		pframe = rtw_set_ie(pframe, _EXT_SUPPORTEDRATES_IE_, (rate_len - 8), (cur_network->SupportedRates + 8), &len);
+	}
+
+	if ((len + TXDESC_SIZE) > 256)
+	{
+		//DBG_871X("marc: beacon frame too large\n");
+		return 0;
+	}
+
+	//fill the tx descriptor
+	ptxdesc = (struct tx_desc *)beacon_frame;
+	
+	//offset 0	
+	ptxdesc->txdw0 |= cpu_to_le32(len & 0x0000ffff); 
+	ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 0x00ff0000); //default = 32 bytes for TX Desc
+	
+	//offset 4	
+	ptxdesc->txdw1 |= cpu_to_le32((0x10 << QSEL_SHT) & 0x00001f00);
+	
+	//offset 8		
+	ptxdesc->txdw2 |= cpu_to_le32(BMC);
+	ptxdesc->txdw2 |= cpu_to_le32(BK);
+
+	//offset 16		
+	ptxdesc->txdw4 = 0x80000000;
+	
+	//offset 20
+	ptxdesc->txdw5 = 0x00000000; //1M	
+	
+	return (len + TXDESC_SIZE);
+}
+#endif
+
+_adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj)
+{
+	_adapter *port0_iface = NULL;
+	int i;
+	for (i=0;i<dvobj->iface_nums;i++) {
+		if (get_iface_type(dvobj->padapters[i]) == IFACE_PORT0)
+			break;
+	}
+
+	if (i<0 || i>=dvobj->iface_nums)
+		rtw_warn_on(1);
+	else
+		port0_iface = dvobj->padapters[i];
+
+	return port0_iface;
+}
+
+#if defined(CONFIG_WOWLAN) || defined(CONFIG_AP_WOWLAN)
+void rtw_get_current_ip_address(PADAPTER padapter, u8 *pcurrentip)
+{
+	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
+	struct in_device *my_ip_ptr = padapter->pnetdev->ip_ptr;
+	u8 ipaddress[4];
+	
+	if ( (pmlmeinfo->state & WIFI_FW_LINKING_STATE) ||
+			pmlmeinfo->state & WIFI_FW_AP_STATE) {
+		if ( my_ip_ptr != NULL ) {
+			struct in_ifaddr *my_ifa_list  = my_ip_ptr->ifa_list ;
+			if ( my_ifa_list != NULL ) {
+				ipaddress[0] = my_ifa_list->ifa_address & 0xFF;
+				ipaddress[1] = (my_ifa_list->ifa_address >> 8) & 0xFF;
+				ipaddress[2] = (my_ifa_list->ifa_address >> 16) & 0xFF;
+				ipaddress[3] = my_ifa_list->ifa_address >> 24;
+				DBG_871X("%s: %d.%d.%d.%d ==========\n", __func__, 
+						ipaddress[0], ipaddress[1], ipaddress[2], ipaddress[3]);
+				_rtw_memcpy(pcurrentip, ipaddress, 4);
+			}
+		}
+	}
+}
+#endif
+#ifdef CONFIG_WOWLAN
+bool rtw_check_pattern_valid(u8 *input, u8 len)
+{
+	int i = 0;
+	bool res = _FALSE;
+	
+	for (i = 0 ; i < len ; i++) {
+		if ((input[i] <= '9' && input[i] >= '0') ||
+		    (input[i] <= 'F' && input[i] >= 'A') ||
+		    (input[i] <= 'f' && input[i] >= 'a'))
+			res = _TRUE;
+		else
+			res = _FALSE;
+	}
+	return res;
+}
+
+bool rtw_read_from_frame_mask(_adapter *adapter, u8 idx)
+{
+	u32 data_l = 0, data_h = 0, rx_dma_buff_sz = 0, page_sz = 0;
+	u16 offset, rx_buf_ptr = 0;
+	u16 cam_start_offset = 0;
+	u16 ctrl_l = 0, ctrl_h = 0;
+	u8 count = 0, tmp = 0;
+	int i = 0;
+	bool res = _TRUE;
+
+	if (idx > MAX_WKFM_NUM) {
+		DBG_871X("[Error]: %s, pattern index is out of range\n",
+			 __func__);
+		return _FALSE;
+	}
+
+	rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW,
+			    (u8 *)&rx_dma_buff_sz);
+	
+	if (rx_dma_buff_sz == 0) {
+		DBG_871X("[Error]: %s, rx_dma_buff_sz is 0!!\n", __func__);
+		return _FALSE;
+	}
+
+	rtw_hal_get_def_var(adapter, HAL_DEF_RX_PAGE_SIZE, (u8 *)&page_sz);
+	
+	if (page_sz == 0) {
+		DBG_871X("[Error]: %s, page_sz is 0!!\n", __func__);
+		return _FALSE;
+	}
+
+	offset = (u16)PageNum(rx_dma_buff_sz, page_sz);
+	cam_start_offset = offset * page_sz;
+
+	ctrl_l = 0x0;
+	ctrl_h = 0x0;
+
+	/* Enable RX packet buffer access */
+	rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT);
+
+	/* Read the WKFM CAM */
+	for (i = 0; i < (WKFMCAM_ADDR_NUM / 2); i++) {
+		/*
+		 * Set Rx packet buffer offset.
+		 * RxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer.
+		 * CAM start offset (unit: 1 byte) =  Index*WKFMCAM_SIZE
+		 * RxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8
+		 * * Index: The index of the wake up frame mask
+		 * * WKFMCAM_SIZE: the total size of one WKFM CAM
+		 * * per entry offset of a WKFM CAM: Addr i * 4 bytes
+		 */
+		rx_buf_ptr =
+			(cam_start_offset + idx*WKFMCAM_SIZE + i*8) >> 3;
+		rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, rx_buf_ptr);
+
+		rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
+		data_l = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_L);
+		data_h = rtw_read32(adapter, REG_PKTBUF_DBG_DATA_H);
+
+		DBG_871X("[%d]: %08x %08x\n", i, data_h, data_l);
+
+		count = 0;
+
+		do {
+			tmp = rtw_read8(adapter, REG_RXPKTBUF_CTRL);
+			rtw_udelay_os(2);
+			count++;
+		} while (!tmp && count < 100);
+
+		if (count >= 100) {
+			DBG_871X("%s count:%d\n", __func__, count);
+			res = _FALSE;
+		}
+	}
+
+	/* Disable RX packet buffer access */
+	rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL,
+		   DISABLE_TRXPKT_BUF_ACCESS);
+	return res;
+}
+
+bool rtw_write_to_frame_mask(_adapter *adapter, u8 idx,
+				 struct  rtl_wow_pattern *context)
+{
+	u32 data = 0, rx_dma_buff_sz = 0, page_sz = 0;
+	u16 offset, rx_buf_ptr = 0;
+	u16 cam_start_offset = 0;
+	u16 ctrl_l = 0, ctrl_h = 0;
+	u8 count = 0, tmp = 0;
+	int res = 0, i = 0;
+
+	if (idx > MAX_WKFM_NUM) {
+		DBG_871X("[Error]: %s, pattern index is out of range\n",
+			 __func__);
+		return _FALSE;
+	}
+
+	rtw_hal_get_def_var(adapter, HAL_DEF_RX_DMA_SZ_WOW,
+			    (u8 *)&rx_dma_buff_sz);
+	
+	if (rx_dma_buff_sz == 0) {
+		DBG_871X("[Error]: %s, rx_dma_buff_sz is 0!!\n", __func__);
+		return _FALSE;
+	}
+
+	rtw_hal_get_def_var(adapter, HAL_DEF_RX_PAGE_SIZE, (u8 *)&page_sz);
+	
+	if (page_sz == 0) {
+		DBG_871X("[Error]: %s, page_sz is 0!!\n", __func__);
+		return _FALSE;
+	}
+
+	offset = (u16)PageNum(rx_dma_buff_sz, page_sz);
+
+	cam_start_offset = offset * page_sz;
+
+	if (IS_HARDWARE_TYPE_8188E(adapter)) {
+		ctrl_l = 0x0001;
+		ctrl_h = 0x0001;
+	} else {
+		ctrl_l = 0x0f01;
+		ctrl_h = 0xf001;
+	}
+
+	/* Enable RX packet buffer access */
+	rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL, RXPKT_BUF_SELECT);
+
+	/* Write the WKFM CAM */
+	for (i = 0; i < WKFMCAM_ADDR_NUM; i++) {
+		/*
+		 * Set Rx packet buffer offset.
+		 * RxBufer pointer increases 1, we can access 8 bytes in Rx packet buffer.
+		 * CAM start offset (unit: 1 byte) =  Index*WKFMCAM_SIZE
+		 * RxBufer pointer addr = (CAM start offset + per entry offset of a WKFMCAM)/8
+		 * * Index: The index of the wake up frame mask
+		 * * WKFMCAM_SIZE: the total size of one WKFM CAM
+		 * * per entry offset of a WKFM CAM: Addr i * 4 bytes
+		 */
+		rx_buf_ptr =
+			(cam_start_offset + idx*WKFMCAM_SIZE + i*4) >> 3;
+		rtw_write16(adapter, REG_PKTBUF_DBG_CTRL, rx_buf_ptr);
+
+		if (i == 0) {
+			if (context->type == PATTERN_VALID)
+				data = BIT(31);
+			else if (context->type == PATTERN_BROADCAST)
+				data = BIT(31) | BIT(26);
+			else if (context->type == PATTERN_MULTICAST)
+				data = BIT(31) | BIT(25);
+			else if (context->type == PATTERN_UNICAST)
+				data = BIT(31) | BIT(24);
+
+			if (context->crc != 0)
+				data |= context->crc;
+
+			rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data);
+			rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
+		} else if (i == 1) {
+			data = 0;
+			rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data);
+			rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_h);
+		} else if (i == 2 || i == 4) {
+			data = context->mask[i - 2];
+			rtw_write32(adapter, REG_PKTBUF_DBG_DATA_L, data);
+			/* write to RX packet buffer*/
+			rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_l);
+		} else if (i == 3 || i == 5) {
+			data = context->mask[i - 2];
+			rtw_write32(adapter, REG_PKTBUF_DBG_DATA_H, data);
+			/* write to RX packet buffer*/
+			rtw_write16(adapter, REG_RXPKTBUF_CTRL, ctrl_h);
+		}
+
+		count = 0;
+		do {
+			tmp = rtw_read8(adapter, REG_RXPKTBUF_CTRL);
+			rtw_udelay_os(2);
+			count++;
+		} while (tmp && count < 100);
+
+		if (count >= 100)
+			res = _FALSE;
+		else
+			res = _TRUE;
+	}
+
+	/* Disable RX packet buffer access */
+	rtw_write8(adapter, REG_PKT_BUFF_ACCESS_CTRL,
+		   DISABLE_TRXPKT_BUF_ACCESS);
+
+	return res;
+}
+
+
+void rtw_dump_priv_pattern(_adapter *adapter, u8 idx)
+{
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
+	char str_1[128];
+	char *p_str;
+	u8 val8 = 0;
+	int i = 0, j = 0, len = 0, max_len = 0;
+
+	DBG_871X("=========[%d]========\n", idx);
+
+	DBG_871X(">>>priv_pattern_content:\n");
+	p_str = str_1;
+	max_len = sizeof(str_1);
+	for (i = 0 ; i < MAX_WKFM_PATTERN_SIZE/8 ; i++) {
+		_rtw_memset(p_str, 0, max_len);
+		len = 0;
+		for (j = 0 ; j < 8 ; j++) {
+			val8 = pwrctl->patterns[idx].content[i*8 + j];
+			len += snprintf(p_str + len, max_len - len,
+					"%02x ", val8);
+		}
+		DBG_871X("%s\n", p_str);
+	}
+
+	DBG_871X(">>>priv_pattern_mask:\n");
+	for (i = 0 ; i < MAX_WKFM_SIZE/8 ; i++) {
+		_rtw_memset(p_str, 0, max_len);
+		len = 0;
+		for (j = 0 ; j < 8 ; j++) {
+			val8 = pwrctl->patterns[idx].mask[i*8 + j];
+			len += snprintf(p_str + len, max_len - len,
+					"%02x ", val8);
+		}
+		DBG_871X("%s\n", p_str);
+	}
+}
+
+void rtw_clean_pattern(_adapter *adapter)
+{
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(adapter);
+	struct rtl_wow_pattern zero_pattern;
+	int i = 0;
+
+	_rtw_memset(&zero_pattern, 0, sizeof(struct rtl_wow_pattern));
+
+	zero_pattern.type = PATTERN_INVALID;
+
+	for (i = 0; i < MAX_WKFM_NUM; i++)
+		rtw_write_to_frame_mask(adapter, i, &zero_pattern);
+
+	pwrctl->wowlan_pattern_idx = 0;
+	rtw_write8(adapter, REG_WKFMCAM_NUM, pwrctl->wowlan_pattern_idx);
+}
+
+void rtw_get_sec_iv(PADAPTER padapter, u8*pcur_dot11txpn, u8 *StaAddr)
+{
+	struct sta_info		*psta;
+	struct security_priv *psecpriv = &padapter->securitypriv;
+
+	_rtw_memset(pcur_dot11txpn, 0, 8);
+	if(NULL == StaAddr)
+		return; 
+	psta = rtw_get_stainfo(&padapter->stapriv, StaAddr);
+	DBG_871X("%s(): StaAddr: %02x %02x %02x %02x %02x %02x\n", 
+		__func__, StaAddr[0], StaAddr[1], StaAddr[2],
+		StaAddr[3], StaAddr[4], StaAddr[5]);
+
+	if(psta)
+	{
+		if (psecpriv->dot11PrivacyAlgrthm != _NO_PRIVACY_ && psta->dot11txpn.val > 0)
+			psta->dot11txpn.val--;
+		AES_IV(pcur_dot11txpn, psta->dot11txpn, 0);
+
+		DBG_871X("%s(): CurrentIV: %02x %02x %02x %02x %02x %02x %02x %02x \n"
+		, __func__, pcur_dot11txpn[0],pcur_dot11txpn[1],
+		pcur_dot11txpn[2],pcur_dot11txpn[3], pcur_dot11txpn[4],
+		pcur_dot11txpn[5],pcur_dot11txpn[6],pcur_dot11txpn[7]);
+	}
+}
+void rtw_set_sec_pn(PADAPTER padapter)
+{
+        struct sta_info         *psta;
+        struct mlme_ext_priv    *pmlmeext = &(padapter->mlmeextpriv);
+        struct mlme_ext_info    *pmlmeinfo = &(pmlmeext->mlmext_info);
+        struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
+		struct security_priv *psecpriv = &padapter->securitypriv;
+
+        psta = rtw_get_stainfo(&padapter->stapriv,
+			get_my_bssid(&pmlmeinfo->network));
+
+        if(psta)
+        {
+		if (pwrpriv->wowlan_fw_iv > psta->dot11txpn.val)
+		{
+			if (psecpriv->dot11PrivacyAlgrthm != _NO_PRIVACY_)
+				psta->dot11txpn.val = pwrpriv->wowlan_fw_iv + 2;
+		} else {
+			DBG_871X("%s(): FW IV is smaller than driver\n", __func__);
+			psta->dot11txpn.val += 2;
+		}
+		DBG_871X("%s: dot11txpn: 0x%016llx\n", __func__ ,psta->dot11txpn.val);
+        }
+}
+#endif //CONFIG_WOWLAN
+
+#ifdef CONFIG_PNO_SUPPORT
+#define	CSCAN_TLV_TYPE_SSID_IE	'S'
+#define CIPHER_IE "key_mgmt="
+#define CIPHER_NONE "NONE"
+#define CIPHER_WPA_PSK "WPA-PSK"
+#define CIPHER_WPA_EAP "WPA-EAP IEEE8021X"
+/*
+ *  SSIDs list parsing from cscan tlv list
+ */
+int rtw_parse_ssid_list_tlv(char** list_str, pno_ssid_t* ssid,
+	int max, int *bytes_left) {
+	char* str;
+
+	int idx = 0;
+
+	if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) {
+		DBG_871X("%s error paramters\n", __func__);
+		return -1;
+	}
+
+	str = *list_str;
+	while (*bytes_left > 0) {
+
+		if (str[0] != CSCAN_TLV_TYPE_SSID_IE) {
+			*list_str = str;
+			DBG_871X("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0]);
+			return idx;
+		}
+
+		/* Get proper CSCAN_TLV_TYPE_SSID_IE */
+		*bytes_left -= 1;
+		str += 1;
+
+		if (str[0] == 0) {
+			/* Broadcast SSID */
+			ssid[idx].SSID_len = 0;
+			memset((char*)ssid[idx].SSID, 0x0, WLAN_SSID_MAXLEN);
+			*bytes_left -= 1;
+			str += 1;
+
+			DBG_871X("BROADCAST SCAN  left=%d\n", *bytes_left);
+		}
+		else if (str[0] <= WLAN_SSID_MAXLEN) {
+			 /* Get proper SSID size */
+			ssid[idx].SSID_len = str[0];
+			*bytes_left -= 1;
+			str += 1;
+
+			/* Get SSID */
+			if (ssid[idx].SSID_len > *bytes_left) {
+				DBG_871X("%s out of memory range len=%d but left=%d\n",
+				__func__, ssid[idx].SSID_len, *bytes_left);
+				return -1;
+			}
+
+			memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len);
+
+			*bytes_left -= ssid[idx].SSID_len;
+			str += ssid[idx].SSID_len;
+
+			DBG_871X("%s :size=%d left=%d\n",
+				(char*)ssid[idx].SSID, ssid[idx].SSID_len, *bytes_left);
+		}
+		else {
+			DBG_871X("### SSID size more that %d\n", str[0]);
+			return -1;
+		}
+
+		if (idx++ >  max) {
+			DBG_871X("%s number of SSIDs more that %d\n", __func__, idx);
+			return -1;
+		}
+	}
+
+	*list_str = str;
+	return idx;
+}
+
+int rtw_parse_cipher_list(struct pno_nlo_info *nlo_info, char* list_str) {
+
+	char *pch, *pnext, *pend;
+	u8 key_len = 0, index = 0;
+
+	pch = list_str;
+
+	if (nlo_info == NULL || list_str == NULL) {
+		DBG_871X("%s error paramters\n", __func__);
+		return -1;
+	}
+
+	while (strlen(pch) != 0) {
+		pnext = strstr(pch, "key_mgmt=");
+		if (pnext != NULL) {
+			pch = pnext + strlen(CIPHER_IE);
+			pend = strstr(pch, "}");
+			if (strncmp(pch, CIPHER_NONE,
+						strlen(CIPHER_NONE)) == 0) {
+				nlo_info->ssid_cipher_info[index] = 0x00;
+			} else if (strncmp(pch, CIPHER_WPA_PSK,
+						strlen(CIPHER_WPA_PSK)) == 0) {
+				nlo_info->ssid_cipher_info[index] = 0x66;
+			} else if (strncmp(pch, CIPHER_WPA_EAP,
+						strlen(CIPHER_WPA_EAP)) == 0) {
+				nlo_info->ssid_cipher_info[index] = 0x01;
+			}
+			index ++;
+			pch = pend + 1;
+		} else {
+			break;
+		}
+	}
+	return 0;
+}
+
+int rtw_dev_nlo_info_set(struct pno_nlo_info *nlo_info, pno_ssid_t* ssid,
+	int num, int pno_time, int pno_repeat, int pno_freq_expo_max) {
+
+	int i = 0;
+	struct file *fp;
+	mm_segment_t fs;
+	loff_t pos = 0;
+	u8 *source = NULL;
+	long len = 0;
+
+	DBG_871X("+%s+\n", __func__);
+
+	nlo_info->fast_scan_period = pno_time;
+	nlo_info->ssid_num = num & BIT_LEN_MASK_32(8);
+	nlo_info->hidden_ssid_num = num & BIT_LEN_MASK_32(8);
+	nlo_info->slow_scan_period = (pno_time * 2);
+	nlo_info->fast_scan_iterations = 5;
+
+	if (nlo_info->hidden_ssid_num > 8)
+		nlo_info->hidden_ssid_num = 8;
+
+	//TODO: channel list and probe index is all empty.
+	for (i = 0 ; i < num ; i++) {
+		nlo_info->ssid_length[i]
+			= ssid[i].SSID_len;
+	}
+
+	/* cipher array */
+	fp = filp_open("/data/misc/wifi/wpa_supplicant.conf", O_RDONLY,  0644);
+	if (IS_ERR(fp)) {
+		DBG_871X("Error, wpa_supplicant.conf doesn't exist.\n");
+		DBG_871X("Error, cipher array using default value.\n");
+		return 0;
+	}
+
+	len = i_size_read(fp->f_path.dentry->d_inode);
+	if (len < 0 || len > 2048) {
+		DBG_871X("Error, file size is bigger than 2048.\n");
+		DBG_871X("Error, cipher array using default value.\n");
+		return 0;
+	}
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	source = rtw_zmalloc(2048);
+
+	if (source != NULL) {
+		len = vfs_read(fp, source, len, &pos);
+		rtw_parse_cipher_list(nlo_info, source);
+		rtw_mfree(source, 2048);
+	}
+
+	set_fs(fs);
+	filp_close(fp, NULL);
+
+	DBG_871X("-%s-\n", __func__);
+	return 0;
+}
+
+int rtw_dev_ssid_list_set(struct pno_ssid_list *pno_ssid_list,
+	pno_ssid_t* ssid, u8 num) {
+
+	int i = 0;
+	if(num > MAX_PNO_LIST_COUNT)
+		num = MAX_PNO_LIST_COUNT;
+
+	for (i = 0 ; i < num ; i++) {
+		_rtw_memcpy(&pno_ssid_list->node[i].SSID,
+			ssid[i].SSID, ssid[i].SSID_len);
+		pno_ssid_list->node[i].SSID_len = ssid[i].SSID_len;
+	}
+	return 0;
+}
+
+int rtw_dev_scan_info_set(_adapter *padapter, pno_ssid_t* ssid,
+	unsigned char ch, unsigned char ch_offset, unsigned short bw_mode) {
+
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	struct pno_scan_info *scan_info = pwrctl->pscan_info;
+	int i;
+
+	scan_info->channel_num = MAX_SCAN_LIST_COUNT;
+	scan_info->orig_ch = ch;
+	scan_info->orig_bw = bw_mode;
+	scan_info->orig_40_offset = ch_offset;
+
+	for(i = 0 ; i < scan_info->channel_num ; i++) {
+		if (i < 11)
+			scan_info->ssid_channel_info[i].active = 1;
+		else
+			scan_info->ssid_channel_info[i].active = 0;
+
+		scan_info->ssid_channel_info[i].timeout = 100;
+
+		scan_info->ssid_channel_info[i].tx_power =
+			PHY_GetTxPowerIndex(padapter, 0, 0x02, bw_mode, i+1);
+
+		scan_info->ssid_channel_info[i].channel = i+1;
+	}
+
+	DBG_871X("%s, channel_num: %d, orig_ch: %d, orig_bw: %d orig_40_offset: %d\n",
+		__func__, scan_info->channel_num, scan_info->orig_ch,
+		scan_info->orig_bw, scan_info->orig_40_offset);
+	return 0;
+}
+
+int rtw_dev_pno_set(struct net_device *net, pno_ssid_t* ssid, int num,
+	int pno_time, int pno_repeat, int pno_freq_expo_max) {
+
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+
+	int ret = -1;
+
+	if (num == 0) {
+		DBG_871X("%s, nssid is zero, no need to setup pno ssid list\n", __func__);
+		return 0;
+	}
+
+	if (pwrctl == NULL) {
+		DBG_871X("%s, ERROR: pwrctl is NULL\n", __func__);
+		return -1;
+	} else {
+		pwrctl->pnlo_info =
+			(pno_nlo_info_t*)rtw_zmalloc(sizeof(pno_nlo_info_t));
+		pwrctl->pno_ssid_list =
+			(pno_ssid_list_t*)rtw_zmalloc(sizeof(pno_ssid_list_t));
+		pwrctl->pscan_info =
+			(pno_scan_info_t*)rtw_zmalloc(sizeof(pno_scan_info_t));
+	}
+
+	if (pwrctl->pnlo_info == NULL ||
+		pwrctl->pscan_info == NULL ||
+		pwrctl->pno_ssid_list == NULL){
+		DBG_871X("%s, ERROR: alloc nlo_info, ssid_list, scan_info fail\n", __func__);
+		goto failing;
+	}
+
+	pwrctl->pno_in_resume = _FALSE;
+
+	pwrctl->pno_inited = _TRUE;
+	/* NLO Info */
+	ret = rtw_dev_nlo_info_set(pwrctl->pnlo_info, ssid, num,
+			pno_time, pno_repeat, pno_freq_expo_max);
+
+	/* SSID Info */
+	ret = rtw_dev_ssid_list_set(pwrctl->pno_ssid_list, ssid, num);
+
+	/* SCAN Info */
+	ret = rtw_dev_scan_info_set(padapter, ssid, pmlmeext->cur_channel,
+			pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
+
+	DBG_871X("+%s num: %d, pno_time: %d, pno_repeat:%d, pno_freq_expo_max:%d+\n",
+		 __func__, num, pno_time, pno_repeat, pno_freq_expo_max);
+
+	return 0;
+
+failing:
+	if (pwrctl->pnlo_info) {
+		rtw_mfree((u8 *)pwrctl->pnlo_info, sizeof(pno_nlo_info_t));
+		pwrctl->pnlo_info = NULL;
+	}
+	if (pwrctl->pno_ssid_list) {
+		rtw_mfree((u8 *)pwrctl->pno_ssid_list, sizeof(pno_ssid_list_t));
+		pwrctl->pno_ssid_list = NULL;
+	}
+	if (pwrctl->pscan_info) {
+		rtw_mfree((u8 *)pwrctl->pscan_info, sizeof(pno_scan_info_t));
+		pwrctl->pscan_info = NULL;
+	}
+
+	return -1;
+}
+
+#ifdef CONFIG_PNO_SET_DEBUG
+void rtw_dev_pno_debug(struct net_device *net) {
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(net);
+	struct pwrctrl_priv *pwrctl = adapter_to_pwrctl(padapter);
+	int i = 0, j = 0;
+
+	DBG_871X("*******NLO_INFO********\n");
+	DBG_871X("ssid_num: %d\n", pwrctl->pnlo_info->ssid_num);
+	DBG_871X("fast_scan_iterations: %d\n",
+			pwrctl->pnlo_info->fast_scan_iterations);
+	DBG_871X("fast_scan_period: %d\n", pwrctl->pnlo_info->fast_scan_period);
+	DBG_871X("slow_scan_period: %d\n", pwrctl->pnlo_info->slow_scan_period);
+	DBG_871X("ssid_length: ");
+	for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+		printk("%d, ", pwrctl->pnlo_info->ssid_length[i]);
+	}
+	DBG_871X("\n");
+
+	DBG_871X("cipher_info: ");
+	for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+		DBG_871X("%d, ", pwrctl->pnlo_info->ssid_cipher_info[i]);
+	}
+	DBG_871X("\n");
+
+	DBG_871X("channel_info: ");
+	for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+		DBG_871X("%d, ", pwrctl->pnlo_info->ssid_channel_info[i]);
+	}
+	DBG_871X("\n");
+
+	DBG_871X("******SSID_LISD******\n");
+	for (i = 0 ; i < MAX_PNO_LIST_COUNT ; i++) {
+		DBG_871X("[%d]SSID: %s \n", i,
+			pwrctl->pno_ssid_list->node[i].SSID);
+	}
+
+	DBG_871X("******SCAN_INFO******\n");
+	DBG_871X("ch_num: %d\n", pwrctl->pscan_info->channel_num);
+	DBG_871X("orig_ch: %d\n", pwrctl->pscan_info->orig_ch);
+	DBG_871X("orig bw: %d\n", pwrctl->pscan_info->orig_bw);
+	DBG_871X("orig 40 offset: %d\n", pwrctl->pscan_info->orig_40_offset);
+	for(i = 0 ; i < MAX_SCAN_LIST_COUNT ; i++) {
+		DBG_871X("[%02d] avtive:%d, timeout:%d, tx_power:%d, ch:%02d\n",
+			i, pwrctl->pscan_info->ssid_channel_info[i].active,
+			pwrctl->pscan_info->ssid_channel_info[i].timeout,
+			pwrctl->pscan_info->ssid_channel_info[i].tx_power,
+			pwrctl->pscan_info->ssid_channel_info[i].channel);
+	}
+	DBG_871X("*****************\n");
+}
+#endif //CONFIG_PNO_SET_DEBUG
+#endif //CONFIG_PNO_SUPPORT
diff --git a/drivers/net/wireless/realtek/rtl8723cs/core/rtw_xmit.c b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_xmit.c
new file mode 100644
index 000000000..04dedd3b0
--- /dev/null
+++ b/drivers/net/wireless/realtek/rtl8723cs/core/rtw_xmit.c
@@ -0,0 +1,5074 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
+ *                                        
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ *
+ ******************************************************************************/
+#define _RTW_XMIT_C_
+
+#include <drv_types.h>
+
+#if defined (PLATFORM_LINUX) && defined (PLATFORM_WINDOWS)
+#error "Shall be Linux or Windows, but not both!\n"
+#endif
+
+
+static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 };
+static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 };
+
+static void _init_txservq(struct tx_servq *ptxservq)
+{
+_func_enter_;
+	_rtw_init_listhead(&ptxservq->tx_pending);
+	_rtw_init_queue(&ptxservq->sta_pending);
+	ptxservq->qcnt = 0;
+_func_exit_;		
+}
+
+
+void	_rtw_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
+{	
+	
+_func_enter_;
+
+	_rtw_memset((unsigned char *)psta_xmitpriv, 0, sizeof (struct sta_xmit_priv));
+
+	_rtw_spinlock_init(&psta_xmitpriv->lock);
+	
+	//for(i = 0 ; i < MAX_NUMBLKS; i++)
+	//	_init_txservq(&(psta_xmitpriv->blk_q[i]));
+
+	_init_txservq(&psta_xmitpriv->be_q);
+	_init_txservq(&psta_xmitpriv->bk_q);
+	_init_txservq(&psta_xmitpriv->vi_q);
+	_init_txservq(&psta_xmitpriv->vo_q);
+	_rtw_init_listhead(&psta_xmitpriv->legacy_dz);
+	_rtw_init_listhead(&psta_xmitpriv->apsd);
+	
+_func_exit_;	
+
+}
+
+s32	_rtw_init_xmit_priv(struct xmit_priv *pxmitpriv, _adapter *padapter)
+{
+	int i;
+	struct xmit_buf *pxmitbuf;
+	struct xmit_frame *pxframe;
+	sint	res=_SUCCESS;   
+	
+_func_enter_;   	
+
+	// We don't need to memset padapter->XXX to zero, because adapter is allocated by rtw_zvmalloc().
+	//_rtw_memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
+	
+	_rtw_spinlock_init(&pxmitpriv->lock);
+	_rtw_spinlock_init(&pxmitpriv->lock_sctx);
+	_rtw_init_sema(&pxmitpriv->xmit_sema, 0);
+	_rtw_init_sema(&pxmitpriv->terminate_xmitthread_sema, 0);
+
+	/* 
+	Please insert all the queue initializaiton using _rtw_init_queue below
+	*/
+
+	pxmitpriv->adapter = padapter;
+	
+	//for(i = 0 ; i < MAX_NUMBLKS; i++)
+	//	_rtw_init_queue(&pxmitpriv->blk_strms[i]);
+	
+	_rtw_init_queue(&pxmitpriv->be_pending);
+	_rtw_init_queue(&pxmitpriv->bk_pending);
+	_rtw_init_queue(&pxmitpriv->vi_pending);
+	_rtw_init_queue(&pxmitpriv->vo_pending);
+	_rtw_init_queue(&pxmitpriv->bm_pending);
+
+	//_rtw_init_queue(&pxmitpriv->legacy_dz_queue);
+	//_rtw_init_queue(&pxmitpriv->apsd_queue);
+
+	_rtw_init_queue(&pxmitpriv->free_xmit_queue);
+
+	/*	
+	Please allocate memory with the sz = (struct xmit_frame) * NR_XMITFRAME, 
+	and initialize free_xmit_frame below.
+	Please also apply  free_txobj to link_up all the xmit_frames...
+	*/
+
+	pxmitpriv->pallocated_frame_buf = rtw_zvmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
+	
+	if (pxmitpriv->pallocated_frame_buf  == NULL){
+		pxmitpriv->pxmit_frame_buf =NULL;
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("alloc xmit_frame fail!\n"));	
+		res= _FAIL;
+		goto exit;
+	}
+	pxmitpriv->pxmit_frame_buf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_frame_buf), 4);
+	//pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 -
+	//						((SIZE_PTR) (pxmitpriv->pallocated_frame_buf) &3);
+
+	pxframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
+
+	for (i = 0; i < NR_XMITFRAME; i++)
+	{
+		_rtw_init_listhead(&(pxframe->list));
+
+		pxframe->padapter = padapter;
+		pxframe->frame_tag = NULL_FRAMETAG;
+
+		pxframe->pkt = NULL;		
+
+		pxframe->buf_addr = NULL;
+		pxframe->pxmitbuf = NULL;
+ 
+		rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xmit_queue.queue));
+
+		pxframe++;
+	}
+
+	pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
+
+	pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
+
+
+	//init xmit_buf
+	_rtw_init_queue(&pxmitpriv->free_xmitbuf_queue);
+	_rtw_init_queue(&pxmitpriv->pending_xmitbuf_queue);
+
+	pxmitpriv->pallocated_xmitbuf = rtw_zvmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
+	
+	if (pxmitpriv->pallocated_xmitbuf  == NULL){
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("alloc xmit_buf fail!\n"));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pxmitpriv->pxmitbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmitbuf), 4);
+	//pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 -
+	//						((SIZE_PTR) (pxmitpriv->pallocated_xmitbuf) &3);
+
+	pxmitbuf = (struct xmit_buf*)pxmitpriv->pxmitbuf;
+
+	for (i = 0; i < NR_XMITBUFF; i++)
+	{
+		_rtw_init_listhead(&pxmitbuf->list);
+
+		pxmitbuf->priv_data = NULL;
+		pxmitbuf->padapter = padapter;
+		pxmitbuf->buf_tag = XMITBUF_DATA;
+
+		/* Tx buf allocation may fail sometimes, so sleep and retry. */
+		if((res=rtw_os_xmit_resource_alloc(padapter, pxmitbuf,(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE)) == _FAIL) {
+			rtw_msleep_os(10);
+			res = rtw_os_xmit_resource_alloc(padapter, pxmitbuf,(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);
+			if (res == _FAIL) {
+				goto exit;
+			}
+		}
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxmitbuf->phead = pxmitbuf->pbuf;
+		pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMITBUF_SZ;
+		pxmitbuf->len = 0;
+		pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+#endif
+
+		pxmitbuf->flags = XMIT_VO_QUEUE;
+
+		rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmitbuf_queue.queue));
+		#ifdef DBG_XMIT_BUF
+		pxmitbuf->no=i;
+		#endif
+
+		pxmitbuf++;
+		
+	}
+
+	pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
+
+	/* init xframe_ext queue,  the same count as extbuf  */
+	_rtw_init_queue(&pxmitpriv->free_xframe_ext_queue);
+	
+	pxmitpriv->xframe_ext_alloc_addr = rtw_zvmalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);
+	
+	if (pxmitpriv->xframe_ext_alloc_addr  == NULL){
+		pxmitpriv->xframe_ext = NULL;
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("alloc xframe_ext fail!\n"));	
+		res= _FAIL;
+		goto exit;
+	}
+	pxmitpriv->xframe_ext = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->xframe_ext_alloc_addr), 4);
+	pxframe = (struct xmit_frame*)pxmitpriv->xframe_ext;
+
+	for (i = 0; i < NR_XMIT_EXTBUFF; i++) {
+		_rtw_init_listhead(&(pxframe->list));
+
+		pxframe->padapter = padapter;
+		pxframe->frame_tag = NULL_FRAMETAG;
+
+		pxframe->pkt = NULL;		
+
+		pxframe->buf_addr = NULL;
+		pxframe->pxmitbuf = NULL;
+		
+		pxframe->ext_tag = 1;
+ 
+		rtw_list_insert_tail(&(pxframe->list), &(pxmitpriv->free_xframe_ext_queue.queue));
+
+		pxframe++;
+	}
+	pxmitpriv->free_xframe_ext_cnt = NR_XMIT_EXTBUFF;
+
+	// Init xmit extension buff
+	_rtw_init_queue(&pxmitpriv->free_xmit_extbuf_queue);
+
+	pxmitpriv->pallocated_xmit_extbuf = rtw_zvmalloc(NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);
+	
+	if (pxmitpriv->pallocated_xmit_extbuf  == NULL){
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("alloc xmit_extbuf fail!\n"));
+		res= _FAIL;
+		goto exit;
+	}
+
+	pxmitpriv->pxmit_extbuf = (u8 *)N_BYTE_ALIGMENT((SIZE_PTR)(pxmitpriv->pallocated_xmit_extbuf), 4);
+
+	pxmitbuf = (struct xmit_buf*)pxmitpriv->pxmit_extbuf;
+
+	for (i = 0; i < NR_XMIT_EXTBUFF; i++)
+	{
+		_rtw_init_listhead(&pxmitbuf->list);
+
+		pxmitbuf->priv_data = NULL;
+		pxmitbuf->padapter = padapter;
+		pxmitbuf->buf_tag = XMITBUF_MGNT;
+
+		if((res=rtw_os_xmit_resource_alloc(padapter, pxmitbuf,MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ, _TRUE)) == _FAIL) {
+			res= _FAIL;
+			goto exit;
+		}
+		
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxmitbuf->phead = pxmitbuf->pbuf;
+		pxmitbuf->pend = pxmitbuf->pbuf + MAX_XMIT_EXTBUF_SZ;
+		pxmitbuf->len = 0;
+		pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+#endif
+
+		rtw_list_insert_tail(&pxmitbuf->list, &(pxmitpriv->free_xmit_extbuf_queue.queue));
+		#ifdef DBG_XMIT_BUF_EXT
+		pxmitbuf->no=i;
+		#endif
+		pxmitbuf++;
+		
+	}
+
+	pxmitpriv->free_xmit_extbuf_cnt = NR_XMIT_EXTBUFF;
+
+	for (i = 0; i<CMDBUF_MAX; i++) {
+		pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];
+		if (pxmitbuf) {
+			_rtw_init_listhead(&pxmitbuf->list);
+
+			pxmitbuf->priv_data = NULL;
+			pxmitbuf->padapter = padapter;
+			pxmitbuf->buf_tag = XMITBUF_CMD;
+
+			if((res=rtw_os_xmit_resource_alloc(padapter, pxmitbuf, MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ, _TRUE)) == _FAIL) {
+				res= _FAIL;
+				goto exit;
+			}
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+			pxmitbuf->phead = pxmitbuf->pbuf;
+			pxmitbuf->pend = pxmitbuf->pbuf + MAX_CMDBUF_SZ;
+			pxmitbuf->len = 0;
+			pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+#endif
+			pxmitbuf->alloc_sz = MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ;
+		}
+	}
+
+	rtw_alloc_hwxmits(padapter);
+	rtw_init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
+
+        for (i = 0; i < 4; i ++)
+	{
+		pxmitpriv->wmm_para_seq[i] = i;
+	}
+
+#ifdef CONFIG_USB_HCI
+	pxmitpriv->txirp_cnt=1;
+
+	_rtw_init_sema(&(pxmitpriv->tx_retevt), 0);
+
+	//per AC pending irp
+	pxmitpriv->beq_cnt = 0;
+	pxmitpriv->bkq_cnt = 0;
+	pxmitpriv->viq_cnt = 0;
+	pxmitpriv->voq_cnt = 0;
+#endif
+
+
+#ifdef CONFIG_XMIT_ACK
+	pxmitpriv->ack_tx = _FALSE;
+	_rtw_mutex_init(&pxmitpriv->ack_tx_mutex);
+	rtw_sctx_init(&pxmitpriv->ack_tx_ops, 0);	
+#endif
+
+	rtw_hal_init_xmit_priv(padapter);
+
+exit:
+
+_func_exit_;	
+
+	return res;
+}
+
+void  rtw_mfree_xmit_priv_lock (struct xmit_priv *pxmitpriv);
+void  rtw_mfree_xmit_priv_lock (struct xmit_priv *pxmitpriv)
+{
+	_rtw_spinlock_free(&pxmitpriv->lock);
+	_rtw_free_sema(&pxmitpriv->xmit_sema);
+	_rtw_free_sema(&pxmitpriv->terminate_xmitthread_sema);
+
+	_rtw_spinlock_free(&pxmitpriv->be_pending.lock);
+	_rtw_spinlock_free(&pxmitpriv->bk_pending.lock);
+	_rtw_spinlock_free(&pxmitpriv->vi_pending.lock);
+	_rtw_spinlock_free(&pxmitpriv->vo_pending.lock);
+	_rtw_spinlock_free(&pxmitpriv->bm_pending.lock);
+
+	//_rtw_spinlock_free(&pxmitpriv->legacy_dz_queue.lock);
+	//_rtw_spinlock_free(&pxmitpriv->apsd_queue.lock);
+
+	_rtw_spinlock_free(&pxmitpriv->free_xmit_queue.lock);
+	_rtw_spinlock_free(&pxmitpriv->free_xmitbuf_queue.lock);
+	_rtw_spinlock_free(&pxmitpriv->pending_xmitbuf_queue.lock);
+}
+
+
+void _rtw_free_xmit_priv (struct xmit_priv *pxmitpriv)
+{
+       int i;
+      _adapter *padapter = pxmitpriv->adapter;
+	struct xmit_frame	*pxmitframe = (struct xmit_frame*) pxmitpriv->pxmit_frame_buf;
+	struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
+	
+ _func_enter_;   
+
+	rtw_hal_free_xmit_priv(padapter);
+ 
+	rtw_mfree_xmit_priv_lock(pxmitpriv);
+ 
+ 	if(pxmitpriv->pxmit_frame_buf==NULL)
+		goto out;
+	
+	for(i=0; i<NR_XMITFRAME; i++)
+	{	
+		rtw_os_xmit_complete(padapter, pxmitframe);
+
+		pxmitframe++;
+	}		
+	
+	for(i=0; i<NR_XMITBUFF; i++)
+	{
+		rtw_os_xmit_resource_free(padapter, pxmitbuf,(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);
+		
+		pxmitbuf++;
+	}
+
+	if(pxmitpriv->pallocated_frame_buf) {
+		rtw_vmfree(pxmitpriv->pallocated_frame_buf, NR_XMITFRAME * sizeof(struct xmit_frame) + 4);
+	}
+	
+
+	if(pxmitpriv->pallocated_xmitbuf) {
+		rtw_vmfree(pxmitpriv->pallocated_xmitbuf, NR_XMITBUFF * sizeof(struct xmit_buf) + 4);
+	}
+
+	/* free xframe_ext queue,  the same count as extbuf  */
+	if ((pxmitframe = (struct xmit_frame*)pxmitpriv->xframe_ext)) {
+		for (i=0; i<NR_XMIT_EXTBUFF; i++) {
+			rtw_os_xmit_complete(padapter, pxmitframe);
+			pxmitframe++;
+		}
+	}
+	if (pxmitpriv->xframe_ext_alloc_addr)
+		rtw_vmfree(pxmitpriv->xframe_ext_alloc_addr, NR_XMIT_EXTBUFF * sizeof(struct xmit_frame) + 4);
+	_rtw_spinlock_free(&pxmitpriv->free_xframe_ext_queue.lock);
+
+	// free xmit extension buff
+	_rtw_spinlock_free(&pxmitpriv->free_xmit_extbuf_queue.lock);
+
+	pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmit_extbuf;
+	for(i=0; i<NR_XMIT_EXTBUFF; i++)
+	{
+		rtw_os_xmit_resource_free(padapter, pxmitbuf,(MAX_XMIT_EXTBUF_SZ + XMITBUF_ALIGN_SZ), _TRUE);
+		
+		pxmitbuf++;
+	}
+
+	if(pxmitpriv->pallocated_xmit_extbuf) {
+		rtw_vmfree(pxmitpriv->pallocated_xmit_extbuf, NR_XMIT_EXTBUFF * sizeof(struct xmit_buf) + 4);
+	}
+
+	for (i=0; i<CMDBUF_MAX; i++) {
+		pxmitbuf = &pxmitpriv->pcmd_xmitbuf[i];
+		if(pxmitbuf!=NULL)
+			rtw_os_xmit_resource_free(padapter, pxmitbuf, MAX_CMDBUF_SZ+XMITBUF_ALIGN_SZ , _TRUE);
+	}
+
+	rtw_free_hwxmits(padapter);
+
+#ifdef CONFIG_XMIT_ACK	
+	_rtw_mutex_free(&pxmitpriv->ack_tx_mutex);	
+#endif	
+
+out:	
+
+_func_exit_;		
+
+}
+
+u8	query_ra_short_GI(struct sta_info *psta)
+{
+	u8	sgi = _FALSE, sgi_20m = _FALSE, sgi_40m = _FALSE, sgi_80m = _FALSE;
+
+#ifdef CONFIG_80211N_HT
+#ifdef CONFIG_80211AC_VHT
+	if (psta->vhtpriv.vht_option) {
+		sgi_80m= psta->vhtpriv.sgi_80m;
+	}
+#endif //CONFIG_80211AC_VHT
+	{
+		sgi_20m = psta->htpriv.sgi_20m;
+		sgi_40m = psta->htpriv.sgi_40m;
+	}
+#endif
+
+	switch(psta->bw_mode){
+		case CHANNEL_WIDTH_80:
+			sgi = sgi_80m;
+			break;
+		case CHANNEL_WIDTH_40:
+			sgi = sgi_40m;
+			break;
+		case CHANNEL_WIDTH_20:
+		default:
+			sgi = sgi_20m;
+			break;
+	}
+
+	return sgi;
+}
+
+static void update_attrib_vcs_info(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	u32	sz;
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	//struct sta_info	*psta = pattrib->psta;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	struct mlme_ext_info	*pmlmeinfo = &(pmlmeext->mlmext_info);
+
+/*
+        if(pattrib->psta)
+	{
+		psta = pattrib->psta;
+	}
+	else
+	{
+		DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+		psta=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0] );
+	}
+
+        if(psta==NULL)
+	{
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return;
+	}
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return;
+	}
+*/
+
+	if (pattrib->nr_frags != 1)
+	{
+		sz = padapter->xmitpriv.frag_len;
+	}
+	else //no frag
+	{
+		sz = pattrib->last_txcmdsz;
+	}
+
+	// (1) RTS_Threshold is compared to the MPDU, not MSDU.
+	// (2) If there are more than one frag in  this MSDU, only the first frag uses protection frame.
+	//		Other fragments are protected by previous fragment.
+	//		So we only need to check the length of first fragment.
+	if(pmlmeext->cur_wireless_mode < WIRELESS_11_24N  || padapter->registrypriv.wifi_spec)
+	{
+		if(sz > padapter->registrypriv.rts_thresh)
+		{
+			pattrib->vcs_mode = RTS_CTS;
+		}
+		else
+		{
+			if(pattrib->rtsen)
+				pattrib->vcs_mode = RTS_CTS;
+			else if(pattrib->cts2self)
+				pattrib->vcs_mode = CTS_TO_SELF;
+			else
+				pattrib->vcs_mode = NONE_VCS;
+		}
+	}
+	else
+	{
+		while (_TRUE)
+		{
+#if 0 //Todo
+			//check IOT action
+			if(pHTInfo->IOTAction & HT_IOT_ACT_FORCED_CTS2SELF)
+			{
+				pattrib->vcs_mode = CTS_TO_SELF;
+				pattrib->rts_rate = MGN_24M;
+				break;
+			}
+			else if(pHTInfo->IOTAction & (HT_IOT_ACT_FORCED_RTS|HT_IOT_ACT_PURE_N_MODE))
+			{
+				pattrib->vcs_mode = RTS_CTS;
+				pattrib->rts_rate = MGN_24M;
+				break;
+			}
+#endif
+
+			//IOT action
+			if((pmlmeinfo->assoc_AP_vendor == HT_IOT_PEER_ATHEROS) && (pattrib->ampdu_en==_TRUE) &&
+				(padapter->securitypriv.dot11PrivacyAlgrthm == _AES_ ))
+			{
+				pattrib->vcs_mode = CTS_TO_SELF;
+				break;
+			}	
+			
+
+			//check ERP protection
+			if(pattrib->rtsen || pattrib->cts2self)
+			{
+				if(pattrib->rtsen)
+					pattrib->vcs_mode = RTS_CTS;
+				else if(pattrib->cts2self)
+					pattrib->vcs_mode = CTS_TO_SELF;
+
+				break;
+			}
+
+			//check HT op mode
+			if(pattrib->ht_en)
+			{
+				u8 HTOpMode = pmlmeinfo->HT_protection;
+				if((pmlmeext->cur_bwmode && (HTOpMode == 2 || HTOpMode == 3)) ||
+					(!pmlmeext->cur_bwmode && HTOpMode == 3) )
+				{
+					pattrib->vcs_mode = RTS_CTS;
+					break;
+				}
+			}
+
+			//check rts
+			if(sz > padapter->registrypriv.rts_thresh)
+			{
+				pattrib->vcs_mode = RTS_CTS;
+				break;
+			}
+
+			//to do list: check MIMO power save condition.
+
+			//check AMPDU aggregation for TXOP
+			if((pattrib->ampdu_en==_TRUE) && (!IS_HARDWARE_TYPE_8812(padapter)))
+			{
+				pattrib->vcs_mode = RTS_CTS;
+				break;
+			}
+
+			pattrib->vcs_mode = NONE_VCS;
+			break;
+		}
+	}
+
+	//for debug : force driver control vrtl_carrier_sense.
+	if(padapter->driver_vcs_en==1)
+	{
+		//u8 driver_vcs_en; //Enable=1, Disable=0 driver control vrtl_carrier_sense.
+		//u8 driver_vcs_type;//force 0:disable VCS, 1:RTS-CTS, 2:CTS-to-self when vcs_en=1.
+		pattrib->vcs_mode = padapter->driver_vcs_type;
+	}	
+	
+}
+
+static void update_attrib_phy_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
+{
+	struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
+
+	pattrib->rtsen = psta->rtsen;
+	pattrib->cts2self = psta->cts2self;
+	
+	pattrib->mdata = 0;
+	pattrib->eosp = 0;
+	pattrib->triggered=0;
+	pattrib->ampdu_spacing = 0;
+	
+	//qos_en, ht_en, init rate, ,bw, ch_offset, sgi
+	pattrib->qos_en = psta->qos_option;
+	
+	pattrib->raid = psta->raid;
+
+	if (mlmeext->cur_bwmode < psta->bw_mode)
+		pattrib->bwmode = mlmeext->cur_bwmode;
+	else
+		pattrib->bwmode = psta->bw_mode;
+
+	pattrib->sgi = query_ra_short_GI(psta);
+
+	pattrib->ldpc = psta->ldpc;
+	pattrib->stbc = psta->stbc;
+
+#ifdef CONFIG_80211N_HT
+	pattrib->ht_en = psta->htpriv.ht_option;
+	pattrib->ch_offset = psta->htpriv.ch_offset;
+	pattrib->ampdu_en = _FALSE;
+
+	if(padapter->driver_ampdu_spacing != 0xFF) //driver control AMPDU Density for peer sta's rx
+		pattrib->ampdu_spacing = padapter->driver_ampdu_spacing;
+	else
+		pattrib->ampdu_spacing = psta->htpriv.rx_ampdu_min_spacing;
+#endif //CONFIG_80211N_HT
+	//if(pattrib->ht_en && psta->htpriv.ampdu_enable)
+	//{
+	//	if(psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
+	//		pattrib->ampdu_en = _TRUE;
+	//}	
+
+#ifdef CONFIG_TDLS
+	if (pattrib->direct_link==_TRUE) {
+		psta = pattrib->ptdls_sta;
+
+		pattrib->raid = psta->raid;
+#ifdef CONFIG_80211N_HT
+		pattrib->bwmode = psta->bw_mode;
+		pattrib->ht_en = psta->htpriv.ht_option;
+		pattrib->ch_offset = psta->htpriv.ch_offset;
+		pattrib->sgi= query_ra_short_GI(psta);
+#endif /* CONFIG_80211N_HT */
+	}
+#endif /* CONFIG_TDLS */
+
+	pattrib->retry_ctrl = _FALSE;
+
+#ifdef CONFIG_AUTO_AP_MODE
+	if(psta->isrc && psta->pid>0)
+		pattrib->pctrl = _TRUE;
+#endif
+
+}
+
+static s32 update_attrib_sec_info(_adapter *padapter, struct pkt_attrib *pattrib, struct sta_info *psta)
+{
+	sint res = _SUCCESS;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct security_priv *psecuritypriv = &padapter->securitypriv;
+	sint bmcast = IS_MCAST(pattrib->ra);
+
+	_rtw_memset(pattrib->dot118021x_UncstKey.skey,  0, 16);		
+	_rtw_memset(pattrib->dot11tkiptxmickey.skey,  0, 16);
+	pattrib->mac_id = psta->mac_id;
+
+	if (psta->ieee8021x_blocked == _TRUE)
+	{
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("\n psta->ieee8021x_blocked == _TRUE \n"));
+
+		pattrib->encrypt = 0;
+
+		if((pattrib->ether_type != 0x888e) && (check_fwstate(pmlmepriv, WIFI_MP_STATE) == _FALSE))
+		{
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("\npsta->ieee8021x_blocked == _TRUE,  pattrib->ether_type(%.4x) != 0x888e\n",pattrib->ether_type));
+			#ifdef DBG_TX_DROP_FRAME
+			DBG_871X("DBG_TX_DROP_FRAME %s psta->ieee8021x_blocked == _TRUE,  pattrib->ether_type(%04x) != 0x888e\n", __FUNCTION__,pattrib->ether_type);
+			#endif
+			res = _FAIL;
+			goto exit;
+		}
+	}
+	else
+	{
+		GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
+		
+#ifdef CONFIG_WAPI_SUPPORT
+		if(pattrib->ether_type == 0x88B4)
+			pattrib->encrypt=_NO_PRIVACY_;
+#endif
+
+		switch(psecuritypriv->dot11AuthAlgrthm)
+		{
+			case dot11AuthAlgrthm_Open:
+			case dot11AuthAlgrthm_Shared:
+			case dot11AuthAlgrthm_Auto:
+				pattrib->key_idx = (u8)psecuritypriv->dot11PrivacyKeyIndex;
+				break;
+			case dot11AuthAlgrthm_8021X:
+				if(bmcast)
+					pattrib->key_idx = (u8)psecuritypriv->dot118021XGrpKeyid;
+				else
+					pattrib->key_idx = 0;
+				break;
+			default:
+				pattrib->key_idx = 0;
+				break;
+		}
+
+		//For WPS 1.0 WEP, driver should not encrypt EAPOL Packet for WPS handshake.
+		if (((pattrib->encrypt ==_WEP40_)||(pattrib->encrypt ==_WEP104_)) && (pattrib->ether_type == 0x888e))
+			pattrib->encrypt=_NO_PRIVACY_;
+		
+	}
+
+#ifdef CONFIG_TDLS
+	if (pattrib->direct_link == _TRUE) {
+		if (pattrib->encrypt > 0)
+			pattrib->encrypt = _AES_;
+	}
+#endif 
+	
+	switch (pattrib->encrypt)
+	{
+		case _WEP40_:
+		case _WEP104_:
+			pattrib->iv_len = 4;
+			pattrib->icv_len = 4;
+			WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+			break;
+
+		case _TKIP_:
+			pattrib->iv_len = 8;
+			pattrib->icv_len = 4;
+
+			if(psecuritypriv->busetkipkey==_FAIL)
+			{				
+				#ifdef DBG_TX_DROP_FRAME
+				DBG_871X("DBG_TX_DROP_FRAME %s psecuritypriv->busetkipkey(%d)==_FAIL drop packet\n", __FUNCTION__, psecuritypriv->busetkipkey);
+				#endif
+				res =_FAIL;
+				goto exit;
+			}
+
+			if(bmcast)
+				TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+			else
+				TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+
+
+			_rtw_memcpy(pattrib->dot11tkiptxmickey.skey, psta->dot11tkiptxmickey.skey, 16);
+			
+			break;
+			
+		case _AES_:
+			
+			pattrib->iv_len = 8;
+			pattrib->icv_len = 8;
+			
+			if(bmcast)
+				AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+			else
+				AES_IV(pattrib->iv, psta->dot11txpn, 0);
+			
+			break;
+
+#ifdef CONFIG_WAPI_SUPPORT
+		case _SMS4_:
+			pattrib->iv_len = 18;
+			pattrib->icv_len = 16;
+			rtw_wapi_get_iv(padapter,pattrib->ra,pattrib->iv);			
+			break;
+#endif
+		default:
+			pattrib->iv_len = 0;
+			pattrib->icv_len = 0;
+			break;
+	}
+
+	if(pattrib->encrypt>0)
+		_rtw_memcpy(pattrib->dot118021x_UncstKey.skey, psta->dot118021x_UncstKey.skey, 16);		
+
+	RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
+		("update_attrib: encrypt=%d  securitypriv.sw_encrypt=%d\n",
+		pattrib->encrypt, padapter->securitypriv.sw_encrypt));
+
+	if (pattrib->encrypt &&
+		((padapter->securitypriv.sw_encrypt == _TRUE) || (psecuritypriv->hw_decrypted == _FALSE)))
+	{
+		pattrib->bswenc = _TRUE;
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,
+			("update_attrib: encrypt=%d securitypriv.hw_decrypted=%d bswenc=_TRUE\n",
+			pattrib->encrypt, padapter->securitypriv.sw_encrypt));
+	} else {
+		pattrib->bswenc = _FALSE;
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("update_attrib: bswenc=_FALSE\n"));
+	}
+
+#if defined(CONFIG_CONCURRENT_MODE) && !defined(DYNAMIC_CAMID_ALLOC)
+	if((pattrib->encrypt && bmcast) || (pattrib->encrypt ==_WEP40_) || (pattrib->encrypt ==_WEP104_))
+	{
+		pattrib->bswenc = _TRUE;//force using sw enc.
+	}
+#endif
+#ifdef DYNAMIC_CAMID_ALLOC
+	if (pattrib->encrypt && bmcast && _rtw_camctl_chk_flags(padapter, SEC_STATUS_STA_PK_GK_CONFLICT_DIS_BMC_SEARCH))
+		pattrib->bswenc = _TRUE;
+#endif
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if(pattrib->encrypt == _SMS4_)
+		pattrib->bswenc = _FALSE;
+#endif
+
+exit:
+
+	return res;
+	
+}
+
+u8	qos_acm(u8 acm_mask, u8 priority)
+{
+	u8	change_priority = priority;
+
+	switch (priority)
+	{
+		case 0:
+		case 3:
+			if(acm_mask & BIT(1))
+				change_priority = 1;
+			break;
+		case 1:
+		case 2:
+			break;
+		case 4:
+		case 5:
+			if(acm_mask & BIT(2))
+				change_priority = 0;
+			break;
+		case 6:
+		case 7:
+			if(acm_mask & BIT(3))
+				change_priority = 5;
+			break;
+		default:
+			DBG_871X("qos_acm(): invalid pattrib->priority: %d!!!\n", priority);
+			break;
+	}
+
+	return change_priority;
+}
+
+static void set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
+{
+	struct ethhdr etherhdr;
+	struct iphdr ip_hdr;
+	s32 UserPriority = 0;
+
+
+	_rtw_open_pktfile(ppktfile->pkt, ppktfile);
+	_rtw_pktfile_read(ppktfile, (unsigned char*)&etherhdr, ETH_HLEN);
+
+	// get UserPriority from IP hdr
+	if (pattrib->ether_type == 0x0800) {
+		_rtw_pktfile_read(ppktfile, (u8*)&ip_hdr, sizeof(ip_hdr));
+//		UserPriority = (ntohs(ip_hdr.tos) >> 5) & 0x3;
+		UserPriority = ip_hdr.tos >> 5;
+	}
+/* 
+	else if (pattrib->ether_type == 0x888e) {
+		// "When priority processing of data frames is supported,
+		// a STA's SME should send EAPOL-Key frames at the highest priority."
+		UserPriority = 7;
+	}
+*/
+	pattrib->priority = UserPriority;
+	pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
+	pattrib->subtype = WIFI_QOS_DATA_TYPE;
+}
+
+#ifdef CONFIG_TDLS
+u8 rtw_check_tdls_established(_adapter *padapter, struct pkt_attrib *pattrib)
+{
+	pattrib->ptdls_sta = NULL;
+
+	pattrib->direct_link = _FALSE;
+	if (padapter->tdlsinfo.link_established == _TRUE) {
+		pattrib->ptdls_sta = rtw_get_stainfo(&padapter->stapriv, pattrib->dst);
+#if 1
+		if((pattrib->ptdls_sta!=NULL)&&
+			(pattrib->ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE)&&
+			(pattrib->ether_type!=0x0806)){
+				pattrib->direct_link = _TRUE;
+				//DBG_871X("send ptk to "MAC_FMT" using direct link\n", MAC_ARG(pattrib->dst));
+		}
+#else
+		if (pattrib->ptdls_sta != NULL &&
+			pattrib->ptdls_sta->tdls_sta_state & TDLS_LINKED_STATE) {
+				pattrib->direct_link = _TRUE;
+				#if 0
+				DBG_871X("send ptk to "MAC_FMT" using direct link\n", MAC_ARG(pattrib->dst));
+				#endif
+		}
+
+		/* ARP frame may be helped by AP*/
+		if (pattrib->ether_type != 0x0806) {
+				pattrib->direct_link = _FALSE;
+		}	
+#endif
+	}
+
+	return pattrib->direct_link;
+}
+
+s32 update_tdls_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
+{
+
+	struct sta_info *psta = NULL;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct security_priv	*psecuritypriv = &padapter->securitypriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct qos_priv		*pqospriv= &pmlmepriv->qospriv;
+
+	s32 res=_SUCCESS;
+	
+	psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+	if (psta == NULL)	{ 
+		res =_FAIL;
+		goto exit;
+	}
+
+	pattrib->mac_id = psta->mac_id;
+	pattrib->psta = psta;
+	pattrib->ack_policy = 0;
+	// get ether_hdr_len
+	pattrib->pkt_hdrlen = ETH_HLEN;
+
+	// [TDLS] TODO: setup req/rsp should be AC_BK
+	if (pqospriv->qos_option &&  psta->qos_option) {
+		pattrib->priority = 4;	//tdls management frame should be AC_VI
+		pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
+		pattrib->subtype = WIFI_QOS_DATA_TYPE;
+	} else {
+		pattrib->priority = 0;
+		pattrib->hdrlen = WLAN_HDR_A3_LEN;
+		pattrib->subtype = WIFI_DATA_TYPE;	
+	}
+
+	//TODO:_lock
+	if(update_attrib_sec_info(padapter, pattrib, psta) == _FAIL)
+	{
+		res = _FAIL;
+		goto exit;
+	}
+
+	update_attrib_phy_info(padapter, pattrib, psta);
+
+
+exit:
+
+	return res;
+}
+
+#endif //CONFIG_TDLS
+
+//get non-qos hw_ssn control register,mapping to REG_HW_SEQ0,1,2,3
+inline u8 rtw_get_hwseq_no(_adapter *padapter)
+{
+	u8 hwseq_num = 0;
+#ifdef CONFIG_CONCURRENT_MODE
+	if(padapter->adapter_type == SECONDARY_ADAPTER)
+		hwseq_num = 1;
+	//else
+	//	hwseq_num = 2;
+#endif //CONFIG_CONCURRENT_MODE
+	return hwseq_num;
+}
+static s32 update_attrib(_adapter *padapter, _pkt *pkt, struct pkt_attrib *pattrib)
+{
+	uint i;
+	struct pkt_file pktfile;
+	struct sta_info *psta = NULL;
+	struct ethhdr etherhdr;
+
+	sint bmcast;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct security_priv	*psecuritypriv = &padapter->securitypriv;
+	struct mlme_priv		*pmlmepriv = &padapter->mlmepriv;
+	struct qos_priv		*pqospriv= &pmlmepriv->qospriv;
+	struct xmit_priv 		*pxmitpriv = &padapter->xmitpriv;
+	sint res = _SUCCESS;
+
+ _func_enter_;
+
+	DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib);
+
+	_rtw_open_pktfile(pkt, &pktfile);
+	i = _rtw_pktfile_read(&pktfile, (u8*)&etherhdr, ETH_HLEN);
+
+	pattrib->ether_type = ntohs(etherhdr.h_proto);
+
+
+	_rtw_memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
+	_rtw_memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
+
+
+	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ||
+		(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
+		_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+		_rtw_memcpy(pattrib->ta, adapter_mac_addr(padapter), ETH_ALEN);
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_adhoc);
+	}
+	else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
+#ifdef CONFIG_TDLS
+		if (rtw_check_tdls_established(padapter, pattrib) == _TRUE)
+			_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);	/* For TDLS direct link Tx, set ra to be same to dst */
+		else
+#endif
+		_rtw_memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
+		_rtw_memcpy(pattrib->ta, adapter_mac_addr(padapter), ETH_ALEN);
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_sta);
+	}
+	else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
+		_rtw_memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
+		_rtw_memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_ap);
+	} 
+	else
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_unknown);
+
+	bmcast = IS_MCAST(pattrib->ra);
+	if (bmcast) {
+		psta = rtw_get_bcmc_stainfo(padapter);
+		if (psta == NULL) { /* if we cannot get psta => drop the pkt */
+			DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sta);
+			RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT "\n", MAC_ARG(pattrib->ra)));
+			#ifdef DBG_TX_DROP_FRAME
+			DBG_871X("DBG_TX_DROP_FRAME %s get sta_info fail, ra:" MAC_FMT"\n", __func__, MAC_ARG(pattrib->ra));
+			#endif
+			res = _FAIL;
+			goto exit;
+		}
+	} else {
+		psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+		if (psta == NULL) { /* if we cannot get psta => drop the pkt */
+			DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_sta);
+			RT_TRACE(_module_rtl871x_xmit_c_, _drv_alert_, ("\nupdate_attrib => get sta_info fail, ra:" MAC_FMT"\n", MAC_ARG(pattrib->ra)));
+			#ifdef DBG_TX_DROP_FRAME
+			DBG_871X("DBG_TX_DROP_FRAME %s get sta_info fail, ra:" MAC_FMT"\n", __func__, MAC_ARG(pattrib->ra));
+			#endif
+			res = _FAIL;
+			goto exit;
+		} else if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _TRUE && !(psta->state & _FW_LINKED)) {
+			DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_ucast_ap_link);
+			res = _FAIL;
+			goto exit;
+		}
+	}
+
+	if (!(psta->state & _FW_LINKED)) {
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_link);
+		DBG_871X("%s, psta("MAC_FMT")->state(0x%x) != _FW_LINKED\n", __func__, MAC_ARG(psta->hwaddr), psta->state);
+		res = _FAIL;
+		goto exit;
+	}
+
+	pattrib->pktlen = pktfile.pkt_len;
+
+	/* TODO: 802.1Q VLAN header */
+	/* TODO: IPV6 */
+
+	if (ETH_P_IP == pattrib->ether_type) {
+		u8 ip[20];
+
+		_rtw_pktfile_read(&pktfile, ip, 20);
+
+		if (GET_IPV4_IHL(ip) * 4 > 20)
+			_rtw_pktfile_read(&pktfile, NULL, GET_IPV4_IHL(ip) - 20);
+
+		pattrib->icmp_pkt = 0;
+		pattrib->dhcp_pkt = 0;
+
+		if (GET_IPV4_PROTOCOL(ip) == 0x01) { /* ICMP */
+			pattrib->icmp_pkt = 1;
+			DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_icmp);
+
+		} else if (GET_IPV4_PROTOCOL(ip) == 0x11) { /* UDP */
+			u8 udp[8];
+
+			_rtw_pktfile_read(&pktfile, udp, 8);
+
+			if ((GET_UDP_SRC(udp) == 68 && GET_UDP_DST(udp) == 67)
+				|| (GET_UDP_SRC(udp) == 67 && GET_UDP_DST(udp) == 68)
+			) {
+				/* 67 : UDP BOOTP server, 68 : UDP BOOTP client */
+				if (pattrib->pktlen > 282) { /* MINIMUM_DHCP_PACKET_SIZE */
+					pattrib->dhcp_pkt = 1;
+					DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_dhcp);
+					if (0)
+						DBG_871X("send DHCP packet\n");
+				}
+			}
+
+		} else if (GET_IPV4_PROTOCOL(ip) == 0x06 /* TCP */
+			&& rtw_st_ctl_chk_reg_s_proto(&psta->st_ctl, 0x06) == _TRUE
+		) {
+			u8 tcp[20];
+
+			_rtw_pktfile_read(&pktfile, tcp, 20);
+
+			if (rtw_st_ctl_chk_reg_rule(&psta->st_ctl, padapter, IPV4_SRC(ip), TCP_SRC(tcp), IPV4_DST(ip), TCP_DST(tcp)) == _TRUE) {
+				if (GET_TCP_SYN(tcp) && GET_TCP_ACK(tcp)) {
+					session_tracker_add_cmd(padapter, psta
+						, IPV4_SRC(ip), TCP_SRC(tcp)
+						, IPV4_SRC(ip), TCP_DST(tcp));
+					if (DBG_SESSION_TRACKER)
+						DBG_871X(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" SYN-ACK\n"
+							, FUNC_ADPT_ARG(padapter)
+							, IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp))
+							, IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)));
+				}
+				if (GET_TCP_FIN(tcp)) {
+					session_tracker_del_cmd(padapter, psta
+						, IPV4_SRC(ip), TCP_SRC(tcp)
+						, IPV4_SRC(ip), TCP_DST(tcp));
+					if (DBG_SESSION_TRACKER)
+						DBG_871X(FUNC_ADPT_FMT" local:"IP_FMT":"PORT_FMT", remote:"IP_FMT":"PORT_FMT" FIN\n"
+							, FUNC_ADPT_ARG(padapter)
+							, IP_ARG(IPV4_SRC(ip)), PORT_ARG(TCP_SRC(tcp))
+							, IP_ARG(IPV4_DST(ip)), PORT_ARG(TCP_DST(tcp)));
+				}
+			}
+		}
+
+	} else if (0x888e == pattrib->ether_type) {
+		DBG_871X_LEVEL(_drv_always_, "send eapol packet\n");
+	}
+
+	if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1))
+		rtw_set_scan_deny(padapter, 3000);
+
+#ifdef CONFIG_LPS
+	// If EAPOL , ARP , OR DHCP packet, driver must be in active mode.
+#ifdef CONFIG_WAPI_SUPPORT
+	if ( (pattrib->ether_type == 0x88B4) || (pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1) )
+#else //!CONFIG_WAPI_SUPPORT
+#if 0
+	if ( (pattrib->ether_type == 0x0806) || (pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1) )
+#else // only ICMP/DHCP packets is as SPECIAL_PACKET, and leave LPS when tx IMCP/DHCP packets.
+	//if ((pattrib->ether_type == 0x888e) || (pattrib->dhcp_pkt == 1) )
+	if (pattrib->icmp_pkt==1)
+	{
+		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_LEAVE, 1);
+	}
+	else if(pattrib->dhcp_pkt==1)
+#endif 
+#endif
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_active);
+		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SPECIAL_PACKET, 1);
+	}
+#endif //CONFIG_LPS
+
+#ifdef CONFIG_BEAMFORMING
+	update_attrib_txbf_info(padapter, pattrib, psta);
+#endif
+
+	//TODO:_lock
+	if(update_attrib_sec_info(padapter, pattrib, psta) == _FAIL)
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_upd_attrib_err_sec);
+		res = _FAIL;
+		goto exit;
+	}
+
+	update_attrib_phy_info(padapter, pattrib, psta);
+
+	//DBG_8192C("%s ==> mac_id(%d)\n",__FUNCTION__,pattrib->mac_id );
+	
+	pattrib->psta = psta;
+	//TODO:_unlock
+	
+	pattrib->pctrl = 0;	
+		
+	pattrib->ack_policy = 0;
+	// get ether_hdr_len
+	pattrib->pkt_hdrlen = ETH_HLEN;//(pattrib->ether_type == 0x8100) ? (14 + 4 ): 14; //vlan tag
+
+	pattrib->hdrlen = WLAN_HDR_A3_LEN;
+	pattrib->subtype = WIFI_DATA_TYPE;	
+	pattrib->priority = 0;
+	
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE|WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE))
+	{
+		if(pattrib->qos_en)
+			set_qos(&pktfile, pattrib);
+	}
+	else
+	{
+#ifdef CONFIG_TDLS
+		if (pattrib->direct_link == _TRUE) {
+			if (pattrib->qos_en)
+				set_qos(&pktfile, pattrib);
+		} else 
+#endif
+		{
+			if (pqospriv->qos_option) {
+				set_qos(&pktfile, pattrib);
+
+				if (pmlmepriv->acm_mask != 0)
+					pattrib->priority = qos_acm(pmlmepriv->acm_mask, pattrib->priority);
+			}
+		}
+	}
+
+	//pattrib->priority = 5; //force to used VI queue, for testing
+	pattrib->hw_ssn_sel = pxmitpriv->hw_ssn_seq_no;
+	rtw_set_tx_chksum_offload(pkt, pattrib);
+
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+static s32 xmitframe_addmic(_adapter *padapter, struct xmit_frame *pxmitframe){
+	sint 			curfragnum,length;
+	u8	*pframe, *payload,mic[8];
+	struct	mic_data		micdata;
+	//struct	sta_info		*stainfo;
+	struct	qos_priv   *pqospriv= &(padapter->mlmepriv.qospriv);	
+	struct	pkt_attrib	 *pattrib = &pxmitframe->attrib;
+	struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+	struct	xmit_priv		*pxmitpriv=&padapter->xmitpriv;
+	u8 priority[4]={0x0,0x0,0x0,0x0};
+	u8 hw_hdr_offset = 0;
+	sint bmcst = IS_MCAST(pattrib->ra);
+
+/*
+	if(pattrib->psta)
+	{
+		stainfo = pattrib->psta;
+	}
+	else
+	{
+		DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+		stainfo=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
+	}	
+	
+	if(stainfo==NULL)
+	{
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return _FAIL;
+	}
+
+	if(!(stainfo->state &_FW_LINKED))
+	{
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, stainfo->state);
+		return _FAIL;
+	}
+*/
+
+_func_enter_;
+
+#ifdef CONFIG_USB_TX_AGGREGATION
+	hw_hdr_offset = TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);;	
+#else
+	#ifdef CONFIG_TX_EARLY_MODE
+	hw_hdr_offset = TXDESC_OFFSET+ EARLY_MODE_INFO_SIZE;
+	#else
+	hw_hdr_offset = TXDESC_OFFSET;
+	#endif
+#endif	
+	
+	if(pattrib->encrypt ==_TKIP_)//if(psecuritypriv->dot11PrivacyAlgrthm==_TKIP_PRIVACY_) 
+	{
+		//encode mic code
+		//if(stainfo!= NULL)
+		{
+			u8 null_key[16]={0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0};
+
+			pframe = pxmitframe->buf_addr + hw_hdr_offset;
+			
+			if(bmcst)
+			{
+				if(_rtw_memcmp(psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey, null_key, 16)==_TRUE){
+					//DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey==0\n");
+					//rtw_msleep_os(10);
+					return _FAIL;
+				}				
+				//start to calculate the mic code
+				rtw_secmicsetkey(&micdata, psecuritypriv->dot118021XGrptxmickey[psecuritypriv->dot118021XGrpKeyid].skey);
+			}
+			else
+			{
+				if(_rtw_memcmp(&pattrib->dot11tkiptxmickey.skey[0],null_key, 16)==_TRUE){
+					//DbgPrint("\nxmitframe_addmic:stainfo->dot11tkiptxmickey==0\n");
+					//rtw_msleep_os(10);
+					return _FAIL;
+				}
+				//start to calculate the mic code
+				rtw_secmicsetkey(&micdata, &pattrib->dot11tkiptxmickey.skey[0]);
+			}
+			
+			if(pframe[1]&1){   //ToDS==1
+				rtw_secmicappend(&micdata, &pframe[16], 6);  //DA
+				if(pframe[1]&2)  //From Ds==1
+					rtw_secmicappend(&micdata, &pframe[24], 6);
+				else
+				rtw_secmicappend(&micdata, &pframe[10], 6);		
+			}	
+			else{	//ToDS==0
+				rtw_secmicappend(&micdata, &pframe[4], 6);   //DA
+				if(pframe[1]&2)  //From Ds==1
+					rtw_secmicappend(&micdata, &pframe[16], 6);
+				else
+					rtw_secmicappend(&micdata, &pframe[10], 6);
+
+			}
+
+                    //if(pqospriv->qos_option==1)
+                    if(pattrib->qos_en)
+				priority[0]=(u8)pxmitframe->attrib.priority;
+
+			
+			rtw_secmicappend(&micdata, &priority[0], 4);
+	
+			payload=pframe;
+
+			for(curfragnum=0;curfragnum<pattrib->nr_frags;curfragnum++){
+				payload=(u8 *)RND4((SIZE_PTR)(payload));
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("===curfragnum=%d, pframe= 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x, 0x%.2x,!!!\n",
+					curfragnum,*payload, *(payload+1),*(payload+2),*(payload+3),*(payload+4),*(payload+5),*(payload+6),*(payload+7)));
+
+				payload=payload+pattrib->hdrlen+pattrib->iv_len;
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("curfragnum=%d pattrib->hdrlen=%d pattrib->iv_len=%d",curfragnum,pattrib->hdrlen,pattrib->iv_len));
+				if((curfragnum+1)==pattrib->nr_frags){
+					length=pattrib->last_txcmdsz-pattrib->hdrlen-pattrib->iv_len-( (pattrib->bswenc) ? pattrib->icv_len : 0);
+					rtw_secmicappend(&micdata, payload,length);
+					payload=payload+length;
+				}
+				else{
+					length=pxmitpriv->frag_len-pattrib->hdrlen-pattrib->iv_len-( (pattrib->bswenc) ? pattrib->icv_len : 0);
+					rtw_secmicappend(&micdata, payload, length);
+					payload=payload+length+pattrib->icv_len;
+					RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("curfragnum=%d length=%d pattrib->icv_len=%d",curfragnum,length,pattrib->icv_len));
+				}
+			}
+			rtw_secgetmic(&micdata,&(mic[0]));
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("xmitframe_addmic: before add mic code!!!\n"));
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("xmitframe_addmic: pattrib->last_txcmdsz=%d!!!\n",pattrib->last_txcmdsz));
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("xmitframe_addmic: mic[0]=0x%.2x ,mic[1]=0x%.2x ,mic[2]=0x%.2x ,mic[3]=0x%.2x \n\
+  mic[4]=0x%.2x ,mic[5]=0x%.2x ,mic[6]=0x%.2x ,mic[7]=0x%.2x !!!!\n",
+				mic[0],mic[1],mic[2],mic[3],mic[4],mic[5],mic[6],mic[7]));
+			//add mic code  and add the mic code length in last_txcmdsz
+
+			_rtw_memcpy(payload, &(mic[0]),8);
+			pattrib->last_txcmdsz+=8;
+			
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("\n ========last pkt========\n"));
+			payload=payload-pattrib->last_txcmdsz+8;
+			for(curfragnum=0;curfragnum<pattrib->last_txcmdsz;curfragnum=curfragnum+8)
+					RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,(" %.2x,  %.2x,  %.2x,  %.2x,  %.2x,  %.2x,  %.2x,  %.2x ",
+					*(payload+curfragnum), *(payload+curfragnum+1), *(payload+curfragnum+2),*(payload+curfragnum+3),
+					*(payload+curfragnum+4),*(payload+curfragnum+5),*(payload+curfragnum+6),*(payload+curfragnum+7)));
+			}
+/*
+			else{
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("xmitframe_addmic: rtw_get_stainfo==NULL!!!\n"));
+			}
+*/		
+	}
+	
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+static s32 xmitframe_swencrypt(_adapter *padapter, struct xmit_frame *pxmitframe){
+
+	struct	pkt_attrib	 *pattrib = &pxmitframe->attrib;
+	//struct 	security_priv	*psecuritypriv=&padapter->securitypriv;
+	
+_func_enter_;
+
+	//if((psecuritypriv->sw_encrypt)||(pattrib->bswenc))	
+	if(pattrib->bswenc)
+	{
+		//DBG_871X("start xmitframe_swencrypt\n");
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_alert_,("### xmitframe_swencrypt\n"));
+		switch(pattrib->encrypt){
+		case _WEP40_:
+		case _WEP104_:
+			rtw_wep_encrypt(padapter, (u8 *)pxmitframe);
+			break;
+		case _TKIP_:
+			rtw_tkip_encrypt(padapter, (u8 *)pxmitframe);
+			break;
+		case _AES_:
+			rtw_aes_encrypt(padapter, (u8 * )pxmitframe);
+			break;
+#ifdef CONFIG_WAPI_SUPPORT
+		case _SMS4_:
+			rtw_sms4_encrypt(padapter, (u8 * )pxmitframe);
+#endif
+		default:
+				break;
+		}
+
+	} else {
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_notice_,("### xmitframe_hwencrypt\n"));
+	}
+
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+s32 rtw_make_wlanhdr (_adapter *padapter , u8 *hdr, struct pkt_attrib *pattrib)
+{
+	u16 *qc;
+
+	struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+	u8 qos_option = _FALSE;
+	sint res = _SUCCESS;
+	u16 *fctrl = &pwlanhdr->frame_ctl;
+
+	//struct sta_info *psta;
+
+	//sint bmcst = IS_MCAST(pattrib->ra);
+
+_func_enter_;
+
+/*
+	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	if(pattrib->psta != psta)
+	{
+		DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
+		return;
+	}
+
+	if(psta==NULL)
+	{
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return _FAIL;
+	}
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return _FAIL;
+	}
+*/
+
+	_rtw_memset(hdr, 0, WLANHDR_OFFSET);
+
+	SetFrameSubType(fctrl, pattrib->subtype);
+
+	if (pattrib->subtype & WIFI_DATA_TYPE)
+	{
+		if ((check_fwstate(pmlmepriv,  WIFI_STATION_STATE) == _TRUE)) {
+#ifdef CONFIG_TDLS
+			if(pattrib->direct_link == _TRUE){
+				//TDLS data transfer, ToDS=0, FrDs=0
+				_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
+
+				if (pattrib->qos_en)
+					qos_option = _TRUE;
+			} 
+			else
+#endif //CONFIG_TDLS
+			{
+				//to_ds = 1, fr_ds = 0;
+				// 1.Data transfer to AP
+				// 2.Arp pkt will relayed by AP
+				SetToDs(fctrl);							
+				_rtw_memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr2, pattrib->ta, ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
+
+				if (pqospriv->qos_option)
+					qos_option = _TRUE;
+			} 
+		}
+		else if ((check_fwstate(pmlmepriv,  WIFI_AP_STATE) == _TRUE) ) {
+			//to_ds = 0, fr_ds = 1;
+			SetFrDs(fctrl);
+			_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr2, get_bssid(pmlmepriv), ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr3, pattrib->src, ETH_ALEN);
+
+			if(pattrib->qos_en)
+				qos_option = _TRUE;
+		}
+		else if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE) ||
+		(check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == _TRUE)) {
+			_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr2, pattrib->ta, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
+
+			if(pattrib->qos_en)
+				qos_option = _TRUE;
+		}
+		else {
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("fw_state:%x is not allowed to xmit frame\n", get_fwstate(pmlmepriv)));
+			res = _FAIL;
+			goto exit;
+		}
+
+		if(pattrib->mdata)
+			SetMData(fctrl);
+
+		if (pattrib->encrypt)
+			SetPrivacy(fctrl);
+
+		if (qos_option)
+		{
+			qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
+
+			if (pattrib->priority)
+				SetPriority(qc, pattrib->priority);
+
+			SetEOSP(qc, pattrib->eosp);
+
+			SetAckpolicy(qc, pattrib->ack_policy);
+		}
+
+		//TODO: fill HT Control Field
+
+		//Update Seq Num will be handled by f/w
+		{
+			struct sta_info *psta;
+			psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+			if(pattrib->psta != psta)
+			{
+				DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
+				return _FAIL;
+			}
+
+			if(psta==NULL)
+			{
+				DBG_871X("%s, psta==NUL\n", __func__);
+				return _FAIL;
+			}
+
+			if(!(psta->state &_FW_LINKED))
+			{
+				DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+				return _FAIL;
+			}
+
+		
+			if(psta)
+			{
+				psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
+				psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
+				pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
+
+				SetSeqNum(hdr, pattrib->seqnum);
+
+#ifdef CONFIG_80211N_HT
+				//check if enable ampdu
+				if(pattrib->ht_en && psta->htpriv.ampdu_enable)
+				{
+					if(psta->htpriv.agg_enable_bitmap & BIT(pattrib->priority))
+						pattrib->ampdu_en = _TRUE;
+				}
+
+				//re-check if enable ampdu by BA_starting_seqctrl
+				if(pattrib->ampdu_en == _TRUE)
+				{					
+					u16 tx_seq;
+
+					tx_seq = psta->BA_starting_seqctrl[pattrib->priority & 0x0f];
+		
+					//check BA_starting_seqctrl
+					if(SN_LESS(pattrib->seqnum, tx_seq))
+					{
+						//DBG_871X("tx ampdu seqnum(%d) < tx_seq(%d)\n", pattrib->seqnum, tx_seq);
+						pattrib->ampdu_en = _FALSE;//AGG BK
+					}
+					else if(SN_EQUAL(pattrib->seqnum, tx_seq))
+					{					
+						psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (tx_seq+1)&0xfff;
+					
+						pattrib->ampdu_en = _TRUE;//AGG EN
+					}
+					else
+					{
+						//DBG_871X("tx ampdu over run\n");
+						psta->BA_starting_seqctrl[pattrib->priority & 0x0f] = (pattrib->seqnum+1)&0xfff;
+						pattrib->ampdu_en = _TRUE;//AGG EN
+					}
+
+				}
+#endif //CONFIG_80211N_HT
+			}
+		}
+		
+	}
+	else
+	{
+
+	}
+
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+s32 rtw_txframes_pending(_adapter *padapter)
+{
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+	return ((_rtw_queue_empty(&pxmitpriv->be_pending) == _FALSE) || 
+			 (_rtw_queue_empty(&pxmitpriv->bk_pending) == _FALSE) || 
+			 (_rtw_queue_empty(&pxmitpriv->vi_pending) == _FALSE) ||
+			 (_rtw_queue_empty(&pxmitpriv->vo_pending) == _FALSE));
+}
+
+s32 rtw_txframes_sta_ac_pending(_adapter *padapter, struct pkt_attrib *pattrib)
+{	
+	struct sta_info *psta;
+	struct tx_servq *ptxservq;
+	int priority = pattrib->priority;
+/*
+	if(pattrib->psta)
+	{
+		psta = pattrib->psta;
+	}
+	else
+	{
+		DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+		psta=rtw_get_stainfo(&padapter->stapriv ,&pattrib->ra[0]);
+	}	
+*/
+	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	if(pattrib->psta != psta)
+	{
+		DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
+		return 0;
+	}
+
+	if(psta==NULL)
+	{
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return 0;
+	}
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return 0;
+	}
+	
+	switch(priority) 
+	{
+			case 1:
+			case 2:
+				ptxservq = &(psta->sta_xmitpriv.bk_q);				
+				break;
+			case 4:
+			case 5:
+				ptxservq = &(psta->sta_xmitpriv.vi_q);				
+				break;
+			case 6:
+			case 7:
+				ptxservq = &(psta->sta_xmitpriv.vo_q);							
+				break;
+			case 0:
+			case 3:
+			default:
+				ptxservq = &(psta->sta_xmitpriv.be_q);							
+			break;
+	
+	}	
+
+	return ptxservq->qcnt;	
+}
+
+#ifdef CONFIG_TDLS
+
+int rtw_build_tdls_ies(_adapter * padapter, struct xmit_frame * pxmitframe, u8 *pframe, struct tdls_txmgmt *ptxmgmt)
+{
+	int res=_SUCCESS;
+
+	switch(ptxmgmt->action_code){
+		case TDLS_SETUP_REQUEST:
+			rtw_build_tdls_setup_req_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+		case TDLS_SETUP_RESPONSE:
+			rtw_build_tdls_setup_rsp_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+		case TDLS_SETUP_CONFIRM:
+			rtw_build_tdls_setup_cfm_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+		case TDLS_TEARDOWN:
+			rtw_build_tdls_teardown_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+		case TDLS_DISCOVERY_REQUEST:
+			rtw_build_tdls_dis_req_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;			
+		case TDLS_PEER_TRAFFIC_INDICATION:
+			rtw_build_tdls_peer_traffic_indication_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+#ifdef CONFIG_TDLS_CH_SW			
+		case TDLS_CHANNEL_SWITCH_REQUEST:
+			rtw_build_tdls_ch_switch_req_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+		case TDLS_CHANNEL_SWITCH_RESPONSE:
+			rtw_build_tdls_ch_switch_rsp_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+#endif			
+		case TDLS_PEER_TRAFFIC_RESPONSE:
+			rtw_build_tdls_peer_traffic_rsp_ies(padapter, pxmitframe, pframe, ptxmgmt);
+			break;
+#ifdef CONFIG_WFD			
+		case TUNNELED_PROBE_REQ:
+			rtw_build_tunneled_probe_req_ies(padapter, pxmitframe, pframe);
+			break;
+		case TUNNELED_PROBE_RSP:
+			rtw_build_tunneled_probe_rsp_ies(padapter, pxmitframe, pframe);
+			break;
+#endif //CONFIG_WFD
+		default:
+			res=_FAIL;
+			break;
+	}
+
+	return res;
+}
+
+s32 rtw_make_tdls_wlanhdr (_adapter *padapter , u8 *hdr, struct pkt_attrib *pattrib, struct tdls_txmgmt *ptxmgmt)
+{
+	u16 *qc;
+	struct rtw_ieee80211_hdr *pwlanhdr = (struct rtw_ieee80211_hdr *)hdr;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	struct qos_priv *pqospriv = &pmlmepriv->qospriv;
+	struct sta_priv 	*pstapriv = &padapter->stapriv;
+	struct sta_info *psta=NULL, *ptdls_sta=NULL;
+	u8 tdls_seq=0, baddr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+	sint res = _SUCCESS;
+	u16 *fctrl = &pwlanhdr->frame_ctl;
+
+_func_enter_;
+
+	_rtw_memset(hdr, 0, WLANHDR_OFFSET);
+
+	SetFrameSubType(fctrl, pattrib->subtype);
+
+	switch(ptxmgmt->action_code){
+		case TDLS_SETUP_REQUEST:
+		case TDLS_SETUP_RESPONSE:
+		case TDLS_SETUP_CONFIRM:
+		case TDLS_PEER_TRAFFIC_INDICATION:
+	case TDLS_PEER_PSM_REQUEST:
+		case TUNNELED_PROBE_REQ:
+		case TUNNELED_PROBE_RSP:
+		case TDLS_DISCOVERY_REQUEST:
+			SetToDs(fctrl);
+			_rtw_memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
+			break;
+		case TDLS_CHANNEL_SWITCH_REQUEST:
+		case TDLS_CHANNEL_SWITCH_RESPONSE:
+		case TDLS_PEER_PSM_RESPONSE:
+		case TDLS_PEER_TRAFFIC_RESPONSE:
+			_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+			_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
+			tdls_seq=1;
+			break;
+		case TDLS_TEARDOWN:
+			if(ptxmgmt->status_code == _RSON_TDLS_TEAR_UN_RSN_)
+			{
+				_rtw_memcpy(pwlanhdr->addr1, pattrib->dst, ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr3, get_bssid(pmlmepriv), ETH_ALEN);
+				tdls_seq=1;
+			}
+			else
+			{
+				SetToDs(fctrl);		
+				_rtw_memcpy(pwlanhdr->addr1, get_bssid(pmlmepriv), ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr2, pattrib->src, ETH_ALEN);
+				_rtw_memcpy(pwlanhdr->addr3, pattrib->dst, ETH_ALEN);
+			}
+			break;
+	}
+
+	if (pattrib->encrypt)
+		SetPrivacy(fctrl);
+
+	if(ptxmgmt->action_code == TDLS_PEER_TRAFFIC_RESPONSE)
+	{
+		SetPwrMgt(fctrl);
+	}
+
+	if (pqospriv->qos_option)
+	{
+		qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
+		if (pattrib->priority)
+			SetPriority(qc, pattrib->priority);
+		SetAckpolicy(qc, pattrib->ack_policy);
+	}
+
+	psta = pattrib->psta;
+ 
+	//  1. update seq_num per link by sta_info
+	//  2. rewrite encrypt to _AES_, also rewrite iv_len, icv_len
+	if(tdls_seq==1){
+		ptdls_sta=rtw_get_stainfo(pstapriv, pattrib->dst);
+		if(ptdls_sta){
+			ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
+			ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
+			pattrib->seqnum = ptdls_sta->sta_xmitpriv.txseq_tid[pattrib->priority];
+			SetSeqNum(hdr, pattrib->seqnum);
+
+			if (pattrib->encrypt){
+				pattrib->encrypt= _AES_;
+				pattrib->iv_len=8;
+				pattrib->icv_len=8;
+				pattrib->bswenc = _FALSE;
+			}
+			pattrib->mac_id = ptdls_sta->mac_id;
+		}else{
+			res=_FAIL;
+			goto exit;
+		}
+	}else if(psta){
+		psta->sta_xmitpriv.txseq_tid[pattrib->priority]++;
+		psta->sta_xmitpriv.txseq_tid[pattrib->priority] &= 0xFFF;
+		pattrib->seqnum = psta->sta_xmitpriv.txseq_tid[pattrib->priority];
+		SetSeqNum(hdr, pattrib->seqnum);
+	}
+
+
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+s32 rtw_xmit_tdls_coalesce(_adapter * padapter, struct xmit_frame * pxmitframe, struct tdls_txmgmt *ptxmgmt)
+{
+	s32 llc_sz;
+
+	u8 *pframe, *mem_start;
+
+	struct sta_info		*psta;
+	struct sta_priv		*pstapriv = &padapter->stapriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	u8 *pbuf_start;
+	s32 bmcst = IS_MCAST(pattrib->ra);
+	s32 res = _SUCCESS;
+	
+_func_enter_;
+
+	if (pattrib->psta) {
+		psta = pattrib->psta;
+	} else {	
+		if(bmcst) {
+			psta = rtw_get_bcmc_stainfo(padapter);
+		} else {
+			psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	        }
+	}
+
+	if (psta==NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	if (pxmitframe->buf_addr == NULL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pbuf_start = pxmitframe->buf_addr;
+	mem_start = pbuf_start + TXDESC_OFFSET;
+
+	if (rtw_make_tdls_wlanhdr(padapter, mem_start, pattrib, ptxmgmt) == _FAIL) {
+		res = _FAIL;
+		goto exit;
+	}
+
+	pframe = mem_start;
+	pframe += pattrib->hdrlen;
+
+	//adding icv, if necessary...
+	if (pattrib->iv_len)
+	{
+		if (psta != NULL)
+		{
+			switch(pattrib->encrypt)
+			{
+				case _WEP40_:
+				case _WEP104_:
+						WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);	
+					break;
+				case _TKIP_:			
+					if(bmcst)
+						TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+					else
+						TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+					break;			
+				case _AES_:
+					if(bmcst)
+						AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+					else
+						AES_IV(pattrib->iv, psta->dot11txpn, 0);
+					break;
+			}
+		}
+
+		_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len);
+		pframe += pattrib->iv_len;
+
+	}
+
+	llc_sz = rtw_put_snap(pframe, pattrib->ether_type);
+	pframe += llc_sz;
+
+	//pattrib->pktlen will be counted in rtw_build_tdls_ies
+	pattrib->pktlen = 0;
+
+	rtw_build_tdls_ies(padapter, pxmitframe, pframe, ptxmgmt);
+
+	if ((pattrib->icv_len >0 )&& (pattrib->bswenc)) {
+		pframe += pattrib->pktlen;
+		_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len); 
+		pframe += pattrib->icv_len;
+	}
+
+	pattrib->nr_frags = 1;
+	pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + llc_sz + 
+			((pattrib->bswenc) ? pattrib->icv_len : 0) + pattrib->pktlen;
+	
+	if (xmitframe_addmic(padapter, pxmitframe) == _FAIL)
+	{
+		res = _FAIL;
+		goto exit;
+	}
+
+	xmitframe_swencrypt(padapter, pxmitframe);
+	
+	update_attrib_vcs_info(padapter, pxmitframe);
+	
+exit:	
+	
+_func_exit_;	
+
+	return res;
+}
+#endif //CONFIG_TDLS
+
+/*
+ * Calculate wlan 802.11 packet MAX size from pkt_attrib
+ * This function doesn't consider fragment case
+ */
+u32 rtw_calculate_wlan_pkt_size_by_attribue(struct pkt_attrib *pattrib)
+{
+	u32	len = 0;
+
+	len = pattrib->hdrlen + pattrib->iv_len; // WLAN Header and IV
+	len += SNAP_SIZE + sizeof(u16); // LLC
+	len += pattrib->pktlen;
+	if (pattrib->encrypt == _TKIP_) len += 8; // MIC
+	len += ((pattrib->bswenc) ? pattrib->icv_len : 0); // ICV
+
+	return len;
+}
+
+/*
+
+This sub-routine will perform all the following:
+
+1. remove 802.3 header.
+2. create wlan_header, based on the info in pxmitframe
+3. append sta's iv/ext-iv
+4. append LLC
+5. move frag chunk from pframe to pxmitframe->mem
+6. apply sw-encrypt, if necessary. 
+
+*/
+s32 rtw_xmitframe_coalesce(_adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)
+{
+	struct pkt_file pktfile;
+
+	s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
+
+	SIZE_PTR addr;
+
+	u8 *pframe, *mem_start;
+	u8 hw_hdr_offset;
+
+	//struct sta_info		*psta;
+	//struct sta_priv		*pstapriv = &padapter->stapriv;
+	//struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+
+	u8 *pbuf_start;
+
+	s32 bmcst = IS_MCAST(pattrib->ra);
+	s32 res = _SUCCESS;
+
+_func_enter_;
+
+/*
+	if (pattrib->psta)
+	{
+		psta = pattrib->psta;
+	} else
+	{	
+		DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+		psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	}
+
+	if(psta==NULL)
+        {
+		
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return _FAIL;
+	}
+
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return _FAIL;
+	}
+*/
+	if (pxmitframe->buf_addr == NULL){
+		DBG_8192C("==> %s buf_addr==NULL \n",__FUNCTION__);
+		return _FAIL;
+	}
+
+	pbuf_start = pxmitframe->buf_addr;
+	
+#ifdef CONFIG_USB_TX_AGGREGATION
+	hw_hdr_offset =  TXDESC_SIZE + (pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
+#else
+	#ifdef CONFIG_TX_EARLY_MODE //for SDIO && Tx Agg
+	hw_hdr_offset = TXDESC_OFFSET + EARLY_MODE_INFO_SIZE;
+	#else
+	hw_hdr_offset = TXDESC_OFFSET;
+	#endif
+#endif
+
+	mem_start = pbuf_start +	hw_hdr_offset;
+
+	if (rtw_make_wlanhdr(padapter, mem_start, pattrib) == _FAIL) {
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n"));
+		DBG_8192C("rtw_xmitframe_coalesce: rtw_make_wlanhdr fail; drop pkt\n");
+		res = _FAIL;
+		goto exit;
+	}
+
+	_rtw_open_pktfile(pkt, &pktfile);
+	_rtw_pktfile_read(&pktfile, NULL, pattrib->pkt_hdrlen);
+
+	frg_inx = 0;
+	frg_len = pxmitpriv->frag_len - 4;//2346-4 = 2342
+
+	while (1)
+	{
+		llc_sz = 0;
+
+		mpdu_len = frg_len;
+
+		pframe = mem_start;
+
+		SetMFrag(mem_start);
+
+		pframe += pattrib->hdrlen;
+		mpdu_len -= pattrib->hdrlen;
+
+		//adding icv, if necessary...
+		if (pattrib->iv_len)
+		{
+/*		
+			//if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
+			//	psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
+			//else
+			//	psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+
+			if (psta != NULL)
+			{
+				switch(pattrib->encrypt)
+				{
+					case _WEP40_:
+					case _WEP104_:
+							WEP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);	
+						break;
+					case _TKIP_:			
+						if(bmcst)
+							TKIP_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+						else
+							TKIP_IV(pattrib->iv, psta->dot11txpn, 0);
+						break;			
+					case _AES_:
+						if(bmcst)
+							AES_IV(pattrib->iv, psta->dot11txpn, pattrib->key_idx);
+						else
+							AES_IV(pattrib->iv, psta->dot11txpn, 0);
+						break;
+#ifdef CONFIG_WAPI_SUPPORT
+					case _SMS4_:
+						rtw_wapi_get_iv(padapter,pattrib->ra,pattrib->iv);
+						break;
+#endif
+				}
+			}
+*/
+			_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len);
+
+			RT_TRACE(_module_rtl871x_xmit_c_, _drv_notice_,
+				 ("rtw_xmitframe_coalesce: keyid=%d pattrib->iv[3]=%.2x pframe=%.2x %.2x %.2x %.2x\n",
+				  padapter->securitypriv.dot11PrivacyKeyIndex, pattrib->iv[3], *pframe, *(pframe+1), *(pframe+2), *(pframe+3)));
+
+			pframe += pattrib->iv_len;
+
+			mpdu_len -= pattrib->iv_len;
+		}
+
+		if (frg_inx == 0) {
+			llc_sz = rtw_put_snap(pframe, pattrib->ether_type);
+			pframe += llc_sz;
+			mpdu_len -= llc_sz;
+		}
+
+		if ((pattrib->icv_len >0) && (pattrib->bswenc)) {
+			mpdu_len -= pattrib->icv_len;
+		}
+
+
+		if (bmcst) {
+			// don't do fragment to broadcat/multicast packets
+			mem_sz = _rtw_pktfile_read(&pktfile, pframe, pattrib->pktlen);
+		} else {
+			mem_sz = _rtw_pktfile_read(&pktfile, pframe, mpdu_len);
+		}
+
+		pframe += mem_sz;
+
+		if ((pattrib->icv_len >0 )&& (pattrib->bswenc)) {
+			_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len); 
+			pframe += pattrib->icv_len;
+		}
+
+		frg_inx++;
+
+		if (bmcst || (rtw_endofpktfile(&pktfile) == _TRUE))
+		{
+			pattrib->nr_frags = frg_inx;
+
+			pattrib->last_txcmdsz = pattrib->hdrlen + pattrib->iv_len + ((pattrib->nr_frags==1)? llc_sz:0) + 
+					((pattrib->bswenc) ? pattrib->icv_len : 0) + mem_sz;
+			
+			ClearMFrag(mem_start);
+
+			break;
+		} else {
+			RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("%s: There're still something in packet!\n", __FUNCTION__));
+		}
+
+		addr = (SIZE_PTR)(pframe);
+
+		mem_start = (unsigned char *)RND4(addr) + hw_hdr_offset;
+		_rtw_memcpy(mem_start, pbuf_start + hw_hdr_offset, pattrib->hdrlen);	
+		
+	}
+
+	if (xmitframe_addmic(padapter, pxmitframe) == _FAIL)
+	{
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("xmitframe_addmic(padapter, pxmitframe)==_FAIL\n"));
+		DBG_8192C("xmitframe_addmic(padapter, pxmitframe)==_FAIL\n");
+		res = _FAIL;
+		goto exit;
+	}
+
+	xmitframe_swencrypt(padapter, pxmitframe);
+
+	if(bmcst == _FALSE)
+		update_attrib_vcs_info(padapter, pxmitframe);
+	else
+		pattrib->vcs_mode = NONE_VCS;
+
+exit:	
+	
+_func_exit_;	
+
+	return res;
+}
+
+#ifdef CONFIG_IEEE80211W
+//broadcast or multicast management pkt use BIP, unicast management pkt use CCMP encryption
+s32 rtw_mgmt_xmitframe_coalesce(_adapter *padapter, _pkt *pkt, struct xmit_frame *pxmitframe)
+{
+	struct pkt_file pktfile;
+	s32 frg_inx, frg_len, mpdu_len, llc_sz, mem_sz;
+	SIZE_PTR addr;
+	u8 *pframe, *mem_start = NULL, *tmp_buf=NULL;
+	u8 hw_hdr_offset, subtype ;
+	struct sta_info		*psta = NULL;
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	u8 *pbuf_start;
+	s32 bmcst = IS_MCAST(pattrib->ra);
+	s32 res = _FAIL;
+	u8 *BIP_AAD=NULL;
+	u8 *MGMT_body=NULL;
+	
+	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	struct rtw_ieee80211_hdr	*pwlanhdr;
+	u8 MME[_MME_IE_LENGTH_];
+	
+	_irqL irqL;
+	u32	ori_len;
+	mem_start = pframe = (u8 *)(pxmitframe->buf_addr) + TXDESC_OFFSET;
+	pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+	
+_func_enter_;
+	ori_len = BIP_AAD_SIZE+pattrib->pktlen;
+	tmp_buf = BIP_AAD = rtw_zmalloc(ori_len);
+	subtype = GetFrameSubType(pframe); //bit(7)~bit(2)
+	
+	if(BIP_AAD == NULL)
+		return _FAIL;
+			
+	_enter_critical_bh(&padapter->security_key_mutex, &irqL);
+	
+	
+	//IGTK key is not install, it may not support 802.11w
+	if(padapter->securitypriv.binstallBIPkey != _TRUE)
+	{
+		DBG_871X("no instll BIP key\n");
+		goto xmitframe_coalesce_success;
+	}
+	//station mode doesn't need TX BIP, just ready the code
+	if(bmcst)
+	{
+		int frame_body_len;
+		u8 mic[16];
+		
+		_rtw_memset(MME, 0, _MME_IE_LENGTH_);
+				
+		//other types doesn't need the BIP
+		if(GetFrameSubType(pframe) != WIFI_DEAUTH && GetFrameSubType(pframe) != WIFI_DISASSOC)
+			goto xmitframe_coalesce_fail;
+		
+		MGMT_body = pframe + sizeof(struct rtw_ieee80211_hdr_3addr);
+		pframe += pattrib->pktlen;
+		
+		//octent 0 and 1 is key index ,BIP keyid is 4 or 5, LSB only need octent 0
+		MME[0]=padapter->securitypriv.dot11wBIPKeyid;
+		//copy packet number
+		_rtw_memcpy(&MME[2], &pmlmeext->mgnt_80211w_IPN, 6);
+		//increase the packet number
+		pmlmeext->mgnt_80211w_IPN++;
+		
+		//add MME IE with MIC all zero, MME string doesn't include element id and length
+		pframe = rtw_set_ie(pframe, _MME_IE_ , 16 , MME, &(pattrib->pktlen));
+		pattrib->last_txcmdsz = pattrib->pktlen;
+		// total frame length - header length
+		frame_body_len = pattrib->pktlen - sizeof(struct rtw_ieee80211_hdr_3addr);
+		
+		//conscruct AAD, copy frame control field
+		_rtw_memcpy(BIP_AAD, &pwlanhdr->frame_ctl, 2);
+		ClearRetry(BIP_AAD);
+		ClearPwrMgt(BIP_AAD);
+		ClearMData(BIP_AAD);
+		//conscruct AAD, copy address 1 to address 3
+		_rtw_memcpy(BIP_AAD+2, pwlanhdr->addr1, 18);
+		//copy management fram body
+		_rtw_memcpy(BIP_AAD+BIP_AAD_SIZE, MGMT_body, frame_body_len);
+		/*//dump total packet include MME with zero MIC
+		{
+			int i;
+			printk("Total packet: ");
+			for(i=0; i < BIP_AAD_SIZE+frame_body_len; i++)
+				printk(" %02x ", BIP_AAD[i]);
+			printk("\n");
+		}*/
+		//calculate mic
+		if(omac1_aes_128(padapter->securitypriv.dot11wBIPKey[padapter->securitypriv.dot11wBIPKeyid].skey
+			, BIP_AAD, BIP_AAD_SIZE+frame_body_len, mic))
+			goto xmitframe_coalesce_fail;
+		
+		/*//dump calculated mic result
+		{
+			int i;
+			printk("Calculated mic result: ");
+			for(i=0; i<16; i++)
+				printk(" %02x ", mic[i]);
+			printk("\n");
+		}*/
+		//copy right BIP mic value, total is 128bits, we use the 0~63 bits
+		_rtw_memcpy(pframe-8, mic, 8);
+		/*/dump all packet after mic ok
+		{
+			int pp;
+			printk("pattrib->pktlen = %d \n", pattrib->pktlen);
+			for(pp=0;pp< pattrib->pktlen; pp++)
+				printk(" %02x ", mem_start[pp]);
+			printk("\n");
+		}*/
+	}
+	else //unicast mgmt frame TX
+	{
+		//start to encrypt mgmt frame
+		if(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC ||
+			subtype == WIFI_REASSOCREQ || subtype == WIFI_ACTION)
+		{
+			if (pattrib->psta)
+				psta = pattrib->psta;
+			else
+			{
+				psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+			}
+		
+			if(psta==NULL)
+			{
+				
+				DBG_871X("%s, psta==NUL\n", __func__);
+				goto xmitframe_coalesce_fail;
+			}
+		
+			if (pxmitframe->buf_addr == NULL) {
+				DBG_871X("%s, pxmitframe->buf_addr\n", __func__);
+				goto xmitframe_coalesce_fail;
+			}
+			
+			//DBG_871X("%s, action frame category=%d \n", __func__, pframe[WLAN_HDR_A3_LEN]);
+			//according 802.11-2012 standard, these five types are not robust types
+			if(subtype == WIFI_ACTION && 
+			(pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_PUBLIC ||
+			pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_HT ||
+			pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_UNPROTECTED_WNM ||
+			pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_SELF_PROTECTED  ||
+			pframe[WLAN_HDR_A3_LEN] == RTW_WLAN_CATEGORY_P2P))
+				goto xmitframe_coalesce_fail;
+			//before encrypt dump the management packet content
+			/*{
+				int i;
+				printk("Management pkt: ");
+				for(i=0; i<pattrib->pktlen; i++)
+				printk(" %02x ", pframe[i]);
+				printk("=======\n");
+			}*/
+			if(pattrib->encrypt>0)
+				_rtw_memcpy(pattrib->dot118021x_UncstKey.skey, psta->dot118021x_UncstKey.skey, 16);
+			
+			/* To use wrong key */
+			if (pattrib->key_type == IEEE80211W_WRONG_KEY) {
+				DBG_871X("use wrong key\n");
+				pattrib->dot118021x_UncstKey.skey[0] = 0xff;
+			}
+			
+			//bakeup original management packet
+			_rtw_memcpy(tmp_buf, pframe, pattrib->pktlen);
+			//move to data portion
+			pframe += pattrib->hdrlen;
+			
+			//802.11w unicast management packet must be _AES_
+			pattrib->iv_len = 8;
+			//it's MIC of AES
+			pattrib->icv_len = 8;
+			
+			switch(pattrib->encrypt)
+			{
+				case _AES_:
+						//set AES IV header
+						AES_IV(pattrib->iv, psta->dot11wtxpn, 0);
+					break;
+				default:
+					goto xmitframe_coalesce_fail;
+			}
+			//insert iv header into management frame
+			_rtw_memcpy(pframe, pattrib->iv, pattrib->iv_len);
+			pframe += pattrib->iv_len;
+			//copy mgmt data portion after CCMP header
+			_rtw_memcpy(pframe, tmp_buf+pattrib->hdrlen, pattrib->pktlen-pattrib->hdrlen);
+			//move pframe to end of mgmt pkt
+			pframe += pattrib->pktlen-pattrib->hdrlen;
+			//add 8 bytes CCMP IV header to length
+			pattrib->pktlen += pattrib->iv_len;
+			/*//dump management packet include AES IV header
+			{
+				int i;
+				printk("Management pkt + IV: ");
+				//for(i=0; i<pattrib->pktlen; i++)
+				//printk(" %02x ", mem_start[i]);
+				printk("@@@@@@@@@@@@@\n");
+			}*/
+			
+			if ((pattrib->icv_len >0 )&& (pattrib->bswenc)) {
+				_rtw_memcpy(pframe, pattrib->icv, pattrib->icv_len); 
+				pframe += pattrib->icv_len;
+			}
+			//add 8 bytes MIC
+			pattrib->pktlen += pattrib->icv_len;
+			//set final tx command size
+			pattrib->last_txcmdsz = pattrib->pktlen;
+	
+			//set protected bit must be beofre SW encrypt
+			SetPrivacy(mem_start);
+			/*//dump management packet include AES header
+			{
+				int i;
+				printk("prepare to enc Management pkt + IV: ");
+				for(i=0; i<pattrib->pktlen; i++)
+				printk(" %02x ", mem_start[i]);
+				printk("@@@@@@@@@@@@@\n");
+			}*/
+			//software encrypt
+			xmitframe_swencrypt(padapter, pxmitframe);
+		}
+	}
+
+xmitframe_coalesce_success:
+	_exit_critical_bh(&padapter->security_key_mutex, &irqL);
+	rtw_mfree(BIP_AAD, ori_len);
+_func_exit_;
+	return _SUCCESS;
+	
+xmitframe_coalesce_fail:
+	_exit_critical_bh(&padapter->security_key_mutex, &irqL);
+	rtw_mfree(BIP_AAD, ori_len);
+_func_exit_;
+
+	return _FAIL;
+}
+#endif //CONFIG_IEEE80211W
+
+/* Logical Link Control(LLC) SubNetwork Attachment Point(SNAP) header
+ * IEEE LLC/SNAP header contains 8 octets
+ * First 3 octets comprise the LLC portion
+ * SNAP portion, 5 octets, is divided into two fields:
+ *	Organizationally Unique Identifier(OUI), 3 octets,
+ *	type, defined by that organization, 2 octets.
+ */
+s32 rtw_put_snap(u8 *data, u16 h_proto)
+{
+	struct ieee80211_snap_hdr *snap;
+	u8 *oui;
+
+_func_enter_;
+
+	snap = (struct ieee80211_snap_hdr *)data;
+	snap->dsap = 0xaa;
+	snap->ssap = 0xaa;
+	snap->ctrl = 0x03;
+
+	if (h_proto == 0x8137 || h_proto == 0x80f3)
+		oui = P802_1H_OUI;
+	else
+		oui = RFC1042_OUI;
+	
+	snap->oui[0] = oui[0];
+	snap->oui[1] = oui[1];
+	snap->oui[2] = oui[2];
+
+	*(u16 *)(data + SNAP_SIZE) = htons(h_proto);
+
+_func_exit_;
+
+	return SNAP_SIZE + sizeof(u16);
+}
+
+void rtw_update_protection(_adapter *padapter, u8 *ie, uint ie_len)
+{
+
+	uint	protection;
+	u8	*perp;
+	sint	 erp_len;
+	struct	xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct	registry_priv *pregistrypriv = &padapter->registrypriv;
+	
+_func_enter_;
+	
+	switch(pxmitpriv->vcs_setting)
+	{
+		case DISABLE_VCS:
+			pxmitpriv->vcs = NONE_VCS;
+			break;
+	
+		case ENABLE_VCS:
+			break;
+	
+		case AUTO_VCS:
+		default:
+			perp = rtw_get_ie(ie, _ERPINFO_IE_, &erp_len, ie_len);
+			if(perp == NULL)
+			{
+				pxmitpriv->vcs = NONE_VCS;
+			}
+			else
+			{
+				protection = (*(perp + 2)) & BIT(1);
+				if (protection)
+				{
+					if(pregistrypriv->vcs_type == RTS_CTS)
+						pxmitpriv->vcs = RTS_CTS;
+					else
+						pxmitpriv->vcs = CTS_TO_SELF;
+				}
+				else
+					pxmitpriv->vcs = NONE_VCS;
+			}
+
+			break;			
+	
+	}
+
+_func_exit_;
+
+}
+
+void rtw_count_tx_stats(PADAPTER padapter, struct xmit_frame *pxmitframe, int sz)
+{
+	struct sta_info *psta = NULL;
+	struct stainfo_stats *pstats = NULL;
+	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	u8	pkt_num = 1;
+
+	if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG)
+	{
+#if defined(CONFIG_USB_TX_AGGREGATION) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pkt_num = pxmitframe->agg_num;
+#endif
+		pmlmepriv->LinkDetectInfo.NumTxOkInPeriod += pkt_num;
+
+		pxmitpriv->tx_pkts += pkt_num;
+
+		pxmitpriv->tx_bytes += sz;
+
+		psta = pxmitframe->attrib.psta;
+		if (psta)
+		{
+			pstats = &psta->sta_stats;
+
+			pstats->tx_pkts += pkt_num;
+
+			pstats->tx_bytes += sz;
+#ifdef CONFIG_TDLS
+			if(pxmitframe->attrib.ptdls_sta != NULL)
+			{
+				pstats = &(pxmitframe->attrib.ptdls_sta->sta_stats);
+				pstats->tx_pkts += pkt_num;
+				pstats->tx_bytes += sz;
+			}
+#endif //CONFIG_TDLS
+		}
+		
+#ifdef CONFIG_CHECK_LEAVE_LPS
+		//traffic_check_for_leave_lps(padapter, _TRUE);
+#endif //CONFIG_LPS
+		
+	}
+}
+
+static struct xmit_buf *__rtw_alloc_cmd_xmitbuf(struct xmit_priv *pxmitpriv,
+		enum cmdbuf_type buf_type)
+{
+	struct xmit_buf *pxmitbuf =  NULL;
+
+_func_enter_;
+
+	pxmitbuf = &pxmitpriv->pcmd_xmitbuf[buf_type];
+	if (pxmitbuf !=  NULL) {
+		pxmitbuf->priv_data = NULL;
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxmitbuf->len = 0;
+		pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+		pxmitbuf->agg_num = 0;
+		pxmitbuf->pg_num = 0;
+#endif
+#ifdef CONFIG_PCI_HCI
+		pxmitbuf->len = 0;
+		pxmitbuf->desc = NULL;
+#endif
+
+		if (pxmitbuf->sctx) {
+			DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
+			rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
+		}
+	} else {
+		DBG_871X("%s fail, no xmitbuf available !!!\n", __func__);
+	}
+
+exit:
+
+_func_exit_;
+
+	return pxmitbuf;
+}
+
+struct xmit_frame *__rtw_alloc_cmdxmitframe(struct xmit_priv *pxmitpriv,
+		enum cmdbuf_type buf_type)
+{
+	struct xmit_frame		*pcmdframe;
+	struct xmit_buf		*pxmitbuf;
+
+	if ((pcmdframe = rtw_alloc_xmitframe(pxmitpriv)) == NULL)
+	{
+		DBG_871X("%s, alloc xmitframe fail\n", __FUNCTION__);
+		return NULL;
+	}
+
+	if ((pxmitbuf = __rtw_alloc_cmd_xmitbuf(pxmitpriv, buf_type)) == NULL) {
+		DBG_871X("%s, alloc xmitbuf fail\n", __FUNCTION__);
+		rtw_free_xmitframe(pxmitpriv, pcmdframe);
+		return NULL;
+	}
+
+	pcmdframe->frame_tag = MGNT_FRAMETAG;
+
+	pcmdframe->pxmitbuf = pxmitbuf;
+
+	pcmdframe->buf_addr = pxmitbuf->pbuf;
+
+	pxmitbuf->priv_data = pcmdframe;
+
+	return pcmdframe;
+
+}
+
+struct xmit_buf *rtw_alloc_xmitbuf_ext(struct xmit_priv *pxmitpriv)
+{
+	_irqL irqL;
+	struct xmit_buf *pxmitbuf =  NULL;
+	_list *plist, *phead;
+	_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
+
+_func_enter_;
+
+	_enter_critical(&pfree_queue->lock, &irqL);
+
+	if(_rtw_queue_empty(pfree_queue) == _TRUE) {
+		pxmitbuf = NULL;
+	} else {
+
+		phead = get_list_head(pfree_queue);
+
+		plist = get_next(phead);
+
+		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+
+		rtw_list_delete(&(pxmitbuf->list));
+	}
+
+	if (pxmitbuf !=  NULL)
+	{
+		pxmitpriv->free_xmit_extbuf_cnt--;
+		#ifdef DBG_XMIT_BUF_EXT
+		DBG_871X("DBG_XMIT_BUF_EXT ALLOC no=%d,  free_xmit_extbuf_cnt=%d\n",pxmitbuf->no, pxmitpriv->free_xmit_extbuf_cnt);
+		#endif
+		
+	
+		pxmitbuf->priv_data = NULL;
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxmitbuf->len = 0;
+		pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+		pxmitbuf->agg_num = 1;
+#endif
+#ifdef CONFIG_PCI_HCI
+		pxmitbuf->len = 0;
+		pxmitbuf->desc = NULL;
+#endif
+
+		if (pxmitbuf->sctx) {
+			DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
+			rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
+		}
+
+	}
+
+	_exit_critical(&pfree_queue->lock, &irqL);
+
+_func_exit_;
+
+	return pxmitbuf;
+}
+
+s32 rtw_free_xmitbuf_ext(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
+{
+	_irqL irqL;
+	_queue *pfree_queue = &pxmitpriv->free_xmit_extbuf_queue;
+
+_func_enter_;
+
+	if(pxmitbuf==NULL)
+	{
+		return _FAIL;
+	}
+
+	_enter_critical(&pfree_queue->lock, &irqL);
+
+	rtw_list_delete(&pxmitbuf->list);
+
+	rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_queue));
+	pxmitpriv->free_xmit_extbuf_cnt++;
+	#ifdef DBG_XMIT_BUF_EXT
+	DBG_871X("DBG_XMIT_BUF_EXT FREE no=%d, free_xmit_extbuf_cnt=%d\n",pxmitbuf->no ,pxmitpriv->free_xmit_extbuf_cnt);
+	#endif
+
+	_exit_critical(&pfree_queue->lock, &irqL);
+
+_func_exit_;
+
+	return _SUCCESS;
+} 
+
+struct xmit_buf *rtw_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
+{
+	_irqL irqL;
+	struct xmit_buf *pxmitbuf =  NULL;
+	_list *plist, *phead;
+	_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
+
+_func_enter_;
+
+	//DBG_871X("+rtw_alloc_xmitbuf\n");
+
+	_enter_critical(&pfree_xmitbuf_queue->lock, &irqL);
+
+	if(_rtw_queue_empty(pfree_xmitbuf_queue) == _TRUE) {
+		pxmitbuf = NULL;
+	} else {
+
+		phead = get_list_head(pfree_xmitbuf_queue);
+
+		plist = get_next(phead);
+
+		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+
+		rtw_list_delete(&(pxmitbuf->list));
+	}
+
+	if (pxmitbuf !=  NULL)
+	{
+		pxmitpriv->free_xmitbuf_cnt--;
+		#ifdef DBG_XMIT_BUF
+		DBG_871X("DBG_XMIT_BUF ALLOC no=%d,  free_xmitbuf_cnt=%d\n",pxmitbuf->no, pxmitpriv->free_xmitbuf_cnt);
+		#endif
+		//DBG_871X("alloc, free_xmitbuf_cnt=%d\n", pxmitpriv->free_xmitbuf_cnt);
+
+		pxmitbuf->priv_data = NULL;
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxmitbuf->len = 0;
+		pxmitbuf->pdata = pxmitbuf->ptail = pxmitbuf->phead;
+		pxmitbuf->agg_num = 0;
+		pxmitbuf->pg_num = 0;
+#endif
+#ifdef CONFIG_PCI_HCI
+		pxmitbuf->len = 0;
+		pxmitbuf->desc = NULL;
+#endif
+
+		if (pxmitbuf->sctx) {
+			DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
+			rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_ALLOC);
+		}
+	}
+	#ifdef DBG_XMIT_BUF
+	else
+	{
+		DBG_871X("DBG_XMIT_BUF rtw_alloc_xmitbuf return NULL\n");
+	}
+	#endif
+
+	_exit_critical(&pfree_xmitbuf_queue->lock, &irqL);
+
+_func_exit_;
+
+	return pxmitbuf;
+}
+
+s32 rtw_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
+{
+	_irqL irqL;
+	_queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
+
+_func_enter_;
+
+	//DBG_871X("+rtw_free_xmitbuf\n");
+
+	if(pxmitbuf==NULL)
+	{
+		return _FAIL;
+	}
+
+	if (pxmitbuf->sctx) {
+		DBG_871X("%s pxmitbuf->sctx is not NULL\n", __func__);
+		rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_BUF_FREE);
+	}
+
+	if(pxmitbuf->buf_tag == XMITBUF_CMD) {
+	}
+	else if(pxmitbuf->buf_tag == XMITBUF_MGNT) {
+		rtw_free_xmitbuf_ext(pxmitpriv, pxmitbuf);
+	}
+	else
+	{
+		_enter_critical(&pfree_xmitbuf_queue->lock, &irqL);
+
+		rtw_list_delete(&pxmitbuf->list);	
+
+		rtw_list_insert_tail(&(pxmitbuf->list), get_list_head(pfree_xmitbuf_queue));
+
+		pxmitpriv->free_xmitbuf_cnt++;
+		//DBG_871X("FREE, free_xmitbuf_cnt=%d\n", pxmitpriv->free_xmitbuf_cnt);
+		#ifdef DBG_XMIT_BUF
+		DBG_871X("DBG_XMIT_BUF FREE no=%d, free_xmitbuf_cnt=%d\n",pxmitbuf->no ,pxmitpriv->free_xmitbuf_cnt);
+		#endif
+		_exit_critical(&pfree_xmitbuf_queue->lock, &irqL);
+	}
+
+_func_exit_;	 
+
+	return _SUCCESS;	
+} 
+
+void rtw_init_xmitframe(struct xmit_frame *pxframe)
+{
+	if (pxframe !=  NULL)//default value setting
+	{
+		pxframe->buf_addr = NULL;
+		pxframe->pxmitbuf = NULL;
+
+		_rtw_memset(&pxframe->attrib, 0, sizeof(struct pkt_attrib));
+		//pxframe->attrib.psta = NULL;
+
+		pxframe->frame_tag = DATA_FRAMETAG;
+
+#ifdef CONFIG_USB_HCI
+		pxframe->pkt = NULL;
+#ifdef USB_PACKET_OFFSET_SZ
+		pxframe->pkt_offset = (PACKET_OFFSET_SZ/8);
+#else
+		pxframe->pkt_offset = 1;//default use pkt_offset to fill tx desc
+#endif
+
+#ifdef CONFIG_USB_TX_AGGREGATION
+		pxframe->agg_num = 1;
+#endif
+
+#endif //#ifdef CONFIG_USB_HCI
+
+#if defined(CONFIG_SDIO_HCI) || defined(CONFIG_GSPI_HCI)
+		pxframe->pg_num = 1;
+		pxframe->agg_num = 1;
+#endif
+
+#ifdef CONFIG_XMIT_ACK
+		pxframe->ack_report = 0;
+#endif
+
+	}
+}
+
+/*
+Calling context:
+1. OS_TXENTRY
+2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
+
+If we turn on USE_RXTHREAD, then, no need for critical section.
+Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
+
+Must be very very cautious...
+
+*/
+struct xmit_frame *rtw_alloc_xmitframe(struct xmit_priv *pxmitpriv)//(_queue *pfree_xmit_queue)
+{
+	/*
+		Please remember to use all the osdep_service api,
+		and lock/unlock or _enter/_exit critical to protect 
+		pfree_xmit_queue
+	*/
+
+	_irqL irqL;
+	struct xmit_frame *pxframe = NULL;
+	_list *plist, *phead;
+	_queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
+
+_func_enter_;
+
+	_enter_critical_bh(&pfree_xmit_queue->lock, &irqL);
+
+	if (_rtw_queue_empty(pfree_xmit_queue) == _TRUE) {
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_alloc_xmitframe:%d\n", pxmitpriv->free_xmitframe_cnt));
+		pxframe =  NULL;
+	} else {
+		phead = get_list_head(pfree_xmit_queue);
+
+		plist = get_next(phead);
+
+		pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+		rtw_list_delete(&(pxframe->list));
+		pxmitpriv->free_xmitframe_cnt--;
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe():free_xmitframe_cnt=%d\n", pxmitpriv->free_xmitframe_cnt));
+	}
+
+	_exit_critical_bh(&pfree_xmit_queue->lock, &irqL);
+
+	rtw_init_xmitframe(pxframe);
+
+_func_exit_;
+
+	return pxframe;
+}
+
+struct xmit_frame *rtw_alloc_xmitframe_ext(struct xmit_priv *pxmitpriv)
+{
+	_irqL irqL;
+	struct xmit_frame *pxframe = NULL;
+	_list *plist, *phead;
+	_queue *queue = &pxmitpriv->free_xframe_ext_queue;
+
+_func_enter_;
+
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	if (_rtw_queue_empty(queue) == _TRUE) {
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_alloc_xmitframe_ext:%d\n", pxmitpriv->free_xframe_ext_cnt));
+		pxframe =  NULL;
+	} else {
+		phead = get_list_head(queue);
+		plist = get_next(phead);
+		pxframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+		rtw_list_delete(&(pxframe->list));
+		pxmitpriv->free_xframe_ext_cnt--;
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_alloc_xmitframe_ext():free_xmitframe_cnt=%d\n", pxmitpriv->free_xframe_ext_cnt));
+	}
+
+	_exit_critical_bh(&queue->lock, &irqL);
+
+	rtw_init_xmitframe(pxframe);
+
+_func_exit_;
+
+	return pxframe;
+}
+
+struct xmit_frame *rtw_alloc_xmitframe_once(struct xmit_priv *pxmitpriv)
+{
+	struct xmit_frame *pxframe = NULL;
+	u8 *alloc_addr;
+
+	alloc_addr = rtw_zmalloc(sizeof(struct xmit_frame) + 4);
+	
+	if (alloc_addr == NULL)
+		goto exit;
+		
+	pxframe = (struct xmit_frame *)N_BYTE_ALIGMENT((SIZE_PTR)(alloc_addr), 4);
+	pxframe->alloc_addr = alloc_addr;
+
+	pxframe->padapter = pxmitpriv->adapter;
+	pxframe->frame_tag = NULL_FRAMETAG;
+
+	pxframe->pkt = NULL;
+
+	pxframe->buf_addr = NULL;
+	pxframe->pxmitbuf = NULL;
+
+	rtw_init_xmitframe(pxframe);
+
+	DBG_871X("################## %s ##################\n", __func__);
+
+exit:
+	return pxframe;
+}
+
+s32 rtw_free_xmitframe(struct xmit_priv *pxmitpriv, struct xmit_frame *pxmitframe)
+{	
+	_irqL irqL;
+	_queue *queue = NULL;
+	_adapter *padapter = pxmitpriv->adapter;
+	_pkt *pndis_pkt = NULL;
+
+_func_enter_;	
+
+	if (pxmitframe == NULL) {
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_, ("======rtw_free_xmitframe():pxmitframe==NULL!!!!!!!!!!\n"));
+		goto exit;
+	}
+
+	if (pxmitframe->pkt){
+		pndis_pkt = pxmitframe->pkt;
+		pxmitframe->pkt = NULL;
+	}
+
+	if (pxmitframe->alloc_addr) {
+		DBG_871X("################## %s with alloc_addr ##################\n", __func__);
+		rtw_mfree(pxmitframe->alloc_addr, sizeof(struct xmit_frame) + 4);
+		goto check_pkt_complete;
+	}
+
+	if (pxmitframe->ext_tag == 0)
+		queue = &pxmitpriv->free_xmit_queue;
+	else if(pxmitframe->ext_tag == 1)
+		queue = &pxmitpriv->free_xframe_ext_queue;
+	else
+		rtw_warn_on(1);
+
+	_enter_critical_bh(&queue->lock, &irqL);
+
+	rtw_list_delete(&pxmitframe->list);	
+	rtw_list_insert_tail(&pxmitframe->list, get_list_head(queue));
+	if (pxmitframe->ext_tag == 0) {
+		pxmitpriv->free_xmitframe_cnt++;
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe():free_xmitframe_cnt=%d\n", pxmitpriv->free_xmitframe_cnt));
+	} else if(pxmitframe->ext_tag == 1) {
+		pxmitpriv->free_xframe_ext_cnt++;
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_debug_, ("rtw_free_xmitframe():free_xframe_ext_cnt=%d\n", pxmitpriv->free_xframe_ext_cnt));
+	} else {
+	}
+
+	_exit_critical_bh(&queue->lock, &irqL);
+
+check_pkt_complete:
+
+	if(pndis_pkt)
+		rtw_os_pkt_complete(padapter, pndis_pkt);
+
+exit:
+
+_func_exit_;
+
+	return _SUCCESS;
+}
+
+void rtw_free_xmitframe_queue(struct xmit_priv *pxmitpriv, _queue *pframequeue)
+{
+	_irqL irqL;
+	_list	*plist, *phead;
+	struct	xmit_frame 	*pxmitframe;
+
+_func_enter_;	
+
+	_enter_critical_bh(&(pframequeue->lock), &irqL);
+
+	phead = get_list_head(pframequeue);
+	plist = get_next(phead);
+	
+	while (rtw_end_of_queue_search(phead, plist) == _FALSE)
+	{
+			
+		pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+		plist = get_next(plist); 
+		
+		rtw_free_xmitframe(pxmitpriv,pxmitframe);
+			
+	}
+	_exit_critical_bh(&(pframequeue->lock), &irqL);
+
+_func_exit_;
+}
+
+s32 rtw_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	DBG_COUNTER(padapter->tx_logs.core_tx_enqueue);
+	if (rtw_xmit_classifier(padapter, pxmitframe) == _FAIL)
+	{
+		RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
+			 ("rtw_xmitframe_enqueue: drop xmit pkt for classifier fail\n"));
+//		pxmitframe->pkt = NULL;
+		return _FAIL;
+	}
+
+	return _SUCCESS;
+}
+
+static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit, struct tx_servq *ptxservq, _queue *pframe_queue)
+{
+	_list	*xmitframe_plist, *xmitframe_phead;
+	struct	xmit_frame	*pxmitframe=NULL;
+
+	xmitframe_phead = get_list_head(pframe_queue);
+	xmitframe_plist = get_next(xmitframe_phead);
+
+	while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+	{
+		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+		/* xmitframe_plist = get_next(xmitframe_plist); */
+
+/*#ifdef RTK_DMP_PLATFORM
+#ifdef CONFIG_USB_TX_AGGREGATION
+		if((ptxservq->qcnt>0) && (ptxservq->qcnt<=2))
+		{
+			pxmitframe = NULL;
+
+			tasklet_schedule(&pxmitpriv->xmit_tasklet);
+
+			break;
+		}
+#endif
+#endif*/
+		rtw_list_delete(&pxmitframe->list);
+
+		ptxservq->qcnt--;
+
+		//rtw_list_insert_tail(&pxmitframe->list, &phwxmit->pending);
+
+		//ptxservq->qcnt--;
+
+		break;		
+
+		//pxmitframe = NULL;
+
+	}
+
+	return pxmitframe;
+}
+
+struct xmit_frame* rtw_dequeue_xframe(struct xmit_priv *pxmitpriv, struct hw_xmit *phwxmit_i, sint entry)
+{
+	_irqL irqL0;
+	_list *sta_plist, *sta_phead;
+	struct hw_xmit *phwxmit;
+	struct tx_servq *ptxservq = NULL;
+	_queue *pframe_queue = NULL;
+	struct xmit_frame *pxmitframe = NULL;
+	_adapter *padapter = pxmitpriv->adapter;
+	struct registry_priv	*pregpriv = &padapter->registrypriv;
+	int i, inx[4];
+#ifdef CONFIG_USB_HCI
+//	int j, tmp, acirp_cnt[4];
+#endif
+
+_func_enter_;
+
+	inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
+
+	if(pregpriv->wifi_spec==1)
+	{
+		int j, tmp, acirp_cnt[4];
+#if 0
+		if(flags<XMIT_QUEUE_ENTRY)
+		{
+			//priority exchange according to the completed xmitbuf flags.
+			inx[flags] = 0;
+			inx[0] = flags;
+		}
+#endif	
+	
+#if defined(CONFIG_USB_HCI) || defined(CONFIG_SDIO_HCI) || defined(CONFIG_PCI_HCI)
+		for(j=0; j<4; j++)
+			inx[j] = pxmitpriv->wmm_para_seq[j];
+#endif
+	}
+
+	_enter_critical_bh(&pxmitpriv->lock, &irqL0);
+
+	for(i = 0; i < entry; i++) 
+	{
+		phwxmit = phwxmit_i + inx[i];
+
+		//_enter_critical_ex(&phwxmit->sta_queue->lock, &irqL0);
+
+		sta_phead = get_list_head(phwxmit->sta_queue);
+		sta_plist = get_next(sta_phead);
+
+		while ((rtw_end_of_queue_search(sta_phead, sta_plist)) == _FALSE)
+		{
+
+			ptxservq= LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
+
+			pframe_queue = &ptxservq->sta_pending;
+
+			pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq, pframe_queue);
+
+			if(pxmitframe)
+			{
+				phwxmit->accnt--;
+
+				//Remove sta node when there is no pending packets.
+				if(_rtw_queue_empty(pframe_queue)) //must be done after get_next and before break
+					rtw_list_delete(&ptxservq->tx_pending);
+
+				//_exit_critical_ex(&phwxmit->sta_queue->lock, &irqL0);
+
+				goto exit;
+			}
+
+			sta_plist = get_next(sta_plist);
+
+		}
+
+		//_exit_critical_ex(&phwxmit->sta_queue->lock, &irqL0);
+
+	}
+
+exit:
+
+	_exit_critical_bh(&pxmitpriv->lock, &irqL0);
+
+_func_exit_;
+
+	return pxmitframe;
+}
+
+#if 1
+struct tx_servq *rtw_get_sta_pending(_adapter *padapter, struct sta_info *psta, sint up, u8 *ac)
+{
+	struct tx_servq *ptxservq=NULL;
+	
+_func_enter_;	
+
+	switch (up) 
+	{
+		case 1:
+		case 2:
+			ptxservq = &(psta->sta_xmitpriv.bk_q);
+			*(ac) = 3;
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : BK \n"));
+			break;
+
+		case 4:
+		case 5:
+			ptxservq = &(psta->sta_xmitpriv.vi_q);
+			*(ac) = 1;
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : VI\n"));
+			break;
+
+		case 6:
+		case 7:
+			ptxservq = &(psta->sta_xmitpriv.vo_q);
+			*(ac) = 0;
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : VO \n"));			
+			break;
+
+		case 0:
+		case 3:
+		default:
+			ptxservq = &(psta->sta_xmitpriv.be_q);
+			*(ac) = 2;
+			RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : BE \n"));				
+		break;
+		
+	}
+
+_func_exit_;
+
+	return ptxservq;			
+}
+#else
+__inline static struct tx_servq *rtw_get_sta_pending
+	(_adapter *padapter, _queue **ppstapending, struct sta_info *psta, sint up)
+{
+	struct tx_servq *ptxservq;
+	struct hw_xmit *phwxmits =  padapter->xmitpriv.hwxmits;
+	
+_func_enter_;	
+
+#ifdef CONFIG_RTL8711
+
+	if(IS_MCAST(psta->hwaddr))
+	{
+		ptxservq = &(psta->sta_xmitpriv.be_q); // we will use be_q to queue bc/mc frames in BCMC_stainfo
+		*ppstapending = &padapter->xmitpriv.bm_pending; 
+	}
+	else
+#endif		
+	{
+		switch (up) 
+		{
+			case 1:
+			case 2:
+				ptxservq = &(psta->sta_xmitpriv.bk_q);
+				*ppstapending = &padapter->xmitpriv.bk_pending;
+				(phwxmits+3)->accnt++;
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : BK \n"));
+				break;
+
+			case 4:
+			case 5:
+				ptxservq = &(psta->sta_xmitpriv.vi_q);
+				*ppstapending = &padapter->xmitpriv.vi_pending;
+				(phwxmits+1)->accnt++;
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : VI\n"));
+				break;
+
+			case 6:
+			case 7:
+				ptxservq = &(psta->sta_xmitpriv.vo_q);
+				*ppstapending = &padapter->xmitpriv.vo_pending;
+				(phwxmits+0)->accnt++;
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : VO \n"));			
+				break;
+
+			case 0:
+			case 3:
+			default:
+				ptxservq = &(psta->sta_xmitpriv.be_q);
+				*ppstapending = &padapter->xmitpriv.be_pending;
+				(phwxmits+2)->accnt++;
+				RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("rtw_get_sta_pending : BE \n"));				
+			break;
+			
+		}
+
+	}
+
+_func_exit_;
+
+	return ptxservq;			
+}
+#endif
+
+/*
+ * Will enqueue pxmitframe to the proper queue,
+ * and indicate it to xx_pending list.....
+ */
+s32 rtw_xmit_classifier(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	//_irqL irqL0;
+	u8	ac_index;
+	struct sta_info	*psta;
+	struct tx_servq	*ptxservq;
+	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
+	struct sta_priv	*pstapriv = &padapter->stapriv;
+	struct hw_xmit	*phwxmits =  padapter->xmitpriv.hwxmits;
+	sint res = _SUCCESS;
+
+_func_enter_;
+
+	DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class);
+
+/*
+	if (pattrib->psta) {
+		psta = pattrib->psta;		
+	} else {
+		DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+		psta = rtw_get_stainfo(pstapriv, pattrib->ra);
+	}
+*/	
+
+	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	if(pattrib->psta != psta)
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_sta);
+		DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
+		return _FAIL;
+	}
+
+	if (psta == NULL) {
+		DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_nosta);
+		res = _FAIL;
+		DBG_8192C("rtw_xmit_classifier: psta == NULL\n");
+		RT_TRACE(_module_rtl871x_xmit_c_,_drv_err_,("rtw_xmit_classifier: psta == NULL\n"));
+		goto exit;
+	}
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_enqueue_class_err_fwlink);
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return _FAIL;
+	}
+
+	ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
+
+	//_enter_critical(&pstapending->lock, &irqL0);
+
+	if (rtw_is_list_empty(&ptxservq->tx_pending)) {
+		rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmits[ac_index].sta_queue));
+	}
+
+	//_enter_critical(&ptxservq->sta_pending.lock, &irqL1);
+
+	rtw_list_insert_tail(&pxmitframe->list, get_list_head(&ptxservq->sta_pending));
+	ptxservq->qcnt++;
+	phwxmits[ac_index].accnt++;
+
+	//_exit_critical(&ptxservq->sta_pending.lock, &irqL1);
+
+	//_exit_critical(&pstapending->lock, &irqL0);
+
+exit:
+
+_func_exit_;
+
+	return res;
+}
+
+void rtw_alloc_hwxmits(_adapter *padapter)
+{
+	struct hw_xmit *hwxmits;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+	pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
+
+	pxmitpriv->hwxmits = NULL;
+
+	pxmitpriv->hwxmits = (struct hw_xmit *)rtw_zmalloc(sizeof (struct hw_xmit) * pxmitpriv->hwxmit_entry);	
+
+	if(pxmitpriv->hwxmits == NULL)
+	{
+		DBG_871X("alloc hwxmits fail!...\n");
+		return;
+	}
+	
+	hwxmits = pxmitpriv->hwxmits;
+
+	if(pxmitpriv->hwxmit_entry == 5)
+	{
+		//pxmitpriv->bmc_txqueue.head = 0;
+		//hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue;
+		hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
+	
+		//pxmitpriv->vo_txqueue.head = 0;
+		//hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue;
+		hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
+
+		//pxmitpriv->vi_txqueue.head = 0;
+		//hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue;
+		hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
+	
+		//pxmitpriv->bk_txqueue.head = 0;
+		//hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
+		hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
+
+      		//pxmitpriv->be_txqueue.head = 0;
+		//hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue;
+		hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
+		
+	}	
+	else if(pxmitpriv->hwxmit_entry == 4)
+	{
+
+		//pxmitpriv->vo_txqueue.head = 0;
+		//hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue;
+		hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
+
+		//pxmitpriv->vi_txqueue.head = 0;
+		//hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue;
+		hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
+
+		//pxmitpriv->be_txqueue.head = 0;
+		//hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue;
+		hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
+	
+		//pxmitpriv->bk_txqueue.head = 0;
+		//hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
+		hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
+	}
+	else
+	{
+		
+
+	}
+	
+
+}
+
+void rtw_free_hwxmits(_adapter *padapter)
+{
+	struct hw_xmit *hwxmits;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+	hwxmits = pxmitpriv->hwxmits;
+	if(hwxmits)
+		rtw_mfree((u8 *)hwxmits, (sizeof (struct hw_xmit) * pxmitpriv->hwxmit_entry));
+}
+
+void rtw_init_hwxmits(struct hw_xmit *phwxmit, sint entry)
+{
+	sint i;
+_func_enter_;	
+	for(i = 0; i < entry; i++, phwxmit++)
+	{
+		//_rtw_spinlock_init(&phwxmit->xmit_lock);
+		//_rtw_init_listhead(&phwxmit->pending);		
+		//phwxmit->txcmdcnt = 0;
+		phwxmit->accnt = 0;
+	}
+_func_exit_;	
+}
+
+#ifdef CONFIG_BR_EXT
+int rtw_br_client_tx(_adapter *padapter, struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	_irqL irqL;
+	//if(check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE)
+	{
+		void dhcp_flag_bcast(_adapter *priv, struct sk_buff *skb);
+		int res, is_vlan_tag=0, i, do_nat25=1;
+		unsigned short vlan_hdr=0;
+		void *br_port = NULL;
+
+		//mac_clone_handle_frame(priv, skb);
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+		br_port = padapter->pnetdev->br_port;
+#else   // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+		rcu_read_lock();
+		br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
+		rcu_read_unlock();
+#endif  // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+		_enter_critical_bh(&padapter->br_ext_lock, &irqL);
+		if (	!(skb->data[0] & 1) &&
+				br_port &&
+				memcmp(skb->data+MACADDRLEN, padapter->br_mac, MACADDRLEN) &&
+				*((unsigned short *)(skb->data+MACADDRLEN*2)) != __constant_htons(ETH_P_8021Q) &&
+				*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP) &&
+				!memcmp(padapter->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN) && padapter->scdb_entry) {
+			memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
+			padapter->scdb_entry->ageing_timer = jiffies;
+			_exit_critical_bh(&padapter->br_ext_lock, &irqL);
+		}
+		else
+		//if (!priv->pmib->ethBrExtInfo.nat25_disable) 		
+		{
+//			if (priv->dev->br_port &&
+//				 !memcmp(skb->data+MACADDRLEN, priv->br_mac, MACADDRLEN)) {
+#if 1
+			if (*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_8021Q)) {
+				is_vlan_tag = 1;
+				vlan_hdr = *((unsigned short *)(skb->data+MACADDRLEN*2+2));
+				for (i=0; i<6; i++)
+					*((unsigned short *)(skb->data+MACADDRLEN*2+2-i*2)) = *((unsigned short *)(skb->data+MACADDRLEN*2-2-i*2));
+				skb_pull(skb, 4);
+			}
+			//if SA == br_mac && skb== IP  => copy SIP to br_ip ?? why
+			if (!memcmp(skb->data+MACADDRLEN, padapter->br_mac, MACADDRLEN) &&
+				(*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP)))
+				memcpy(padapter->br_ip, skb->data+WLAN_ETHHDR_LEN+12, 4);
+
+			if (*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_IP)) {
+				if (memcmp(padapter->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN)) {
+					void *scdb_findEntry(_adapter *priv, unsigned char *macAddr, unsigned char *ipAddr);
+					
+					if ((padapter->scdb_entry = (struct nat25_network_db_entry *)scdb_findEntry(padapter,
+								skb->data+MACADDRLEN, skb->data+WLAN_ETHHDR_LEN+12)) != NULL) {
+						memcpy(padapter->scdb_mac, skb->data+MACADDRLEN, MACADDRLEN);
+						memcpy(padapter->scdb_ip, skb->data+WLAN_ETHHDR_LEN+12, 4);
+						padapter->scdb_entry->ageing_timer = jiffies;
+						do_nat25 = 0;
+					}
+				}
+				else {
+					if (padapter->scdb_entry) {
+						padapter->scdb_entry->ageing_timer = jiffies;
+						do_nat25 = 0;
+					}
+					else {
+						memset(padapter->scdb_mac, 0, MACADDRLEN);
+						memset(padapter->scdb_ip, 0, 4);
+					}
+				}
+			}
+			_exit_critical_bh(&padapter->br_ext_lock, &irqL);
+#endif // 1
+			if (do_nat25)
+			{
+				int nat25_db_handle(_adapter *priv, struct sk_buff *skb, int method);
+				if (nat25_db_handle(padapter, skb, NAT25_CHECK) == 0) {
+					struct sk_buff *newskb;
+
+					if (is_vlan_tag) {
+						skb_push(skb, 4);
+						for (i=0; i<6; i++)
+							*((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
+						*((unsigned short *)(skb->data+MACADDRLEN*2)) = __constant_htons(ETH_P_8021Q);
+						*((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr;
+					}
+
+					newskb = rtw_skb_copy(skb);
+					if (newskb == NULL) {
+						//priv->ext_stats.tx_drops++;
+						DEBUG_ERR("TX DROP: rtw_skb_copy fail!\n");
+						//goto stop_proc;
+						return -1;
+					}
+					rtw_skb_free(skb);
+
+					*pskb = skb = newskb;
+					if (is_vlan_tag) {
+						vlan_hdr = *((unsigned short *)(skb->data+MACADDRLEN*2+2));
+						for (i=0; i<6; i++)
+							*((unsigned short *)(skb->data+MACADDRLEN*2+2-i*2)) = *((unsigned short *)(skb->data+MACADDRLEN*2-2-i*2));
+						skb_pull(skb, 4);
+					}
+				}
+
+				if (skb_is_nonlinear(skb))
+					DEBUG_ERR("%s(): skb_is_nonlinear!!\n", __FUNCTION__);
+					
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
+				res = skb_linearize(skb, GFP_ATOMIC);
+#else	// (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
+				res = skb_linearize(skb);
+#endif	// (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18))
+				if (res < 0) {				
+						DEBUG_ERR("TX DROP: skb_linearize fail!\n");
+						//goto free_and_stop;
+						return -1;
+				}
+				
+				res = nat25_db_handle(padapter, skb, NAT25_INSERT);
+				if (res < 0) {
+					if (res == -2) {
+						//priv->ext_stats.tx_drops++;
+						DEBUG_ERR("TX DROP: nat25_db_handle fail!\n");
+						//goto free_and_stop;
+						return -1;
+
+					}
+					// we just print warning message and let it go
+					//DEBUG_WARN("%s()-%d: nat25_db_handle INSERT Warning!\n", __FUNCTION__, __LINE__);
+					//return -1; // return -1 will cause system crash on 2011/08/30!
+					return 0;
+				}
+			}
+
+			memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
+
+			dhcp_flag_bcast(padapter, skb);
+
+			if (is_vlan_tag) {
+				skb_push(skb, 4);
+				for (i=0; i<6; i++)
+					*((unsigned short *)(skb->data+i*2)) = *((unsigned short *)(skb->data+4+i*2));
+				*((unsigned short *)(skb->data+MACADDRLEN*2)) = __constant_htons(ETH_P_8021Q);
+				*((unsigned short *)(skb->data+MACADDRLEN*2+2)) = vlan_hdr;
+			}
+		}
+#if 0		
+		else{
+			if (*((unsigned short *)(skb->data+MACADDRLEN*2)) == __constant_htons(ETH_P_8021Q)) {
+				is_vlan_tag = 1;
+			}
+				
+			if(is_vlan_tag){
+				if(ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A_VALN(skb->data)){
+                                        memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
+				}
+			}else
+			{
+				if(ICMPV6_MCAST_MAC(skb->data) && ICMPV6_PROTO1A(skb->data)){
+                                        memcpy(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN);
+				}
+			}	
+		}
+#endif	// 0
+
+		// check if SA is equal to our MAC
+		if (memcmp(skb->data+MACADDRLEN, GET_MY_HWADDR(padapter), MACADDRLEN)) {
+			//priv->ext_stats.tx_drops++;
+			DEBUG_ERR("TX DROP: untransformed frame SA:%02X%02X%02X%02X%02X%02X!\n",
+				skb->data[6],skb->data[7],skb->data[8],skb->data[9],skb->data[10],skb->data[11]);
+			//goto free_and_stop;
+			return -1;
+		}
+	}
+	return 0;
+}
+#endif	// CONFIG_BR_EXT
+
+u32 rtw_get_ff_hwaddr(struct xmit_frame *pxmitframe)
+{
+	u32 addr;
+	struct pkt_attrib *pattrib = &pxmitframe->attrib;	
+	
+	switch(pattrib->qsel)
+	{
+		case 0:
+		case 3:
+			addr = BE_QUEUE_INX;
+		 	break;
+		case 1:
+		case 2:
+			addr = BK_QUEUE_INX;
+			break;				
+		case 4:
+		case 5:
+			addr = VI_QUEUE_INX;
+			break;		
+		case 6:
+		case 7:
+			addr = VO_QUEUE_INX;
+			break;
+		case 0x10:
+			addr = BCN_QUEUE_INX;
+			break;
+		case 0x11://BC/MC in PS (HIQ)
+			addr = HIGH_QUEUE_INX;
+			break;
+		case 0x12:
+		default:
+			addr = MGT_QUEUE_INX;
+			break;		
+			
+	}
+
+	return addr;
+
+}
+
+static void do_queue_select(_adapter	*padapter, struct pkt_attrib *pattrib)
+{
+	u8 qsel;
+		
+	qsel = pattrib->priority;
+	RT_TRACE(_module_rtl871x_xmit_c_,_drv_info_,("### do_queue_select priority=%d ,qsel = %d\n",pattrib->priority ,qsel));
+
+#ifdef CONFIG_CONCURRENT_MODE	
+//	if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
+//		qsel = 7;//
+#endif
+	
+	pattrib->qsel = qsel;
+}
+
+/*
+ * The main transmit(tx) entry
+ *
+ * Return
+ *	1	enqueue
+ *	0	success, hardware will handle this xmit frame(packet)
+ *	<0	fail
+ */
+s32 rtw_monitor_xmit_entry(struct sk_buff *skb, struct net_device *ndev)
+{
+	int ret = 0;
+	int rtap_len;
+	int qos_len = 0;
+	int dot11_hdr_len = 24;
+	int snap_len = 6;
+	unsigned char *pdata;
+	u16 frame_ctl;
+	unsigned char src_mac_addr[6];
+	unsigned char dst_mac_addr[6];
+	struct rtw_ieee80211_hdr *dot11_hdr;
+	struct ieee80211_radiotap_header *rtap_hdr;
+	_adapter *padapter = (_adapter *)rtw_netdev_priv(ndev);
+
+	if (skb)
+		rtw_mstat_update(MSTAT_TYPE_SKB, MSTAT_ALLOC_SUCCESS, skb->truesize);
+
+	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
+		goto fail;
+
+	rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
+	if (unlikely(rtap_hdr->it_version))
+		goto fail;
+
+	rtap_len = ieee80211_get_radiotap_len(skb->data);
+	if (unlikely(skb->len < rtap_len))
+		goto fail;
+
+	if (rtap_len != 12) {
+		DBG_8192C("radiotap len (should be 14): %d\n", rtap_len);
+		goto fail;
+	}
+
+	/* Skip the ratio tap header */
+	skb_pull(skb, rtap_len);
+
+	dot11_hdr = (struct rtw_ieee80211_hdr *)skb->data;
+	frame_ctl = le16_to_cpu(dot11_hdr->frame_ctl);
+	/* Check if the QoS bit is set */
+
+	if ((frame_ctl & RTW_IEEE80211_FCTL_FTYPE) == RTW_IEEE80211_FTYPE_DATA) {
+
+		struct xmit_frame		*pmgntframe;
+		struct pkt_attrib	*pattrib;
+		unsigned char	*pframe;
+		struct rtw_ieee80211_hdr *pwlanhdr;
+		struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+		struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+		u8 *buf = skb->data;
+		u32 len = skb->len;
+		u8 category, action;
+		int type = -1;
+
+		pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+		if (pmgntframe == NULL) {
+			rtw_udelay_os(500);
+			goto fail;
+		}
+		pattrib = &pmgntframe->attrib;
+
+		update_monitor_frame_attrib(padapter, pattrib);
+
+		pattrib->retry_ctrl = _FALSE;
+
+		_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+		_rtw_memcpy(pframe, (void *)buf, len);
+
+		pattrib->pktlen = len;
+
+		pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+		if (is_broadcast_mac_addr(pwlanhdr->addr3) || is_broadcast_mac_addr(pwlanhdr->addr1))
+			pattrib->rate = MGN_24M;
+
+		pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
+		pattrib->seqnum = pmlmeext->mgnt_seq;
+		pmlmeext->mgnt_seq++;
+
+		pattrib->last_txcmdsz = pattrib->pktlen;
+
+		dump_mgntframe(padapter, pmgntframe);
+
+	} else {
+		struct xmit_frame		*pmgntframe;
+		struct pkt_attrib	*pattrib;
+		unsigned char	*pframe;
+		struct rtw_ieee80211_hdr *pwlanhdr;
+		struct xmit_priv	*pxmitpriv = &(padapter->xmitpriv);
+		struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+		u8 *buf = skb->data;
+		u32 len = skb->len;
+		u8 category, action;
+		int type = -1;
+
+		pmgntframe = alloc_mgtxmitframe(pxmitpriv);
+		if (pmgntframe == NULL)
+			goto fail;
+
+		pattrib = &pmgntframe->attrib;
+		update_mgntframe_attrib(padapter, pattrib);
+		pattrib->retry_ctrl = _FALSE;
+
+		_rtw_memset(pmgntframe->buf_addr, 0, WLANHDR_OFFSET + TXDESC_OFFSET);
+
+		pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
+
+		_rtw_memcpy(pframe, (void *)buf, len);
+
+		pattrib->pktlen = len;
+
+		pwlanhdr = (struct rtw_ieee80211_hdr *)pframe;
+
+		pmlmeext->mgnt_seq = GetSequence(pwlanhdr);
+		pattrib->seqnum = pmlmeext->mgnt_seq;
+		pmlmeext->mgnt_seq++;
+
+		pattrib->last_txcmdsz = pattrib->pktlen;
+
+		dump_mgntframe(padapter, pmgntframe);
+
+	}
+
+fail:
+
+		rtw_skb_free(skb);
+
+		return 0;
+}
+
+/*
+ * The main transmit(tx) entry
+ *
+ * Return
+ *	1	enqueue
+ *	0	success, hardware will handle this xmit frame(packet)
+ *	<0	fail
+ */
+s32 rtw_xmit(_adapter *padapter, _pkt **ppkt)
+{
+	static u32 start = 0;
+	static u32 drop_cnt = 0;
+#ifdef CONFIG_AP_MODE
+	_irqL irqL0;
+#endif
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+	struct xmit_frame *pxmitframe = NULL;
+#ifdef CONFIG_BR_EXT
+	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
+	void *br_port = NULL;
+#endif	// CONFIG_BR_EXT
+
+	s32 res;
+
+	DBG_COUNTER(padapter->tx_logs.core_tx);
+
+	if (start == 0)
+		start = rtw_get_current_time();
+
+	pxmitframe = rtw_alloc_xmitframe(pxmitpriv);
+
+	if (rtw_get_passing_time_ms(start) > 2000) {
+		if (drop_cnt)
+			DBG_871X("DBG_TX_DROP_FRAME %s no more pxmitframe, drop_cnt:%u\n", __FUNCTION__, drop_cnt);
+		start = rtw_get_current_time();
+		drop_cnt = 0;
+	}
+
+	if (pxmitframe == NULL) {
+		drop_cnt ++;
+		RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: no more pxmitframe\n"));
+		DBG_COUNTER(padapter->tx_logs.core_tx_err_pxmitframe);
+		return -1;
+	}
+
+#ifdef CONFIG_BR_EXT
+
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+	br_port = padapter->pnetdev->br_port;
+#else   // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+	rcu_read_lock();
+	br_port = rcu_dereference(padapter->pnetdev->rx_handler_data);
+	rcu_read_unlock();
+#endif  // (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 35))
+
+	if( br_port && check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) == _TRUE)
+	{
+		res = rtw_br_client_tx(padapter, ppkt);
+		if (res == -1)
+		{
+			rtw_free_xmitframe(pxmitpriv, pxmitframe);
+			DBG_COUNTER(padapter->tx_logs.core_tx_err_brtx);
+			return -1;
+		}
+	}	
+
+#endif	// CONFIG_BR_EXT
+
+	res = update_attrib(padapter, *ppkt, &pxmitframe->attrib);
+
+#ifdef CONFIG_WAPI_SUPPORT
+	if(pxmitframe->attrib.ether_type != 0x88B4)
+	{
+		if(rtw_wapi_drop_for_key_absent(padapter, pxmitframe->attrib.ra))
+		{
+			WAPI_TRACE(WAPI_RX,"drop for key absend when tx \n");
+			res = _FAIL;
+		}
+	}
+#endif
+	if (res == _FAIL) {
+		RT_TRACE(_module_xmit_osdep_c_, _drv_err_, ("rtw_xmit: update attrib fail\n"));
+		#ifdef DBG_TX_DROP_FRAME
+		DBG_871X("DBG_TX_DROP_FRAME %s update attrib fail\n", __FUNCTION__);
+		#endif
+		rtw_free_xmitframe(pxmitpriv, pxmitframe);
+		return -1;
+	}
+	pxmitframe->pkt = *ppkt;
+
+	rtw_led_control(padapter, LED_CTL_TX);
+
+	do_queue_select(padapter, &pxmitframe->attrib);
+
+#ifdef CONFIG_AP_MODE
+	_enter_critical_bh(&pxmitpriv->lock, &irqL0);
+	if(xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe) == _TRUE)
+	{
+		_exit_critical_bh(&pxmitpriv->lock, &irqL0);
+		DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue);
+		return 1;		
+	}
+	_exit_critical_bh(&pxmitpriv->lock, &irqL0);
+#endif
+
+	//pre_xmitframe
+	if (rtw_hal_xmit(padapter, pxmitframe) == _FALSE)
+		return 1;
+
+	return 0;
+}
+
+#ifdef CONFIG_TDLS
+sint xmitframe_enqueue_for_tdls_sleeping_sta(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	sint ret=_FALSE;
+
+	_irqL irqL;
+	struct sta_info *ptdls_sta=NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct pkt_attrib *pattrib = &pxmitframe->attrib;
+	struct mlme_ext_priv	*pmlmeext = &(padapter->mlmeextpriv);
+	int i;
+	
+	ptdls_sta=rtw_get_stainfo(pstapriv, pattrib->dst);
+	if(ptdls_sta==NULL){
+		return ret;
+	}else if(ptdls_sta->tdls_sta_state&TDLS_LINKED_STATE){
+
+		if(pattrib->triggered==1)
+		{
+			ret = _TRUE;
+			return ret;
+		}
+
+		_enter_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);	
+		
+		if(ptdls_sta->state&WIFI_SLEEP_STATE)
+		{
+			rtw_list_delete(&pxmitframe->list);
+		
+			//_enter_critical_bh(&psta->sleep_q.lock, &irqL);	
+			
+			rtw_list_insert_tail(&pxmitframe->list, get_list_head(&ptdls_sta->sleep_q));
+			
+			ptdls_sta->sleepq_len++;
+			ptdls_sta->sleepq_ac_len++;
+
+			//indicate 4-AC queue bit in TDLS peer traffic indication
+			switch(pattrib->priority)
+			{
+				case 1:
+				case 2:
+					ptdls_sta->uapsd_bk |= BIT(1);
+					break;
+				case 4:
+				case 5:
+					ptdls_sta->uapsd_vi |= BIT(1);
+					break;
+				case 6:
+				case 7:
+					ptdls_sta->uapsd_vo |= BIT(1);
+					break;
+				case 0:
+				case 3:
+				default:
+					ptdls_sta->uapsd_be |= BIT(1);
+					break;
+			}
+
+			/* Transmit TDLS PTI via AP */
+			if(ptdls_sta->sleepq_len==1)
+				rtw_tdls_cmd(padapter, ptdls_sta->hwaddr, TDLS_ISSUE_PTI);
+
+			ret = _TRUE;
+		}
+
+		_exit_critical_bh(&ptdls_sta->sleep_q.lock, &irqL);	
+	}
+
+	return ret;
+	
+}
+#endif //CONFIG_TDLS
+
+#define RTW_HIQ_FILTER_ALLOW_ALL 0
+#define RTW_HIQ_FILTER_ALLOW_SPECIAL 1
+#define RTW_HIQ_FILTER_DENY_ALL 2
+
+inline bool xmitframe_hiq_filter(struct xmit_frame *xmitframe)
+{
+	bool allow = _FALSE;
+	_adapter *adapter = xmitframe->padapter;
+	struct registry_priv *registry = &adapter->registrypriv;
+
+if (rtw_get_intf_type(adapter) != RTW_PCIE) {
+
+	if (adapter->registrypriv.wifi_spec == 1) {
+		allow = _TRUE;
+	} else if (registry->hiq_filter == RTW_HIQ_FILTER_ALLOW_SPECIAL) {
+	
+		struct pkt_attrib *attrib = &xmitframe->attrib;
+
+		if (attrib->ether_type == 0x0806
+			|| attrib->ether_type == 0x888e
+			#ifdef CONFIG_WAPI_SUPPORT
+			|| attrib->ether_type == 0x88B4
+			#endif
+			|| attrib->dhcp_pkt
+		) {
+			if (0)
+				DBG_871X(FUNC_ADPT_FMT" ether_type:0x%04x%s\n", FUNC_ADPT_ARG(xmitframe->padapter)
+					, attrib->ether_type, attrib->dhcp_pkt?" DHCP":"");
+			allow = _TRUE;
+		}
+	}
+	else if (registry->hiq_filter == RTW_HIQ_FILTER_ALLOW_ALL) {
+		allow = _TRUE;
+	}
+	else if (registry->hiq_filter == RTW_HIQ_FILTER_DENY_ALL) {
+	}
+	else {
+		rtw_warn_on(1);
+	}
+}
+	return allow;
+}
+
+#if defined(CONFIG_AP_MODE) || defined(CONFIG_TDLS)
+
+sint xmitframe_enqueue_for_sleeping_sta(_adapter *padapter, struct xmit_frame *pxmitframe)
+{
+	_irqL irqL;
+	sint ret=_FALSE;
+	struct sta_info *psta=NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct pkt_attrib *pattrib = &pxmitframe->attrib;
+	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
+	sint bmcst = IS_MCAST(pattrib->ra);
+	bool update_tim = _FALSE;
+#ifdef CONFIG_TDLS
+
+	if( padapter->tdlsinfo.link_established == _TRUE )
+	{
+		ret = xmitframe_enqueue_for_tdls_sleeping_sta(padapter, pxmitframe);
+	}
+#endif //CONFIG_TDLS
+
+	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == _FALSE)
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_fwstate);
+	    return ret;
+	}
+/*
+	if(pattrib->psta)
+	{
+		psta = pattrib->psta;
+	}
+	else
+	{
+		DBG_871X("%s, call rtw_get_stainfo()\n", __func__);
+		psta=rtw_get_stainfo(pstapriv, pattrib->ra);
+	}
+*/
+	psta = rtw_get_stainfo(&padapter->stapriv, pattrib->ra);
+	if(pattrib->psta != psta)
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_sta);
+		DBG_871X("%s, pattrib->psta(%p) != psta(%p)\n", __func__, pattrib->psta, psta);
+		return _FALSE;
+	}
+
+	if(psta==NULL)
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_nosta);
+		DBG_871X("%s, psta==NUL\n", __func__);
+		return _FALSE;
+	}
+
+	if(!(psta->state &_FW_LINKED))
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_link);
+		DBG_871X("%s, psta->state(0x%x) != _FW_LINKED\n", __func__, psta->state);
+		return _FALSE;
+	}
+
+	if(pattrib->triggered==1)
+	{
+		DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_warn_trigger);
+		//DBG_871X("directly xmit pspoll_triggered packet\n");
+
+		//pattrib->triggered=0;
+		if (bmcst && xmitframe_hiq_filter(pxmitframe) == _TRUE)
+			pattrib->qsel = QSLT_HIGH;//HIQ
+
+		return ret;
+	}
+
+
+	if(bmcst)
+	{
+		_enter_critical_bh(&psta->sleep_q.lock, &irqL);	
+	
+		if(pstapriv->sta_dz_bitmap)//if anyone sta is in ps mode
+		{
+			//pattrib->qsel = QSLT_HIGH;//HIQ
+			
+			rtw_list_delete(&pxmitframe->list);
+			
+			//_enter_critical_bh(&psta->sleep_q.lock, &irqL);	
+			
+			rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+			
+			psta->sleepq_len++;
+
+			if (!(pstapriv->tim_bitmap & BIT(0)))
+				update_tim = _TRUE;
+
+			pstapriv->tim_bitmap |= BIT(0);//
+			pstapriv->sta_dz_bitmap |= BIT(0);
+
+			//DBG_871X("enqueue, sq_len=%d, tim=%x\n", psta->sleepq_len, pstapriv->tim_bitmap);
+			if (padapter->registrypriv.wifi_spec == 1) {
+				/*
+				*if (update_tim == _TRUE)
+				*	rtw_chk_hi_queue_cmd(padapter);
+				*/
+			} else {
+
+				if (update_tim == _TRUE) {
+					if (is_broadcast_mac_addr(pattrib->ra))
+						_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "buffer BC");
+					else
+						_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "buffer MC");
+				} else {
+					chk_bmc_sleepq_cmd(padapter);
+				}
+			}
+
+			//_exit_critical_bh(&psta->sleep_q.lock, &irqL);				
+			
+			ret = _TRUE;			
+
+			DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_mcast);
+			
+		}
+		
+		_exit_critical_bh(&psta->sleep_q.lock, &irqL);	
+		
+		return ret;
+		
+	}
+	
+
+	_enter_critical_bh(&psta->sleep_q.lock, &irqL);	
+	
+	if(psta->state&WIFI_SLEEP_STATE)
+	{
+		u8 wmmps_ac=0;
+	
+		if(pstapriv->sta_dz_bitmap&BIT(psta->aid))	
+		{			
+			rtw_list_delete(&pxmitframe->list);
+		
+			//_enter_critical_bh(&psta->sleep_q.lock, &irqL);	
+			
+			rtw_list_insert_tail(&pxmitframe->list, get_list_head(&psta->sleep_q));
+			
+			psta->sleepq_len++;
+
+			switch(pattrib->priority)
+			{
+				case 1:
+				case 2:
+					wmmps_ac = psta->uapsd_bk&BIT(0);
+					break;
+				case 4:
+				case 5:
+					wmmps_ac = psta->uapsd_vi&BIT(0);
+					break;
+				case 6:
+				case 7:
+					wmmps_ac = psta->uapsd_vo&BIT(0);
+					break;
+				case 0:
+				case 3:
+				default:
+					wmmps_ac = psta->uapsd_be&BIT(0);
+					break;
+			}
+
+			if(wmmps_ac)
+				psta->sleepq_ac_len++;
+
+			if(((psta->has_legacy_ac) && (!wmmps_ac)) ||((!psta->has_legacy_ac)&&(wmmps_ac)))
+			{
+				if (!(pstapriv->tim_bitmap & BIT(psta->aid)))
+					update_tim = _TRUE;
+
+				pstapriv->tim_bitmap |= BIT(psta->aid);
+
+				//DBG_871X("enqueue, sq_len=%d, tim=%x\n", psta->sleepq_len, pstapriv->tim_bitmap);
+
+				if(update_tim == _TRUE)
+				{
+					//DBG_871X("sleepq_len==1, update BCNTIM\n");
+					//upate BCN for TIM IE
+					_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "buffer UC");
+				}
+			}
+
+			//_exit_critical_bh(&psta->sleep_q.lock, &irqL);			
+
+			//if(psta->sleepq_len > (NR_XMITFRAME>>3))
+			//{
+			//	wakeup_sta_to_xmit(padapter, psta);
+			//}	
+
+			ret = _TRUE;
+
+			DBG_COUNTER(padapter->tx_logs.core_tx_ap_enqueue_ucast);
+		}
+
+	}
+
+	_exit_critical_bh(&psta->sleep_q.lock, &irqL);	
+
+	return ret;
+	
+}
+
+static void dequeue_xmitframes_to_sleeping_queue(_adapter *padapter, struct sta_info *psta, _queue *pframequeue)
+{
+	sint ret;
+	_list	*plist, *phead;
+	u8	ac_index;
+	struct tx_servq	*ptxservq;
+	struct pkt_attrib	*pattrib;
+	struct xmit_frame 	*pxmitframe;
+	struct hw_xmit *phwxmits =  padapter->xmitpriv.hwxmits;
+	
+	phead = get_list_head(pframequeue);
+	plist = get_next(phead);
+	
+	while (rtw_end_of_queue_search(phead, plist) == _FALSE)
+	{			
+		pxmitframe = LIST_CONTAINOR(plist, struct xmit_frame, list);
+
+		plist = get_next(plist);
+		
+		pattrib = &pxmitframe->attrib;
+
+		pattrib->triggered = 0;
+  		
+		ret = xmitframe_enqueue_for_sleeping_sta(padapter, pxmitframe);	
+
+		if(_TRUE == ret)
+		{
+			ptxservq = rtw_get_sta_pending(padapter, psta, pattrib->priority, (u8 *)(&ac_index));
+
+			ptxservq->qcnt--;
+			phwxmits[ac_index].accnt--;
+		}
+		else
+		{
+			//DBG_871X("xmitframe_enqueue_for_sleeping_sta return _FALSE\n");
+		}
+		
+	}
+	
+}
+
+void stop_sta_xmit(_adapter *padapter, struct sta_info *psta)
+{	
+	_irqL irqL0;	
+	struct sta_info *psta_bmc;
+	struct sta_xmit_priv *pstaxmitpriv;
+	struct sta_priv *pstapriv = &padapter->stapriv;	
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;	
+	
+	pstaxmitpriv = &psta->sta_xmitpriv;
+
+	//for BC/MC Frames
+	psta_bmc = rtw_get_bcmc_stainfo(padapter);
+	
+			
+	_enter_critical_bh(&pxmitpriv->lock, &irqL0);
+
+	psta->state |= WIFI_SLEEP_STATE;
+	
+#ifdef CONFIG_TDLS
+	if( !(psta->tdls_sta_state & TDLS_LINKED_STATE) )
+#endif //CONFIG_TDLS
+	pstapriv->sta_dz_bitmap |= BIT(psta->aid);
+	
+	
+
+	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vo_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->vo_q.tx_pending));
+
+
+	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->vi_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->vi_q.tx_pending));
+
+
+	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->be_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	
+
+	dequeue_xmitframes_to_sleeping_queue(padapter, psta, &pstaxmitpriv->bk_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->bk_q.tx_pending));
+
+#ifdef CONFIG_TDLS
+	if (!(psta->tdls_sta_state & TDLS_LINKED_STATE) && (psta_bmc != NULL)) {
+#endif //CONFIG_TDLS
+
+
+	//for BC/MC Frames
+	pstaxmitpriv = &psta_bmc->sta_xmitpriv;
+	dequeue_xmitframes_to_sleeping_queue(padapter, psta_bmc, &pstaxmitpriv->be_q.sta_pending);
+	rtw_list_delete(&(pstaxmitpriv->be_q.tx_pending));
+	
+
+#ifdef CONFIG_TDLS	
+		}
+#endif //CONFIG_TDLS	
+	_exit_critical_bh(&pxmitpriv->lock, &irqL0);
+	
+
+}	
+
+void wakeup_sta_to_xmit(_adapter *padapter, struct sta_info *psta)
+{	 
+	_irqL irqL;	 
+	u8 update_mask=0, wmmps_ac=0;
+	struct sta_info *psta_bmc;
+	_list	*xmitframe_plist, *xmitframe_phead;
+	struct xmit_frame *pxmitframe=NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+	psta_bmc = rtw_get_bcmc_stainfo(padapter);
+	
+
+	//_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+	_enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+	xmitframe_phead = get_list_head(&psta->sleep_q);
+	xmitframe_plist = get_next(xmitframe_phead);
+
+	while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+	{
+		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+		xmitframe_plist = get_next(xmitframe_plist);
+
+		rtw_list_delete(&pxmitframe->list);
+
+		switch(pxmitframe->attrib.priority)
+		{
+			case 1:
+			case 2:
+				wmmps_ac = psta->uapsd_bk&BIT(1);
+				break;
+			case 4:
+			case 5:
+				wmmps_ac = psta->uapsd_vi&BIT(1);
+				break;
+			case 6:
+			case 7:
+				wmmps_ac = psta->uapsd_vo&BIT(1);
+				break;
+			case 0:
+			case 3:
+			default:
+				wmmps_ac = psta->uapsd_be&BIT(1);
+				break;
+		}
+
+		psta->sleepq_len--;
+		if(psta->sleepq_len>0)
+			pxmitframe->attrib.mdata = 1;
+		else
+			pxmitframe->attrib.mdata = 0;
+
+		if(wmmps_ac)
+		{
+			psta->sleepq_ac_len--;
+			if(psta->sleepq_ac_len>0)
+			{
+				pxmitframe->attrib.mdata = 1;
+				pxmitframe->attrib.eosp = 0;
+			}
+			else
+			{
+				pxmitframe->attrib.mdata = 0;
+				pxmitframe->attrib.eosp = 1;
+			}
+		}
+
+		pxmitframe->attrib.triggered = 1;
+
+/*
+		_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+		if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
+		{
+			rtw_os_xmit_complete(padapter, pxmitframe);
+		}
+		_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+*/
+		rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+
+
+	}
+
+	if(psta->sleepq_len==0)
+	{
+#ifdef CONFIG_TDLS
+		if( psta->tdls_sta_state & TDLS_LINKED_STATE )
+		{
+			if(psta->state&WIFI_SLEEP_STATE)
+				psta->state ^= WIFI_SLEEP_STATE;
+
+			_exit_critical_bh(&pxmitpriv->lock, &irqL);
+			return;
+		}
+#endif //CONFIG_TDLS
+
+		if (pstapriv->tim_bitmap & BIT(psta->aid)) {
+			//DBG_871X("wakeup to xmit, qlen==0, update_BCNTIM, tim=%x\n", pstapriv->tim_bitmap);
+			//upate BCN for TIM IE
+			//update_BCNTIM(padapter);
+			update_mask = BIT(0);
+		}
+
+		pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+		if(psta->state&WIFI_SLEEP_STATE)
+			psta->state ^= WIFI_SLEEP_STATE;
+
+		if(psta->state & WIFI_STA_ALIVE_CHK_STATE)
+		{
+			DBG_871X("%s alive check\n", __func__);
+			psta->expire_to = pstapriv->expire_to;
+			psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
+		}
+
+		pstapriv->sta_dz_bitmap &= ~BIT(psta->aid);
+	}
+
+	//for BC/MC Frames
+	if(!psta_bmc)
+		goto _exit;
+
+	if((pstapriv->sta_dz_bitmap&0xfffe) == 0x0)//no any sta in ps mode
+	{
+		xmitframe_phead = get_list_head(&psta_bmc->sleep_q);
+		xmitframe_plist = get_next(xmitframe_phead);
+
+		while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+		{
+			pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+			xmitframe_plist = get_next(xmitframe_plist);
+
+			rtw_list_delete(&pxmitframe->list);
+
+			psta_bmc->sleepq_len--;
+			if(psta_bmc->sleepq_len>0)
+				pxmitframe->attrib.mdata = 1;
+			else
+				pxmitframe->attrib.mdata = 0;
+
+
+			pxmitframe->attrib.triggered = 1;
+/*
+			_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+			if(rtw_hal_xmit(padapter, pxmitframe) == _TRUE)
+			{
+				rtw_os_xmit_complete(padapter, pxmitframe);
+			}
+			_enter_critical_bh(&psta_bmc->sleep_q.lock, &irqL);
+
+*/
+			rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+
+		}
+
+		if(psta_bmc->sleepq_len==0)
+		{
+			if (pstapriv->tim_bitmap & BIT(0)) {
+				//DBG_871X("wakeup to xmit, qlen==0, update_BCNTIM, tim=%x\n", pstapriv->tim_bitmap);
+				//upate BCN for TIM IE
+				//update_BCNTIM(padapter);
+				update_mask |= BIT(1);
+			}
+			pstapriv->tim_bitmap &= ~BIT(0);
+			pstapriv->sta_dz_bitmap &= ~BIT(0);
+		}
+
+	}	
+
+_exit:
+
+	//_exit_critical_bh(&psta_bmc->sleep_q.lock, &irqL);	
+	_exit_critical_bh(&pxmitpriv->lock, &irqL);
+
+	if(update_mask)
+	{
+		//update_BCNTIM(padapter);
+		if ((update_mask & (BIT(0)|BIT(1))) == (BIT(0)|BIT(1)))
+			_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "clear UC&BMC");
+		else if ((update_mask & BIT(1)) == BIT(1))
+			_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "clear BMC");
+		else
+			_update_beacon(padapter, _TIM_IE_, NULL, _TRUE, "clear UC");
+	}
+	
+}
+
+void xmit_delivery_enabled_frames(_adapter *padapter, struct sta_info *psta)
+{
+	_irqL irqL;
+	u8 wmmps_ac=0;
+	_list	*xmitframe_plist, *xmitframe_phead;
+	struct xmit_frame *pxmitframe=NULL;
+	struct sta_priv *pstapriv = &padapter->stapriv;
+	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
+
+
+	//_enter_critical_bh(&psta->sleep_q.lock, &irqL);
+	_enter_critical_bh(&pxmitpriv->lock, &irqL);
+
+	xmitframe_phead = get_list_head(&psta->sleep_q);
+	xmitframe_plist = get_next(xmitframe_phead);
+
+	while ((rtw_end_of_queue_search(xmitframe_phead, xmitframe_plist)) == _FALSE)
+	{			
+		pxmitframe = LIST_CONTAINOR(xmitframe_plist, struct xmit_frame, list);
+
+		xmitframe_plist = get_next(xmitframe_plist);
+
+		switch(pxmitframe->attrib.priority)
+		{
+			case 1:
+			case 2:
+				wmmps_ac = psta->uapsd_bk&BIT(1);
+				break;
+			case 4:
+			case 5:
+				wmmps_ac = psta->uapsd_vi&BIT(1);
+				break;
+			case 6:
+			case 7:
+				wmmps_ac = psta->uapsd_vo&BIT(1);
+				break;
+			case 0:
+			case 3:
+			default:
+				wmmps_ac = psta->uapsd_be&BIT(1);
+				break;	
+		}
+		
+		if(!wmmps_ac)
+			continue;
+
+		rtw_list_delete(&pxmitframe->list);
+
+		psta->sleepq_len--;
+		psta->sleepq_ac_len--;
+
+		if(psta->sleepq_ac_len>0)
+		{
+			pxmitframe->attrib.mdata = 1;
+			pxmitframe->attrib.eosp = 0;
+		}
+		else
+		{
+			pxmitframe->attrib.mdata = 0;
+			pxmitframe->attrib.eosp = 1;
+		}
+
+		pxmitframe->attrib.triggered = 1;
+		rtw_hal_xmitframe_enqueue(padapter, pxmitframe);
+
+		if((psta->sleepq_ac_len==0) && (!psta->has_legacy_ac) && (wmmps_ac))
+		{
+#ifdef CONFIG_TDLS
+			if(psta->tdls_sta_state & TDLS_LINKED_STATE )
+			{
+				//_exit_critical_bh(&psta->sleep_q.lock, &irqL);
+				goto exit;
+			}
+#endif //CONFIG_TDLS
+			pstapriv->tim_bitmap &= ~BIT(psta->aid);
+
+			//DBG_871X("wakeup to xmit, qlen==0, update_BCNTIM, tim=%x\n", pstapriv->tim_bitmap);
+			//upate BCN for TIM IE
+			//update_BCNTIM(padapter);
+			update_beacon(padapter, _TIM_IE_, NULL, _TRUE);
+			//update_mask = BIT(0);
+		}
+	
+	}	
+
+exit:
+	//_exit_critical_bh(&psta->sleep_q.lock, &irqL);	
+	_exit_critical_bh(&pxmitpriv->lock, &irqL);
+
+	return;
+}
+
+#endif /* defined(CONFIG_AP_MODE) || defined(CONFIG_TDLS) */
+
+#ifdef CONFIG_XMIT_THREAD_MODE
+void enqueue_pending_xmitbuf(
+	struct xmit_priv *pxmitpriv,
+	struct xmit_buf *pxmitbuf)
+{
+	_irqL irql;
+	_queue *pqueue;
+	_adapter *pri_adapter = pxmitpriv->adapter;
+
+	pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+	_enter_critical_bh(&pqueue->lock, &irql);
+	rtw_list_delete(&pxmitbuf->list);
+	rtw_list_insert_tail(&pxmitbuf->list, get_list_head(pqueue));
+	_exit_critical_bh(&pqueue->lock, &irql);
+
+
+
+#if defined(CONFIG_SDIO_HCI) && defined(CONFIG_CONCURRENT_MODE)
+	if (pri_adapter->adapter_type > PRIMARY_ADAPTER)
+		pri_adapter = pri_adapter->pbuddy_adapter;
+#endif  //SDIO_HCI + CONCURRENT
+	_rtw_up_sema(&(pri_adapter->xmitpriv.xmit_sema));
+
+}
+
+void enqueue_pending_xmitbuf_to_head(
+	struct xmit_priv *pxmitpriv,
+	struct xmit_buf *pxmitbuf)
+{
+	_irqL irql;
+	_queue *pqueue;
+	_adapter *pri_adapter = pxmitpriv->adapter;
+
+	pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+	_enter_critical_bh(&pqueue->lock, &irql);
+	rtw_list_delete(&pxmitbuf->list);
+	rtw_list_insert_head(&pxmitbuf->list, get_list_head(pqueue));
+	_exit_critical_bh(&pqueue->lock, &irql);
+}
+
+struct xmit_buf* dequeue_pending_xmitbuf(
+	struct xmit_priv *pxmitpriv)
+{
+	_irqL irql;
+	struct xmit_buf *pxmitbuf;
+	_queue *pqueue;
+
+
+	pxmitbuf = NULL;
+	pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+	_enter_critical_bh(&pqueue->lock, &irql);
+
+	if (_rtw_queue_empty(pqueue) == _FALSE)
+	{
+		_list *plist, *phead;
+
+		phead = get_list_head(pqueue);
+		plist = get_next(phead);
+		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+		rtw_list_delete(&pxmitbuf->list);
+	}
+
+	_exit_critical_bh(&pqueue->lock, &irql);
+
+	return pxmitbuf;
+}
+
+struct xmit_buf* dequeue_pending_xmitbuf_under_survey(
+	struct xmit_priv *pxmitpriv)
+{
+	_irqL irql;
+	struct xmit_buf *pxmitbuf;
+#ifdef CONFIG_USB_HCI	
+	struct xmit_frame *pxmitframe;
+#endif 
+	_queue *pqueue;
+
+
+	pxmitbuf = NULL;
+	pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+	_enter_critical_bh(&pqueue->lock, &irql);
+
+	if (_rtw_queue_empty(pqueue) == _FALSE)
+	{
+		_list *plist, *phead;
+		u8 type;
+
+		phead = get_list_head(pqueue);
+		plist = phead;
+		do {
+			plist = get_next(plist);
+				if (plist == phead) break;
+			
+			pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
+
+#ifdef CONFIG_USB_HCI
+			pxmitframe = (struct xmit_frame*)pxmitbuf->priv_data;
+			if(pxmitframe)
+			{
+				type = GetFrameSubType(pxmitbuf->pbuf + TXDESC_SIZE + pxmitframe->pkt_offset * PACKET_OFFSET_SZ);
+			}
+			else
+			{
+				DBG_871X("%s, !!!ERROR!!! For USB, TODO ITEM \n", __FUNCTION__);
+			}
+#else
+			type = GetFrameSubType(pxmitbuf->pbuf + TXDESC_OFFSET);
+#endif
+
+			if ((type == WIFI_PROBEREQ) ||
+				(type == WIFI_DATA_NULL) ||
+				(type == WIFI_QOS_DATA_NULL))
+			{
+				rtw_list_delete(&pxmitbuf->list);
+				break;
+			}
+			pxmitbuf = NULL;
+		} while (1);
+	}
+
+	_exit_critical_bh(&pqueue->lock, &irql);
+
+	return pxmitbuf;
+}
+
+sint check_pending_xmitbuf(
+	struct xmit_priv *pxmitpriv)
+{
+	_irqL irql;
+	_queue *pqueue;
+	sint	ret = _FALSE;
+
+	pqueue = &pxmitpriv->pending_xmitbuf_queue;
+
+	_enter_critical_bh(&pqueue->lock, &irql);
+
+	if(_rtw_queue_empty(pqueue) == _FALSE)
+		ret = _TRUE;
+
+	_exit_critical_bh(&pqueue->lock, &irql);
+
+	return ret;
+}
+
+thread_return rtw_xmit_thread(thread_context context)
+{
+	s32 err;
+	PADAPTER padapter;
+
+
+	err = _SUCCESS;
+	padapter = (PADAPTER)context;
+
+	thread_enter("RTW_XMIT_THREAD");
+
+	do {
+		err = rtw_hal_xmit_thread_handler(padapter);
+		flush_signals_thread();
+	} while (_SUCCESS == err);
+
+	_rtw_up_sema(&padapter->xmitpriv.terminate_xmitthread_sema);
+
+	thread_exit();
+}
+#endif
+
+bool rtw_xmit_ac_blocked(_adapter *adapter)
+{
+	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
+	_adapter *iface;
+	struct mlme_ext_priv *mlmeext;
+	struct mlme_ext_info *mlmeextinfo;
+	bool blocked = _FALSE;
+	int i;
+
+	for (i = 0; i < dvobj->iface_nums; i++) {
+		iface = dvobj->padapters[i];
+		mlmeext = &iface->mlmeextpriv;
+
+		/* check scan state */
+		if (mlmeext_scan_state(mlmeext) != SCAN_DISABLE
+			&& mlmeext_scan_state(mlmeext) != SCAN_BACK_OP
+		) {
+			blocked = _TRUE;
+			goto exit;
+		}
+
+		if (mlmeext_scan_state(mlmeext) == SCAN_BACK_OP
+			&& !mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_TX_RESUME)
+		) {
+			blocked = _TRUE;
+			goto exit;
+		}
+	}
+
+exit:
+	return blocked;
+}
+
+void rtw_sctx_init(struct submit_ctx *sctx, int timeout_ms)
+{
+	sctx->timeout_ms = timeout_ms;
+	sctx->submit_time= rtw_get_current_time();
+#ifdef PLATFORM_LINUX /* TODO: add condition wating interface for other os */
+	init_completion(&sctx->done);
+#endif
+	sctx->status = RTW_SCTX_SUBMITTED;
+}
+
+int rtw_sctx_wait(struct submit_ctx *sctx, const char *msg)
+{
+	int ret = _FAIL;
+	unsigned long expire; 
+	int status = 0;
+
+#ifdef PLATFORM_LINUX
+	expire= sctx->timeout_ms ? msecs_to_jiffies(sctx->timeout_ms) : MAX_SCHEDULE_TIMEOUT;
+	if (!wait_for_completion_timeout(&sctx->done, expire)) {
+		/* timeout, do something?? */
+		status = RTW_SCTX_DONE_TIMEOUT;
+		DBG_871X("%s timeout: %s\n", __func__, msg);
+	} else {
+		status = sctx->status;
+	}
+#endif
+
+	if (status == RTW_SCTX_DONE_SUCCESS) {
+		ret = _SUCCESS;
+	}
+
+	return ret;
+}
+
+bool rtw_sctx_chk_waring_status(int status)
+{
+	switch(status) {
+	case RTW_SCTX_DONE_UNKNOWN:
+	case RTW_SCTX_DONE_BUF_ALLOC:
+	case RTW_SCTX_DONE_BUF_FREE:
+
+	case RTW_SCTX_DONE_DRV_STOP:
+	case RTW_SCTX_DONE_DEV_REMOVE:
+		return _TRUE;
+	default:
+		return _FALSE;
+	}
+}
+
+void rtw_sctx_done_err(struct submit_ctx **sctx, int status)
+{
+	if (*sctx) {
+		if (rtw_sctx_chk_waring_status(status))
+			DBG_871X("%s status:%d\n", __func__, status);
+		(*sctx)->status = status;
+		#ifdef PLATFORM_LINUX
+		complete(&((*sctx)->done));
+		#endif
+		*sctx = NULL;
+	}
+}
+
+void rtw_sctx_done(struct submit_ctx **sctx)
+{
+	rtw_sctx_done_err(sctx, RTW_SCTX_DONE_SUCCESS);
+}
+
+#ifdef CONFIG_XMIT_ACK
+
+#ifdef CONFIG_XMIT_ACK_POLLING
+s32 c2h_evt_hdl(_adapter *adapter, u8 *c2h_evt, c2h_id_filter filter);
+
+/**
+ * rtw_ack_tx_polling -
+ * @pxmitpriv: xmit_priv to address ack_tx_ops
+ * @timeout_ms: timeout msec
+ *
+ * Init ack_tx_ops and then do c2h_evt_hdl() and polling ack_tx_ops repeatedly
+ * till tx report or timeout
+ * Returns: _SUCCESS if TX report ok, _FAIL for others
+ */
+int rtw_ack_tx_polling(struct xmit_priv *pxmitpriv, u32 timeout_ms)
+{
+	int ret = _FAIL;
+	struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
+	_adapter *adapter = container_of(pxmitpriv, _adapter, xmitpriv);
+
+	pack_tx_ops->submit_time = rtw_get_current_time();
+	pack_tx_ops->timeout_ms = timeout_ms;
+	pack_tx_ops->status = RTW_SCTX_SUBMITTED;
+
+	do {
+		c2h_evt_hdl(adapter, NULL, rtw_hal_c2h_id_filter_ccx(adapter));
+		if (pack_tx_ops->status != RTW_SCTX_SUBMITTED)
+			break;
+
+		if (rtw_is_drv_stopped(adapter)) {
+			pack_tx_ops->status = RTW_SCTX_DONE_DRV_STOP;
+			break;
+		}
+		if (rtw_is_surprise_removed(adapter)) {
+			pack_tx_ops->status = RTW_SCTX_DONE_DEV_REMOVE;
+			break;
+		}
+		
+		rtw_msleep_os(10);
+	} while (rtw_get_passing_time_ms(pack_tx_ops->submit_time) < timeout_ms);
+
+	if (pack_tx_ops->status == RTW_SCTX_SUBMITTED) {
+		pack_tx_ops->status = RTW_SCTX_DONE_TIMEOUT;
+		DBG_871X("%s timeout\n", __func__);
+	}
+
+	if (pack_tx_ops->status == RTW_SCTX_DONE_SUCCESS)
+		ret = _SUCCESS;
+
+	return ret;
+}
+#endif
+
+int rtw_ack_tx_wait(struct xmit_priv *pxmitpriv, u32 timeout_ms)
+{
+#ifdef CONFIG_XMIT_ACK_POLLING
+	return rtw_ack_tx_polling(pxmitpriv, timeout_ms);
+#else
+	struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
+
+	pack_tx_ops->submit_time = rtw_get_current_time();
+	pack_tx_ops->timeout_ms = timeout_ms;
+	pack_tx_ops->status = RTW_SCTX_SUBMITTED;
+
+	return rtw_sctx_wait(pack_tx_ops, __func__);
+#endif
+}
+
+void rtw_ack_tx_done(struct xmit_priv *pxmitpriv, int status)
+{
+	struct submit_ctx *pack_tx_ops = &pxmitpriv->ack_tx_ops;
+	
+	if (pxmitpriv->ack_tx) {
+		rtw_sctx_done_err(&pack_tx_ops, status);
+	} else {
+		DBG_871X("%s ack_tx not set\n", __func__);
+	}
+}
+#endif //CONFIG_XMIT_ACK
+
-- 
2.34.1

